Skip to content

Instantly share code, notes, and snippets.

data Tree a
= EmptyTree
| Tree { root :: Node a }
data Node a
= Node {
value :: a,
children :: [Node a] }
treeWalkR :: Tree a -> [a]
treeWalkR EmptyTree = []
treeWalkR (Tree root) = treeWalkR' root
treeWalkR' :: Node a -> [a]
treeWalkR' (Node v children) = v : concatMap treeWalkR' children
treeWalkH :: Tree a -> [a]
treeWalkH EmptyTree = []
treeWalkH (Tree root) = treeWalkH' root
treeWalkH' :: Node a -> [a]
treeWalkH' = reverse . loop [] []
where
loop out [] (Node v []) = v:out -- End of traversal
loop out stack (Node v (c:cs)) = loop (v:out) (toStack (cs:stack)) c
loop out (h:t) (Node v []) = loop (v:out) (toStack (tail h:t)) (head h)
treeWalkM :: Tree a -> [a]
treeWalkM EmptyTree = []
treeWalkM (Tree root) = treeWalkM' root
treeWalkM' :: Node a -> [a]
treeWalkM' n = runCont (loop n) id
where
loop (Node v cs) = do
rs <- mapM loop cs
return (v : concat rs)
foldMergeSort :: (Ord a) => [a] -> [a]
foldMergeSort =
foldl1 (flip merge) . map snd . foldl addToCounter []
where
addToCounter counter x = propagate ((1::Int,[x]) : counter)
propagate [] = []
propagate [x] = [x]
propagate counter@(x:y:xs) -- x arrived last => combine on right
| fst x == fst y = propagate ((fst x + fst y, merge (snd y) (snd x)) : xs)
| otherwise = counter
foldMonoidTree :: (Monoid a) => [a] -> a
foldMonoidTree =
foldl1 (flip (<>)) . map snd . foldl addToCounter []
where
addToCounter counter x = propagate ((1::Int,x) : counter)
propagate [] = []
propagate [x] = [x]
propagate counter@(x:y:xs) -- x arrived last => combine on right
| fst x == fst y = propagate ((fst x + fst y, snd y <> snd x) : xs)
| otherwise = counter
treeWalkC :: Tree a -> [a]
treeWalkC EmptyTree = []
treeWalkC (Tree root) = treeWalkC' root
treeWalkC' :: Node a -> [a]
treeWalkC' n = loop n id
where
loop (Node v cs) cont = loopChildren cs (cont . (v:))
loopChildren [] cont = cont []
loopChildren (c:cs) cont =
testCases :: [(Int, String)]
testCases = [ (0, "0"), (1, "1"), (3, "Fizz"), (5, "Buzz")
, (7, "7"), (15, "FizzBuzz"), (100, "Buzz")]
tests :: Test
tests = TestList $ map createTestCase testCases
where
createTestCase (input, expected) =
let label = "FizzBuzz of " ++ show input
in TestCase $ assertEqual label expected (fizzBuzz input)
newtype Fizz = Fizz Int deriving (Show)
newtype Buzz = Buzz Int deriving (Show)
newtype Other = Other Int deriving (Show)
instance Arbitrary Fizz where
arbitrary = do
x <- (arbitrary `suchThat` (\n -> fizzBuzz n == "Fizz"))
return (Fizz x)
instance Arbitrary Buzz where
fizzBuzz :: Int -> String
fizzBuzz 0 = "0"
fizzBuzz n =
let res = fizzBuzzImpl [newRule 3 "Fizz", newRule 5 "Buzz"] n
in if res == ""
then show n
else res
type Rule = Int -> String