Generating sorted list of all possible coprimes

前端 未结 4 1021
走了就别回头了
走了就别回头了 2021-01-22 07:07

I need to generate infinite sorted list of all coprimes. The first element in each pair must be less than the second. The sorting must be done in ascending order -- by the sum o

4条回答
  •  南方客
    南方客 (楼主)
    2021-01-22 07:46

    Here's a possible solution following Chapter 9 of Richard Bird's Thinking Functionally in Haskell:

    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
    

    And the result is:

    > take 10 $ coprimes
    [(2,3),(2,5),(3,4),(3,5),(2,7),(4,5),(3,7),(2,9),(3,8),(4,7)]
    

    Note that the natural definition of mergeAll would be foldr1 merge, but this doesn't work because it will try to find the minimum of the first elements of all the list before returning the first element, and hence you end up in an infinite loop. However, since we know that the lists are in ascending order and the minimum is the first element of the first list xmerge does the trick.


    Note: this solution appears to be significantly (like 2 order of magnitudes) slower than Carsten "naive" answer. So I advise to avoid this if you are interested in performance. Yet it still is an interesting approach that might be effective in other situations.

提交回复
热议问题