@@ -27,32 +27,16 @@ int Solve(string input) {
27
27
q . Enqueue ( maze , 0 ) ;
28
28
cost . Add ( maze , 0 ) ;
29
29
30
- bool finished ( Maze maze ) {
31
- bool colMatch ( int icol , char c ) {
32
- for ( var pt = new Point ( 2 , icol ) ; maze . ItemAt ( pt ) != '#' ; pt = pt . Below ) {
33
- if ( maze . ItemAt ( pt ) != c ) {
34
- return false ;
35
- }
36
- }
37
- return true ;
38
- }
39
- return colMatch ( 3 , 'A' ) && colMatch ( 5 , 'B' ) && colMatch ( 7 , 'C' ) && colMatch ( 9 , 'D' ) ;
40
- }
41
-
42
30
while ( q . Count > 0 ) {
43
- while ( cost [ q . UnorderedItems . First ( ) . Element ] != q . UnorderedItems . First ( ) . Priority ) {
44
- q . Dequeue ( ) ;
45
- }
46
-
47
- maze = q . Dequeue ( ) ; ;
31
+ maze = q . Dequeue ( ) ;
48
32
49
- if ( finished ( maze ) ) {
33
+ if ( maze . Finished ( ) ) {
50
34
return cost [ maze ] ;
51
35
}
52
36
53
37
foreach ( var n in Neighbours ( maze ) ) {
54
- if ( n . cost + cost [ maze ] < cost . GetValueOrDefault ( n . maze , int . MaxValue ) ) {
55
- cost [ n . maze ] = n . cost + cost [ maze ] ;
38
+ if ( cost [ maze ] + n . cost < cost . GetValueOrDefault ( n . maze , int . MaxValue ) ) {
39
+ cost [ n . maze ] = cost [ maze ] + n . cost ;
56
40
q . Enqueue ( n . maze , cost [ n . maze ] ) ;
57
41
}
58
42
}
@@ -63,10 +47,11 @@ bool colMatch(int icol, char c) {
63
47
64
48
Maze GetMaze ( string input ) {
65
49
var map = input . Split ( "\n " ) ;
66
- var maze = new Maze ( 0 , 0 , 0 , 0 , map . Length > 6 ) ;
67
- foreach ( var y in Enumerable . Range ( 0 , map . Length ) ) {
68
- foreach ( var x in Enumerable . Range ( 0 , map [ 0 ] . Length ) ) {
69
- maze = maze . SetItem ( new Point ( y , x ) , y < map . Length && x < map [ y ] . Length ? map [ y ] [ x ] : '#' ) ;
50
+ var maze = new Maze ( map . Length > 6 ) ;
51
+ foreach ( var irow in Enumerable . Range ( 0 , map . Length ) ) {
52
+ foreach ( var icol in Enumerable . Range ( 0 , map [ 0 ] . Length ) ) {
53
+ maze = maze . SetItem (
54
+ new Point ( irow , icol ) , irow < map . Length && icol < map [ irow ] . Length ? map [ irow ] [ icol ] : '#' ) ;
70
55
}
71
56
}
72
57
return maze ;
@@ -76,15 +61,6 @@ int stepCost(char actor) {
76
61
return actor == 'A' ? 1 : actor == 'B' ? 10 : actor == 'C' ? 100 : 1000 ;
77
62
}
78
63
79
- char getChDst ( int icol ) {
80
- return
81
- icol == 3 ? 'A' :
82
- icol == 5 ? 'B' :
83
- icol == 7 ? 'C' :
84
- icol == 9 ? 'D' :
85
- throw new Exception ( ) ;
86
- }
87
-
88
64
int getIcolDst ( char ch ) {
89
65
return
90
66
ch == 'A' ? 3 :
@@ -94,19 +70,7 @@ int getIcolDst(char ch) {
94
70
throw new Exception ( ) ;
95
71
}
96
72
97
- bool finishedColumn ( Maze maze , int icol ) {
98
- var pt = new Point ( 2 , icol ) ;
99
- var chDst = getChDst ( icol ) ;
100
- while ( maze . ItemAt ( pt ) != '#' ) {
101
- if ( maze . ItemAt ( pt ) != chDst ) {
102
- return false ;
103
- }
104
- pt = pt . Below ;
105
- }
106
- return true ;
107
- }
108
-
109
- IEnumerable < ( Maze maze , int cost ) > Neighbours ( Maze maze ) {
73
+ ( Maze maze , int cost ) HallwayToRoom ( Maze maze ) {
110
74
111
75
bool columnIsClean ( int icol , char ch ) {
112
76
var pt = new Point ( 2 , icol ) ;
@@ -133,44 +97,38 @@ Point step(Point pt) {
133
97
return true ;
134
98
}
135
99
136
- // le-e lehet menni?
137
- ( Maze maze , int cost ) Lemegy ( Maze maze ) {
138
- for ( var icol = 1 ; icol < 12 ; icol ++ ) {
139
- var ch = maze . ItemAt ( new Point ( 1 , icol ) ) ;
140
-
141
- if ( ch == '.' ) {
142
- continue ;
143
- }
100
+ for ( var icol = 1 ; icol < 12 ; icol ++ ) {
101
+ var ch = maze . ItemAt ( new Point ( 1 , icol ) ) ;
144
102
145
- var icolDst = getIcolDst ( ch ) ;
103
+ if ( ch == '.' ) {
104
+ continue ;
105
+ }
146
106
147
- if ( rowIsClean ( icol , icolDst ) && columnIsClean ( icolDst , ch ) ) {
148
- var steps = Math . Abs ( icolDst - icol ) ;
149
- var pt = new Point ( 1 , icolDst ) ;
107
+ var icolDst = getIcolDst ( ch ) ;
150
108
151
- while ( maze . ItemAt ( pt . Below ) == '.' ) {
152
- pt = pt . Below ;
153
- steps ++ ;
154
- }
109
+ if ( rowIsClean ( icol , icolDst ) && columnIsClean ( icolDst , ch ) ) {
110
+ var steps = Math . Abs ( icolDst - icol ) ;
111
+ var pt = new Point ( 1 , icolDst ) ;
155
112
156
- var l = Lemegy ( maze . SetItem ( new Point ( 1 , icol ) , '.' ) . SetItem ( pt , ch ) ) ;
157
- return ( l . maze , l . cost + steps * stepCost ( ch ) ) ;
113
+ while ( maze . ItemAt ( pt . Below ) == '.' ) {
114
+ pt = pt . Below ;
115
+ steps ++ ;
158
116
}
117
+
118
+ var l = HallwayToRoom ( maze . SetItem ( new Point ( 1 , icol ) , '.' ) . SetItem ( pt , ch ) ) ;
119
+ return ( l . maze , l . cost + steps * stepCost ( ch ) ) ;
159
120
}
160
- return ( maze , 0 ) ;
161
121
}
122
+ return ( maze , 0 ) ;
123
+ }
162
124
163
- var lemegy = Lemegy ( maze ) ;
164
- if ( lemegy . cost != 0 ) {
165
- yield return lemegy ;
166
- yield break ;
167
- }
125
+ IEnumerable < ( Maze maze , int cost ) > RoomToHallway ( Maze maze ) {
168
126
var allowedHColumns = new int [ ] { 1 , 2 , 4 , 6 , 8 , 10 , 11 } ;
169
127
170
128
// fel lehet-e menni
171
129
foreach ( var icol in new [ ] { 3 , 5 , 7 , 9 } ) {
172
130
173
- if ( finishedColumn ( maze , icol ) ) {
131
+ if ( maze . FinishedColumn ( icol ) ) {
174
132
continue ;
175
133
}
176
134
@@ -192,10 +150,11 @@ Point step(Point pt) {
192
150
while ( maze . ItemAt ( ptDst ) == '.' ) {
193
151
194
152
if ( allowedHColumns . Contains ( ptDst . icol ) ) {
195
- yield return (
196
- maze . SetItem ( ptSrc , '.' ) . SetItem ( ptDst , ch ) ,
197
- ( stepsV + stepsH ) * stepCost ( ch )
198
- ) ;
153
+ var mazeT = maze . SetItem ( ptSrc , '.' ) . SetItem ( ptDst , ch ) ;
154
+ var c = ( stepsV + stepsH ) * stepCost ( ch ) ;
155
+ // (mazeT, c) = (Lemegy(mazeT).maze, c + Lemegy(mazeT).cost);
156
+
157
+ yield return ( mazeT , c ) ;
199
158
}
200
159
201
160
if ( dj == - 1 ) {
@@ -209,6 +168,11 @@ Point step(Point pt) {
209
168
}
210
169
}
211
170
171
+ IEnumerable < ( Maze maze , int cost ) > Neighbours ( Maze maze ) {
172
+ var hallwayToRoom = HallwayToRoom ( maze ) ;
173
+ return hallwayToRoom . cost != 0 ? new [ ] { hallwayToRoom } : RoomToHallway ( maze ) ;
174
+ }
175
+
212
176
}
213
177
214
178
record Point ( int irow , int icol ) {
@@ -217,7 +181,22 @@ record Point(int irow, int icol) {
217
181
public Point Left => new Point ( irow , icol - 1 ) ;
218
182
public Point Right => new Point ( irow , icol + 1 ) ;
219
183
}
220
- record Maze ( int a , int b , int c , int d , bool big ) {
184
+
185
+ record Maze {
186
+
187
+ bool big ;
188
+ int a , b , c , d ;
189
+
190
+ public Maze ( bool big ) : this ( 0 , 0 , 0 , 0 , big ) {
191
+ }
192
+
193
+ private Maze ( int a , int b , int c , int d , bool big ) {
194
+ this . a = a ;
195
+ this . b = b ;
196
+ this . c = c ;
197
+ this . d = d ;
198
+ this . big = big ;
199
+ }
221
200
222
201
int BitFromPoint ( Point pt ) =>
223
202
( big , pt . irow , pt . icol ) switch {
@@ -256,6 +235,37 @@ int BitFromPoint(Point pt) =>
256
235
_ => 1 << 31 ,
257
236
} ;
258
237
238
+ private int ColumnMask ( char ch ) {
239
+ if ( big ) {
240
+ switch ( ch ) {
241
+ case 'A' : return ( 1 << 11 ) | ( 1 << 15 ) | ( 1 << 19 ) | ( 1 << 23 ) ;
242
+ case 'B' : return ( 1 << 12 ) | ( 1 << 16 ) | ( 1 << 20 ) | ( 1 << 24 ) ;
243
+ case 'C' : return ( 1 << 13 ) | ( 1 << 17 ) | ( 1 << 21 ) | ( 1 << 25 ) ;
244
+ case 'D' : return ( 1 << 14 ) | ( 1 << 18 ) | ( 1 << 22 ) | ( 1 << 26 ) ;
245
+ }
246
+ } else {
247
+ switch ( ch ) {
248
+ case 'A' : return ( 1 << 11 ) | ( 1 << 15 ) ;
249
+ case 'B' : return ( 1 << 12 ) | ( 1 << 16 ) ;
250
+ case 'C' : return ( 1 << 13 ) | ( 1 << 17 ) ;
251
+ case 'D' : return ( 1 << 14 ) | ( 1 << 18 ) ;
252
+ }
253
+ }
254
+ throw new Exception ( ) ;
255
+ }
256
+
257
+ public bool FinishedColumn ( int icol ) =>
258
+ icol switch {
259
+ 3 => ( a & ColumnMask ( 'A' ) ) == ColumnMask ( 'A' ) ,
260
+ 5 => ( b & ColumnMask ( 'B' ) ) == ColumnMask ( 'B' ) ,
261
+ 7 => ( c & ColumnMask ( 'C' ) ) == ColumnMask ( 'C' ) ,
262
+ 9 => ( d & ColumnMask ( 'D' ) ) == ColumnMask ( 'D' ) ,
263
+ _ => throw new Exception ( )
264
+ } ;
265
+
266
+ public bool Finished ( ) =>
267
+ FinishedColumn ( 3 ) && FinishedColumn ( 5 ) && FinishedColumn ( 7 ) && FinishedColumn ( 9 ) ;
268
+
259
269
public char ItemAt ( Point pt ) {
260
270
var bit = BitFromPoint ( pt ) ;
261
271
return
@@ -264,7 +274,6 @@ public char ItemAt(Point pt) {
264
274
( b & bit ) != 0 ? 'B' :
265
275
( c & bit ) != 0 ? 'C' :
266
276
( d & bit ) != 0 ? 'D' :
267
- ( d & bit ) != 0 ? 'D' :
268
277
'.' ;
269
278
}
270
279
@@ -277,17 +286,17 @@ public Maze SetItem(Point pt, char ch) {
277
286
}
278
287
279
288
return ch switch {
280
- '.' =>
281
- this with {
282
- a = a & ~ bit ,
283
- b = b & ~ bit ,
284
- c = c & ~ bit ,
285
- d = d & ~ bit
286
- } ,
287
- 'A' => this with { a = a | bit } ,
288
- 'B' => this with { b = b | bit } ,
289
- 'C' => this with { c = c | bit } ,
290
- 'D' => this with { d = d | bit } ,
289
+ '.' => new Maze (
290
+ a & ~ bit ,
291
+ b & ~ bit ,
292
+ c & ~ bit ,
293
+ d & ~ bit ,
294
+ big
295
+ ) ,
296
+ 'A' => new Maze ( a | bit , b , c , d , big ) ,
297
+ 'B' => new Maze ( a , b | bit , c , d , big ) ,
298
+ 'C' => new Maze ( a , b , c | bit , d , big ) ,
299
+ 'D' => new Maze ( a , b , c , d | bit , big ) ,
291
300
_ => throw new Exception ( )
292
301
} ;
293
302
}
0 commit comments