module Main where import Data.Map (Map) import qualified Data.Map as Map myBag = "shiny gold" parseContained :: [String] -> [(Int, String)] parseContained [] = [] parseContained (count:b:c:_:rest) = (read count, unwords [b,c]):parseContained rest parseLine :: [String] -> (String, [(Int, String)]) parseLine s = (leadingBag, contained) where leadingBag = unwords $ take 2 s trailingBags = drop 4 s contained = case head trailingBags of "no" -> [] _ -> parseContained trailingBags canContain :: Map String [(Int, String)] -> String -> Bool canContain m outer = myBag `elem` inners || any (canContain m) inners where (Just inners) = map snd <$> Map.lookup outer m countNested :: String -> Map String [(Int, String)] -> Int countNested s m = if null l then 0 else sum $ map counter l where (Just l) = Map.lookup s m counter (count, bag) = count + count * countNested bag m main :: IO () main = do n <- map (parseLine . words) . lines <$> readFile "input/07" let q = Map.fromList n print $ length $ filter (== True) $ map (canContain q . fst) $ Map.toList q print $ countNested myBag q