Jens Kadenbach преди 2 години
родител
ревизия
08306ed57d
променени са 2 файла, в които са добавени 53 реда и са изтрити 34 реда
  1. 27
    31
      src/Day9.hs
  2. 26
    3
      test/Day9Spec.hs

+ 27
- 31
src/Day9.hs Целия файл

@@ -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)

+ 26
- 3
test/Day9Spec.hs Целия файл

@@ -29,6 +29,17 @@ expectedPositions = sort [
29 29
   (0,0),(1,0),(2,0),(3,0)
30 30
   ]
31 31
 
32
+testInput2 :: String
33
+testInput2 = [str|R 5
34
+                 |U 8
35
+                 |L 8
36
+                 |D 3
37
+                 |R 17
38
+                 |D 10
39
+                 |L 25
40
+                 |U 20
41
+                 |]
42
+
32 43
 spec :: Spec
33 44
 spec =
34 45
   describe "Day9" $ do
@@ -51,7 +62,7 @@ spec =
51 62
         step (0, 1) (Step (0, -1)) `shouldBe` (0, 0)
52 63
       it "normalizes movement" $ do
53 64
         normalizeMovement still `shouldBe` []
54
-        normalizeMovement (left 1) `shouldBe` [Step (-1, 0)]
65
+        normalizeMovement (left 2) `shouldBe` [Step (-1, 0),Step (-1, 0)]
55 66
         normalizeMovement (right 1) `shouldBe` [Step (1, 0)]
56 67
         normalizeMovement (up 1) `shouldBe` [Step (0, 1)]
57 68
         normalizeMovement (down 2) `shouldBe` [Step (0, -1), Step (0, -1)]
@@ -74,6 +85,18 @@ spec =
74 85
         positions `shouldBe` expectedPositions
75 86
       it "solves the riddle" $ do
76 87
         input <- readFile "ressources/day09-input"
77
-        let movements = parseMovements input
78
-        let positions = concatMap normalizeMovement >>> recordPositions >>> fst >>> length $ movements
88
+        let headSteps = parseMovements >>> concatMap normalizeMovement $ input
89
+        let allTails = buildTails headSteps
90
+        let positions = (!! 1)  >>> fst >>> length $ allTails
79 91
         positions `shouldBe` 5878
92
+      it "solves example of part 2" $ do
93
+        let headSteps = parseMovements >>> concatMap normalizeMovement $ testInput2
94
+        let allTails = buildTails headSteps
95
+        let tail9Positions = fst $ allTails !! 9
96
+        length tail9Positions `shouldBe` 36
97
+      it "solves the riddle part 2" $ do
98
+        input <- readFile "ressources/day09-input"
99
+        let headSteps = parseMovements >>> concatMap normalizeMovement $ input
100
+        let allTails = buildTails headSteps
101
+        let positions = (!! 9)  >>> fst >>> length $ allTails
102
+        positions `shouldBe` 2405

Loading…
Отказ
Запис