2023 day 8 part 1 in Haskell
This commit is contained in:
parent
7293f37fe7
commit
e9ece2a757
|
@ -0,0 +1,19 @@
|
|||
cabal-version: 3.0
|
||||
name: Day08
|
||||
version: 0.1.0.0
|
||||
license: NONE
|
||||
build-type: Simple
|
||||
extra-doc-files: CHANGELOG.md
|
||||
|
||||
common warnings
|
||||
ghc-options: -Wall
|
||||
|
||||
executable Day08
|
||||
import: warnings
|
||||
main-is: Day08.hs
|
||||
build-depends: base ^>=4.17.2.1
|
||||
, attoparsec ^>=0.14.4
|
||||
, text ^>=2.1
|
||||
, containers ^>=0.6.7
|
||||
hs-source-dirs: .
|
||||
default-language: Haskell2010
|
|
@ -0,0 +1,62 @@
|
|||
{-# LANGUAGE OverloadedStrings #-}
|
||||
|
||||
module Main where
|
||||
|
||||
import Data.Attoparsec.Text as A
|
||||
import Data.List (isSuffixOf)
|
||||
import Data.Map (Map, fromList, keys, (!))
|
||||
import qualified Data.Text as T
|
||||
import qualified Data.Text.IO as TIO
|
||||
|
||||
type Address = [Char]
|
||||
|
||||
type Addresses = Map Address (Address, Address)
|
||||
|
||||
type Input = ([Char], Addresses)
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
input <- TIO.getContents >>= parseInput
|
||||
putStrLn ("Part 1: " <> show (part1 input))
|
||||
putStrLn ("Part 2: " <> show (part2 input))
|
||||
|
||||
part1 :: Input -> Int
|
||||
part1 (p, m) = solution p m "AAA"
|
||||
|
||||
part2 :: Input -> Int
|
||||
part2 (p, m) = foldl1 lcm $ map (solution p m) starts
|
||||
where
|
||||
starts = filter ("A" `isSuffixOf`) $ keys m
|
||||
|
||||
solution :: [Char] -> Addresses -> Address -> Int
|
||||
solution p m start = fst $ head $ filter (done . snd) $ zip [0 ..] $ scanl (step m) start $ cycle p
|
||||
|
||||
step :: Addresses -> Address -> Char -> Address
|
||||
step m src i = next
|
||||
where
|
||||
current = m ! src
|
||||
next = case i of
|
||||
'L' -> fst current
|
||||
'R' -> snd current
|
||||
_ -> error "The only expected instructions are 'L' and 'R'"
|
||||
|
||||
done :: Address -> Bool
|
||||
done = ("Z" `isSuffixOf`)
|
||||
|
||||
parseInput :: T.Text -> IO Input
|
||||
parseInput s = case parseOnly inputParser s of
|
||||
Right i -> pure i
|
||||
Left e -> error e
|
||||
|
||||
inputParser :: Parser Input
|
||||
inputParser = do
|
||||
instructions <- takeTill isEndOfLine <* endOfLine <* endOfLine
|
||||
tree <- many1 lineParser <* endOfInput
|
||||
return (T.unpack instructions, fromList tree)
|
||||
|
||||
lineParser :: Parser (Address, (Address, Address))
|
||||
lineParser = do
|
||||
src <- A.take 3 <* string " = ("
|
||||
l <- A.take 3 <* string ", "
|
||||
r <- A.take 3 <* string ")" <* endOfLine
|
||||
return (T.unpack src, (T.unpack l, T.unpack r))
|
|
@ -0,0 +1,9 @@
|
|||
RL
|
||||
|
||||
AAA = (BBB, CCC)
|
||||
BBB = (DDD, EEE)
|
||||
CCC = (ZZZ, GGG)
|
||||
DDD = (DDD, DDD)
|
||||
EEE = (EEE, EEE)
|
||||
GGG = (GGG, GGG)
|
||||
ZZZ = (ZZZ, ZZZ)
|
|
@ -0,0 +1,5 @@
|
|||
LLR
|
||||
|
||||
AAA = (BBB, BBB)
|
||||
BBB = (AAA, ZZZ)
|
||||
ZZZ = (ZZZ, ZZZ)
|
|
@ -0,0 +1,10 @@
|
|||
LR
|
||||
|
||||
11A = (11B, XXX)
|
||||
11B = (XXX, 11Z)
|
||||
11Z = (11B, XXX)
|
||||
22A = (22B, XXX)
|
||||
22B = (22C, 22C)
|
||||
22C = (22Z, 22Z)
|
||||
22Z = (22B, 22B)
|
||||
XXX = (XXX, XXX)
|
Loading…
Reference in New Issue