-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay15.java
112 lines (99 loc) · 3.09 KB
/
Day15.java
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
// Look at Day15a for a prettier, but slower, solution without recursion.
// It uses bfs to identify the set of locations to be moved
import com.horstmann.adventofcode.*;
CharGrid grid;
CharGrid grid2;
String moves;
String widen(String s) {
return s.chars().mapToObj(c -> switch(c) {
case '@' -> "@.";
case 'O' -> "[]";
default -> "" + ((char) c) + ((char) c);
}).collect(Collectors.joining());
}
void parse(Path path) throws IOException {
grid = null;
moves = "";
var lines = Files.readAllLines(path);
for (int i = 0; i < lines.size(); i++) {
if (lines.get(i).strip().length() == 0) {
grid = CharGrid.parse(lines.subList(0, i));
grid2 = CharGrid.parse(lines.subList(0, i).stream().map(this::widen).toList());
}
else if (grid != null) moves += lines.get(i);
}
}
Location move(Location p, Direction d) {
Location n = p.moved(d);
if (!grid.isValid(n)) return p;
char c = grid.get(n);
if (c == 'O') move(n, d);
if (c == '.') {
grid.put(n, grid.get(p));
grid.put(p, '.');
return n;
} else {
return p;
}
}
Location move2(Location p, Direction d) {
if (canMove(p, d)) {
doMove(p, d);
return p.moved(d);
} else return p;
}
boolean canMove(Location p, Direction d) {
Location n = p.moved(d);
if (!grid2.isValid(n)) return false;
char c = grid2.get(n);
if (d == Direction.W || d == Direction.E) {
if (c == '[' || c == ']') return canMove(n, d);
else return grid2.get(n) == '.';
}
else {
if (c == '[') return canMove(n, d) && canMove(n.moved(Direction.E), d);
else if (c == ']') return canMove(n, d) && canMove(n.moved(Direction.W), d);
else return c == '.';
}
}
void doMove(Location p, Direction d) {
Location n = p.moved(d);
char c = grid2.get(n);
if (d == Direction.W || d == Direction.E) {
if (c == '[' || c == ']') doMove(n, d);
}
else {
if (c == '[') {
doMove(n, d); doMove(n.moved(Direction.E), d);
} else if (c == ']') {
doMove(n, d); doMove(n.moved(Direction.W), d);
}
}
grid2.put(n, grid2.get(p));
grid2.put(p, '.');
}
int gps(Location loc) { return 100 * loc.row() + loc.col(); }
Location robot; // Otherwise can't assign in forEach--don't code like that at home!
Object part1() {
robot = grid.findFirst('@');
moves.chars().forEach(c -> { robot = move(robot, Direction.ofSymbol(c)); });
return grid.findAll('O').mapToInt(this::gps).sum();
}
Object part2() {
robot = grid2.findFirst('@');
moves.chars().forEach(c -> { robot = move2(robot, Direction.ofSymbol(c)); });
return grid2.findAll('[').mapToInt(this::gps).sum();
}
void main() throws IOException {
Util.time(() -> {
parse(Util.inputPath("a"));
IO.println(part1());
IO.println(part2());
parse(Util.inputPath("b"));
IO.println(part1());
IO.println(part2());
parse(Util.inputPath("z"));
IO.println(part1());
IO.println(part2());
});
}