From a7ef2ed5435d4c8fae26dfa5f9937c1d5daeb5f4 Mon Sep 17 00:00:00 2001 From: Adam Ruzicka Date: Sat, 2 Dec 2023 14:16:13 +0100 Subject: [PATCH] 2023 day 2 in Haskell --- 2023/02/day2.hs | 68 +++++++++++++++++++++++++++++++++++++++++++++++++ 2023/02/example | 5 ++++ 2 files changed, 73 insertions(+) create mode 100644 2023/02/day2.hs create mode 100644 2023/02/example diff --git a/2023/02/day2.hs b/2023/02/day2.hs new file mode 100644 index 0000000..3f30b97 --- /dev/null +++ b/2023/02/day2.hs @@ -0,0 +1,68 @@ +{-# LANGUAGE OverloadedStrings #-} + +import Data.Text qualified as T +import Text.Printf (printf) + +type Set = (Integer, Integer, Integer) + +type Game = (Integer, [Set]) + +emptySet = (0, 0, 0) + +part1 :: [Game] -> Integer +part1 = sum . map fst . filter (all setWithinLimits . snd) + +part2 :: [Game] -> Integer +part2 = sum . map (setPower . minimumSet . snd) + +minimumSet :: [Set] -> Set +minimumSet ss = (maximum $ map first ss, maximum $ map second ss, maximum $ map third ss) + where + first (r, _, _) = r + second (_, g, _) = g + third (_, _, b) = b + +setWithinLimits (r, g, b) = r <= 12 && g <= 13 && b <= 14 + +parseGame :: T.Text -> Game +parseGame s = (parseId $ head parts, parseSets $ last parts) + where + parts = T.splitOn ":" s + +parseId :: T.Text -> Integer +parseId = read . T.unpack . last . T.words + +parseSets :: T.Text -> [Set] +parseSets = map parseSet . T.splitOn ";" + +parseSet :: T.Text -> Set +parseSet = sumSets . map parseDraw . T.splitOn "," + +addSets :: Set -> Set -> Set +addSets (r1, g1, b1) (r2, g2, b2) = (r1 + r2, g1 + g2, b1 + b2) + +sumSets :: [Set] -> Set +sumSets = foldl addSets emptySet + +setPower :: Set -> Integer +setPower (r, g, b) = r * g * b + +parseDraw :: T.Text -> Set +parseDraw s = setOf count color + where + setOf n "red" = (n, 0, 0) + setOf n "green" = (0, n, 0) + setOf n "blue" = (0, 0, n) + parts = T.words s + color = last parts + count = read $ T.unpack $ head parts + +parseInput :: T.Text -> [Game] +parseInput = map parseGame . T.lines + +main :: IO () +main = do + contents <- getContents + let parsed = parseInput $ T.pack contents + putStr $ printf "Part 1: %d\n" $ part1 parsed + putStr $ printf "Part 2: %d\n" $ part2 parsed diff --git a/2023/02/example b/2023/02/example new file mode 100644 index 0000000..295c36d --- /dev/null +++ b/2023/02/example @@ -0,0 +1,5 @@ +Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green +Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue +Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red +Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red +Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green