@@ -38,48 +38,55 @@ memoise2 :: (Ord a, Ord b) => Map (a, b) c -> (a -> b -> c) -> a -> b -> (Map (a
38
38
memoise2 mem f a b
39
39
| (a, b) `M.member` mem = (mem, mem M. ! (a, b))
40
40
| otherwise = (M. insert (a, b) res mem, res)
41
- where res = f a b
41
+ where
42
+ res = f a b
43
+
44
+ memoRec2 :: (Ord a , Ord b ) => Map (a , b ) c -> (Map (a , b ) c -> a -> b -> (Map (a , b ) c , c )) -> a -> b -> (Map (a , b ) c , c )
45
+ memoRec2 mem f a b
46
+ | (a, b) `M.member` mem = (mem, mem M. ! (a, b))
47
+ | otherwise = (M. insert (a, b) res mem', res)
48
+ where
49
+ (mem', res) = f mem a b
42
50
43
- memoise3 :: (Ord a , Ord b , Ord c ) => Map (a , b , c ) d -> (a -> b -> c -> d ) -> a -> b -> c -> (Map (a , b , c ) d , d )
51
+ memoise3 :: (Ord a , Ord b , Ord c ) => Map (a , b , c ) d -> (a -> b -> c -> d ) -> a -> b -> c -> (Map (a , b , c ) d , d )
44
52
memoise3 mem f a b c
45
53
| (a, b, c) `M.member` mem = (mem, mem M. ! (a, b, c))
46
54
| otherwise = (M. insert (a, b, c) res mem, res)
47
- where res = f a b c
48
-
49
-
55
+ where
56
+ res = f a b c
50
57
51
58
goToY :: [(Int , Int )] -> (Int , Int ) -> (Int , Int ) -> String
52
59
goToY possible (x, y) (x', y')
53
60
| x == x' && y == y' = []
54
- | y < y' && (x, y+ 1 ) `elem` possible = ' v' : goToY possible (x, y + 1 ) (x', y')
55
- | y > y' && (x, y- 1 ) `elem` possible = ' ^' : goToY possible (x, y - 1 ) (x', y')
56
- | x < x' && (x+ 1 , y) `elem` possible = ' >' : goToY possible (x + 1 , y) (x', y')
57
- | x > x' && (x- 1 , y) `elem` possible = ' <' : goToY possible (x - 1 , y) (x', y')
61
+ | y < y' && (x, y + 1 ) `elem` possible = ' v' : goToY possible (x, y + 1 ) (x', y')
62
+ | y > y' && (x, y - 1 ) `elem` possible = ' ^' : goToY possible (x, y - 1 ) (x', y')
63
+ | x < x' && (x + 1 , y) `elem` possible = ' >' : goToY possible (x + 1 , y) (x', y')
64
+ | x > x' && (x - 1 , y) `elem` possible = ' <' : goToY possible (x - 1 , y) (x', y')
58
65
59
66
goToX :: [(Int , Int )] -> (Int , Int ) -> (Int , Int ) -> String
60
67
goToX possible (x, y) (x', y')
61
68
| x == x' && y == y' = []
62
- | x < x' && (x+ 1 , y) `elem` possible = ' >' : goToX possible (x + 1 , y) (x', y')
63
- | x > x' && (x- 1 , y) `elem` possible = ' <' : goToX possible (x - 1 , y) (x', y')
64
- | y < y' && (x, y+ 1 ) `elem` possible = ' v' : goToX possible (x, y + 1 ) (x', y')
65
- | y > y' && (x, y- 1 ) `elem` possible = ' ^' : goToX possible (x, y - 1 ) (x', y')
69
+ | x < x' && (x + 1 , y) `elem` possible = ' >' : goToX possible (x + 1 , y) (x', y')
70
+ | x > x' && (x - 1 , y) `elem` possible = ' <' : goToX possible (x - 1 , y) (x', y')
71
+ | y < y' && (x, y + 1 ) `elem` possible = ' v' : goToX possible (x, y + 1 ) (x', y')
72
+ | y > y' && (x, y - 1 ) `elem` possible = ' ^' : goToX possible (x, y - 1 ) (x', y')
66
73
67
74
isValid :: [(Int , Int )] -> (Int , Int ) -> String -> Bool
68
75
isValid validSpots xy [] = xy `elem` validSpots
69
- isValid validSpots (x, y) (' v' : s) = (x, y) `elem` validSpots && isValid validSpots (x, y+ 1 ) s
70
- isValid validSpots (x, y) (' ^' : s) = (x, y) `elem` validSpots && isValid validSpots (x, y- 1 ) s
71
- isValid validSpots (x, y) (' >' : s) = (x, y) `elem` validSpots && isValid validSpots (x+ 1 , y) s
72
- isValid validSpots (x, y) (' <' : s) = (x, y) `elem` validSpots && isValid validSpots (x- 1 , y) s
76
+ isValid validSpots (x, y) (' v' : s) = (x, y) `elem` validSpots && isValid validSpots (x, y + 1 ) s
77
+ isValid validSpots (x, y) (' ^' : s) = (x, y) `elem` validSpots && isValid validSpots (x, y - 1 ) s
78
+ isValid validSpots (x, y) (' >' : s) = (x, y) `elem` validSpots && isValid validSpots (x + 1 , y) s
79
+ isValid validSpots (x, y) (' <' : s) = (x, y) `elem` validSpots && isValid validSpots (x - 1 , y) s
73
80
74
- generalEmulator :: Map (Int , Int ) Char -> (Int , Int ) -> String -> String
81
+ generalEmulator :: Map (Int , Int ) Char -> (Int , Int ) -> String -> String
75
82
generalEmulator poss posA code = sub code posA
76
83
where
77
84
sub [] _ = []
78
- sub (' A' : l) xy = poss M. ! xy : sub l xy
79
- sub (' v' : l) (x, y) = sub l (x, y+ 1 )
80
- sub (' ^' : l) (x, y) = sub l (x, y- 1 )
81
- sub (' >' : l) (x, y) = sub l (x+ 1 , y)
82
- sub (' <' : l) (x, y) = sub l (x- 1 , y)
85
+ sub (' A' : l) xy = poss M. ! xy : sub l xy
86
+ sub (' v' : l) (x, y) = sub l (x, y + 1 )
87
+ sub (' ^' : l) (x, y) = sub l (x, y - 1 )
88
+ sub (' >' : l) (x, y) = sub l (x + 1 , y)
89
+ sub (' <' : l) (x, y) = sub l (x - 1 , y)
83
90
84
91
numericalEmulator :: String -> String
85
92
numericalEmulator code = generalEmulator numMap (2 , 3 ) code
@@ -104,18 +111,18 @@ directionalEmulator code = generalEmulator dirMap (2, 0) code
104
111
where
105
112
dirMap = M. fromList $ [((1 , 0 ), ' ^' ), ((2 , 0 ), ' A' ), ((0 , 1 ), ' <' ), ((1 , 1 ), ' v' ), ((2 , 1 ), ' >' )]
106
113
107
-
108
- sequencerC :: [(Int , Int )] -> (Int , Int ) -> (Int , Int ) -> ((Int , Int ), Set String )
109
- sequencerC valid xy' xy = (xy', S. map (++ " A" ) goTos)
114
+ sequencerC :: [(Int , Int )] -> (Int , Int ) -> (Int , Int ) -> Set String
115
+ sequencerC valid xy' xy = S. map (++ " A" ) goTos
110
116
where
111
117
goTos = S. fromList $ shorten . map (\ gt -> gt valid xy xy') $ [goToX, goToY]
112
118
113
119
sequencer :: Map Char (Int , Int ) -> String -> (Int , Int ) -> Set String
114
120
sequencer poss [] _ = S. singleton []
115
121
sequencer poss (e : l) xy = sConcat $ S. map (\ r -> S. map (++ r) goTos) $ nextRes
116
122
where
123
+ xy' = (poss M. ! e)
117
124
nextRes = sequencer poss l xy'
118
- (xy', goTos) = sequencerC (M. elems poss) (poss M. ! e) xy
125
+ goTos = sequencerC (M. elems poss) xy' xy
119
126
120
127
numericalSequencer :: String -> Set String
121
128
numericalSequencer code = sequencer numMap code (numMap M. ! ' A' )
@@ -135,41 +142,38 @@ numericalSequencer code = sequencer numMap code (numMap M.! 'A')
135
142
(' A' , (2 , 3 ))
136
143
]
137
144
138
-
139
145
directionalSequencer :: String -> Set String
140
- directionalSequencer code = sequencer dirMap code (dirMap M. ! ' A' )
146
+ directionalSequencer code = sequencer dirMap code (dirMap M. ! ' A' )
141
147
where
142
148
dirMap = M. fromList $ [(' ^' , (1 , 0 )), (' A' , (2 , 0 )), (' <' , (0 , 1 )), (' v' , (1 , 1 )), (' >' , (2 , 1 ))]
143
149
144
-
145
150
depthMemorySequencer :: Map ((Int , Int ), ((Int , Int ), Int )) Int -> Int -> String -> (Map ((Int , Int ), ((Int , Int ), Int )) Int , Int )
146
151
depthMemorySequencer mem depth code = sub mem depth code
147
152
where
148
153
dirMap = M. fromList $ [(' ^' , (1 , 0 )), (' A' , (2 , 0 )), (' <' , (0 , 1 )), (' v' , (1 , 1 )), (' >' , (2 , 1 ))]
154
+ minLength = length . head . sortOn length
149
155
150
- subc' :: Map ((Int , Int ), ((Int , Int ), Int )) Int -> Int -> (Int , Int ) -> (Int , Int ) -> (Map ((Int , Int ), ((Int , Int ), Int )) Int , Int )
151
- subc' mem' 1 c xy = memoise2 mem' (\ c (xy, d) -> (length . head . sortOn length . S. toList) . snd $ sequencerC (M. elems dirMap) c xy) c (xy, 1 )
152
- subc' mem' d c xy
153
- | (c, (xy, d)) `M.member` mem' = (mem', mem' M. ! (c, (xy, d)))
154
- | otherwise = (M. insert (c, (xy, d)) r newMem, r)
156
+ subc' :: Map ((Int , Int ), ((Int , Int ), Int )) Int -> (Int , Int ) -> (Int , Int ) -> Int -> (Map ((Int , Int ), ((Int , Int ), Int )) Int , Int )
157
+ subc' mem' c xy 1 = memoise2 mem' f c (xy, 1 )
155
158
where
159
+ f c (xy, 1 ) = minLength . S. toList $ sequencerC (M. elems dirMap) c xy
160
+ subc' mem' c xy d = memoRec2 mem' f c (xy, d)
161
+ where
162
+ f m' c (xy, d) = S. foldl (\ (m, r) s -> second (min r) $ sub m (d - 1 ) s) (m', maxBound ) $ sequencerC (M. elems dirMap) c xy
156
163
157
- (newMem, r) = S. foldl (\ (m, r) s -> second (min r) $ sub m (d- 1 ) s) (mem', maxBound ) . snd $ sequencerC (M. elems dirMap) c xy
158
-
159
- sub :: Map ((Int , Int ), ((Int , Int ), Int )) Int -> Int -> String -> (Map ((Int , Int ), ((Int , Int ), Int )) Int , Int )
160
- sub mem' d s = second snd $ foldl (\ (m, (p, r)) e -> second (\ r' -> (dirMap M. ! e, r + r')) $ subc' m d (dirMap M. ! e) p) (mem', ((dirMap M. ! ' A' ), 0 )) s -- foldl
161
-
162
-
164
+ sub :: Map ((Int , Int ), ((Int , Int ), Int )) Int -> Int -> String -> (Map ((Int , Int ), ((Int , Int ), Int )) Int , Int )
165
+ sub mem' d s = second snd $ foldl f (mem', (dirMap M. ! ' A' , 0 )) s
166
+ where
167
+ f (m, (p, r)) e = second (\ r' -> (dirMap M. ! e, r + r')) $ subc' m (dirMap M. ! e) p d
163
168
164
169
getComplexity :: Int -> String -> Int
165
- getComplexity depth code = trace (show sequenceLength ++ " *" ++ show codeValue) codeValue * sequenceLength
170
+ getComplexity depth code = trace (show sequenceLength ++ " *" ++ show codeValue) codeValue * sequenceLength
166
171
where
167
172
codeValue = read $ takeWhile isDigit code
168
173
numSequences = numericalSequencer code
169
174
170
175
sequenceLength = snd $ foldl (\ (m, r) s -> second (min r) $ depthMemorySequencer m depth s) (M. empty, maxBound ) numSequences
171
176
172
-
173
177
part1 :: Input -> Output
174
178
part1 = sum . map (getComplexity 2 )
175
179
@@ -185,4 +189,4 @@ main = do
185
189
print input
186
190
187
191
print $ part1 input -- (== 248684) $
188
- print $ part2 input -- (== 307055584161760) $
192
+ print $ part2 input -- (== 307055584161760) $
0 commit comments