我的代码给出的 Key error beyond a limit

My code gives Key error beyond a limit

我正在解决 Project Euler problem 34

我给出的代码如下:

import functools

limit = int(input())

factDict = { 0:1, 1:1, 2:2, 3:6, 4:24, 5:120, 6:720, 7:5040, 8:40320, 9:362880 }

for i in range(10, limit):
    listNum = list(map(int, list(str(i))))
    #print(listNum)
    sumFact = functools.reduce(lambda x, y: factDict[x] + factDict[y], listNum)
    if(sumFact%i == 0):
        print(i)

它在 140 之前工作正常,然后给出:

Traceback (most recent call last):
  File "solution.py", line 10, in <module>
    sumFact=functools.reduce(lambda x, y: factDict[x]+factDict[y], listNum)
  File "solution.py", line 10, in <lambda>
    sumFact=functools.reduce(lambda x, y: factDict[x]+factDict[y], listNum)
KeyError: 25

我也打印了list,发现没有问题

我哪里错了?

您没有正确使用 functools.reduce()

这:functools.reduce(lambda x, y: factDict[x] + factDict[y], listNum) 应用于 [1, 4, 0] 将(尝试)计算:

factDict[factDict[1] + factDict[4]] + factDict[0]

导致这个索引错误(factDict[1] + factDict[4] 等于 25)。

根据to the doc

The left argument, x, is the accumulated value

因此,如果您使用 factDict[x],您将用其阶乘(不是您想要的)替换累加值。

所以你必须离开 x 'alone'。

然后,要初始化为 "neutral",你可以只使用 0,这样,它实际上会计算(对于 140):0 + factDict[1] + factDict[4] + factDict[0]

所以最后:

#!/usr/bin/env python3

import functools

limit = int(input())

factDict = { 0:1, 1:1, 2:2, 3:6, 4:24, 5:120, 6:720, 7:5040, 8:40320, 9:362880 }

for i in range(10, limit):
    listNum = list(map(int, list(str(i))))
    #print(listNum)
    sumFact = functools.reduce(lambda x, y: x + factDict[y], listNum, 0)
    if(sumFact == i):
        print("Found: " + str(i))

此外,我更改了 sumFact == i 中的最后一个测试,因为您正在寻找等于其阶乘总和的数字,而不是其阶乘总和的除数。 (如评论所述,您可以使用您喜欢的测试)。

PS 这并没有给出很多结果:

$ ./test_script.py
1000000
Found: 145
Found: 40585

reduce 方法没有按照您的预期工作。访问 https://docs.python.org/2/library/functions.html#reduce

sumFact = functools.reduce(lambda x, y: factDict[x] + factDict[y], listNum).

在该表达式中,x 是累加值,y 是可迭代对象 (listNum) 的更新值。 异常发生时,listNum的值为[1,4,0​​]。此时reduce函数所做的计算是:

accum_value = factDict[1]+factDict[4] # accum_value is set to 25
accum_value = factDict[accum_value]+factDict[0] # Keyerror factDict does not have the key 25.

纠正这个问题的一种方法是像这样在 reduce 函数中设置一个初始化器。

import functools
limit = int(input())
factDict = { 0:1, 1:1, 2:2, 3:6, 4:24, 5:120, 6:720, 7:5040, 8:40320, 9:362880 }

for i in range(10, limit):
    listNum = list(map(int, list(str(i))))
    #print(listNum)
    sumFact = functools.reduce(lambda x, y: x + factDict[y], listNum[1:len(listNum)],factDict[listNum[0]])
    #print sumFact
    if(sumFact%i == 0):
        print(i) 

请注意,此代码将显示除以其数字的阶乘之和的数字。