58 lines
1.7 KiB
Haskell
58 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 - 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)))
|