{-# 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 - 1) score' :: Card -> Int score' (Card i w p) = length $ w `intersect` p update' :: Int -> M.Map Int Int -> [Int] -> M.Map Int Int update' n = foldr (M.update (\x -> Just (x+n)))