{-# OPTIONS_GHC -Wno-x-partial #-} import Aoc import Data.List ( transpose ) import Data.Bifunctor ( bimap ) parseLine :: String -> (String, [Int]) parseLine line = let [name, "capacity", capacity, "durability", durability, "flavor", flavor, "texture", texture, "calories", calories] = words line in let read' = read . init in (init name, [read calories, read' capacity, read' durability, read' flavor, read' texture]) part1' :: (Int -> Bool) -> [(String, [Int])] -> Int part1' cond ingredients = maximum $ map (product . tail) $ filter (cond . head) $ map (map (max 0 . sum) . transpose . map (uncurry map . bimap (*) snd) . (`zip` ingredients)) $ starsAndBars 100 (length ingredients - 1) part1 :: [(String, [Int])] -> Int part1 = part1' $ const True part2 :: [(String, [Int])] -> Int part2 = part1' (==500) main :: IO () main = aocMain (map parseLine) part1 part2