HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Generating double linear sequence in Haskell

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
linearsequencegeneratingdoublehaskell

Problem

Need some comments on making the below code more effective. I'm pretty new to Haskell.

The sequence in generateSeq is generated by the rule that if x is in the sequence then x2+1 and x3+1 are also in the sequence.

getNumberAt gets the n'th number in the (sorted) generated sequence.

The code works but somehow I feel that I'm overcomplicating this. Any pointers are appreciated!

generateSeq :: Int -> [Integer]
    generateSeq x
        | x == 0 = [1]
        | otherwise = sort $ prev++toAppend
                         where prev = generateSeq(x-1)
                               toAppend = [next*2+1,next*3+1]
                               next = head $ drop(x-1) prev

    getNumberAt :: Int -> Integer
    getNumberAt n = nub(generateSeq n)!!n

    -- Test this!
    main =
       print $ getNumberAt 321

Solution

Repeatedly sorting is asympotically slower than keeping a sorted data structure, nub takes quadratic time, head . drop (x-1) = (!!x), and try to use library-defined recursion combinators instead of explicitly using recursion.

import qualified Data.Set as S

generateSeq :: [Integer]
generateSeq = unfoldr (fmap foo . S.minView) $ singleton 1 where
  foo :: (Integer, S.Set Integer) -> (Integer, S.Set Integer)
  foo (x, s) = (x, S.insert (2*x+1) $ S.insert (3*x+1) s)


looks up comonad stuff on a hunch

import qualified Data.Set as S
import Control.Comonad

generateSeq :: [Integer]
generateSeq = unfoldr ((fmap . extend . uncurry) foo . S.minView) $ singleton 1 where
  foo :: Integer -> S.Set Integer -> S.Set Integer
  foo x = S.insert (2*x+1) . S.insert (3*x+1)

Code Snippets

import qualified Data.Set as S

generateSeq :: [Integer]
generateSeq = unfoldr (fmap foo . S.minView) $ singleton 1 where
  foo :: (Integer, S.Set Integer) -> (Integer, S.Set Integer)
  foo (x, s) = (x, S.insert (2*x+1) $ S.insert (3*x+1) s)
import qualified Data.Set as S
import Control.Comonad

generateSeq :: [Integer]
generateSeq = unfoldr ((fmap . extend . uncurry) foo . S.minView) $ singleton 1 where
  foo :: Integer -> S.Set Integer -> S.Set Integer
  foo x = S.insert (2*x+1) . S.insert (3*x+1)

Context

StackExchange Code Review Q#147413, answer score: 4

Revisions (0)

No revisions yet.