2023 day 4 in Haskell

This commit is contained in:
aru 2023-12-04 12:44:50 +01:00
parent 08228bdea9
commit bd527054a2
3 changed files with 92 additions and 0 deletions

19
2023/04/Day04.cabal Normal file
View File

@ -0,0 +1,19 @@
cabal-version: 3.0
name: Day04
version: 0.1.0.0
license: NONE
build-type: Simple
extra-doc-files: CHANGELOG.md
common warnings
ghc-options: -Wall
executable Day04
import: warnings
main-is: Main.hs
build-depends: base ^>=4.17.2.1
, attoparsec ^>=0.14.4
, text ^>=2.1
, containers ^>=0.6.7
hs-source-dirs: app
default-language: Haskell2010

67
2023/04/app/Main.hs Normal file
View File

@ -0,0 +1,67 @@
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Data.Char (isDigit)
import Data.Map (fromList, member, (!))
import qualified Data.Text as T
import qualified Data.Text.IO as TIO
import Data.Attoparsec.Text
type WinningNumbers = [Integer]
type MyNumbers = [Integer]
type Game = (Integer, WinningNumbers, MyNumbers)
type Input = [Game]
main :: IO ()
main = do
input <- parseInput <$> TIO.getContents
putStrLn ("Part 1: " <> show (part1 input))
putStrLn ("Part 2: " <> show (part2 input))
parseInput :: T.Text -> Input
parseInput s = case parseOnly inputParser s of
Right i -> i
Left e -> error e
part1 :: Input -> Int
part1 gs = sum $ map cardValue gs
cardValue :: Game -> Int
cardValue = value . winCount
where
value 0 = 0
value n = 2 ^ (n - 1)
part2 :: Input -> Int
part2 games = walkCards $ zip [0..] $ map winCount games
walkCards :: [(Int, Int)] -> Int
walkCards x = walkCards' (map fst x) 0
where
walkCards' [] acc = acc
walkCards' (id:xs) acc = walkCards' xs (acc + walkCards' (additional id) 1)
additional id = [next | n <- [1..(winCounts ! id)], let next = id + n, next <= lastId]
winCounts = fromList x
lastId = fst $ last x
winCount :: Game -> Int
winCount (_, ws, ms) = length $ filter (`elem` ws) ms
inputParser :: Parser Input
inputParser = sepBy1 gameParser endOfLine <* skipSpace <* endOfInput
gameParser :: Parser Game
gameParser = do
string "Card"
skipSpace
id <- decimal
string ": "
winning <- parseNumberList
string " | "
my <- parseNumberList
return (id, winning, my)
parseNumberList :: Parser [Integer]
parseNumberList = sepBy1 (skipSpace *> decimal) " "

6
2023/04/example Normal file
View File

@ -0,0 +1,6 @@
Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1
Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11