Jens Kadenbach преди 2 години
родител
ревизия
9bd3d62eec
променени са 6 файла, в които са добавени 2206 реда и са изтрити 10 реда
  1. 5
    0
      aoc2022.cabal
  2. 1
    0
      package.yaml
  3. 2000
    0
      ressources/day09-input
  4. 110
    0
      src/Day9.hs
  5. 11
    10
      src/Lib.hs
  6. 79
    0
      test/Day9Spec.hs

+ 5
- 0
aoc2022.cabal Целия файл

@@ -48,6 +48,7 @@ library
48 48
       Day7.Interpreter
49 49
       Day7.Parser
50 50
       Day8
51
+      Day9
51 52
       Lib
52 53
       Shared
53 54
   other-modules:
@@ -67,6 +68,7 @@ library
67 68
     , parsec
68 69
     , split
69 70
     , text
71
+    , transformers
70 72
     , vector
71 73
   default-language: Haskell2010
72 74
 
@@ -90,6 +92,7 @@ executable aoc2022-exe
90 92
     , parsec
91 93
     , split
92 94
     , text
95
+    , transformers
93 96
     , vector
94 97
   default-language: Haskell2010
95 98
 
@@ -105,6 +108,7 @@ test-suite aoc2022-test
105 108
       Day6Spec
106 109
       Day7Spec
107 110
       Day8Spec
111
+      Day9Spec
108 112
       Paths_aoc2022
109 113
   hs-source-dirs:
110 114
       test
@@ -122,5 +126,6 @@ test-suite aoc2022-test
122 126
     , parsec
123 127
     , split
124 128
     , text
129
+    , transformers
125 130
     , vector
126 131
   default-language: Haskell2010

+ 1
- 0
package.yaml Целия файл

@@ -33,6 +33,7 @@ dependencies:
33 33
 - matrix
34 34
 - vector
35 35
 - megaparsec
36
+- transformers
36 37
 
37 38
 ghc-options:
38 39
 - -Wall

+ 2000
- 0
ressources/day09-input
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 110
- 0
src/Day9.hs Целия файл

@@ -0,0 +1,110 @@
1
+module Day9
2
+  ( parseMovements,
3
+    Move (..),
4
+    Grid (..),
5
+    startGrid,
6
+    up,
7
+    down,
8
+    left,
9
+    right,
10
+    diag,
11
+    still,
12
+    step,
13
+    recordPositions,
14
+    normalizeMovement,
15
+    Step (..),
16
+    follow,
17
+    day9
18
+  )
19
+where
20
+
21
+import Control.Arrow ((>>>))
22
+import Data.List (nub)
23
+
24
+newtype Move = Move (Int, Int)
25
+  deriving (Show, Eq)
26
+
27
+newtype Step = Step (Int, Int)
28
+  deriving (Show, Eq)
29
+
30
+up :: Int -> Move
31
+up y = Move (0, y)
32
+
33
+down :: Int -> Move
34
+down y = Move (0, y * (-1))
35
+
36
+left :: Int -> Move
37
+left x = Move (x * (-1), 0)
38
+
39
+right :: Int -> Move
40
+right x = Move (x, 0)
41
+
42
+diag :: Int -> Move
43
+diag x = Move (x, x)
44
+
45
+still :: Move
46
+still = Move (0, 0)
47
+
48
+type Pos = (Int, Int)
49
+
50
+data Grid = Grid {h :: Pos, t :: Pos} deriving (Show, Eq)
51
+
52
+recordPositions :: [Step] -> [Pos]
53
+recordPositions steps = nub (lastTailPos:positions)
54
+  where
55
+    (positions, _, Grid { t = lastTailPos}) = recordPositions' [] steps startGrid
56
+    recordPositions' :: [Pos] -> [Step] -> Grid -> ([Pos], [Step], Grid)
57
+    recordPositions' pos [] grid = (pos, [], grid)
58
+    recordPositions' pos (m : ms) Grid {h = headPos, t = tailPos} =
59
+      let newHead = headPos `step` m
60
+          followStep = follow newHead tailPos
61
+          newTail = tailPos `step` followStep
62
+       in recordPositions' (tailPos : pos) ms Grid {h = newHead, t = newTail}
63
+
64
+startGrid :: Grid
65
+startGrid = Grid {h = p, t = p}
66
+  where
67
+    p = (0, 0)
68
+
69
+parseMovements :: String -> [Move]
70
+parseMovements = lines >>> map toMove
71
+  where
72
+    toMove ('U' : ' ' : xs) = up $ read xs
73
+    toMove ('D' : ' ' : xs) = down $ read xs
74
+    toMove ('L' : ' ' : xs) = left $ read xs
75
+    toMove ('R' : ' ' : xs) = right $ read xs
76
+    toMove _ = error "cannot parse movement"
77
+
78
+normalizeMovement :: Move -> [Step]
79
+normalizeMovement (Move (dx, 0)) = replicate (abs dx) (Step (signum dx, 0))
80
+normalizeMovement (Move (0, dy)) = replicate (abs dy) (Step (0, signum dy))
81
+normalizeMovement m = error $ "cannot normalize movement: " ++ show m
82
+
83
+step :: Pos -> Step -> Pos
84
+step (x, y) (Step (dx, dy)) = (x + dx, y + dy)
85
+
86
+distance :: Pos -> Pos -> Int
87
+distance (x, y) (x2, y2) = floor (dx ** 2 + dy ** 2)
88
+  where
89
+    dx :: Double
90
+    dx = fromIntegral $ x - x2
91
+    dy :: Double
92
+    dy = fromIntegral $ y - y2
93
+
94
+follow :: Pos -> Pos -> Step
95
+follow p1@(x1, y1) p2@(x2, y2)
96
+  | distance p1 p2 > 2 = Step (signum dx, signum dy)
97
+  | abs dx == 2 = Step (signum dx, 0)
98
+  | abs dy == 2 = Step (0, signum dy)
99
+  | otherwise = Step (0, 0)
100
+  where
101
+    dx = x1 - x2
102
+    dy = y1 - y2
103
+
104
+day9 :: IO ()
105
+day9 = do
106
+   input <- readFile "ressources/day09-input"
107
+   putStrLn "Day9"
108
+   let movements = parseMovements input
109
+   let positions = concatMap normalizeMovement >>> recordPositions >>> length $ movements
110
+   putStrLn ("Number of distinct positions " ++ show positions)

