{-# Language QuasiQuotes, ImportQualifiedPost #-}
module Main (main) where
import Data.Map (Map)
import Data.Map qualified as Map
import Advent (format)
main :: IO ()
IO ()
main =
do [(Int, [[(Int, String)]])]
input <- [format|2023 2 (Game %d: (%d %s)&(, )&(; )%n)*|]
let summaries :: [(Int, Map String Int)]
summaries = [(Int
i, [[(Int, String)]] -> Map String Int
summarizeGame [[(Int, String)]]
rounds) | (Int
i, [[(Int, String)]]
rounds) <- [(Int, [[(Int, String)]])]
input]
Int -> IO ()
forall a. Show a => a -> IO ()
print ([Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int
i | (Int
i, Map String Int
summary) <- [(Int, Map String Int)]
summaries, (Int -> Int -> Bool) -> Map String Int -> Map String Int -> Bool
forall k a b.
Ord k =>
(a -> b -> Bool) -> Map k a -> Map k b -> Bool
Map.isSubmapOfBy Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
(<=) Map String Int
summary Map String Int
part1])
Int -> IO ()
forall a. Show a => a -> IO ()
print ([Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Map String Int -> Int
forall a. Num a => Map String a -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
product Map String Int
summary | (Int
_, Map String Int
summary) <- [(Int, Map String Int)]
summaries])
summarizeGame :: [[(Int, String)]] -> Map String Int
summarizeGame :: [[(Int, String)]] -> Map String Int
summarizeGame [[(Int, String)]]
rs = (Int -> Int -> Int) -> [Map String Int] -> Map String Int
forall (f :: * -> *) k a.
(Foldable f, Ord k) =>
(a -> a -> a) -> f (Map k a) -> Map k a
Map.unionsWith Int -> Int -> Int
forall a. Ord a => a -> a -> a
max [[(Int, String)] -> Map String Int
summarizeRound [(Int, String)]
r | [(Int, String)]
r <- [[(Int, String)]]
rs]
summarizeRound :: [(Int, String)] -> Map String Int
summarizeRound :: [(Int, String)] -> Map String Int
summarizeRound [(Int, String)]
r = (Int -> Int -> Int) -> [(String, Int)] -> Map String Int
forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
Map.fromListWith Int -> Int -> Int
forall a. Num a => a -> a -> a
(+) [(String
color, Int
count) | (Int
count, String
color) <- [(Int, String)]
r]
part1 :: Map String Int
part1 :: Map String Int
part1 = [(String, Int)] -> Map String Int
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [(String
"red", Int
12), (String
"green", Int
13), (String
"blue", Int
14)]