2023-12-08 15:58:49 +01:00
{- # LANGUAGE LambdaCase # -}
import Control.Arrow
import Data.Char
import Data.List.Split
import qualified Data.Map as M
type LR a = ( a , a ) -> a
2023-12-09 20:45:02 +01:00
type Tunnels = M . Map String ( String , String )
2023-12-08 15:58:49 +01:00
main :: IO ()
2023-12-09 20:45:02 +01:00
main = interact $ show . day08 . parse . lines
2023-12-08 15:58:49 +01:00
2023-12-09 20:45:02 +01:00
parse :: [ String ] -> ( [ LR String ] , Tunnels )
2023-12-08 15:58:49 +01:00
parse =
cycle .
map
( \ case
'L' -> fst
'R' -> snd
_ -> error " Malformed directions input " ) .
head &&&
M . fromList . map parseLine . tail . tail
parseLine :: String -> ( String , ( String , String ) )
parseLine s = ( a , ( b , c ) )
where
[ a , b , c ] = wordsBy ( not . isAlphaNum ) s
2023-12-09 20:45:02 +01:00
day08 :: ( [ LR String ] , Tunnels ) -> ( Int , Int )
day08 ( lrs , m ) = day08a lrs m *** day08b lrs m $ ( " AAA " , starts )
where
starts = filter ( ( == 'A' ) . last ) ( M . keys m )
day08a :: [ LR String ] -> Tunnels -> String -> Int
2023-12-08 15:58:49 +01:00
day08a _ _ [ _ , _ , 'Z' ] = 0
day08a ( lr : lrs ) m pos = 1 + day08a lrs m ( lr ( m M .! pos ) )
2023-12-09 20:45:02 +01:00
day08b :: [ LR String ] -> Tunnels -> [ String ] -> Int
2023-12-08 15:58:49 +01:00
day08b lrs m starts = foldr1 lcm $ map ( day08a lrs m ) starts