用列表推导式生成勾股数。

3

我刚接触Python,想学习如何使用列表推导式。

这是一个打印小于用户输入值n的勾股三元组列表的代码:

n = int(input("Enter the value of n:"))

a = 0
b = 0
c = 0
m = 2
triples = []

while c < n:
    for i in range(1, m, 1):
        a = m*m - i*i
        b = 2*m*i
        c = m*m + i*i
        if c > n:
            break
        triples.append((a, b, c))
    m += 1

print(triples)

它有点可行,但我想用Python中的列表推导式来做同样的事情,我们该怎么做?
例如,如果我输入17,则输出应为[(3,4,5), (8,6,10),(5,12,13), (15,8,17), (9,12,15)],然而我没有得到(9,12,15)

1
这个序列不会为任何值的 n 生成 (9, 12, 15)。你需要完全改变你的三元组生成逻辑。 - Arya McCarthy
1
无论如何,您正在提出两个不同的问题。一个是关于列表推导式,另一个是为什么您的三元组生成器无法生成所有可能的三元组。 - Arya McCarthy
@AryaMcCarthy 我用了这个教程,但是这个教程有问题吗?http://www.geeksforgeeks.org/generate-pythagorean-triplets - AngelaChang
1
你有没有在教程中看到这个提示:“上述方法不能生成所有小于给定限制的三元组。例如,“9 12 15”是一个有效的三元组,但不会被上述方法打印出来。”?这正是你遇到问题的情况。 - Arya McCarthy
2个回答

3
请查看官方Python列表推导文档,它很好地解释了它们的工作原理。
至于你的实际问题,以下应该是一个等价的列表推导式,用于打印勾股三元组直到n:
n = int(input('Enter the value of n: '))
print([(a, b, c) for a in range(1, n + 1) for b in range(a, n + 1)
       for c in range(b, n + 1) if a**2 + b**2 == c**2])

希望您清楚当前代码存在的问题 :) 使用示例:
Enter the value of n: 17
[(3, 4, 5), (5, 12, 13), (6, 8, 10), (8, 15, 17), (9, 12, 15)]

编辑:一种更有效率的版本,利用了 Python 3.8 的海象运算符

import math

n = int(input('Enter the value of n: '))
print([(a, b, int(c)) for a in range(1, n + 1) for b in range(a, n + 1)
       if (c := math.sqrt(a**2 + b**2)) % 1 == 0 and c <= n])

可以通过在范围部分中删除c来更高效地实现,如下所示,只使用两个范围: a = range(1,101) [(i,j,math.sqrt(ii+jj)) for i in a for j in a if math.sqrt(ii+jj)%1==0] - michael
@michael,我的修改是否与您描述的逻辑相同? - Sash Sinha

0

您可以使用 itertools。尝试这个 -

import itertools

n = int(input("Enter the value of n:"))

print([(a,b,c) for a, b, c in itertools.product(range(1,n+1), repeat=3) if a**2 + b**2 == c**2])

想要了解更多关于 itertoolsproduct 的内容,请点击以下链接 - https://docs.python.org/3/library/itertools.html#itertools.product

使用 product 我们可以得到一个包含三个元素的元组,我们将其解包为三个变量 a、b、c,并使用推导式仅包括满足 if 条件的元组。

然而,这段代码会生成重复项,例如 (3,4,5) 和 (4,3,5)。

要删除重复项,您可以轻松修改 if 语句,如下所示 -

print([(a,b,c) for a, b, c in itertools.product(range(1,n+1), repeat=3) if a < b < c and a**2 + b**2 == c**2])

这段修改后的代码将会在 n=17 时输出以下结果 -

[(3, 4, 5), (5, 12, 13), (6, 8, 10), (8, 15, 17), (9, 12, 15)]

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