寻找勾股数三元组。

3

我需要找到所有勾股数中的"a"和"b"值。例如,我会将数字作为参数指定,并找到所有该数字的勾股数。这是我的老师给我的一些示例代码:

>>> pytriples(5)
>>> [3,4,5] #would return this
>>> pytriples(25)
>>> [7,24,25] #would return this
>>> [15,20,25] #would return this

基本上,我需要编写pytriples程序,如果不重复使用“a”和“b”,我将获得满分。这是我开发的内容-问题在于我没有任何方法可以删除重复项。
这是我的代码:
def pytriples(c):
    newlist = []
    for a in range(0, c):
        if ((c**2 - a**2)**0.5)%1 == 0:
            b = ((c**2 - a**2)**0.5)
            newlist.append([a,b,c])
    for i in newlist: #this part is supposed to remove the duplicates
        print i[0] #was used for debugging but I could not figure out why duplicates were not removed
        if i[0] >= i[1]:
            newlist.remove(i)
    return newlist

3
请查看此链接:https://dev59.com/RHRB5IYBdhLWcg3wl4Sc 该链接讨论如何生成唯一有序的勾股三元组。 - avasal
6个回答

1

不确定这是否是您想要的...

您可以从三元组列表中删除重复项,例如

假设您已经将所有三元组存储在列表l

In [39]: l
Out[39]: [(1, 2, 3), (2, 3, 4), (2, 1, 3)]

要从中删除所有重复项,您可以使用以下方法

In [40]: set(map(tuple, [sorted(x) for x in l]))
Out[40]: set([(2, 3, 4), (1, 2, 3)])

然后您可以将其转换为列表以进行进一步处理。

In [41]: list(set(map(tuple, [sorted(x) for x in l])))
Out[41]: [(2, 3, 4), (1, 2, 3)]

在您的情况下,

在循环内修改您正在迭代的列表是一个不好的想法,

因为一旦您删除了假设的item1,item2就变成了item1,但是循环已经迭代了列表中的item1,所以该检查将被跳过,您将无法获得所需的输出。

考虑一个小例子。

In [43]: l
Out[43]: [(1, 2, 3), (2, 3, 4), (2, 1, 3)]

In [44]: for i in l:
   ....:     if i[0] == 2:
   ....:         l.remove(i)
   ....:

In [45]: l
Out[45]: [(1, 2, 3), (2, 1, 3)]

虽然使用 set() 通常是去除重复项的好方法,但在这种情况下(triplet[0] >= triplet[1]),我们了解到重复项的结构,可能会使列表推导式的方法更快。+1,不过。 :) - Eric O. Lebigot
我还没有学过那个,但从我的代码来看,我只需要知道为什么它不能用for循环删除列表元素。 - Alex Mann
@AlexMann:在循环中修改正在迭代的列表是一个不好的想法,相反地,只需创建一个不同的列表,在循环中附加所需的值,然后返回/打印它。 - avasal

0

在迭代列表时修改它是应该避免的

可以通过简单的列表推导来实现您想要的删除元素的方式:

newlist = [triplet for triplet in newlist if triplet[0] < triplet[1]]

使用set可能更简单。 - 9000
set 不错,但需要对三元组进行排序。我猜测 set 方法较慢,因为它没有利用我们知道重复项长什么样子(triplet[0] >= triplet[1])这一事实。 - Eric O. Lebigot

0

不要把重复的元素放入数组,然后再使用一个循环来将它们拿出来,而是一开始就不要放入。你可以修改

        newlist.append([a,b,c])

        if a<b: newlist.append([a,b,c])

删除所有 for i in newlist: 循环及其内容。

(注意,a 不能等于 b,因为sqrt(2)是无理数。)


0

我不想进行完整的扫描,而是更愿意预先计算足够的三元组并尝试找到匹配。如果所有数字都小于给定的数字,则我会在运行时计算更多 :)

您的算法有一个正确的想法,但可以更简单地实现。一些基本的三角学可以完全消除重复。

def pytriplets(hypotenuse):
    result = []
    # we only need to check half the triangles,
    # the rest are the same triangles with catheti swapped.
    # 0.71 is approximated sin(pi / 4). Biggest possible catheti are
    # in the isosceles triangle; no bigger should ever be checked. 
    # +1 is because range() excludes the top bound. 
    for a in range(1, int(hypotenuse * 0.71) + 1):
        hypo_squared = hypotenuse * hypotenuse
        a_squared = a * a
        # Square root will give us slight approximation errors;
        # explicitly make our other cathetus integer.
        b = int((hypo_squared  - a_squared) ** 0.5)
        if a_squared + b*b == hypo_squared:
            # A perfect match!
            result.append((hypotenuse, a, b)) # appending a tuple
    return result

print pytriplets(5)
print pytriplets(25)

0

我生成了所有小于c的完全平方数列表,并使用两个指针从列表的两端开始,尝试找到这些数字的和为c^2的数对,直到它们相交。

def pythogorian_triplets(c):
    c_square = c ** 2
    #list of perfect squares below c_square
    squares = [1]
    #populating the list
    for i in range(1, c - 1):
        squares.append(squares[-1] + (i << 1) + 1)

    i = 0
    j = c - 2
    l = c - 1

    while j >= i and i < l:
        while (squares[i] + squares[j] < c_square) and i < l and j > i:
            i = i + 1
        if squares[i] + squares[j] == c_square:
            print (i + 1, j + 1, c)
        j = j - 1

if __name__ == '__main__':
    pythogorian_triplets(int(raw_input()))

0

导入数学模块

def main(): for x in range(1, 1000): for y in range(1, 1000): for z in range(1, 1000): if x * x == y * y + z * z and x + y + z == 1000: print y, z, x print '-'*50

if __name__ == '__main__': main()


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