-
Notifications
You must be signed in to change notification settings - Fork 0
/
run.hs
46 lines (37 loc) · 1.27 KB
/
run.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
{-# LANGUAGE TupleSections #-}
import Data.List
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HashMap
parse :: String -> ((String, String), [((String, String), Int)])
parse = go . words
where go (c1:c2:_:_:"no":_) = ((c1, c2), [])
go (c1:c2:_:_:rest) =
((c1, c2), readBags rest)
readBags [] = []
readBags (n:c1:c2:_:rest) = ((c1, c2), read n):readBags rest
parseAll =
map parse . lines
rels = concatMap (\(p, cs) -> map ((,p) . fst) cs)
expand rules x = x:map snd (filter ((== x) . fst) rules)
findAll rules =
let vals = iterate (nub . concatMap (expand rules)) [("shiny", "gold")]
in fst . head . filter (uncurry (==)) $ zip (drop 1 vals) vals
part1 = length . drop 1 . findAll . rels
loeb :: Functor a => a (a x -> x) -> a x
loeb x = fmap (\a -> a (loeb x)) x
totalBags rules =
let ruleMap = HashMap.fromList rules
lookupCount m x =
sum
. map (\(c, n) -> n * (1 + lookupCount m c))
$ ruleMap HashMap.! x
ss = HashMap.fromList
. map (\x -> (x, flip lookupCount x))
. map fst
$ rules
in loeb ss
part2 input = totalBags input HashMap.! ("shiny", "gold")
main = do
input <- parseAll <$> readFile "input.txt"
print (part1 input)
print (part2 input)