adventofcode/2023/app/Day4.hs
2023-12-05 21:03:12 +01:00

60 lines
1.7 KiB
Haskell

{-# LANGUAGE TupleSections #-}
module Day4 where
import System.IO
import ParseLib.Abstract
import Data.Char (isSpace)
import Prelude hiding ((*>), (<$), (<*))
import qualified Data.Map as M
import Debug.Trace
main :: IO ()
main = do
handle <- openFile "app/Day4-input.txt" ReadMode
input <- hGetContents handle
let cards = map (fst . head . parse parseCard) (lines input)
putStr "Part 1: "
print $ sum (map score cards)
putStr "Part 2: "
print $ sum
$ foldl
-- For every card, get the score and get a list of the clones it
-- would produce and update the accumulator a with a[i] copies.
(\a c@(Card i _ _) -> update' (a M.! i) a [i+1..i+score' c])
-- A map of (i, n) where i is the card id and n is the number of copies
(M.fromList $ map (, 1) [1..length cards])
cards
type Id = Int
type Winning = [Int]
type Pulls = [Int]
data Card = Card Id Winning Pulls deriving Show
whitespace :: Parser Char [Char]
whitespace = greedy (satisfy isSpace)
number :: Parser Char Int
number = whitespace *> natural
-- Cars needs Int -> [Int] -> [Int] so
-- number :: Parser Char Int
-- greedy number :: Parser Char [Int]
parseCard :: Parser Char Card
parseCard = Card <$ token "Card" <*> number <* symbol ':' <*>
greedy number <* whitespace <* symbol '|' <*> greedy number
intersect :: (Foldable t, Eq a) => t a -> [a] -> [a]
intersect xs = filter (`elem` xs)
score :: Card -> Int
score c = round $ 2 ^ score' c
score' :: Card -> Int
score' (Card i w p) | null intr = 0
| otherwise = length intr
where intr = w `intersect` p
update' :: Int -> M.Map Int Int -> [Int] -> M.Map Int Int
update' n = foldr (M.update (\x -> Just (x+n)))