Skip to content

Commit e3186a6

Browse files
committed
AoC 2024 Day 15 - java
1 parent 401731c commit e3186a6

File tree

3 files changed

+231
-1
lines changed

3 files changed

+231
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
| | 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 |
1010
| ---| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
1111
| python3 | [](src/main/python/AoC2024_01.py) | [](src/main/python/AoC2024_02.py) | [](src/main/python/AoC2024_03.py) | [](src/main/python/AoC2024_04.py) | [](src/main/python/AoC2024_05.py) | [](src/main/python/AoC2024_06.py) | [](src/main/python/AoC2024_07.py) | [](src/main/python/AoC2024_08.py) | [](src/main/python/AoC2024_09.py) | [](src/main/python/AoC2024_10.py) | [](src/main/python/AoC2024_11.py) | [](src/main/python/AoC2024_12.py) | [](src/main/python/AoC2024_13.py) | [](src/main/python/AoC2024_14.py) | [](src/main/python/AoC2024_15.py) | | | | | | | | | | |
12-
| java | [](src/main/java/AoC2024_01.java) | [](src/main/java/AoC2024_02.java) | [](src/main/java/AoC2024_03.java) | [](src/main/java/AoC2024_04.java) | [](src/main/java/AoC2024_05.java) | [](src/main/java/AoC2024_06.java) | [](src/main/java/AoC2024_07.java) | [](src/main/java/AoC2024_08.java) | | [](src/main/java/AoC2024_10.java) | [](src/main/java/AoC2024_11.java) | [](src/main/java/AoC2024_12.java) | | [](src/main/java/AoC2024_14.java) | | | | | | | | | | | |
12+
| java | [](src/main/java/AoC2024_01.java) | [](src/main/java/AoC2024_02.java) | [](src/main/java/AoC2024_03.java) | [](src/main/java/AoC2024_04.java) | [](src/main/java/AoC2024_05.java) | [](src/main/java/AoC2024_06.java) | [](src/main/java/AoC2024_07.java) | [](src/main/java/AoC2024_08.java) | | [](src/main/java/AoC2024_10.java) | [](src/main/java/AoC2024_11.java) | [](src/main/java/AoC2024_12.java) | | [](src/main/java/AoC2024_14.java) | [](src/main/java/AoC2024_15.java)| | | | | | | | | | |
1313
| rust | [](src/main/rust/AoC2024_01/src/main.rs) | [](src/main/rust/AoC2024_02/src/main.rs) | [](src/main/rust/AoC2024_03/src/main.rs) | [](src/main/rust/AoC2024_04/src/main.rs) | [](src/main/rust/AoC2024_05/src/main.rs) | [](src/main/rust/AoC2024_06/src/main.rs) | [](src/main/rust/AoC2024_07/src/main.rs) | [](src/main/rust/AoC2024_08/src/main.rs) | | [](src/main/rust/AoC2024_10/src/main.rs) | | | [](src/main/rust/AoC2024_13/src/main.rs) | [](src/main/rust/AoC2024_14/src/main.rs) | | | | | | | | | | | |
1414
<!-- @END:ImplementationsTable:2024@ -->
1515

