aoc2023

advent of code 2023
Log | Files | Refs | Feed | README

day2.hs (2271B)


      1 -- AOC 2023: Day 2
      2 --
      3 -- There is a game where you want to determine the number of each
      4 -- colour of cube in bag. The bag contains red, green, and blue
      5 -- cubes.
      6 --
      7 -- Task 1: Grab a random handful of cubes and count each colour.
      8 -- Do this a few times per game and perform many games. This will
      9 -- result in a list of data such as:
     10 --
     11 -- Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
     12 -- ...
     13 -- Game N: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green
     14 --
     15 -- After this data was collected you are told that the bag
     16 -- contained only 12 red, 13 green, and 14 blue cubes. Provide
     17 -- the sum of all the valid game's numbers.
     18 --
     19 -- Task 2: The power of a set of cubes is the minimum number of
     20 -- each colour needed to make a game valid. Provide the sum of
     21 -- the powers of all games.
     22 --
     23 {-# LANGUAGE OverloadedStrings #-}
     24 
     25 import qualified Data.Text as T
     26 import qualified Data.Text.IO as TI
     27 import Text.Printf (printf)
     28 
     29 splitgame :: T.Text -> (Int, [(Int, T.Text)])
     30 splitgame st =
     31     let (gn, t) = T.breakOn ": " st
     32         n = read $ T.unpack $ snd $ T.break (== ' ') gn :: Int
     33         tuples =
     34             map to_int_text . map (T.break (== ' ')) $
     35             T.splitOn ", " $ T.replace ": " "" $ T.replace ";" "," t
     36      in (n, tuples)
     37 
     38 to_int_text :: (T.Text, T.Text) -> (Int, T.Text)
     39 to_int_text (f, s) = (read (T.unpack f) :: Int, s)
     40 
     41 get_colour_list :: T.Text -> [(Int, T.Text)] -> [Int]
     42 get_colour_list c l = map fst $ filter ((== c) . snd) l
     43 
     44 get_rgb_triple :: [(Int, T.Text)] -> ([Int], [Int], [Int])
     45 get_rgb_triple l =
     46     let r = get_colour_list " red" l
     47         g = get_colour_list " green" l
     48         b = get_colour_list " blue" l
     49      in (r, g, b)
     50 
     51 isvalidgame :: (Int, [(Int, T.Text)]) -> Int
     52 isvalidgame (n, t) =
     53     let (r, g, b) = get_rgb_triple t
     54      in if (null $ filter (> 12) r) &&
     55            (null $ filter (> 13) g) && (null $ filter (> 14) b)
     56             then n
     57             else 0
     58 
     59 gamepower :: (Int, [(Int, T.Text)]) -> Int
     60 gamepower (_, t) =
     61     let (r, g, b) = get_rgb_triple t
     62      in (foldr1 max r) * (foldr1 max g) * (foldr1 max b)
     63 
     64 main = do
     65     contents <- TI.getContents
     66     let games = map splitgame $ T.lines contents
     67     printf "Task 1: %8d\n" (sum $ map isvalidgame games)
     68     printf "Task 2: %8d\n" (sum $ map gamepower games)