使用其中一个直角边小于某个限制条件生成勾股数三元组

3

现在我用以下方法计算(原始)勾股数

def generateTriples(limit):
    for n in xrange(1, limit):
        if (n**2 + (n+1)**2 > limit): 
            break
        for m in xrange(n+1, limit, 2):
            if (n**2 + m**2 > limit): 
                break
            if (gcd(n, m) > 1): 
                continue
            yield (m**2 - n**2, 2*m*n, m**2 + n**2)

但是这样的操作会输出所有三元组,其中所有的边长都小于等于限制。例如:
for triple in generateTriples(25):
    print triple
'''
(3, 4, 5)
(15, 8, 17)
(5, 12, 13)
(7, 24, 25)
'''

但我想做的是改变方式,只限制腿长。斜边可以无限大 - 我只想让min(leg1,leg2)小于或等于限制。

我也希望生成非原始值,这意味着在所有项上按k缩放(也使min(leg1,leg2)小于等于限制),但我担心这样会得到重复项。

任何建议将不胜感激。


你应该看一下我的修改。原始版本无法找到所有的三元组;我包装了你的新版本,相当高效,并且可以找到所有的三元组。 - agf
1个回答

3

此函数确定与完美三元组中的一条腿配对的最大可能斜边,然后使用您的函数实际搜索三元组:

from fractions import gcd

def generateTriples(limit):
    for n in xrange(1, limit):
        if (n**2 + (n+1)**2 > limit):
            break
        for m in xrange(n+1, limit, 2):
            if (n**2 + m**2 > limit):
                break
            if (gcd(n, m) > 1):
                continue
            yield (m**2 - n**2, 2*m*n, m**2 + n**2)

def generate_triples_limit_leg(leg):
    limit = leg**2 / 2 + 1

    for triple in generateTriples(limit):
        if min(triple) <= leg:
            yield triple

print list(generate_triples_limit_leg(i))

这个版本不能找到所有的三元组,但是可以直接在最短边上操作:

def generate_triples(limit):
    # for each number up to the limit
    # Python ranges don't include the max number
    # start from 4 because 1 and 2 are invalid
    # and 3 and 4 give the same triplet
    for i in range(4, limit + 1):
        # if i is odd
        if i % 2:
            # the two larger legs are the integers
            # above and below half of the square of the smallest leg
            # // is floor division
            big = i**2 // 2
            yield i, big, big + 1
        else:
            # the two other legs are the integers
            # above and below half of the smallest leg squared
            big = (i // 2)**2
            yield i, big - 1, big + 1


print list(generate_triples(10))
# [(3, 4, 5), (5, 12, 13), (6, 8, 10),  (7, 24, 25), 
#             (8, 15, 17), (9, 40, 41), (10, 24, 26)]

有趣...你有这段代码片段和/或算法的来源吗? - Jason S
2
好的,很酷——所以你正在寻找所有长边和斜边之差为1或2的三元组。这似乎是欧几里得的方法(http://en.wikipedia.org/wiki/Formulas_for_generating_Pythagorean_triples)。不幸的是,这并不能找到所有原始勾股数:它会错过其他差距大于两个的勾股数,比如(20,21,29)和(30,80,89)。 - Jason S
1
@JasonS 噢,好的,那么聪明地包装他现有的函数是正确的方法。我会试着做到这一点。 - agf
@JasonS 好的,我写了一个包装器来找到理论上的最大斜边长度,然后使用AOAOne的函数来生成实际的三元组。 - agf
1
@agf: ints = iter(xrange(leg, 2**31-1)).否则你会得到TypeError: xrange object is not an iterator。你可以改进寻找最大值的方法。理论上,最大的i是使i ** 2 - (i-1) ** 2> = leg ** 2的最小值,这将减少到i = (leg ** 2)/2 + 1 - Avaris
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接