module Main where import Data.List.Split (splitOn) type Red = Int type Green = Int type Blue = Int data Cube = RedQuantity Red | GreenQuantity Green | BlueQuantity Blue deriving (Show) data CubeSum = CubeSum {red :: Red, green :: Green, blue :: Blue} deriving (Show) partTwo :: [String] -> Int partTwo = sum . map (powerCube . makeCubes) powerCube :: [Cube] -> Int powerCube = getCubePower . foldr minimumSetCube CubeSum {red = 0, green = 0, blue = 0} getCubePower :: CubeSum -> Int getCubePower CubeSum {red = _red, green = _green, blue = _blue} = _red * _green * _blue minimumSetCube :: Cube -> CubeSum -> CubeSum minimumSetCube (RedQuantity q) CubeSum {red = _red, green = _green, blue = _blue} = CubeSum {red = max _red q, green = _green, blue = _blue} minimumSetCube (GreenQuantity q) CubeSum {red = _red, green = _green, blue = _blue} = CubeSum {red = _red, green = max _green q, blue = _blue} minimumSetCube (BlueQuantity q) CubeSum {red = _red, green = _green, blue = _blue} = CubeSum {red = _red, green = _green, blue = max _blue q} partOne :: [String] -> [Int] partOne = map fst . filter (all validate . snd) . zip [1 ..] . map makeCubes where validate (RedQuantity n) = n <= 12 validate (GreenQuantity n) = n <= 13 validate (BlueQuantity n) = n <= 14 makeCubes :: String -> [Cube] makeCubes = map createCube . splitOn "," . replaceSemiColon . last . splitOn ":" replaceSemiColon :: String -> String replaceSemiColon = map toComma where toComma ';' = ',' toComma x = x parseElem :: String -> (String, String) parseElem (_ : s) = (cube, nb) where nb = head splited cube = last splited splited = splitOn " " s parseElem _ = undefined getElem :: (String, String) -> Cube getElem ("red", nb) = RedQuantity (read nb :: Red) getElem ("green", nb) = GreenQuantity (read nb :: Green) getElem ("blue", nb) = BlueQuantity (read nb :: Blue) getElem _ = undefined createCube :: String -> Cube createCube = getElem . parseElem getCubeSum :: [Cube] -> CubeSum getCubeSum = foldr cubeAddition CubeSum {red = 0, green = 0, blue = 0} cubeAddition :: Cube -> CubeSum -> CubeSum cubeAddition (RedQuantity q) CubeSum {red = _red, green = _green, blue = _blue} = CubeSum {red = _red + q, green = _green, blue = _blue} cubeAddition (GreenQuantity q) CubeSum {red = _red, green = _green, blue = _blue} = CubeSum {red = _red, green = _green + q, blue = _blue} cubeAddition (BlueQuantity q) CubeSum {red = _red, green = _green, blue = _blue} = CubeSum {red = _red, green = _green, blue = _blue + q} main :: IO () main = do content <- readFile "input.txt" (print . sum . partOne . lines) content (print . partTwo . lines) content putStrLn "Yes, it works!"