【问题标题】:Euler Project problem #12 Python code gives weird resultsEuler Project 问题 #12 Python 代码给出了奇怪的结果
【发布时间】:2019-07-31 08:38:50
【问题描述】:

我试图解决 Project Euler 的problem number 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。

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

【问题讨论】:

  • 请注意,TriangularNo(n) 只是 n*(n+1)/2 避免了所有不必要的循环。
  • @Voo 聪明!谢谢

标签: python number-theory


【解决方案1】:

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

1, 1, 3, 1, 2, 3, 6, 1, 2, 5, 10 ...

【讨论】:

    【解决方案2】:

    虽然将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)。上面的代码大约需要 的 1/3。现在考虑两者达到 > 500 个因子需要多长时间。最后,为了实现既定目标:

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

    原始代码中的比较:

    if int(length)>=500:
    

    应该是:

    if length > 500:
    

    虽然因素的数量跳跃的方式,它对 500 没有影响。但对于较小的限制,对于测试,它可以产生影响。

    【讨论】:

      猜你喜欢
      • 2021-02-14
      • 2011-12-08
      • 1970-01-01
      • 2017-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-19
      相关资源
      最近更新 更多