packages feed

unfoldable-0.9.1: examples/brackets.hs

-- From https://byorgey.wordpress.com/2016/10/25/adventures-in-enumerating-balanced-brackets/
import Data.Unfolder
import Data.MemoTrie (memo2)
import Control.Applicative

enumBrackets :: Unfolder f => Int -> f String
enumBrackets n = enumBracketsTail n 0

enumBracketsTail :: Unfolder f => Int -> Int -> f String
enumBracketsTail = enumBracketsTail'
  where
    -- Ensure memoization happens for a specific `f`
    enumBracketsTail' = memo2 enumBracketsTail''
    enumBracketsTail'' 0 c = pure (replicate c ')')
    enumBracketsTail'' n 0 = ('(':) <$> enumBracketsTail' (n-1) 1
    enumBracketsTail'' n c =
      ('(':) <$> enumBracketsTail' (n-1) (c+1)
      <|>
      ((')':) <$> enumBracketsTail' n (c-1))

{-

>>> enumBrackets 3 :: [String]
["((()))","(()())","(())()","()(())","()()()"]
>>> getNth (enumBrackets 40) 16221270422764920820
"((((((((()((())()(()()()())(()))((()()()()(()((()())))((()())))))))()))()())()))"
>>> size (enumBrackets 100)
896519947090131496687170070074100632420837521538745909320

-}