-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy path20.rs
More file actions
258 lines (240 loc) · 21.4 KB
/
20.rs
File metadata and controls
258 lines (240 loc) · 21.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
use std::time::Instant;
use std::collections::{HashMap, HashSet, VecDeque};
use itertools::Itertools;
const INPUT: [&str; 129] = [
" A U K C I L Q W ",
" V H F D F Z S E ",
" #############################################.#.#######.#####.###.#########.###.###########.####################################### ",
" #...#.#.........#.#.......#...#.#.....#.....#.#.....#.........#.......#...#.#.#.....#.#.#.....#...#...#.#.#...........#.....#.#.#.# ",
" ###.#.#####.#.###.#######.###.#.###.#####.#.#.#####.#######.###.#########.#.#.#.#####.#.###.###.#.###.#.#.###.#.#.###.#.#####.#.#.# ",
" #.#...#.#.#.#.#.........#.................#.....#.#.......#...#...#.......#...#...#.#.#.........#.............#.#.#.#.#...#.......# ",
" #.#.###.#.#.#######.###.#.###.###.#.###.#.#.#.###.###.#####.###.#########.###.#.###.#.#####.#######.###.###.#######.###.###.####### ",
" #...#.......#.......#.....#.....#.#.#.#.#.#.#.#.....#...#.....#...#.#.........#.....#...#.#.....#.#.#.#...#...#.....#.....#.......# ",
" ###.#######.###########.###.#.#######.#.#######.###.#.#######.#.###.###.#########.###.###.#.#####.###.#.###.#####.###.#.###.#.##### ",
" #...........#.#.#.........#.#...#...#...#.......#.....#.......#.#...#.#.....#.....#.......#.......#.#...#.............#.....#.....# ",
" #.#.#######.#.#.#.#.#####.#######.#####.#####.#.#########.#.#.#.#.#.#.#.#.#.###.#.#####.#.#.#######.###.#####.#####.#.############# ",
" #.#.#.#.#.........#.#.......#...#...........#.#.#...#.....#.#.#...#...#.#.#...#.#.#.....#.............#.....#.....#.#.#.#.......#.# ",
" #####.#.###.#####.#############.###.###.#######.#.#.###.#####.#######.#####.#.#.###.#.#.#.#.#####.#####.#.###.#####.#.#.#####.###.# ",
" #.........#.#.#...#...#.#.#...#.#.#.#.....#.......#...#.....#.#.........#.#.#.#...#.#.#.#.#.#.#...#.#...#.#.......#.#...#.....#...# ",
" #######.#####.#.#.###.#.#.#.#.#.#.#####.###.###.###.#.#.#######.#######.#.###.###.###.#######.###.#.#####.###.#.#######.#####.###.# ",
" #.#.......#...#.#.#.......#.#.#...........#.#.#...#.#.#...#.......#.#.#.#.#...#...#...#.........#.#...#.....#.#.#.#.#.#.#.#...#...# ",
" #.#.#.#.#####.#########.#####.#####.#.#.#####.#.#####.#.###.###.###.#.###.#.###.#####.#.###########.#####.#######.#.#.###.#.###.### ",
" #...#.#.#...#.....#.#.....#...#.#...#.#...#.....#.....#.#.....#.........#.....#.....#...#.............#.#.#.#.#.#...#.#.#.....#.#.# ",
" #######.###.#.#####.#.#.#.###.#.#####.###.###.#.#####.#.#######.#.#.#.#####.#.#.#.#.#.#.#.###.###.#.#.#.###.#.#.#.###.#.###.###.#.# ",
" #.#...................#.#.........#...#.#...#.#...#...#.....#...#.#.#...#...#.#.#.#.#.#.#.#.....#.#.#.......#.#...#.#.#...#.......# ",
" #.#.###.#####.#.#.###########.#.###.###.#.#####.#.###.#.#########.###.#######.#.#.###.###.###.###########.###.#.###.#.#.###.#.#.### ",
" #...#.#.#.....#.#.#...#.#.....#.#.#.#.#.......#.#.#.#.#.....#.#...#.....#...#.#.#.#.....#...#.#.#.#.#.#...#.#.....#.#.#...#.#.#.#.# ",
" #####.#.###.#.#####.#.#.#######.#.###.#.#.###.#####.#.#####.#.#######.###.###.#.#####.###.#####.#.#.#.#####.#.###.#.#.#.###.#####.# ",
" #.......#.#.#.#.#.#.#.#...#.............#.#...#.....#.#.........#.......#.....#.....#...........#.#.#.......#.#.#.......#.#.......# ",
" #########.#####.#.###.###.###.#.#.#####.#######.#####.#.#####.#######.#####.#.#.#######.#.###.###.#.#.#########.#######.#.###.##### ",
" #.....#...#...#...#...#.#...#.#.#.#.#.....#.........#.#...#.#.#...#.#.#.#...#.#.#.......#...#.............#...#.#.........#.#.....# ",
" #.#.#####.###.#.###.###.###.#.#.###.#####.###.#.###.#.###.#.#####.#.#.#.#####.#.#####.#.#.#.#.###.#.#########.#.###.#.#.###.#.##### ",
" #.#...#.....#.#.........#.....#.#...........#.#.#...#.#...........#...#.......#.#.....#.#.#.#.#.#.#.....#.#...#...#.#.#.......#.#.# ",
" ###.#####.#.#.#####.#.#.###.###.###.#.#.###.###.#.###.#.#####.#######.#.#####.#.#####.#.#####.#.#####.###.###.#.#####.###.#.###.#.# ",
" #.......#.#.#.#...#.#.#.#.....#.#...#.#.#...#...#.#...#.#...#.#.....#.#.....#.#.....#.#.#...#...#.#.#...#.#.........#.#.#.#.....#.# ",
" ###.#######.#.###.#####.###.#########.#.#######.#.#.###.#.#.###.###.#.#.###.###.#####.###.###.###.#.#####.#.#####.#####.#####.###.# ",
" #.#...#.#.....#.....#.....#.#.........#.....#...#.#...#...#.#...#.#.#.#.#.....#...#.........#.#.#.#...#...#.#.#.#.#.#.#...........# ",
" #.#.###.###.#.#####.###.#############.#.#.#####.#.###.###.#####.#.#.#.#######.#.#######.#.#####.#.#.#####.###.#.#.#.#.###.###.##### ",
" #...#.#.#...#...#.#.#.#.......#.....#.#.#.#.....#.#...#.......#.#.#.....#.#...#.#.......#.#...#.#...#.#.#...#.#.#...#.#.#.#.......# ",
" ###.#.#.#.#######.#.#.###.#######.#####.#####.#.#.#.#.#.#######.#########.#.#.#.#####.#####.###.#.###.#.#.###.#.#.###.#.###.#.##### ",
" #...#.....#.#.#...#...#.#.#.#.#...........#...#.#...#.#.......#...#.........#.#.....#.........#.......#.#...#...#...#...#.#.#.....# ",
" #.#.#####.#.#.###.#.###.#.#.#.#.#######.#######.#########.#.###.#######.###########.#######.#####.#.###.#.#####.#.#####.#.###.##### ",
" #.#...#...#.#.#.....#.......#.#...# E S Z J C A R X #.#...#...#.......#.#.#.#.#.....#.# ",
" ###.#####.#.#.###.#######.###.##### L Y M G D U D A #.#######.#####.###.#.#.#.#####.#.# ",
" #.#.#.#.....#.#...#...#.....#.#...# #.......#...#.....#.#...#...#......XA",
" #.#.#.###.###.###.#.#####.###.###.# #.###.#.#.#.#.###.#.#.#.#.#.#.#.#.# ",
" #.............#.....#.......#.....# WC..#...#.#.#.#...#.....#...#...#.#.# ",
" #.#.###.###.###.###.###.###.#.###.# ###.#.###.#####.#######.###.###.#.# ",
"RD..#...#.#.......#.....#...#...#.#.# #...#.#...#...#.#...#...#...#...#.# ",
" #.#########.###.###.#.###.#.#.#.#.# ###.###.#.#.#.#.#.#########.#####.# ",
" #...#.....#...#...#.#.....#.#.#...# #.......#...#.....#.....#.....#...# ",
" #.#####.#######.#.###.###.#.#.#.### #.#############.###.#############.# ",
" #.#...#.#.....#.#.#.#.#.#.#.#.#....UZ #.#.........#.#.#.#.#.#.#.....#.#.# ",
" #####.#.#.#######.#.###.#.#.#####.# ###.#######.#.#.#.#.#.#.#.#.###.### ",
" #.....#.....#...#.#.#...#.#...#...# TR..#.#...#.....#...#...#.#.#.#.#...# ",
" #.###.#.#######.#.#.###.###.####### #.#.#.#.#.#.#.###.#.###.###.#.###.# ",
"ZM....#.......#.#.#.#.#.....#.#.#...# #.#.#.#...#.#...#.#................EL",
" ###.###.#####.#.###.###.#.###.###.# #.#.#.#############.#########.#.#.# ",
" #...#.#...#.......#.....#.........# #...#...............#.......#.#.#.# ",
" ###.#.#.#####.###.#.###.#.#######.# #.#.#######################.####### ",
" #.#.#.#.......#.......#.#.....#....UH #.#.#.........#.....#.#...#...#.#..AU",
" #.###.############################# #######.###.#####.###.#.###.#.#.#.# ",
" #.......#.............#...........# TZ..........#.................#......ZZ",
" #.#####.#.#.#.#.###.#####.#.#.###.# ###################.#.#####.#.##### ",
" #.....#...#.#.#.#.#...#.#.#.#...#..WT ET..#.#.......#.#...#.#.....#.#.#...# ",
" #####.###.#.#######.###.#.#.#####.# #.#.#.###.###.#.###############.### ",
" #.....#...#...#.....#.....#...#...# #.#...#.........#.#.#.....#.#......TZ",
" #.#.#.#.#.#######.###.###.######### #.#.###.#.###.###.#.#.#.#.#.#.#.### ",
"TR..#.#.#.#...#.........#.....#.....# #.#.#...#...#.#.#.....#.#.#...#.#.# ",
" #############.###.###########.##### #.#.#.#########.#####.#.#####.###.# ",
" #...#...#...#.#...#...........#.#.# #...#.................#...........# ",
" #.#.#.#.###.###.#####.#.###.###.#.# #.################################# ",
"WT..#...#.....#...#.#...#.#...#.#...# #.#.......#...#...#...............# ",
" #.###.#.###.#####.###.###.###.###.# ###.###.###.#.###.#.#.#.#.#####.#.# ",
" #.#...#.#.....#...#...#.#.......#.# QS..#.#.#.....#.......#.#.#.#.....#.# ",
" #####.#.###.#####.#.#.#.#######.#.# #.#.#.#####.###.#.#.#########.###.# ",
" #...#.#.#...........#.#.#.#.#......WE #.#.......#.#.#.#.#.#.......#.#.#..JG",
" #.#######.###.#.#######.#.#.####### #.#######.###.#####.#####.#####.#.# ",
" #.....#...#...#.#.#.......#.......# #.............#.#.#.#.#...#...#...# ",
" #.#.#.#######.#.#.###.###.###.###.# ###.###########.#.###.###.###.##### ",
"UZ..#.#.#.#...#.#.#.#...#...#...#...# XR..#.#...........#.#.#.#...........# ",
" ###.###.#.#.#.###.###.#.###.#.###.# #.###.###.#####.#.#.#.###.#.###.### ",
" #.....#...#.#.#.....#.#...#.#.#.#..AQ #.#...#.....#.............#.#......WC",
" ###.###.#.#####.###.#.###.###.#.### #.###.###.#######.#.#.#.###.#.###.# ",
" #.#.....#.........#...#.........#.# #.#.#.#.#.#.......#.#.#...#.#.#.#.# ",
" #.#########.###.#####.###.###.###.# #.#.#.#.#######################.### ",
" #.......#.....#.....#...#.#.#...#..LS #.......#.#.......#.....#...#.#.#.# ",
" #.###.#################.#.#.#####.# #######.#.#.#######.#####.###.#.#.# ",
" #.#.......#.#...#.#.#...#.#.......# #.#.#.#.#...#.........#.........#.# ",
" #.#.#######.###.#.#.#######.###.#.# #.#.#.###.#.#.#######.#.#.#.###.#.# ",
"SY..#.....#.#.....#...#.#...#.#.#.#.# ER..........#.#.#.#.#.....#.#.#...#..XR",
" ###.#.###.#.###.###.#.#.#####.###.# #.#####.###.#.#.#.#.###.#######.#.# ",
" #...#.......#.....................# #.#.#...#...#.....#.#.#.#.#.....#.# ",
" #######.###.#######.#.#.###.#.#.#.# #.#.#######.###.#.###.#.#.#####.#.# ",
" #.........#.....#...#.#.#.#.#.#.#.# #.....#.#.......#.#...........#...# ",
" #.#####.#.#######.#.#.#.#.#####.#.# L E I K N A #.#####.###.#.###.#.#####.#######.# ",
" #...#.#.#...#.#...#.#.#.....#.#.#.# Z M F F T V #...#.......#...#.#...#.......#...# ",
" #####.#.###.#.###.#.#.#.#.#.#.#############.#########.#########.#######.#######.#####.#################.#.###.#.#####.#.###.#####.# ",
" #.......#.......#.#.#.#.#.#.....#...#...........#.#...#.#.......#.#.#.........#...#.......#...#.#.....#.#.#.#.#.....#.#.#.....#...# ",
" #.###.#.#.#.#####.###.###.#.#.#.###.#.#####.#.###.#.#.#.###.#####.#.#####.#.#####.#######.#.###.###.#######.#.#.#######.#####.#.#.# ",
" #.#...#.#.#.....#.#.....#.#.#.#...#...#.#...#.....#.#.#.....#.....#.......#.#.#.#.#.....#...#.....#.#.#.......#.#.#.........#.#.#.# ",
" #####.#.###.###.#.###.###.#.#.#########.#.#.#.###.#.#######.#.#.#.#.#.#.#.###.#.#.###.#.#.#####.###.#.#####.###.#.#####.#####.###.# ",
" #...#.#.#.....#.#.#.....#.#.#.#.#.....#...#.#.#...#...#...#.#.#.#.#.#.#.#.#.#.#...#...#.................#...#.........#.#.......#.# ",
" #.#.#.#.###.#####.#.#.#.###.#.#.#.#.#########.###.#.#####.#.#.#.#######.###.#.#.###.#####.#####.#.#.###.###.#.#####.#######.#.###.# ",
" #.#...#.#.....#...#.#.#...#.#...#.#.....#.....#...#.#.#.......#...#.#.#...#.......#.#.#.#...#.#.#.#.#.....#.#.....#...#.....#...#.# ",
" #.###.#.#.#.#.###.###.#######.#######.#.#.###.###.#.#.###########.#.#.#.###.#######.#.#.#####.###########.#####.###.#########.###.# ",
" #.#...#.#.#.#...#.#.....#.....#.#.....#.#...#.#...#.#.....#.......#.......#...#.................#...#.....#.......#.#.#.#.#.....#.# ",
" #####.###.#.###.#####.#.###.#.#.#######.#########.#.#.###.###.#####.#######.#.###.#.###.###.###.#.###########.#.#.###.#.#.#.#####.# ",
" #.....#.#.#.#.#.#.#...#.#.#.#.#.#.#.........#.#.#.#.#.#.#.#.......#.#.....#.#.#...#.#...#.....#.#...#...#.#...#.#.........#...#...# ",
" #.###.#.#####.#.#.#.#.#.#.#####.#.#####.###.#.#.#.#.#.#.#.#####.#.#.#.#.###.###.###.###.#########.#.#.###.###.###.#####.###.###.### ",
" #.#.......#.......#.#.#.#...#...........#.........#.....#.#.#.#.#.#.#.#.#.#...#...#.#...........#.#.#.......#.#.#.....#...#.#...#.# ",
" #####.#.#####.###.###.###.#####.#.#.#.#.#######.#########.#.#.###.#.#.#.#.#.#.###.#.#####.#####.#.#####.#.#####.#.#####.#.#####.#.# ",
" #.....#.#...#...#.#...#.....#...#.#.#.#...#.#.....#.............#.#...#...#.#.#.#.#.....#.....#.........#...#.........#.#.....#...# ",
" #.#.#.#.###.#####.#########.#####.#########.#####.#.###.#####.###.###.#.###.###.#########.###.#.#######.###.###.###.#.#.#.###.#.#.# ",
" #.#.#.#.#...............#.......#...#...#...#.#...#.#.#...#...#.....#.#...#.#.........#.....#.#.....#...#.....#...#.#.#.#.#.#.#.#.# ",
" #.#.###.#.#.###.#.###.#.#####.#######.#####.#.###.#.#.###.#######.#######.#.#####.#.###.#.#####.###.#######.#.#.#.#.#.#####.###.### ",
" #.#.#.#.#.#...#.#.#...#.#.........#.....#...#.....#.....#.#...#...#.#.#...#.#.#...#.#.#.#.....#...#.#...#...#.#.#.#.#.........#...# ",
" #.###.#.###.#.###.###.###.###.###.#####.###.#.#######.#######.#.###.#.###.#.#.###.###.###.#####.#######.###.###.###.###.#.#.###.#.# ",
" #.#.......#.#.#.....#...#.#.#.#...#.#...#.........#...#.#.#...#.....#.#...#...........#.......#.#.........#.#.#.#.....#.#.#.#...#.# ",
" #.###.###.#.###.#.#########.#####.#.#.#####.###.###.###.#.###.###.###.###.#.#####.#.#.#.###.###.###.#.###.###.#######.#.###.###.### ",
" #.#...#...#.#...#...#.#...#.................#.#.#.......#.......#...#.....#.#.#.#.#.#.#.#.#.#.......#.#.#...#.#...#...#.#...#.....# ",
" #.#.#.#.#.###.###.###.###.#######.###.#.#.#.#.#.#####.#####.###.#.#######.#.#.#.#.#####.#.#.###.#.#####.#####.#.#######.#.#####.### ",
" #.#.#.#.#.#.....#...#...#.#.......#...#.#.#...#.#.#...#.#...#.#...#...#...#.#.........#...#...#.#...#...#.#.....#...#...#...#.....# ",
" #####.#######.###.###.###.#.#.#######.#######.###.#.#.#.###.#######.#.#.#####.#.#.#######.#######.#####.#.###.#####.#############.# ",
" #.....#.......#.#.#.........#.#.#.....#...#.......#.#.#.#.#.#...#...#.#.....#.#.#.#.#...#.#.#.#...#...#.#.........#.....#.#...#.#.# ",
" ###.#######.#.#.#####.#########.###.#.###.###.###.#.###.#.#.#.#.#.#.#.###.#####.###.###.#.#.#.#######.#.#.#.#.#.###.#####.#.###.### ",
" #.....#...#.#.#...........#.........#.#.......#...#.#.....#...#.#.#.#...#.#.......#.#.#.....#.#...#.......#.#.#.#.#...............# ",
" #.#####.#######.#.###.#.#####.###.###.#####.###.###.#.#####.#######.###.#.#.#######.#.#.###.#.###.#.#############.#.#.###.#######.# ",
" #...#...........#...#.#...#...#.#.#.#.#.#.#.#.....#...#.#.#.....#.....#...#.....#.#.......#.....#...#...#...#...#...#...#...#.....# ",
" #.#.#.#####.#####.###.#.###.###.###.#.#.#.#####.#####.#.#.#.#########.#####.#.#.#.#.#.#.#####.###.###.###.###.#####.###.###.###.### ",
" #.#.#...#.....#...#...#.#.....#.......#.........#.......#.......#.........#.#.#...#.#.#.....#.......................#.....#.#.....# ",
" ###############################################.#######.#####.#########.#######.#.#.############################################### ",
" A L N E A E E ",
" Q S T R A M T ",
];
const W: usize = INPUT.len();
const H: usize = INPUT[0].len();
#[derive(Copy,Clone)]
enum EdgeType { Outer, Inner, Normal }
type Graph = HashMap<(usize,usize), Vec<(usize,usize,EdgeType)>>;
fn find_portals(map: &[Vec<char>]) -> Vec<(String,usize,usize)> {
let mut portals = Vec::new();
for i in 1..(W-1) {
for j in 1..(H-1) {
let from = map[i][j];
if !from.is_ascii_uppercase() { continue; }
let neighbours = [
(map[i-1][j], i-1, j),
(map[i+1][j], i+1, j),
(map[i][j-1], i, j-1),
(map[i][j+1], i, j+1),
];
if let Some(&(_,x,y)) = neighbours.iter().find(|(c,_,_)| *c == '.') {
let to = neighbours.iter().find(|(c,_,_)| c.is_ascii_uppercase()).unwrap().0;
let name = [from, to].iter().sorted().collect();
portals.push((name,x,y));
}
}
}
portals
}
fn connect_portals(g: &mut Graph, portals: &[(String, usize, usize)]) {
let (max_x,max_y) = (W-3,H-3);
for (p1,x,y) in portals {
let o = portals.iter().find(|(p2,x2,y2)| p1 == p2 && x != x2 && y != y2);
if let Some(&(_,i,j)) = o {
let t = if i == 2 || j == 2 {
EdgeType::Inner
} else if i == max_x || j == max_y {
EdgeType::Inner
} else {
EdgeType::Outer
};
g.get_mut(&(*x,*y)).unwrap().push((i,j,t));
}
}
}
fn create_graph(map: &[Vec<char>], portals: &[(String, usize, usize)]) -> Graph {
let mut g = (0..W).cartesian_product(0..H)
.filter(|&(i,j)| map[i][j] == '.')
.map(|(i,j)| {
let neighbours = [(i-1,j), (i+1,j), (i,j-1), (i,j+1)].iter()
.filter(|&&(x,y)| map[x][y] == '.')
.map(|&(x,y)| (x,y,EdgeType::Normal))
.collect();
((i,j), neighbours)
})
.collect();
connect_portals(&mut g, portals);
g
}
fn bfs_part_one(graph: &Graph, (x,y): (usize,usize), goal: (usize,usize)) -> usize {
let mut queue = VecDeque::new();
let mut visited = HashSet::new();
queue.push_back((x,y,0));
visited.insert((x,y));
loop {
let (ux,uy,len) = queue.pop_front().unwrap();
if (ux,uy) == goal { return len; }
visited.insert((ux,uy));
for &(x,y,_) in &graph[&(ux,uy)] {
if visited.contains(&(x,y)) { continue; }
queue.push_back((x,y,len+1))
}
}
}
fn bfs_part_two(graph: &Graph, (x,y): (usize,usize), goal: (usize,usize)) -> usize {
let mut visited = HashSet::new();
let mut queue = VecDeque::new();
queue.push_back((x,y,0,0));
visited.insert((x,y,0));
loop {
let (ux,uy,level,len) = queue.pop_front().unwrap();
if level == 0 && (ux,uy) == goal { return len; }
visited.insert((ux,uy,level));
for &(x,y,t) in &graph[&(ux,uy)] {
let level = level + match (t,level) {
(EdgeType::Outer,0) => continue,
(EdgeType::Outer,_) => -1,
(EdgeType::Inner,25) => continue,
(EdgeType::Inner,_) => 1,
(EdgeType::Normal,_) => 0,
};
if visited.contains(&(x,y,level)) { continue; }
queue.push_back((x,y,level,len+1));
};
}
}
fn main() {
let now = Instant::now();
let map = INPUT.iter().map(|s| s.chars().collect_vec()).collect_vec();
let portals = find_portals(&map);
let g = create_graph(&map, &portals);
let &(_,x1,y1) = portals.iter().find(|(p,_,_)| p == "AA").unwrap();
let &(_,x2,y2) = portals.iter().find(|(p,_,_)| p == "ZZ").unwrap();
let part_one = bfs_part_one(&g, (x1,y1), (x2,y2));
let part_two = bfs_part_two(&g, (x1,y1), (x2,y2));
println!("Part one: {}", part_one);
println!("Part two: {}", part_two);
println!("Time: {}ms", now.elapsed().as_millis());
}