Skip to content

Commit 6676c8f

Browse files
committed
day 23
1 parent d37d67f commit 6676c8f

File tree

1 file changed

+97
-88
lines changed

1 file changed

+97
-88
lines changed

2021/Day23/Solution.cs

Lines changed: 97 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -27,32 +27,16 @@ int Solve(string input) {
2727
q.Enqueue(maze, 0);
2828
cost.Add(maze, 0);
2929

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-
4230
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();
4832

49-
if (finished(maze)) {
33+
if (maze.Finished()) {
5034
return cost[maze];
5135
}
5236

5337
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;
5640
q.Enqueue(n.maze, cost[n.maze]);
5741
}
5842
}
@@ -63,10 +47,11 @@ bool colMatch(int icol, char c) {
6347

6448
Maze GetMaze(string input) {
6549
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] : '#');
7055
}
7156
}
7257
return maze;
@@ -76,15 +61,6 @@ int stepCost(char actor) {
7661
return actor == 'A' ? 1 : actor == 'B' ? 10 : actor == 'C' ? 100 : 1000;
7762
}
7863

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-
8864
int getIcolDst(char ch) {
8965
return
9066
ch == 'A' ? 3 :
@@ -94,19 +70,7 @@ int getIcolDst(char ch) {
9470
throw new Exception();
9571
}
9672

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) {
11074

11175
bool columnIsClean(int icol, char ch) {
11276
var pt = new Point(2, icol);
@@ -133,44 +97,38 @@ Point step(Point pt) {
13397
return true;
13498
}
13599

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));
144102

145-
var icolDst = getIcolDst(ch);
103+
if (ch == '.') {
104+
continue;
105+
}
146106

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);
150108

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);
155112

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++;
158116
}
117+
118+
var l = HallwayToRoom(maze.SetItem(new Point(1, icol), '.').SetItem(pt, ch));
119+
return (l.maze, l.cost + steps * stepCost(ch));
159120
}
160-
return (maze, 0);
161121
}
122+
return (maze, 0);
123+
}
162124

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) {
168126
var allowedHColumns = new int[] { 1, 2, 4, 6, 8, 10, 11 };
169127

170128
// fel lehet-e menni
171129
foreach (var icol in new[] { 3, 5, 7, 9 }) {
172130

173-
if (finishedColumn(maze, icol)) {
131+
if (maze.FinishedColumn(icol)) {
174132
continue;
175133
}
176134

@@ -192,10 +150,11 @@ Point step(Point pt) {
192150
while (maze.ItemAt(ptDst) == '.') {
193151

194152
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);
199158
}
200159

201160
if (dj == -1) {
@@ -209,6 +168,11 @@ Point step(Point pt) {
209168
}
210169
}
211170

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+
212176
}
213177

214178
record Point(int irow, int icol) {
@@ -217,7 +181,22 @@ record Point(int irow, int icol) {
217181
public Point Left => new Point(irow, icol - 1);
218182
public Point Right => new Point(irow, icol + 1);
219183
}
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+
}
221200

222201
int BitFromPoint(Point pt) =>
223202
(big, pt.irow, pt.icol) switch {
@@ -256,6 +235,37 @@ int BitFromPoint(Point pt) =>
256235
_ => 1 << 31,
257236
};
258237

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+
259269
public char ItemAt(Point pt) {
260270
var bit = BitFromPoint(pt);
261271
return
@@ -264,7 +274,6 @@ public char ItemAt(Point pt) {
264274
(b & bit) != 0 ? 'B' :
265275
(c & bit) != 0 ? 'C' :
266276
(d & bit) != 0 ? 'D' :
267-
(d & bit) != 0 ? 'D' :
268277
'.';
269278
}
270279

@@ -277,17 +286,17 @@ public Maze SetItem(Point pt, char ch) {
277286
}
278287

279288
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),
291300
_ => throw new Exception()
292301
};
293302
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy