58 lines
1.6 KiB
Haskell
58 lines
1.6 KiB
Haskell
import Control.Exception (assert)
|
|
|
|
main :: IO ()
|
|
main = do
|
|
instructions <- getContents
|
|
putStrLn (solution1 instructions)
|
|
putStrLn (solution2 instructions)
|
|
|
|
solution1 :: String -> String
|
|
solution1 input = show (uncurry (*) (navigate (parseInstructions input)))
|
|
|
|
solution2 :: String -> String
|
|
solution2 input = show (uncurry (*) (navigate2 (parseInstructions input)))
|
|
|
|
parseInstructions :: String -> [(Int, Int)]
|
|
parseInstructions instructions =
|
|
map parseLine (lines instructions)
|
|
where
|
|
parseLine line = case break (== ' ') line of
|
|
("forward", distance) -> (read distance, 0)
|
|
("down", distance) -> (0, read distance)
|
|
("up", distance) -> (0, (-read distance))
|
|
_ -> error "Invalid line"
|
|
|
|
navigate :: [(Int, Int)] -> (Int, Int)
|
|
navigate instructions =
|
|
foldl1 sumTuples instructions
|
|
where
|
|
sumTuples :: (Int, Int) -> (Int, Int) -> (Int, Int)
|
|
sumTuples (a, b) (c, d) = (a + c, b + d)
|
|
|
|
navigate2 :: [(Int, Int)] -> (Int, Int)
|
|
navigate2 instructions =
|
|
takePosition (foldl navigate (0, 0, 0) instructions)
|
|
where
|
|
navigate :: (Int, Int, Int) -> (Int, Int) -> (Int, Int, Int)
|
|
navigate (horz, depth, aim) (speed, dir) = (horz + speed, depth + aim * speed, aim + dir)
|
|
takePosition :: (Int, Int, Int) -> (Int, Int)
|
|
takePosition (x,y,_) = (x,y)
|
|
|
|
-- Tests
|
|
|
|
testInput1 :: String
|
|
testInput1 = unlines [
|
|
"forward 5",
|
|
"down 5",
|
|
"forward 8",
|
|
"up 3",
|
|
"down 8",
|
|
"forward 2"
|
|
]
|
|
|
|
test1 :: String
|
|
test1 = assert ((solution1 testInput1) == "150") "success"
|
|
|
|
test2 :: String
|
|
test2 = assert ((solution2 testInput1) == "900") "success"
|