在Python中进行有效的迭代而无需使用范围

时间:2018-07-06 18:43:07

标签: python for-loop math

我正在研究Project Euler的问题45。提示如下:

三角形,五边形和六边形的数字由以下公式生成:

T n = n n +1)/ 2

P n = n (3 n − 1)/ 2

H n = n (2 n -1)

可以验证T 285 = P 165 = H 143 = 40755。

查找下一个也是五边形和六边形的三角形。

我确实有一个可行的解决方案,但是在提供不依赖于对range使用任意值的答案时遇到了一些困难。

我当前的代码:

import collections
import time
start_time = time.time()

nums = []

for x in range(56000):
    t, p, h = (x * (x + 1) / 2) , x * (((3 * x) - 1) / 2), (x * ((2 * x) - 1))
    nums.extend([t, p, h])

j = [i for i, count in collections.Counter(nums).items() if count > 2]
pos = j.index(40755)
result = j[pos + 1]
print result
print("--- %s seconds ---" % (time.time() - start_time))

输出:

  

1533776805

     

--- 0.197566986084秒---

如何在不使用range的情况下在相同的时间内找到相同的答案?我想获得相同的输出,但不指定迭代次数。我尝试使用itertools.count,但是在nums列表中搜索与上述条件匹配的值会花费很长时间。

谢谢。

1 个答案:

答案 0 :(得分:3)

更好的方法是遍历六边形数字的所有索引,然后查看那些数字也是五角形数字。 (正如@Mbo在一条评论中教给我的那样,所有六边形数字也是三角形数字,因此我们可以跳过该检查。)无需尝试任何更高的六边形数字。这是我针对此问题的代码,它使用一个while循环而没有任何range。询问您是否需要进一步解释根据三角数或五角数计算指数的公式。

"""Project Euler #0045 Triangular, pentagonal, and hexagonal

Triangle, pentagonal, and hexagonal numbers are generated by the
following formulae:

Triangle    T(n)=n(n+1)/2   1, 3, 6, 10, 15, ...
Pentagonal  P(n)=n(3n−1)/2  1, 5, 12, 22, 35, ...
Hexagonal   H(n)=n(2n−1)    1, 6, 15, 28, 45, ...

It can be verified that T(285) = P(165) = H(143) = 40755.

Find the next triangle number that is also pentagonal and hexagonal.

ANSWER: T(55385) = P(31977) = H(27693) = 1533776805
"""
from math import sqrt

_1_50 = 1 << 50  # 2**50 == 1,125,899,906,842,624
known_answer_hexagonal = 143

n_hex = known_answer_hexagonal
x = 1
while x <= _1_50:
    n_hex += 1
    x = n_hex * (2 * n_hex - 1)  # we know this is hexagonal

    sqrt_pen = sqrt(1 + 24 * x)
    if not sqrt_pen.is_integer():
        continue
    n_pen = (sqrt_pen + 1) / 6
    if not n_pen.is_integer():
        continue
    sqrt_tri = sqrt(1 + 8 * x)  # all hexagonal numbers are also triangular
    n_tri = (sqrt_tri - 1) / 2

    print('T({}) = P({}) = H({}) = {}'.format(
            int(n_tri), int(n_pen), int(n_hex), int(x)))
    break

在我的系统上,这花费了0.026999950408935547秒,而您的代码花费了0.12299680709838867秒,是我的代码的4倍以上。