毕达哥拉斯三重奏的Haskell无限列表

时间:2014-03-15 02:50:38

标签: haskell recursion

我一直在尝试这个问题几个小时,仍然坚持下去。谁能帮忙。寻找建议:

使用列表推导来定义一个函数三元组n ,它返回一个正整数三元组的列表 (x,y,z)都小于或等于 n ,这样 x ^ 2 + y ^ 2 = z ^ 2 < / p>

不要产生重复的三元组或三元组,它们是已经生成的三元组的排列。

3 个答案:

答案 0 :(得分:1)

我有一些代码可以解决这个问题......

branchTriple = [
   \(a,b,c) -> (a - 2*b + 2*c, 2*a - b + 2*c, 2*a - 2*b + 3*c),
   \(a,b,c) -> (a + 2*b + 2*c, 2*a + b + 2*c, 2*a + 2*b + 3*c),
   \(a,b,c) -> (2*b - a + 2*c, b - 2*a + 2*c, 2*b - 2*a + 3*c)
 ]

primitiveTriples l = pt (3,4,5) where
  pt x = x : concatMap pt (filter l $ map ($ x) branchTriple)
allTriples l = let
  pt = primitiveTriples l
  mtriple (a,b,c) n = (a*n, b*n, c*n)
  multiples p = takeWhile l $ map (mtriple p) [1..]
  in concatMap multiples pt

usage n = allTriples (\(a,b,c) -> all (<= n) [a,b,c])

此代码使用Tree of primitive Pythagorean triplets。我将重新格式化以使用列表推导作为读者的练习。

答案 1 :(得分:0)

您可以使用以下代码:

isSquare x = x == head (dropWhile (< x) squares)
  where squares = scanl1 (+) [1,3..]

然后定义:

triples n = take n [(i,j,truncate (sqrt (fromIntegral (i*i+j*j) :: Double))) | i <- [1 ..], j <- [1 ..i-1], isSquare(i*i+j*j)]

在这种情况下,第一个元素总是大于第二个元素。

如果您还想要订购元组的元素,请尝试:

triples n = take n [(j,i,truncate (sqrt (fromIntegral (i*i+j*j) :: Double))) | i <- [1..], j <- [1..i-1], isSquare(i*i+j*j)]

使用第一种方法测试数字是否为正方形是非常低效的,您可以将其替换为:

isSquare x = let x' = truncate $ sqrt (fromIntegral x :: Double) in x'*x' == x

答案 2 :(得分:0)

这是否符合要求?

ghci> [(x,y,z) | z<-[1..], x<-[1..z], y<-[1..z], x^2+y^2==z^2, x<y ]
   [(3,4,5),(6,8,10),(5,12,13),(9,12,15),(8,15,17),(12,16,20),
    (7,24,25),(15,20,25),(10,24,26),(20,21,29),(18,24,30),(16,30,34),
    (21,28,35),(12,35,37),(15,36,39),(24,32,40),(9,40,41), 
       ....^Cinterrupted