Haskell 中的毕达哥拉斯三元组没有对称解

发布于 2024-12-02 06:07:16 字数 357 浏览 0 评论 0原文

我必须在 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)。我需要摆脱它们,但我不知道如何做。谁能帮助我吗?

I gotta do the Pythagorean triple in Haskell without symmetrical solutions. My try is:

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)]

and I get as a result:

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

As you can see, I´m getting symmetrical solutions like: (3,4,5) (4,3,5). I need to get rid of them but I don´t know how. Can anyone help me?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

无声情话 2024-12-09 06:07:16

每次有一个副本时,都会有一个版本,其中 a 大于 b,而另一个版本中 b 大于 a。因此,如果您想确保只获得其中一个,则只需确保 a 始终等于或小于 b,反之亦然。

实现此目的的一种方法是将其作为条件添加到列表理解中。

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

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

Every time you have a duplicate you have one version in which a is greater than b and one where b is greater than a. So if you want to make sure you only ever get one of them, you just need to make sure that either a is always equal to or less than b or vice versa.

One way to achieve this would be to add it as a condition to the list comprehension.

Another, more efficient way, would be to change b's generator to b <- [1..a], so it only generates values for b which are smaller or equal to a.

Speaking of efficiency: There is no need to iterate over c at all. Once you have values for a and b, you could simply calculate (a^2)+(b^2) and check whether it has a natural square root.

依 靠 2024-12-09 06:07:16

根本不了解 Haskell(也许你现在正在学习它?),但如果你只能采用 a 小于或等于的那些,你似乎可以摆脱它们b。这将消除重复项。

Don't know Haskell at all (perhaps you're learning it now?) but it seems like you could get rid of them if you could take only the ones for which a is less than or equal to b. That would get rid of the duplicates.

删除会话 2024-12-09 06:07:16

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

http://en.wikipedia.org/wiki/Formulas_for_generate_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

Try with a simple recursive generator:

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

(new article)
http://en.wikipedia.org/wiki/Tree_of_primitive_Pythagorean_triples

EDIT (7 May 2014)

Here I have made infinite generator that can generate primitive triplets ordered by perimeter (but can be modified to be ordered by other parameter - hypotenuses, area, ...) as long as it holds that any triplet is smaller that any generated from generator matrix according to provided compare function

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
撩动你心 2024-12-09 06:07:16

您可以执行以下操作:

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

You can do the following:

pythagorean = [ (x,y,m*m+n*n) | 
                                m <- [2..], 
                                n <- [1 .. m-1], 
                                let x = m*m-n*n, 
                                let y = 2*m*n ]
冷血 2024-12-09 06:07:16

这可能有效:从本教程中得到它

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

This might work: 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]  
梦在深巷 2024-12-09 06:07:16

列表理解语法使这变得简单:

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]

这基本上是说我们从 as、bs 和 cs 构建一个列表,其中 a1 更改为 db 从当前的 a 更改为 d< /code> 等。它还表示 a^2 + b^2 == c^2 应该成立。

List comprehension syntax makes this easy:

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]

This basically says than we build a list from as,bs and cs, where a changes from 1 to d, b changes from current a to d and etc. It also says that a^2 + b^2 == c^2 should hold.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文