Euler Project问题#12 Python代码给出了奇怪的结果

时间:2019-03-09 13:51:15

标签: python python-3.x

我正在尝试解决Euler项目的第12个问题。这是问题所在:

  

三角形数字的序列是通过添加自然数生成的   数字。所以第7个三角数将是1 + 2 + 3 + 4 + 5 + 6 + 7   =28。前十个术语是:

     

1、3、6、10、15、21、28、36、45、55,...

     

让我们列出前七个三角形数字的因数:

     
      
  • 1:1
  •   
  • 3:1,3
  •   
  • 6:1、2、3、6
  •   
  • 10:1、2、5、10
  •   
  • 15:1、3、5、15
  •   
  • 21:1、3、7、21
  •   
  • 28:1、2、4、7、14、28
  •   
     

我们可以看到28是第一个超过5的三角形   除数。

     

超过五个的第一个三角形的值是多少   一百个除数?

我定义了两个功能来完成这项工作:

1)allfactor(x):这以列表的形式为我们提供了给定数字的所有因子。示例:allfactor(10)给了我们[1, 2, 5, 10]

2)TriangularNo(x):这给了我们第n个三角数。示例TriangularNo(5)给了我们5

这是我编写的完整代码:

facs=[]

def allfacof(x):
    for i in range(1,int(x/2)+1):
        if x%i==0:
            facs.append(i)
        else:
            pass
    facs.append(x)
    return(facs)



def TriangularNo(x):
    no=0
    for i in range(1,x+1):
        no=no+i
    return(no)

a=0 # a will tell us the number of iterations

while True:
    a+=1
    N=TriangularNo(a)
    length=(len(allfacof(N)))
    if int(length)>=500:
        print(N)
        break
    else:
        pass

运行此代码时,我得到1378作为输出,这显然是错误的,因为事实证明len(allfacof(1378))8而不是问题中要求的500

while循环中,我使用if int(length)>=500:,所以这意味着当我的代码运行时,length以某种方式获得了值= 500,但是当我单独运行该函数时,它说它的长度是8。

我只是无法找出错误。请帮助我

2 个答案:

答案 0 :(得分:2)

问题是您将facs用作全局变量,而只附加到该项目。您应该使其成为allfacof()的成员,以便在每个值之后将其清除。 如果您查看facs,就会发现它等于

  

1、1、3、1、2、3、6、1、2、5、10 ...

答案 1 :(得分:1)

尽管将facs移到all_factors_of()可以解决您的直接问题,但是此代码的下一个问题是性能。让我们首先考虑三角数的生成。 @Voo建议的优化:

def TriangularNo(n):
    return n * (n + 1) / 2
如果我们要寻找任意三角形数,则

很好-但是我们不是。我们正在寻找顺序三角形数字,因此在这种情况下,公式会降低我们的代码!当按顺序进行时,您只需要做几个加法就可以得到下一个三角数-但是使用公式,您需要做一个加法,乘法和除法!如果要按顺序进行,价格会更高。由于我们 是按顺序进行的,因此这似乎是Python生成器的完美用法:

def triangular_number_generator():
    triangle = number = 1

    while True:
        yield triangle
        number += 1
        triangle += number

其中清楚地说明了要获得下一个三角形数字所需的两个加法运算。现在,让我们考虑一下分解函数:

您的因式分解函数会按顺序产生因子 ,从而降低性能。但是我们只关心因子数量,顺序无关紧要。因此,当我们分解为28时,可以同时在因子列表 中添加1和28。同上2和14-使14成为我们的新上限。类似地,4和7,其中7成为新的上限。因此,我们可以更快地收集因子,并迅速降低需要检查的上限。这是其余的代码:

def factors_of(number):
    divisor = 1
    limit = number
    factors = []

    while divisor <= limit:

        if number % divisor == 0:
            factors.append(divisor)

            remainder = number // divisor

            if remainder != divisor:
                factors.append(remainder)

            limit = remainder - 1

        divisor += 1

    return factors

triangular = triangular_number_generator()
number = next(triangular)
factors = factors_of(number)

while len(factors) <= 200:
    number = next(triangular)
    factors = factors_of(number)

print(number)

它如何比较?如果我们以小于200个因子的下限运行您的固定代码,则大约需要分钟来得出答案(2031120)。上面的代码大约需要 second 的1/3。现在考虑达到500个因子都需要花费多长时间。最后,要达到既定目标:

为五个的第一个三角形的值是多少 一百个除数?

原始代码中的此比较:

if int(length)>=500:

取而代之的是:

if length > 500:

尽管因子数量的跳跃方式对500个而言并没有什么不同。但是对于较小的限制,对于测试而言,它可以有所不同。