Tweaked solution 9 a bit, to check all approaches are finding the same set of items
[summerofcode2018soln.git] / src / task0 / task0.hs
1 import qualified Data.HashMap.Strict as M
2 import Data.List (foldl') -- import the strict fold
3 import Data.List.Split (splitOn)
4
5 -- a key-value store for recording how often each name is seen
6 type NameCount = M.HashMap String Int
7
8 main :: IO ()
9 main = do
10 -- text <- readFile "data/small_invites.txt"
11 text <- readFile "data/00-invites.txt"
12 print $ part1 text
13 print $ part2 text
14
15 -- use `words` here as I don't need to worry about the comma delimiters
16 part1 :: String -> Int
17 part1 = maximum . map (length . words) . lines
18
19 part2 :: String -> Int
20 part2 inviteText = M.size popular
21 where -- split names on the delimieter, use `concatMap` to give just one long list
22 invites = concatMap (splitOn ", ") $ lines inviteText
23 -- count the names
24 invited = nameCounts invites
25 -- popular are those mentioned more than once
26 popular = M.filter (> 1) invited
27
28
29 -- count how many times each name appears.
30 -- It's a fold over the list of names, creating the name count HashMap.
31 -- As each name is taken from the list, we find how many times we've seen it
32 -- before, add one to it, then update the HashMap with the new count.
33 nameCounts :: [String] -> NameCount
34 nameCounts names = foldl' includeName M.empty names
35 where includeName nc name = M.insert name (1 + count name nc) nc
36 -- a default count of 0 for each name
37 count name = M.lookupDefault 0 name