我正在研究Project Euler的第22期问题:
使用names.txt(右键单击和“保存链接/目标为...”),一个包含超过五千个名字的46K文本文件,首先按字母顺序排序。然后计算每个名称的字母值,将该值乘以列表中的字母位置以获得名称分数。
例如,当列表按字母顺序排序时,COLIN, 值得3 + 15 + 12 + 9 + 14 = 53,是第938名 名单。因此,COLIN将获得938×53 = 49714的分数。
文件中所有名称分数的总和是多少?
http://projecteuler.net/problem=22
当我编译下面的代码时,我得到答案 871196077 。正确答案应为 871198282 。
导入时间
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() print euler_22() print“运行时间:”+ str(time.time() - tstart)
我试图找到一个类似解决方案的程序,但我只知道Python,这限制了选项。 我用更简单的文本文件运行程序,我创建了,我可以在没有程序的情况下得到答案,所有这些都有效。我搜索了问题的答案,但这也没有帮助,因为我找不到遗漏点。
我是初学者,所以我非常感谢有关程序和Python的任何提示,不仅仅是那些能帮我正确解决问题的提示。
非常感谢!
答案 0 :(得分:3)
你不小心弄错了一个名字。
此处qnames
是您的代码生成的名称的排序列表,sorted_names
是我的:
>>> for a,b in zip(qnames, sorted_names):
... if a != b:
... print a, b
...
ALONS ALONSO
为了好玩:一个单行 - 嵌套的列表理解,avast ye!
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(",")]) ]) ] )
或更可读:
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:
Code golf版本(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(",")])])])
答案 1 :(得分:1)
我只是交叉检查你的代码,看起来你无意中砍掉了最后一个字的最后一个字符。要从最后一个单词中删除引号,请使用:
names[-1] = names[-1][:-1]
答案 2 :(得分: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()