List 生成所有可能条件的排序列表

List 生成所有可能条件的排序列表,list,sorting,haskell,primes,infinite,List,Sorting,Haskell,Primes,Infinite,我需要生成所有coprime的无限排序列表。 每对中的第一个元素必须小于第二个元素。 排序必须按升序进行——按对的元素之和;如果两个和相等,则按对的第一个元素 因此,结果列表必须是 [(2,3),(2,5),(3,4),(3,5),(2,7),(4,5),(3,7),(2,9),(3,8),(4,7)...` 这是我的解决办法 coprimes :: [(Int, Int)] coprimes = sortBy (\t1 t2 -> if uncurry (+) t1 <= unc

我需要生成所有coprime的无限排序列表。 每对中的第一个元素必须小于第二个元素。 排序必须按升序进行——按对的元素之和;如果两个和相等,则按对的第一个元素

因此,结果列表必须是

[(2,3),(2,5),(3,4),(3,5),(2,7),(4,5),(3,7),(2,9),(3,8),(4,7)...`
这是我的解决办法

coprimes :: [(Int, Int)]
coprimes = sortBy (\t1 t2 -> if uncurry (+) t1 <= uncurry (+) t2 then LT else GT) $ helper [2..]
    where helper xs = [(x,y) | x <- xs, y <- xs, x < y, gcd x y == 1]
coprimes::[(Int,Int)]

coprimes=sortBy(\t1 t2->if uncurry(+)t1),但如果您首先生成所有可能的对,然后对它们进行过滤,这可能不是最理想的方法

因此,使用您的标准:

pairs :: [(Integer,Integer)]
pairs = [ (i,l-i) | l <- [1..], i <- [1..l-1] ]

coprimes :: [(Integer,Integer)]
coprimes = [ (i,j) | (i,j) <- pairs, 1 < i, i < j,gcd i j == 1]

当然,现在你可以把脑海中出现的一些
1
i
放到
对定义中,甚至可以将它们连接起来,但我认为这里发生的事情更加明显,正如@Bakuriu所建议的,合并无限列表是一个解决方案,但魔鬼在细节中

软件包中的函数可以实现这一点,因此您可以编写:

import Data.Universe.Helpers

coprimes = diagonal [ go n | n <- [2..] ]
  where go n = [ (n,k) | k <- [n+1..], gcd n k == 1 ]

并筛选此列表。

以下是Richard Bird在Haskell中功能性思考的第9章中可能的解决方案:

请注意,
mergeAll
的自然定义将是
foldr1 merge
,但这不起作用,因为它将在返回第一个元素之前尝试查找所有列表的第一个元素的最小值,因此您将进入一个无限循环。然而,因为我们知道列表是按升序排列的,最小值um是第一个列表的第一个元素
xmerge
起作用


注意:这个解决方案似乎比Carsten的“幼稚”答案慢很多(比如2个数量级)。因此,如果您对性能感兴趣,我建议您避免使用这个方法。但它仍然是一个有趣的方法,在其他情况下可能会有效

我需要生成所有coprime的无限排序列表。每对中的第一个元素必须小于第二个。排序必须按升序进行——按对的元素之和;如果两个和相等,则按对的第一个元素

所以,我们生成和和和第一个元素的升序对,并且只保留coprimes。简单

[ (first, second)
| sum <- [3..]
, first <- [2..sum `div` 2]
, let second = sum-first
, gcd first second == 1
]
[(第一,第二)

|总之,技巧可能是以升序为
2
、为
3
生成对,并将它们合并。您可以使用from
data ordlist
,而不是
foldr1 xmerge
。它使用树状结构进行折叠,因此应该会带来显著的算法(我的意思是,复杂度)优势(因此,加速)。比较返回相等和的
EQ
,但该包中的所有函数都是左偏的,所以这没关系。@daniel wagner是《宇宙基础》的作者。他的答案就在你的前面(这个)。
[ (1,1) ] ++ [ (1,2), (2,1) ] ++ [ (1,3), (2,2), (3,1) ] ++ ...
coprimes = mergeAll $ map coprimes' [2..]

coprimes' n = [(n, m) | m <- [n+1..], gcd m n == 1]

merge (x:xs) (y:ys)
    | s x < s y =  x:merge xs (y:ys)
    | s x == s y = x:y:merge xs ys
    | otherwise = y:merge (x:xs) ys
    where s (x, y) = x+y

xmerge (x:xs) ys = x:merge xs ys

mergeAll = foldr1 xmerge
> take 10 $ coprimes
[(2,3),(2,5),(3,4),(3,5),(2,7),(4,5),(3,7),(2,9),(3,8),(4,7)]
[ (first, second)
| sum <- [3..]
, first <- [2..sum `div` 2]
, let second = sum-first
, gcd first second == 1
]