Day 9 - Part 2

This commit is contained in:
Jens Kadenbach
2022-12-09 18:53:29 +01:00
parent dc5a757eb6
commit 08306ed57d
2 changed files with 53 additions and 34 deletions

View File

@@ -2,7 +2,6 @@ module Day9
( parseMovements,
Move (..),
Grid (..),
startGrid,
up,
down,
left,
@@ -14,12 +13,13 @@ module Day9
normalizeMovement,
Step (..),
follow,
day9
buildTails,
day9,
)
where
import Control.Arrow ((>>>))
import Control.Monad.Trans.State.Strict (State, runState, modify)
import Control.Monad.Trans.State.Strict (State, modify, runState)
import qualified Data.Set as S
newtype Move = Move (Int, Int)
@@ -53,28 +53,31 @@ data Grid = Grid {h :: Pos, t :: Pos} deriving (Show, Eq)
data MovementLog = MovementLog {visited :: S.Set Pos, recordedSteps :: [Step]}
deriving (Show, Eq)
appendOne :: (Pos, Step) -> MovementLog -> MovementLog
appendOne (p, s) (MovementLog v steps) =
logOne :: (Pos, Step) -> MovementLog -> MovementLog
logOne (p, s) (MovementLog v steps) =
MovementLog (S.insert p v) (s : steps)
buildTails :: [Step] -> [([Pos], [Step])]
buildTails steps = iterate (snd >>> recordPositions) ([], steps)
recordPositions :: [Step] -> ([Pos], [Step])
recordPositions steps = (allPositions, allSteps)
where
-- insert last tail position
allPositions = S.toList $ S.insert lastTailPos (visited state)
allSteps = reverse (recordedSteps state)
((_, Grid { t = lastTailPos}), state) = runState (recordPositions' steps startGrid) (MovementLog S.empty [])
((_, Grid {t = lastTailPos}), state) =
runState (recordPositions' steps Grid {h = (0,0), t = (0,0)}) (MovementLog S.empty [])
recordPositions' :: [Step] -> Grid -> State MovementLog ([Step], Grid)
recordPositions' [] grid = return ([], grid)
recordPositions' (m : ms) Grid {h = headPos, t = tailPos} =
let newHead = headPos `step` m
followStep = follow newHead tailPos
newTail = tailPos `step` followStep
in modify (appendOne (newTail, followStep)) >> recordPositions' ms Grid {h = newHead, t = newTail}
startGrid :: Grid
startGrid = Grid {h = p, t = p}
where
p = (0, 0)
in modify (logOne (newTail, followStep))
>> recordPositions' ms Grid {h = newHead, t = newTail}
parseMovements :: String -> [Move]
parseMovements = lines >>> map toMove
@@ -93,19 +96,9 @@ normalizeMovement m = error $ "cannot normalize movement: " ++ show m
step :: Pos -> Step -> Pos
step (x, y) (Step (dx, dy)) = (x + dx, y + dy)
distance :: Pos -> Pos -> Int
distance (x, y) (x2, y2) = floor (dx ** 2 + dy ** 2)
where
dx :: Double
dx = fromIntegral $ x - x2
dy :: Double
dy = fromIntegral $ y - y2
follow :: Pos -> Pos -> Step
follow p1@(x1, y1) p2@(x2, y2)
| distance p1 p2 > 2 = Step (signum dx, signum dy)
| abs dx == 2 = Step (signum dx, 0)
| abs dy == 2 = Step (0, signum dy)
follow (x1, y1) (x2, y2)
| abs dx > 1 || abs dy > 1 = Step (signum dx, signum dy)
| otherwise = Step (0, 0)
where
dx = x1 - x2
@@ -115,6 +108,9 @@ day9 :: IO ()
day9 = do
input <- readFile "ressources/day09-input"
putStrLn "Day9"
let movements = parseMovements input
let positions = concatMap normalizeMovement >>> recordPositions >>> fst >>> length $ movements
let headSteps = parseMovements >>> concatMap normalizeMovement $ input
let allTails = buildTails headSteps
let positions = (!! 1) >>> fst >>> length $ allTails
putStrLn ("Number of distinct positions " ++ show positions)
let tail9 = (!! 9) >>> fst >>> length $ allTails
putStrLn ("Number of distinct positions of tail 9" ++ show tail9)

View File

@@ -29,6 +29,17 @@ expectedPositions = sort [
(0,0),(1,0),(2,0),(3,0)
]
testInput2 :: String
testInput2 = [str|R 5
|U 8
|L 8
|D 3
|R 17
|D 10
|L 25
|U 20
|]
spec :: Spec
spec =
describe "Day9" $ do
@@ -51,7 +62,7 @@ spec =
step (0, 1) (Step (0, -1)) `shouldBe` (0, 0)
it "normalizes movement" $ do
normalizeMovement still `shouldBe` []
normalizeMovement (left 1) `shouldBe` [Step (-1, 0)]
normalizeMovement (left 2) `shouldBe` [Step (-1, 0),Step (-1, 0)]
normalizeMovement (right 1) `shouldBe` [Step (1, 0)]
normalizeMovement (up 1) `shouldBe` [Step (0, 1)]
normalizeMovement (down 2) `shouldBe` [Step (0, -1), Step (0, -1)]
@@ -74,6 +85,18 @@ spec =
positions `shouldBe` expectedPositions
it "solves the riddle" $ do
input <- readFile "ressources/day09-input"
let movements = parseMovements input
let positions = concatMap normalizeMovement >>> recordPositions >>> fst >>> length $ movements
let headSteps = parseMovements >>> concatMap normalizeMovement $ input
let allTails = buildTails headSteps
let positions = (!! 1) >>> fst >>> length $ allTails
positions `shouldBe` 5878
it "solves example of part 2" $ do
let headSteps = parseMovements >>> concatMap normalizeMovement $ testInput2
let allTails = buildTails headSteps
let tail9Positions = fst $ allTails !! 9
length tail9Positions `shouldBe` 36
it "solves the riddle part 2" $ do
input <- readFile "ressources/day09-input"
let headSteps = parseMovements >>> concatMap normalizeMovement $ input
let allTails = buildTails headSteps
let positions = (!! 9) >>> fst >>> length $ allTails
positions `shouldBe` 2405