2012-05-08 36 views
4

我工作的項目歐拉的問題22:項目歐拉#22 Python,缺少2205點?

使用names.txt中(右鍵「目標另存/目標爲...」),載有超過五千年的名字一個46K的文本文件,首先按字母順序排序。然後計算每個名稱的字母值,將此值乘以列表中的字母位置以獲得名稱分數。

例如,當列表按字母順序排序時,值爲3 + 15 + 12 + 9 + 14 = 53的COLIN 是 列表中的第938個名稱。因此,COLIN將獲得938×53 = 49714的分數。

文件中所有名稱得分的總和是多少?

http://projecteuler.net/problem=22

當我編譯下面我的代碼,我得到的答案。正確的答案應該是。

導入時間

DEF euler_22():

## Creates a sorted list of the names in Py_Euler_22.txt 
names = open('Py_Euler_22.txt', 'r') 
names = names.read() 
names = names.split('","') 
names[0] = names[0][1:] 
names[-1] = names[-1][:-2] 
names = sorted(names) 

## Creates a dictionary: letter -> value 
value_letters = {} 
start = ord("A") 
for i in range(0, 26): 
    value_letters[chr(start+i)] = i+1 

result = 0 

for i in range(1, len(names)+1): 
    name = names[i-1] 
    sum_letters = 0 
    for letter in name: 
     sum_letters += value_letters[letter]*i 
     # = value of the letter multiplied with the name position 
    result += sum_letters 
return result 

TSTART =了time.time() 打印euler_22() 打印 「運行時間:」 + STR(了time.time( ) - tstart)

我試圖找到一個類似的解決方案,但我只知道Python,這限制了選項。 我用更簡單的文本文件運行程序,我創建了,我可以在沒有程序的情況下獲得答案,並且所有程序都可以工作。我搜索了這個問題的答案,但這也沒有幫助,因爲我無法找到缺點。

我是一名初學者,所以我非常感謝關於程序和Python的任何提示,而不僅僅是那些,這將幫助我正確地解決問題。

非常感謝!

+2

爲什麼這個'名稱[0] =名[0] [1:] 名稱[-1] =名[-1] [: - 2]' ?? –

+0

從名字和姓氏中刪除引號;我認爲''''分隔每個名字的''',並且去掉'''會更好,但是他的代碼會起作用。 –

+0

@AdamMatan,您需要使用名稱[-1] [: - 1]來刪除姓氏 – spinlok

回答

1

我剛剛交叉檢查了你的代碼,看起來你無意中將最後一個單詞的最後一個字符截斷了。要從最後一個字中去掉引號,請使用:

names[-1] = names[-1][:-1] 
0

這是加載文件時的一個簡單錯誤。試着這樣來代替:

import ast 
with open('Py_Euler_22.txt') as f: 
    names = sorted(ast.literal_eval(f.read())) 

順便說一句,遍歷range,然後使用i索引到另一個容器是很少適當的。我在說這部分:

for i in range(1, len(names)+1): 
    name = names[i-1] 

只需使用for name in names:來代替這裏。

+1

'ast'對初學者來說有點「黑魔法」 –

+0

這是... 我真的不明白它 這是第三個程序,我正在使用文本文件編寫,但是,謝謝,我會把它列在一些事情上,我想理解。 對於第二個,它看起來像最簡單的方式來跟蹤名稱的位置: > sum_letters + = value_letters [letter] * i –

+0

啊,爲此,您應該使用'for i,name枚舉(名字)'。 – wim

3

你意外地毀了一個名字。

這裏qnames是你的代碼產生名字的排序列表,並sorted_names是我:

>>> for a,b in zip(qnames, sorted_names): 
...  if a != b: 
...   print a, b 
... 
ALONS ALONSO 

爲了好玩:一個班輪 - 嵌套列表內涵,AVAST你們!

print sum ([ (pos+1) * nv for pos, nv in enumerate([ sum ([ ord(char) - 64 for char in name ]) for name in sorted([name.strip('"') for name in open('names.txt','r').readline().split(",")]) ]) ]) 

或者其可讀性:

魔法是ASCII A是整數65,ASCII B是整數66,等等 - 這樣ord(char) - 64讓你的char 「信價值」 。


編輯2:

完整的,人類可讀的,解決方案,我擠在一條線路爲您的娛樂。

with open('names.txt','r') as f: 
    data = f.readline(); 

names = [name.strip('"') for name in data.split(",")] 
sorted_names = sorted(names) 
name_values = [ sum ([ ord(char) - 64 for char in name ]) for name in sorted_names ] 
name_position_values = [ (pos+1) * nv for pos, nv in enumerate(name_values) ] 
total_sum = sum(name_position_values) 

# debug output 
from pprint import pprint 
#position, word value, position * word value, word 
pprint(zip(xrange(1,len(names)+1),name_values,name_position_values,sorted_names)) 

注意大量使用列表解析[x for x in list_of_xes]而不是循環的,並且sum()函數而不是for x in xes: sum += x

這裏還有一些其他的技巧,但回家的教訓是,處理列表的列表解析和函數可以使你的代碼更簡單,更容易閱讀。


編輯3:

pprint.pprint()功能是一個 「漂亮print()」。這對調試非常有用。


編輯4:

代碼高爾夫球版本(142個字):

print sum([(p+1)*v for p,v in enumerate([sum(map(ord,n))-64*len(n) for n in sorted([n[1:-1] for n in open('names.txt').read().split(",")])])]) 
+0

+1爲可讀版本旁邊的單行。 –

+2

@AdamMatan:這一行很有趣。我拿了我的完整代碼,並用列表本身將每個引用替換爲一個列表!我絕對不會試圖從頭開始寫一行。 (*哦,和孩子們:不要在家裏試試。*) –

+0

謝謝!我不喜歡它作爲初學者,因爲它很難一步一步地遵循代碼,而且我讀的教程都沒有教導它。 但也許我應該嘗試更頻繁地使用它。在一行中看到一個代碼是很了不起的,這與代碼有很多行 –

0

而不是試圖一次當你轉換文件內容,以去除所有從名字報價到列表中,當你處理列表時將它們去掉。

# Project Euler Problem 22 
# Name Scores 

def score(name): 
    total = 0 

    for char in name: 
     total += (ord(char) - 64) # scale so A = 1, B = 2... 

    return total 

def main(): 
    # Open the names file for reading 
    infile = open('names.txt', 'r') 

    # Read the entire contents of the file 
    file_contents = infile.read() 

    # Close the file 
    infile.close() 

    # Convert file contents to a list of quoted names and sort them 
    list_of_names = file_contents.split(',') 
    list_of_names.sort() 

    position = 1 
    total = 0 
    for name in list_of_names: 
     name = name.strip('"') # strip the quotes from names individually 
     total += score(name) * position 
     position += 1 

    print(total) 

if __name__ == "__main__": 
    main()