src/main/java/AoC2024_15.java

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
import static com.github.pareronia.aoc.IntegerSequence.Range.range;
2+
import static java.util.stream.Collectors.joining;
3+
import static java.util.stream.Collectors.toMap;
4+
5+
import java.util.ArrayDeque;
6+
import java.util.ArrayList;
7+
import java.util.Deque;
8+
import java.util.List;
9+
import java.util.Map;
10+
import java.util.Set;
11+
12+
import com.github.pareronia.aoc.CharGrid;
13+
import com.github.pareronia.aoc.Grid.Cell;
14+
import com.github.pareronia.aoc.StringOps;
15+
import com.github.pareronia.aoc.Utils;
16+
import com.github.pareronia.aoc.geometry.Direction;
17+
import com.github.pareronia.aoc.solution.Sample;
18+
import com.github.pareronia.aoc.solution.Samples;
19+
import com.github.pareronia.aoc.solution.SolutionBase;
20+
21+
public final class AoC2024_15
22+
extends SolutionBase<AoC2024_15.Input, Integer, Integer> {
23+
24+
private static final char FLOOR = '.';
25+
private static final char WALL = '#';
26+
private static final char ROBOT = '@';
27+
private static final char BOX = 'O';
28+
private static final char BIG_BOX_LEFT = '[';
29+
private static final char BIG_BOX_RIGHT = ']';
30+
31+
private AoC2024_15(final boolean debug) {
32+
super(debug);
33+
}
34+
35+
public static AoC2024_15 create() {
36+
return new AoC2024_15(false);
37+
}
38+
39+
public static AoC2024_15 createDebug() {
40+
return new AoC2024_15(true);
41+
}
42+
43+
@Override
44+
protected Input parseInput(final List<String> inputs) {
45+
final List<List<String>> blocks = StringOps.toBlocks(inputs);
46+
final Grid grid = new Grid(CharGrid.from(blocks.get(0)));
47+
final List<Direction> dirs = Utils.asCharacterStream(
48+
blocks.get(1).stream().collect(joining()))
49+
.map(Direction::fromChar)
50+
.toList();
51+
return new Input(grid, dirs);
52+
}
53+
54+
private int solve(
55+
final CharGrid grid,
56+
final List<Direction> dirs,
57+
final GetToMove getToMove
58+
) {
59+
Cell robot = grid.getAllEqualTo(ROBOT).findFirst().orElseThrow();
60+
for (final Direction dir : dirs) {
61+
final List<Cell> toMove = getToMove.getToMove(grid, robot, dir);
62+
if (toMove.isEmpty()) {
63+
continue;
64+
}
65+
final Map<Cell, Character> vals = toMove.stream()
66+
.collect(toMap(tm -> tm, grid::getValue));
67+
robot = robot.at(dir);
68+
for (final Cell cell : toMove) {
69+
grid.setValue(cell, FLOOR);
70+
}
71+
for (final Cell cell : toMove) {
72+
grid.setValue(cell.at(dir), vals.get(cell));
73+
}
74+
}
75+
return grid.findAllMatching(Set.of(BOX, BIG_BOX_LEFT)::contains)
76+
.mapToInt(cell -> cell.getRow() * 100 + cell.getCol())
77+
.sum();
78+
}
79+
80+
@Override
81+
public Integer solvePart1(final Input input) {
82+
final GetToMove getToMove = (grid, robot, dir) -> {
83+
final List<Cell> toMove = new ArrayList<>(List.of(robot));
84+
final Deque<Cell> q = new ArrayDeque<>(toMove);
85+
while (!q.isEmpty()) {
86+
final Cell cell = q.pop();
87+
final Cell nxt = cell.at(dir);
88+
if (q.contains(nxt)) {
89+
continue;
90+
}
91+
switch (grid.getValue(nxt)) {
92+
case WALL:
93+
return List.of();
94+
case BOX:
95+
q.add(nxt);
96+
toMove.add(nxt);
97+
break;
98+
}
99+
}
100+
return toMove;
101+
};
102+
103+
return solve(input.grid.getGrid(), input.dirs, getToMove);
104+
}
105+
106+
@Override
107+
public Integer solvePart2(final Input input) {
108+
final GetToMove getToMove = (grid, robot, dir) -> {
109+
final List<Cell> toMove = new ArrayList<>(List.of(robot));
110+
final Deque<Cell> q = new ArrayDeque<>(toMove);
111+
while (!q.isEmpty()) {
112+
final Cell cell = q.pop();
113+
final Cell nxt = cell.at(dir);
114+
if (q.contains(nxt)) {
115+
continue;
116+
}
117+
switch (grid.getValue(nxt)) {
118+
case WALL:
119+
return List.of();
120+
case BIG_BOX_LEFT:
121+
final Cell right = nxt.at(Direction.RIGHT);
122+
q.add(nxt);
123+
q.add(right);
124+
toMove.add(nxt);
125+
toMove.add(right);
126+
break;
127+
case BIG_BOX_RIGHT:
128+
final Cell left = nxt.at(Direction.LEFT);
129+
q.add(nxt);
130+
q.add(left);
131+
toMove.add(nxt);
132+
toMove.add(left);
133+
break;
134+
}
135+
}
136+
return toMove;
137+
};
138+
139+
return solve(input.grid.getWideGrid(), input.dirs, getToMove);
140+
}
141+
142+
@Override
143+
@Samples({
144+
@Sample(method = "part1", input = TEST1, expected = "2028"),
145+
@Sample(method = "part1", input = TEST2, expected = "10092"),
146+
@Sample(method = "part2", input = TEST2, expected = "9021"),
147+
})
148+
public void samples() {
149+
}
150+
151+
public static void main(final String[] args) throws Exception {
152+
AoC2024_15.create().run();
153+
}
154+
155+
private static final String TEST1 = """
156+
########
157+
#..O.O.#
158+
##@.O..#
159+
#...O..#
160+
#.#.O..#
161+
#...O..#
162+
#......#
163+
########
164+
165+
<^^>>>vv<v>>v<<
166+
""";
167+
private static final String TEST2 = """
168+
##########
169+
#..O..O.O#
170+
#......O.#
171+
#.OO..O.O#
172+
173+
#O#..O...#
174+
#O..O..O.#
175+
#.OO.O.OO#
176+
#....O...#
177+
##########
178+
179+
<vv>^<v^>v>^vv^v>v<>v^v<v<^vv<<<^><<><>>v<vvv<>^v^>^<<<><<v<<<v^vv^v>^
180+
vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<<v<^v>^<^^>>>^<v<v
181+
><>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^<v>v^^<^^vv<
182+
<<v<^>>^^^^>>>v^<>vvv^><v<<<>^^^vv^<vvv>^>v<^^^^v<>^>vvvv><>>v^<<^^^^^
183+
^><^><>>><>^^<<^^v>>><^<v>^<vv>>v>>>^v><>^v><<<<v>>v<v<v>vvv>^<><<>^><
184+
^>><>^v<><^vvv<^^<><v<<<<<><^v<<<><<<^^<v<^^^><^>>^<v^><<<^>>^v<v^v<v^
185+
>^>>^v>vv>^<<^v<>><<><<v<<v><>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^
186+
<><^^>^^^<><vvvvv^v<v<<>^v<v>v<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<>
187+
^^>vv<^v^v<vv>^<><v<^v>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<><<v>
188+
v^^>>><<^^<>>^v^<v^vv<>v^<<>^<^v^v><^<<<><<^<v><v<>vv>>v><v^<vv<>v^<<^
189+
""";
190+
191+
private interface GetToMove {
192+
List<Cell> getToMove(CharGrid grid, Cell robot, Direction dir);
193+
}
194+
195+
record Grid(CharGrid gridIn) {
196+
private static final Map<Character, char[]> SCALE_UP = Map.of(
197+
FLOOR, new char[] { FLOOR, FLOOR },
198+
WALL, new char[] { WALL, WALL },
199+
ROBOT, new char[] { ROBOT, FLOOR },
200+
BOX, new char[] { BIG_BOX_LEFT, BIG_BOX_RIGHT }
201+
);
202+
203+
public CharGrid getGrid() {
204+
return this.gridIn.copy();
205+
}
206+
207+
public CharGrid getWideGrid() {
208+
final char[][] chars = new char[this.gridIn.getHeight()][];
209+
for (final int r : range(this.gridIn.getHeight())) {
210+
final char[] row = new char[2 * this.gridIn.getWidth()];
211+
for(final int c : range(this.gridIn.getWidth())) {
212+
final char ch = this.gridIn.getValue(Cell.at(r, c));
213+
row[2 * c] = SCALE_UP.get(ch)[0];
214+
row[2 * c + 1] = SCALE_UP.get(ch)[1];
215+
}
216+
chars[r] = row;
217+
}
218+
return new CharGrid(chars);
219+
}
220+
}
221+
222+
record Input(Grid grid, List<Direction> dirs) {}
223+
}

src/main/java/com/github/pareronia/aoc/CharGrid.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ public CharGrid doClone() {
5353
throw new RuntimeException(e);
5454
}
5555
}
56+
57+
public CharGrid copy() {
58+
final char[][] chars = Stream.of(this.cells)
59+
.map(row -> Arrays.copyOf(row, row.length))
60+
.toArray(char[][]::new);
61+
return new CharGrid(chars);
62+
}
5663

5764
public CharGrid addRow(final String string ) {
5865
assertTrue(string.length() == getWidth(), () -> "Invalid row length.");

0 commit comments

Comments
 (0)