diff options
Diffstat (limited to 'execs/Day07.hs')
-rw-r--r-- | execs/Day07.hs | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/execs/Day07.hs b/execs/Day07.hs new file mode 100644 index 0000000..1587e2b --- /dev/null +++ b/execs/Day07.hs | |||
@@ -0,0 +1,36 @@ | |||
1 | module Main where | ||
2 | |||
3 | import Data.Map (Map) | ||
4 | import qualified Data.Map as Map | ||
5 | |||
6 | myBag = "shiny gold" | ||
7 | |||
8 | parseContained :: [String] -> [(Int, String)] | ||
9 | parseContained [] = [] | ||
10 | parseContained (count:b:c:_:rest) = (read count, unwords [b,c]):parseContained rest | ||
11 | |||
12 | parseLine :: [String] -> (String, [(Int, String)]) | ||
13 | parseLine s = (leadingBag, contained) | ||
14 | where leadingBag = unwords $ take 2 s | ||
15 | trailingBags = drop 4 s | ||
16 | contained = case head trailingBags of | ||
17 | "no" -> [] | ||
18 | _ -> parseContained trailingBags | ||
19 | |||
20 | canContain :: Map String [(Int, String)] -> String -> Bool | ||
21 | canContain m outer = myBag `elem` inners || any (canContain m) inners | ||
22 | where (Just inners) = map snd <$> Map.lookup outer m | ||
23 | |||
24 | countNested :: String -> Map String [(Int, String)] -> Int | ||
25 | countNested s m = if null l | ||
26 | then 0 | ||
27 | else sum $ map counter l | ||
28 | where (Just l) = Map.lookup s m | ||
29 | counter (count, bag) = count + count * countNested bag m | ||
30 | |||
31 | main :: IO () | ||
32 | main = do | ||
33 | n <- map (parseLine . words) . lines <$> readFile "input/07" | ||
34 | let q = Map.fromList n | ||
35 | print $ length $ filter (== True) $ map (canContain q . fst) $ Map.toList q | ||
36 | print $ countNested myBag q | ||