项目Euler:45(或更多Python生成器)

时间:2015-12-15 21:16:02

标签: python python-3.x generator

来自Project Euler的problem 45

  

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

     

三角形Tn = n x(n + 1)/ 2 1,3,6,10,15 ......

     

五角形Pn = n x(3n-1)/ 2 1,5,12,22,35 ......   六边形Hn = n×(2n-1)1,6,15,28,45,......

     

可以证实T285 = P165 = H143 = 40755。

     

找到下一个三角形和六角形的三角形数字。

这是我的代码:

def triangle_generator():
    n = 1
    while True:
        t = n * (n + 1) // 2
        yield t
        n += 1


def pentagonal_generator():
    n = 1
    while True:
        p = n * ((3 * n) - 1) // 2
        yield p
        n += 1


def hexagonal_generator():
    n = 1
    while True:
        h = n * ((2 * n) - 1)
        yield h
        n += 1


def tph():
    tg = triangle_generator()
    pg = pentagonal_generator()
    hg = hexagonal_generator()

    tg_temp_list = []
    pg_temp_list = []
    while True:
        h = next(hg)
        t = 0
        p = 0
        while t < h:
            t = next(tg)
            tg_temp_list.append(t)
        while p < h:
            p = next(pg)
            pg_temp_list.append(p)
        if h in tg_temp_list and h in pg_temp_list:
            print("Found! {}".format(h))
        else:
            tg_temp_list = tg_temp_list[-2:]
            pg_temp_list = pg_temp_list[-2:]

因此,产生一个六边形数字,然后填充两个临时列表 - 一个来自triangle_generator(),另一个来自pentagonal_generator()。然后,检查所产生的六边形数是否在这两个列表中。如果没有,临时列表将被清空,除了最后一个元素,产生另一个六边形数字,整个过程无限期重复。<​​/ p>

我的问题:(假设纯粹的数学方法除外)Python是否提供了更方便(Pythonic)的方法来实现tph()函数?

2 个答案:

答案 0 :(得分:1)

也许更优雅,不确定更有效率。但是我的想法是,如果你可以合并迭代器,在每个pop上返回最低的#,即优先级队列,那么你的代码可以更清晰。

import heapq

def tph():
    tg = triangle_generator()
    pg = pentagonal_generator()
    hg = hexagonal_generator()
    count = 0
    last_n = 0
    for n in heapq.merge(tg, pg, hg):
        if n == last_n:
            count += 1
        else:
            count = 1

        if count == 3:
            print(n)

        last_n = n

答案 1 :(得分:0)

这个问题可以通过计算和评估每个下一个三角形,五边形和六边形数字来解决,但是Project Euler问题主要是巧妙的数学和编程的良好组合。从wiki开始,我们知道每个六边形数字都是三角形数字

因此,我们只需要遍历六边形数字,并在我们找到一个也是五边形数字时立即停止!通过一些简单的数学,我们发现当且仅当(sqrt(24 * candidate_value + 1) + 1) / 6是整数时,数字才是五边形。

然后,问题变为以下代码:

import math


i = 144

while True:
    hexagonal = i * (2 * i - 1)

    if ((math.sqrt(24 * hexagonal + 1) + 1) / 6).is_integer():
        print("Found it! The next occurence is {}".format(hexagonal))
        break
    i += 1