优化Project Euler#5的Python代码

时间:2014-01-29 22:12:14

标签: python optimization

这是我对Project Euler中第五个问题的解决方案。有没有办法改善while循环条件而不是使用和?

table = range(1,21)
result = 1
pf = 2
while sum(table) > len(table):
   flag = False
   for x,y in enumerate(table):
      if y % pf == 0:
         table[x] = y/pf 
         flag = True
   if flag:
      result *= pf
   else:
      pf += 1
print result

3 个答案:

答案 0 :(得分:3)

使用高阶函数而不是循环编写程序总是更清楚,因为控制循环操作的所有无关变量都会消失。这是一个与您的计算执行相同计算的程序,但whilefor循环消失,变量tableresultpfflag;变量xy仍然存在,但仅限于辅助函数中的支持角色,而不是主要计算的一部分:

>>> from fractions import gcd
>>> def lcm(x,y): return x*y/gcd(x,y)
...
>>> print reduce(lcm,range(1,21))
232792560

答案 1 :(得分:1)

使用常量。当你想回去尝试不同的价值时,你会更容易理解。

MAX_DIVISOR = 20
table = range(1,MAX_DIVISOR + 1)
result = 1
pf = 2
while pf < MAX_DIVISOR + 1:
   flag = False
   for x,y in enumerate(table):
      if y % pf == 0:
     table[x] = y/pf 
     flag = True
   if flag:
      result *= pf
   else:
      pf += 1
print result

答案 2 :(得分:0)

您可以使用any()来测试表格,如下所示:

while any(n != 1 for n in table):
    # do stuff

我认为这比sum(table) > len(table)更清晰。

另外,正如@JoeClacks建议的那样,使用常量。

完整的修订解决方案:

MAX_DIVISOR = 20
table = list(range(1, MAX_DIVISOR+1))

result = 1
pf = 2

while any(n != 1 for n in table):
    assert pf <= MAX_DIVISOR
    flag = False
    for i,n in enumerate(table):
        if n % pf == 0:
            table[i] = n//pf
            flag = True
    if flag:
        result *= pf
    else:
        pf += 1

print(result)

我添加了assert以确保pf仅具有合法值;只要代码中没有错误就不需要这样做,但是自己进行代码完整性检查是一个好主意。

我使用in作为索引和数字,而不是xy

我使用Python的整数除法运算符//而不是/,因此代码在Python 3.x上的工作方式与在Python 2.x上相同。另外,我编写print语句的方式在Python 3.x和Python 2.x中同样有效。

我根据PEP 8将缩进更改为4个空格的步骤。

http://www.python.org/dev/peps/pep-0008/

注意:我喜欢这个算法来解决这个问题。它很优雅。你有没有发明这个,从书中得到它,或者是什么?

编辑:实际上,之前已经在StackOverflow上讨论了Project Euler问题5。这是我刚刚与上述答案进行比较的答案。这个几乎比上面快十倍。这有点棘手!

https://stackoverflow.com/a/8026041/166949