module Day02 where import Data.Maybe (fromMaybe) import Text.Read (readMaybe) data Move = Horizontal Int | Depth Int deriving Show data Position = Position {hPos :: Int, depth :: Int, aim::Int} deriving Show initialPosition :: Position initialPosition = Position {hPos =0, depth = 0, aim = 0} updatePosition :: Position -> Move -> Position updatePosition p@(Position {hPos = h}) (Horizontal m) = p{hPos = h + m} updatePosition p@(Position {depth = d}) ( Depth m) = p{depth = d + m} updatePosition' :: Position -> Move -> Position updatePosition' p@(Position {hPos=h, depth=d, aim=a}) (Horizontal m) = p{hPos=h+m, depth =d+a*m} updatePosition' p@(Position {hPos=h, depth=d, aim=a}) (Depth m) = p{aim=a+m} readDataLines:: (String -> Maybe a) -> String -> Either String [a] readDataLines f s = case mapM f (lines s) of Just xs -> Right xs Nothing -> Left "Error parsing string" finalPosition :: [Move] -> Position finalPosition = foldl updatePosition initialPosition finalPosition' :: [Move] -> Position finalPosition' = foldl updatePosition' initialPosition calcResult:: Position -> Int calcResult Position {hPos = h, depth =d } = h*d day02Part1 :: String -> String day02Part1 s = case readDataLines readMove s of Right xs -> show . calcResult . finalPosition $ xs Left e -> e day02Part2 :: String -> String day02Part2 s = case readDataLines readMove s of Right xs -> show . calcResult . finalPosition' $ xs readDirection ::String -> Maybe (Int -> Move) readDirection "forward" = Just Horizontal readDirection "down" = Just Depth readDirection "up" = Just (Depth . negate) readDirection _ = Nothing readMove :: String -> Maybe Move readMove s = case words s of [dirStr, distStr] -> readDirection dirStr <*> readMaybe distStr _ -> Nothing