Project Euler#22 Python,2205分缺失?

时间:2012-05-08 06:30:46

标签: python

我正在研究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的任何提示,不仅仅是那些能帮我正确解决问题的提示。

非常感谢!

3 个答案:

答案 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()