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)
