|
@@ -2,7 +2,6 @@ module Day9
|
2
|
2
|
( parseMovements,
|
3
|
3
|
Move (..),
|
4
|
4
|
Grid (..),
|
5
|
|
- startGrid,
|
6
|
5
|
up,
|
7
|
6
|
down,
|
8
|
7
|
left,
|
|
@@ -14,12 +13,13 @@ module Day9
|
14
|
13
|
normalizeMovement,
|
15
|
14
|
Step (..),
|
16
|
15
|
follow,
|
17
|
|
- day9
|
|
16
|
+ buildTails,
|
|
17
|
+ day9,
|
18
|
18
|
)
|
19
|
19
|
where
|
20
|
20
|
|
21
|
21
|
import Control.Arrow ((>>>))
|
22
|
|
-import Control.Monad.Trans.State.Strict (State, runState, modify)
|
|
22
|
+import Control.Monad.Trans.State.Strict (State, modify, runState)
|
23
|
23
|
import qualified Data.Set as S
|
24
|
24
|
|
25
|
25
|
newtype Move = Move (Int, Int)
|
|
@@ -50,31 +50,34 @@ type Pos = (Int, Int)
|
50
|
50
|
|
51
|
51
|
data Grid = Grid {h :: Pos, t :: Pos} deriving (Show, Eq)
|
52
|
52
|
|
53
|
|
-data MovementLog = MovementLog { visited :: S.Set Pos, recordedSteps :: [Step] }
|
|
53
|
+data MovementLog = MovementLog {visited :: S.Set Pos, recordedSteps :: [Step]}
|
54
|
54
|
deriving (Show, Eq)
|
55
|
55
|
|
56
|
|
-appendOne :: (Pos, Step) -> MovementLog -> MovementLog
|
57
|
|
-appendOne (p, s) (MovementLog v steps) =
|
58
|
|
- MovementLog (S.insert p v) (s:steps)
|
|
56
|
+logOne :: (Pos, Step) -> MovementLog -> MovementLog
|
|
57
|
+logOne (p, s) (MovementLog v steps) =
|
|
58
|
+ MovementLog (S.insert p v) (s : steps)
|
|
59
|
+
|
|
60
|
+buildTails :: [Step] -> [([Pos], [Step])]
|
|
61
|
+buildTails steps = iterate (snd >>> recordPositions) ([], steps)
|
59
|
62
|
|
60
|
63
|
recordPositions :: [Step] -> ([Pos], [Step])
|
61
|
64
|
recordPositions steps = (allPositions, allSteps)
|
62
|
65
|
where
|
|
66
|
+ -- insert last tail position
|
63
|
67
|
allPositions = S.toList $ S.insert lastTailPos (visited state)
|
64
|
68
|
allSteps = reverse (recordedSteps state)
|
65
|
|
- ((_, Grid { t = lastTailPos}), state) = runState (recordPositions' steps startGrid) (MovementLog S.empty [])
|
|
69
|
+
|
|
70
|
+ ((_, Grid {t = lastTailPos}), state) =
|
|
71
|
+ runState (recordPositions' steps Grid {h = (0,0), t = (0,0)}) (MovementLog S.empty [])
|
|
72
|
+
|
66
|
73
|
recordPositions' :: [Step] -> Grid -> State MovementLog ([Step], Grid)
|
67
|
74
|
recordPositions' [] grid = return ([], grid)
|
68
|
75
|
recordPositions' (m : ms) Grid {h = headPos, t = tailPos} =
|
69
|
76
|
let newHead = headPos `step` m
|
70
|
77
|
followStep = follow newHead tailPos
|
71
|
78
|
newTail = tailPos `step` followStep
|
72
|
|
- in modify (appendOne (newTail, followStep)) >> recordPositions' ms Grid {h = newHead, t = newTail}
|
73
|
|
-
|
74
|
|
-startGrid :: Grid
|
75
|
|
-startGrid = Grid {h = p, t = p}
|
76
|
|
- where
|
77
|
|
- p = (0, 0)
|
|
79
|
+ in modify (logOne (newTail, followStep))
|
|
80
|
+ >> recordPositions' ms Grid {h = newHead, t = newTail}
|
78
|
81
|
|
79
|
82
|
parseMovements :: String -> [Move]
|
80
|
83
|
parseMovements = lines >>> map toMove
|
|
@@ -93,19 +96,9 @@ normalizeMovement m = error $ "cannot normalize movement: " ++ show m
|
93
|
96
|
step :: Pos -> Step -> Pos
|
94
|
97
|
step (x, y) (Step (dx, dy)) = (x + dx, y + dy)
|
95
|
98
|
|
96
|
|
-distance :: Pos -> Pos -> Int
|
97
|
|
-distance (x, y) (x2, y2) = floor (dx ** 2 + dy ** 2)
|
98
|
|
- where
|
99
|
|
- dx :: Double
|
100
|
|
- dx = fromIntegral $ x - x2
|
101
|
|
- dy :: Double
|
102
|
|
- dy = fromIntegral $ y - y2
|
103
|
|
-
|
104
|
99
|
follow :: Pos -> Pos -> Step
|
105
|
|
-follow p1@(x1, y1) p2@(x2, y2)
|
106
|
|
- | distance p1 p2 > 2 = Step (signum dx, signum dy)
|
107
|
|
- | abs dx == 2 = Step (signum dx, 0)
|
108
|
|
- | abs dy == 2 = Step (0, signum dy)
|
|
100
|
+follow (x1, y1) (x2, y2)
|
|
101
|
+ | abs dx > 1 || abs dy > 1 = Step (signum dx, signum dy)
|
109
|
102
|
| otherwise = Step (0, 0)
|
110
|
103
|
where
|
111
|
104
|
dx = x1 - x2
|
|
@@ -113,8 +106,11 @@ follow p1@(x1, y1) p2@(x2, y2)
|
113
|
106
|
|
114
|
107
|
day9 :: IO ()
|
115
|
108
|
day9 = do
|
116
|
|
- input <- readFile "ressources/day09-input"
|
117
|
|
- putStrLn "Day9"
|
118
|
|
- let movements = parseMovements input
|
119
|
|
- let positions = concatMap normalizeMovement >>> recordPositions >>> fst >>> length $ movements
|
120
|
|
- putStrLn ("Number of distinct positions " ++ show positions)
|
|
109
|
+ input <- readFile "ressources/day09-input"
|
|
110
|
+ putStrLn "Day9"
|
|
111
|
+ let headSteps = parseMovements >>> concatMap normalizeMovement $ input
|
|
112
|
+ let allTails = buildTails headSteps
|
|
113
|
+ let positions = (!! 1) >>> fst >>> length $ allTails
|
|
114
|
+ putStrLn ("Number of distinct positions " ++ show positions)
|
|
115
|
+ let tail9 = (!! 9) >>> fst >>> length $ allTails
|
|
116
|
+ putStrLn ("Number of distinct positions of tail 9" ++ show tail9)
|