import Data.Char import Data.List import Control.Monad import qualified Data.Map.Strict as Map import Data.Map.Strict ((!)) realSue :: Map.Map String (Int -> Bool) realSue = Map.fromList [ -- for part 1, make all functions equalities ("children", (==3)), ("cats", (>7)), ("samoyeds", (==2)), ("pomeranians",(<3)), ("akitas", (==0)), ("vizslas", (==0)), ("goldfish", (<5)), ("trees", (>3)), ("cars", (==2)), ("perfumes", (==1))] parse :: String -> [(String,Int)] parse s = parse' $ drop 2 $ words s parse' :: [String] -> [(String,Int)] parse' [] = [] parse' (k:v:xs) = (init k,read $ takeWhile isDigit v) : parse' xs matches :: [(String,Int)] -> Map.Map String (Int -> Bool) -> Bool matches [] _ = True matches ((k,v):atts) map = (map ! k) v && matches atts map day16 :: IO () day16 = do input <- liftM (zip [1..] . map parse . lines) $ readFile "day16.txt" sequence_ $ map (print . fst) $ filter (\(i,atts) -> matches atts realSue) input main = day16