2 import qualified Data.Text.IO as TIO
4 import Data.Attoparsec.Text
5 import Control.Applicative
7 type Course = [Command]
8 data Command = Forward Int
13 data Position = Position Int Int -- forward, depth
16 data AimedPosition = AimedPosition Int Int Int -- forward, depth, aim
21 do text <- TIO.readFile "data/advent02.txt"
22 let course = successfulParse text
26 part1 :: Course -> Int
27 part1 course = finalH * finalD
28 where (Position finalH finalD) = followCourse course
30 part2 :: Course -> Int
31 part2 course = finalH * finalD
32 where (AimedPosition finalH finalD _) = followAimedCourse course
34 followCourse :: Course -> Position
35 followCourse = foldl courseStep (Position 0 0)
37 courseStep :: Position -> Command -> Position
38 courseStep (Position h d) (Forward n) = Position (h + n) d
39 courseStep (Position h d) (Up n) = Position h (d - n)
40 courseStep (Position h d) (Down n) = Position h (d + n)
42 followAimedCourse :: Course -> AimedPosition
43 followAimedCourse = foldl courseAimedStep (AimedPosition 0 0 0)
45 courseAimedStep :: AimedPosition -> Command -> AimedPosition
46 courseAimedStep (AimedPosition h d a) (Forward n) = AimedPosition (h + n) (d + a * n) a
47 courseAimedStep (AimedPosition h d a) (Up n) = AimedPosition h d (a - n)
48 courseAimedStep (AimedPosition h d a) (Down n) = AimedPosition h d (a + n)
51 -- Parse the input file
53 courseP = commandP `sepBy` endOfLine
54 commandP = forwardP <|> upP <|> downP
56 forwardP = Forward <$> ("forward " *> decimal)
57 upP = Up <$> ("up " *> decimal)
58 downP = Down <$> ("down " *> decimal)
60 -- successfulParse :: Text -> (Integer, [Maybe Integer])
61 successfulParse input =
62 case parseOnly courseP input of
63 Left _err -> [] -- TIO.putStr $ T.pack $ parseErrorPretty err
64 Right course -> course