Advertisement
bss03

Advent of Code 2020 Day 12

Dec 12th, 2020
1,408
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. {-# language RecordWildCards #-}
  2.  
  3. import Control.Arrow ((&&&))
  4. import Data.List (foldl')
  5. import Data.Maybe (listToMaybe)
  6.  
  7. data Action = North | South | East | West | TurnLeft | TurnRight | Forward deriving (Eq, Show)
  8.  
  9. data Instruction = MkInstruction { action :: Action, value :: Int } deriving (Eq, Show)
  10.  
  11. parseLine :: String -> Maybe Instruction
  12. parseLine [] = Nothing
  13. parseLine (d:n) = MkInstruction <$> charAction d <*> fmap fst (listToMaybe $ reads n)
  14.  
  15. charAction :: Char -> Maybe Action
  16. charAction 'N' = pure North
  17. charAction 'S' = pure South
  18. charAction 'E' = pure East
  19. charAction 'W' = pure West
  20. charAction 'L' = pure TurnLeft
  21. charAction 'R' = pure TurnRight
  22. charAction 'F' = pure Forward
  23. charAction _ = Nothing
  24.  
  25. data Ship =
  26.  MkShip
  27.  { xPos :: Int
  28.  , yPos :: Int
  29.  , xDir :: Int
  30.  , yDir :: Int
  31.  } deriving (Eq, Show)
  32.  
  33. initShip :: Ship
  34. initShip = MkShip{ xPos = 0, yPos = 0, xDir = 1, yDir = 0 }
  35.  
  36. applyShipInstruction :: Instruction -> Ship -> Ship
  37. applyShipInstruction MkInstruction{ action = North, value = delta } s = s{ yPos = yPos s + delta }
  38. applyShipInstruction MkInstruction{ action = South, value = delta } s = s{ yPos = yPos s - delta }
  39. applyShipInstruction MkInstruction{ action = East, value = delta } s = s{ xPos = xPos s + delta }
  40. applyShipInstruction MkInstruction{ action = West, value = delta } s = s{ xPos = xPos s - delta }
  41. applyShipInstruction MkInstruction{ action = TurnLeft, value = degrees } s =
  42.  foldr ($) s $ replicate (degrees `quot` 90) oneLeft
  43. where oneLeft ss = ss{ xDir = negate $ yDir ss, yDir = xDir ss }
  44. applyShipInstruction MkInstruction{ action = TurnRight, value = degrees } s =
  45.  foldr ($) s $ replicate (degrees `quot` 90) oneRight
  46. where oneRight ss = ss{ xDir = yDir ss, yDir = negate $ xDir ss }
  47. applyShipInstruction MkInstruction{ action = Forward, value = scale } s =
  48.  s{ xPos = xPos s + scale * xDir s, yPos = yPos s + scale * yDir s }
  49.  
  50. shipManhattan :: Ship -> Int
  51. shipManhattan MkShip{..} = abs xPos + abs yPos
  52.  
  53. part1 :: [Instruction] -> Int
  54. part1 = shipManhattan . foldl' (flip applyShipInstruction) initShip
  55.  
  56. initWaypoint :: Waypoint
  57. initWaypoint = MkWaypoint { xWay = 10, yWay = 1 }
  58.  
  59. data Waypoint = MkWaypoint { xWay :: Int, yWay :: Int } deriving (Eq, Show)
  60.  
  61. applyWaypointedInstruction :: Instruction -> (Ship, Waypoint) -> (Ship, Waypoint)
  62. applyWaypointedInstruction MkInstruction{ action = North, value = delta } (s, w) =
  63.   (s, w{ yWay = yWay w + delta })
  64. applyWaypointedInstruction MkInstruction{ action = South, value = delta } (s, w) =
  65.   (s, w{ yWay = yWay w - delta })
  66. applyWaypointedInstruction MkInstruction{ action = East, value = delta } (s, w) =
  67.   (s, w{ xWay = xWay w + delta })
  68. applyWaypointedInstruction MkInstruction{ action = West, value = delta } (s, w) =
  69.   (s, w{ xWay = xWay w - delta })
  70. applyWaypointedInstruction MkInstruction{ action = TurnLeft, value = degrees } (s, w) =
  71.   (s, foldr ($) w $ replicate (degrees `quot` 90) oneLeft)
  72.  where oneLeft ww = ww{ xWay = negate $ yWay ww, yWay = xWay ww }
  73. applyWaypointedInstruction MkInstruction{ action = TurnRight, value = degrees } (s, w) =
  74.   (s, foldr ($) w $ replicate (degrees `quot` 90) oneRight)
  75.  where oneRight ww = ww{ xWay = yWay ww, yWay = negate $ xWay ww }
  76. applyWaypointedInstruction MkInstruction{ action = Forward, value = scale } (s, w) =
  77.   (s{ xPos = xPos s + scale * xWay w, yPos = yPos s + scale * yWay w}, w)
  78.  
  79. part2 :: [Instruction] -> Int
  80. part2 = shipManhattan . fst . foldl' (flip applyWaypointedInstruction) (initShip, initWaypoint)
  81.  
  82. interactive :: Show a => (String -> a) -> IO ()
  83. interactive f = getContents >>= print . f
  84.  
  85. main :: IO ()
  86. main = interactive (fmap (part1 &&& part2) . traverse parseLine . lines)
  87.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement