import Data.Complex import Data.List
Parsing is dead easy. Assuming line-based instructions, I just pass the first character as-is and convert the number to a
parseInstruction :: String -> (Char,Double) :n) = (i,read n)parseInstruction (i
Why a double? I’m going to use
Complex numbers, and in Haskell they only have a useful
Num instance if the underlying type implements
Double it is, even if the coordinates are only expected to take integer values.
type C = Complex Double
In part 1,
NESW mean to move the ship by the specified distance, whereas the
LRF series implement “turtle graphics”. So my step function maintains the ship’s position and direction.
go1 :: (C,C) -> (Char,Double) -> (C,C) = case i of go1 (pos,hdg) (i,n) 'N' -> (pos + (0 :+ n) ,hdg) 'S' -> (pos - (0 :+ n) ,hdg) 'W' -> (pos - (n :+ 0) ,hdg) 'E' -> (pos + (n :+ 0) ,hdg) 'F' -> (pos + (n :+ 0)*hdg,hdg) 'L' -> (pos ,hdg * (0 :+ 1 )^a) 'R' -> (pos ,hdg * (0 :+ (-1))^a) where a | round n `mod` 90 == 0 = round n `div` 90
In part 2, a “waypoint” is introduced. Its use looks more like like a speed vector than a navigational waypoint, but let’s play along. Here the only way to move is the
NESW adjust the vector by addition,
LR by rotation.
go2 :: (C,C) -> (Char,Double) -> (C,C) = case i of go2 (pos,wpt) (i,n) 'N' -> (pos ,wpt + (0 :+ n)) 'S' -> (pos ,wpt - (0 :+ n)) 'W' -> (pos ,wpt - (n :+ 0)) 'E' -> (pos ,wpt + (n :+ 0)) 'L' -> (pos ,wpt * (0 :+ 1 )^a) 'R' -> (pos ,wpt * (0 :+ (-1))^a) 'F' -> (pos + (n :+ 0)*wpt,wpt) where a | round n `mod` 90 == 0 = round n `div` 90
All that’s left is to fold the instructions, pairing the appropriate
go function with its starting vector.
main :: IO () = do main <- map parseInstruction . lines <$> readFile "day12.in" instrs let (destination1,_) = foldl' go1 (0 :+ 0, 1 :+ 0) instrs print $ round (dist destination1) let (destination2,_) = foldl' go2 (0 :+ 0,10 :+ 1) instrs print $ round (dist destination2)
And measuring the distance to the origin by Manhattan distance, because for some reason that’s what makes sense during a storm.
dist :: C -> Double :+ y) = abs x + abs ydist (x
This concludes today’s solution. See you soon!