+ 11
- 10
src/Lib.hs Целия файл

@@ -2,21 +2,22 @@ module Lib
2 2
     ( someFunc
3 3
     ) where
4 4
 
5
-import Day1
6
-import Day2
7
-import Day3
8
-import Day4
9
-import Day5
10
-import Day6
11
-import Day7
12
-import Day8
5
+import Day1 (day1)
6
+import Day2 (day2)
7
+import Day3 (day3)
8
+import Day4 (day4)
9
+import Day5 (day5)
10
+import Day6 (day6)
11
+import Day7 (day7)
12
+import Day8 (day8)
13
+import Day9 (day9)
13 14
 
14 15
 days :: [IO ()]
15
-days = [day1, day2, day3, day4, day5, day6, day7, day8]
16
+days = [day1, day2, day3, day4, day5, day6, day7, day8, day9]
16 17
 
17 18
 sep :: IO ()
18 19
 sep = putStrLn "---------"
19 20
 
20 21
 someFunc :: IO ()
21 22
 someFunc = mapM_ (>> sep) days
22
-  
23
+

+ 79
- 0
test/Day9Spec.hs Целия файл

@@ -0,0 +1,79 @@
1
+{-# LANGUAGE QuasiQuotes #-}
2
+
3
+module Day9Spec (spec) where
4
+
5
+import Control.Arrow ((>>>))
6
+import Day9
7
+import Test.Hspec
8
+import Text.Heredoc
9
+import Data.List (sort)
10
+
11
+testInput :: String
12
+testInput =
13
+  [str|R 4
14
+                |U 4
15
+                |L 3
16
+                |D 1
17
+                |R 4
18
+                |D 1
19
+                |L 5
20
+                |R 2
21
+                |]
22
+
23
+expectedPositions :: [(Int, Int)]
24
+expectedPositions = sort [
25
+              (2,4),(3,4),
26
+                    (3,3),(4,3),
27
+        (1,2),(2,2),(3,2),(4,2),
28
+                          (4,1),
29
+  (0,0),(1,0),(2,0),(3,0)
30
+  ]
31
+
32
+spec :: Spec
33
+spec =
34
+  describe "Day9" $ do
35
+    describe "Part1" $ do
36
+      it "parses the instructions" $ do
37
+        parseMovements testInput
38
+          `shouldBe` [ right 4,
39
+                       up 4,
40
+                       left 3,
41
+                       down 1,
42
+                       right 4,
43
+                       down 1,
44
+                       left 5,
45
+                       right 2
46
+                     ]
47
+      it "moves a step" $ do
48
+        step (0, 0) (Step (1, 1)) `shouldBe` (1, 1)
49
+        step (0, 0) (Step (1, 0)) `shouldBe` (1, 0)
50
+        step (1, 0) (Step (-1, 0)) `shouldBe` (0, 0)
51
+        step (0, 1) (Step (0, -1)) `shouldBe` (0, 0)
52
+      it "normalizes movement" $ do
53
+        normalizeMovement still `shouldBe` []
54
+        normalizeMovement (left 1) `shouldBe` [Step (-1, 0)]
55
+        normalizeMovement (right 1) `shouldBe` [Step (1, 0)]
56
+        normalizeMovement (up 1) `shouldBe` [Step (0, 1)]
57
+        normalizeMovement (down 2) `shouldBe` [Step (0, -1), Step (0, -1)]
58
+      it "follows the head" $ do
59
+        follow (1, 0) (0, 0) `shouldBe` Step (0, 0)
60
+        follow (0, 1) (0, 0) `shouldBe` Step (0, 0)
61
+        follow (1, 1) (0, 0) `shouldBe` Step (0, 0)
62
+        follow (2, 1) (0, 0) `shouldBe` Step (1, 1)
63
+        follow (1, 2) (0, 0) `shouldBe` Step (1, 1)
64
+        follow (2, 2) (0, 0) `shouldBe` Step (1, 1)
65
+        follow (4, 2) (3, 0) `shouldBe` Step (1, 1)
66
+      it "moves around and records tail position" $ do
67
+        let positions = parseMovements
68
+                >>> concatMap normalizeMovement
69
+                >>> recordPositions
70
+                >>> sort
71
+                $ testInput
72
+        length positions `shouldBe` 13
73
+        positions `shouldBe` expectedPositions
74
+      it "solves the riddle" $ do
75
+        input <- readFile "ressources/day09-input"
76
+        putStrLn "Day9"
77
+        let movements = parseMovements input
78
+        let positions = concatMap normalizeMovement >>> recordPositions >>> length $ movements
79
+        positions `shouldBe` 5878

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