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