Haskell中无对称解的毕达哥拉斯三元函数



我要在Haskell中做毕达哥拉斯三重,没有对称的解决方案。我的尝试是:

terna :: Int -> [(Int,Int,Int)]
terna x = [(a,b,c)|a<-[1..x], b<-[1..x], c<-[1..x], (a^2)+(b^2) == (c^2)]

,我得到结果:

Main> terna 10
[(3,4,5),(4,3,5),(6,8,10),(8,6,10)]

正如你所看到的,我得到了对称的解,如:(3,4,5)(4,3,5)。我需要摆脱他们,但我不知道该怎么做。有人能帮我吗?

每次你有一个副本,你就有一个版本a大于b,一个版本b大于a,所以如果你想确保你只得到一个,你只需要确保a总是等于或小于b,反之亦然。

实现这一点的一种方法是将其作为条件添加到列表推导式中。

另一种更有效的方法是将b的生成器更改为b <- [1..a],这样它只生成b小于或等于a的值。

说到效率:根本不需要遍历c。有了ab的值后,可以简单地计算(a^2)+(b^2)并检查它是否有一个自然平方根。

根本不知道Haskell(也许你现在正在学习它?),但似乎你可以摆脱他们,如果你可以只采取那些a小于或等于b

尝试使用一个简单的递归生成器:

http://en.wikipedia.org/wiki/Formulas_for_generating_Pythagorean_triples


(新)http://en.wikipedia.org/wiki/Tree_of_primitive_Pythagorean_triples

EDIT(2014年5月7日)

这里我做了一个无限生成器,它可以生成按周长排序的原始三元组(但可以修改为按其他参数排序-斜边,面积,…),只要它保持任何三元组小于根据提供的比较函数

从生成器矩阵生成的任何三元组
import Data.List -- for mmult
merge f x [] = x
merge f [] y = y
merge f (x:xs) (y:ys)
               | f x y     =  x : merge f xs     (y:ys) 
               | otherwise =  y : merge f (x:xs) ys 

mmult :: Num a => [[a]] -> [[a]] -> [[a]] 
mmult a b = [ [ sum $ zipWith (*) ar bc | bc <- (transpose b) ] | ar <- a ]
tpgen_matrix = [[[ 1,-2, 2],[ 2 ,-1, 2],[ 2,-2, 3]],
                [[ 1, 2, 2],[ 2 , 1, 2],[ 2, 2, 3]],
                [[-1, 2, 2],[-2 , 1, 2],[-2, 2, 3]]]
matrixsum  =  sum . map sum
tripletsorter x y =  ( matrixsum  x ) < ( matrixsum y ) -- compare perimeter
triplegen_helper b =  foldl1 
            ( merge tripletsorter ) 
            [ h : triplegen_helper h | x <- tpgen_matrix , let h = mmult x b ]
triplets =  x : triplegen_helper x  where x = [[3],[4],[5]]
main =  mapM print $ take 10 triplets

您可以这样做:

pythagorean = [ (x,y,m*m+n*n) | 
                                m <- [2..], 
                                n <- [1 .. m-1], 
                                let x = m*m-n*n, 
                                let y = 2*m*n ]

这可能有用:从本教程中获得

triangles x = [(a,b,c) | c <- [1..x], b <- [1..c], a <- [1..b] , a^2 + b^2 == c^2]  

列表推导语法使得这很容易:

triplets :: Integer -> [(Integer, Integer, Integer)]
triplets d = [(a,b,c) | a <- [1..d], b <- [a..d], c <- [b..d], a^2 + b^2 == c^2]

这基本上是说我们从a s, b s和c s中构建一个列表,其中a1更改为d, b从当前a更改为d等等。它还说a^2 + b^2 == c^2应该保持

最新更新