Last active
November 3, 2016 07:54
-
-
Save mheinzel/37aa92191ea08c89e3d0633e73d5d50e to your computer and use it in GitHub Desktop.
Counting letters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import qualified Data.Map.Strict as M | |
import Data.Map.Strict (Map) | |
import Data.Tuple (swap) | |
import Data.List | |
-- task: map each element to how often it already occured before | |
-- count "abbcccghabc" -> [1,1,2,1,2,3,1,1,2,3,4] | |
-- useful helper function: | |
insertWithAndGet :: Ord k => (a -> a -> a) -> k -> a -> Map k a -> (a, Map k a) | |
insertWithAndGet f k v m = (newValue, M.insert k newValue m) | |
where newValue = maybe v (f v) $ M.lookup k m | |
-- using foldl | |
-- laziness not preserved because of foldl | |
count :: Ord a => [a] -> [Int] | |
count = reverse . snd . foldl f (M.empty, []) | |
where | |
f (m, ns) x = (newMap, n:ns) | |
where (n, newMap) = insertWithAndGet (+) x 1 m | |
-- explicit recursion | |
count' :: Ord a => [a] -> [Int] | |
count' = go M.empty | |
where | |
go _ [] = [] | |
go m (x:xs) = n : go newMap xs | |
where (n, newMap) = insertWithAndGet (+) x 1 m | |
-- abstracting over the recursion | |
someFold :: (x -> acc -> (n, acc)) -> acc -> [x] -> [n] | |
someFold _ _ [] = [] | |
someFold f acc (x:xs) = n : someFold f newAcc xs | |
where | |
(n, newAcc) = f x acc | |
count'' :: Ord a => [a] -> [Int] | |
count'' = someFold (\x -> insertWithAndGet (+) x 1) M.empty | |
-- using the predefined mapAccumL | |
count''' :: Ord a => [a] -> [Int] | |
count''' = snd . mapAccumL (\m x -> swap $ insertWithAndGet (+) x 1 m) M.empty |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment