【问题标题】:Code finding the first triangular number with more than 500 divisors will not finish running查找第一个具有超过 500 个除数的三角数的代码将无法完成运行
【发布时间】:2018-04-28 23:36:46
【问题描述】:

好的,所以我正在研究Euler Problem 12(找到第一个因数超过 500 的三角形数),我的代码(在 Python 3 中)如下:

factors = 0
y=1

def factornum(n):
    x = 1
    f = []
    while x <= n:
        if n%x == 0:
            f.append(x)
        x+=1
    return len(f)

def triangle(n):
    t = sum(list(range(1,n)))
    return t

while factors<=500:
    factors = factornum(triangle(y))
    y+=1

print(y-1)

基本上,一个函数会遍历输入数字 n 以下的所有数字,检查它们是否均分为 n,如果是,则将它们添加到列表中,然后返回该列表中的长度。另一个通过将列表中从 1 到输入数字的所有数字相加并返回总和来生成一个三角形数字。然后,while 循环继续使用迭代变量y 作为triangle 函数的输入生成一个三角数,然后在其上运行factornum 函数并将结果放入factors 变量中。循环继续运行,y 变量继续递增,直到因子数超过 500。然后打印结果。

但是,当我运行它时,什么也没有发生 - 没有错误,没有输出,它只是继续运行和运行。现在,我知道我的代码不是最有效的,但我让它运行了相当长一段时间,但它仍然没有产生结果,所以在我看来更有可能是某个地方出现了错误。我一遍又一遍,似乎找不到错误。

我只是要求不要直接给出完整的解决方案或大幅改进的解决方案,而是指出我的错误或需要改进的地方,因为我做欧拉问题的原因是为了改进我的编码.谢谢!

【问题讨论】:

  • 尝试在 while 循环中打印 y 和因数。
  • 有一个更好的写法sum(list(range(1,n)))...(n**2 + n) / 2

标签: python python-3.x math


【解决方案1】:

你的算法效率很低。

如果您要求指针而不是完整的解决方案,主要指针是:

  1. 有一种更有效的方法来计算下一个triangular number。 wiki中有一个明确的公式。此外,如果您生成所有数字的序列,则将下一个 n 添加到前一个数字会更有效。 (sum(list(range(1,n))) 中的旁注 list 对我来说根本没有意义。如果您仍然想使用这种方法,sum(xrange(1,n) 可能会更有效,因为它不需要实现范围)

  2. factorize numbers 有很多更有效的方法

  3. 有一种更有效的方法来计算因子数。它实际上是在 Euler 之后调用的:见Euler's totient function

一般来说,欧拉项目问题(就像在许多其他编程竞赛中一样)不应该通过纯粹的蛮力来解决。你应该先想出一些公式和/或更有效的算法。

【讨论】:

    【解决方案2】:

    据我所知,您的代码可以工作,但计算因子的数量需要很长时间。对于 150 个因子,运行大约需要 20 秒,随着您寻找越来越多的因子,时间会急剧增加。

    减少处理时间的一种方法是减少您正在执行的计算次数。如果你分析你的代码,你每次都在计算n%1,这是一个不必要的计算,因为你知道每个整数都可以被它自己和一个整数整除。还有其他方法可以减少计算次数吗?也许通过记住如果一个数能被 20 整除,它也能被 2、4、5 和 10 整除?

    我可以更具体,但你想要一个正确方向的指针。

    【讨论】:

      【解决方案3】:

      从外观上看,代码运行良好,但这并不是最好的方法。例如,一种简单的优化方法是直到数字减半。另外,尝试考虑如何使用主要因素来做到这一点,这可能是另一种解决方案。祝你好运!

      【讨论】:

        【解决方案4】:

        首先你必须定义一个因子函数:

        from functools import reduce
        
        def factors(n):
            step = 2 if n % 2 else 1
            return set(reduce(list.__add__,
                          ([i, n//i] for i in range(1, int(pow(n,0.5) + 1)) if n % i 
        == 0)))
        

        这将创建一个集合并将所有 n 的因子放入其中。

        其次,使用 while 循环,直到得到 500 个因子:

        a = 1
        x = 1
        while len(factors(a)) < 501:
            x += 1
            a += x
        

        此循环将在 len(factors(a)) = 500 处停止。 简单的 print(a),你就会得到答案。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-03-17
          • 1970-01-01
          • 2013-03-22
          • 2020-12-10
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多