2023 day 4 in Haskell
This commit is contained in:
parent
08228bdea9
commit
bd527054a2
|
@ -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
|
|
@ -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) " "
|
|
@ -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
|
Loading…
Reference in New Issue