import Control.Lens import Data.List.Split import Linear.V3 type Game = (Int, [V3 Int]) main :: IO () main = do input <- init . splitOn "\n" <$> readFile "input" let parsed = map parse input print $ day2a parsed print $ day2b parsed parse :: String -> Game parse x = (read $ init gameID, sets) where gameID = words x !! 1 sets = map (parseSet . map words . splitOn ", ") $ splitOn "; " $ last $ splitOn ": " x parseSet :: [[String]] -> V3 Int parseSet ([x, "red"]:xs) = V3 (read x) 0 0 + parseSet xs parseSet ([x, "green"]:xs) = V3 0 (read x) 0 + parseSet xs parseSet ([x, "blue"]:xs) = V3 0 0 (read x) + parseSet xs parseSet [] = V3 0 0 0 (>?) :: V3 Int -> V3 Int -> Bool (>?) (V3 a b c) (V3 a' b' c') | a >= a' && b >= b' && c >= c' = True | otherwise = False day2a :: [Game] -> Int day2a [] = 0 day2a ((n, xs):games) | all (V3 12 13 14 >?) xs = n + day2a games | otherwise = day2a games day2b :: [Game] -> Int day2b [] = 0 day2b ((_, game):games) = product (map (`getMin` game) [_x, _y, _z]) + day2b games where getMin x = maximum . map (^. x)