1
0
Fork 0
advent-of-code/2020/12/Day12.hs
2022-09-21 09:19:53 -04:00

95 lines
2.4 KiB
Haskell

module Day12 ( Action
, Inst
, action
, value
, Program
, parseProgram
, State
, position
, heading
, start
, run
) where
import Data.Char
import Text.ParserCombinators.ReadP
data Action = N | S | E | W | L | R | F
deriving (Eq, Show)
data Inst = Inst { action :: Action, value :: Int }
deriving (Eq, Show)
inst :: ReadP Inst
inst = do
a <- action'
v <- int
return $ Inst a v
where
int :: ReadP Int
int = do
digits <- munch1 isDigit
return $ read digits
action' :: ReadP Action
action' = do
a <- choice $ map char "NSEWLRF"
return $ case a of
'N' -> N
'S' -> S
'E' -> E
'W' -> W
'L' -> L
'R' -> R
'F' -> F
type Program = [Inst]
program :: ReadP Program
program = inst `sepBy1` skipSpaces
parse p s = parsedResult $ readP_to_S p s
where
parsedResult [(a, _)] = a
parsedResult (a:as) = parsedResult as
parsedResult _ = error "Parser error"
parseProgram = parse program
data State = State { position :: (Int, Int)
, heading :: Action -- This isn't "correct"
} deriving (Eq, Show)
start = State (0, 0) E
updatePosition :: State -> ((Int -> Int), (Int -> Int)) -> State
updatePosition s (deltaX, deltaY) = State np (heading s)
where
(x, y) = position s
np = (deltaX x, deltaY y)
updateHeading :: State -> Action -> State
updateHeading s nh = State (position s) nh
travel :: State -> Inst -> State
travel s i = updatePosition s $ case i of
(Inst N d) -> (id, (+) d)
(Inst E d) -> ((+) d, id)
(Inst S d) -> (id, (-) d)
(Inst W d) -> ((-) d, id)
headings = cycle [N, E, S, W]
rotate h (Inst d v) = headings !! (v `div` 90)
where
headings = dropWhile (/= h) $ cycle $ case d of
R -> [N, E, S, W]
L -> [N, W, S, E]
tick :: State -> Inst -> State
tick s i@(Inst a v)
| a == N || a == S || a == E || a == W = travel s i
| a == L || a == R = updateHeading s $ rotate (heading s) i
| a == F = travel s (Inst (heading s) v)
run :: Program -> State
run = foldl tick start