我必须在没有对称解决方案的Haskell中完成Pythagorean三重奏。我的尝试是:
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)。我需要摆脱它们,但我不知道如何。任何人都可以帮助我吗?
答案 0 :(得分:13)
每次复制时,您都有一个版本,其中a大于b,另一个版本的b大于a。因此,如果您想确保只获得其中一个,则只需确保a
始终等于或小于b
,反之亦然。
实现这一目标的一种方法是将其作为列表理解的条件添加。
另一种更有效的方法是将b
的生成器更改为b <- [1..a]
,因此它只会为b
生成小于或等于a
的值
说到效率:根本不需要迭代c
。获得a
和b
的值后,您只需计算(a^2)+(b^2)
并检查其是否具有自然平方根。
答案 1 :(得分:5)
根本不知道Haskell(也许你现在正在学习它?)但是如果你只能拿出a
小于或等于的那个,你似乎可以摆脱它们b
。这将摆脱重复。
答案 2 :(得分:4)
尝试使用简单的递归生成器:
http://en.wikipedia.org/wiki/Formulas_for_generating_Pythagorean_triples
(新文章)
http://en.wikipedia.org/wiki/Tree_of_primitive_Pythagorean_triples
编辑(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
答案 3 :(得分:2)
您可以执行以下操作:
pythagorean = [ (x,y,m*m+n*n) |
m <- [2..],
n <- [1 .. m-1],
let x = m*m-n*n,
let y = 2*m*n ]
答案 4 :(得分:2)
这可能有效:Got it from this tutorial
triangles x = [(a,b,c) | c <- [1..x], b <- [1..c], a <- [1..b] , a^2 + b^2 == c^2]