Skip to content

Commit 209290d

Browse files
aoc 2024 day 14
1 parent cb33c35 commit 209290d

File tree

4 files changed

+183
-15
lines changed

4 files changed

+183
-15
lines changed

src/main/java/dev/jacobandersen/codechallenges/challenge/adventofcode/year2024/Year2024.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ public static List<Day> getDays() {
3434
new Day11(),
3535
new Day12(),
3636
new Day13()
37+
// Day 6 part 2 is slow due to slow update algorithm
3738
// new Day14()
3839
);
3940
}
Lines changed: 91 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,108 @@
11
package dev.jacobandersen.codechallenges.challenge.adventofcode.year2024.day14;
22

33
import dev.jacobandersen.codechallenges.challenge.adventofcode.Day;
4+
import dev.jacobandersen.codechallenges.util.Grid;
5+
import dev.jacobandersen.codechallenges.util.Pair;
6+
7+
import java.util.ArrayList;
8+
import java.util.Collection;
9+
import java.util.Iterator;
10+
import java.util.List;
411

512
public class Day14 extends Day {
13+
private static final int ROWS = 103, COLS = 101;
14+
615
public Day14() {
716
super(2024, 14, "Restroom Redoubt");
817
}
918

19+
public record Robot(Pair<Integer, Integer> position, Pair<Integer, Integer> velocity) {}
20+
21+
public List<Robot> loadRobots() {
22+
return getInputLinesNoBlanks().stream().map(line -> {
23+
final String[] parts = line.split(" ");
24+
final String pos = parts[0].substring(2), vel = parts[1].substring(2);
25+
return new Robot(Pair.fromStringPair(pos, Integer::parseInt).reverse(), Pair.fromStringPair(vel, Integer::parseInt).reverse());
26+
}).toList();
27+
}
28+
29+
public Grid<List<Robot>> loadInitialState() {
30+
final Grid<List<Robot>> patrolArea = Grid.emptyGrid(ROWS, COLS, ArrayList::new);
31+
32+
loadRobots().forEach(robot -> {
33+
List<Robot> lst = patrolArea.get(robot.position);
34+
lst.add(robot);
35+
36+
patrolArea.set(robot.position, lst);
37+
});
38+
39+
return patrolArea;
40+
}
41+
42+
public Grid<List<Robot>> tickRobots(Grid<List<Robot>> in) {
43+
final Grid<List<Robot>> updatedGrid = Grid.emptyGrid(ROWS, COLS, ArrayList::new);
44+
45+
in.forEach(robots -> {
46+
List<Robot> lst = robots.value();
47+
Iterator<Robot> itr = lst.iterator();
48+
while (itr.hasNext()) {
49+
final Robot robot = itr.next();
50+
final Pair<Integer, Integer> currentPos = robot.position();
51+
final Pair<Integer, Integer> velocity = robot.velocity();
52+
final Pair<Integer, Integer> newPosition = updatedGrid.locateWrappedPosition(currentPos.first() + velocity.first(), currentPos.second() + velocity.second());
53+
final List<Robot> currentRobots = updatedGrid.get(newPosition);
54+
currentRobots.add(new Robot(newPosition, velocity));
55+
updatedGrid.set(newPosition, currentRobots);
56+
itr.remove();
57+
}
58+
});
59+
60+
return updatedGrid;
61+
}
62+
1063
@Override
1164
public String partOne() {
12-
getInputLinesNoBlanks().forEach(System.out::println);
13-
return "";
65+
Grid<List<Robot>> room = loadInitialState();
66+
67+
for (int i = 0; i < 100; i++) {
68+
room = tickRobots(room);
69+
}
70+
71+
return String.valueOf(
72+
room.getQuadrants().stream()
73+
.mapToInt(quad ->
74+
quad.map(ctx -> ctx.value().size())
75+
.getBackingList().stream()
76+
.flatMap(Collection::stream)
77+
.reduce(0, Integer::sum)
78+
)
79+
.reduce(1, (a, b) -> a * b)
80+
);
1481
}
1582

1683
@Override
1784
public String partTwo() {
18-
return "";
85+
Grid<List<Robot>> room = loadInitialState();
86+
87+
int seconds = 0;
88+
while (true) {
89+
seconds++;
90+
91+
room = tickRobots(room);
92+
93+
Grid<Integer> asRobotCounts = room.map(ctx -> ctx.value().size());
94+
boolean hasSharedPositions = asRobotCounts.getBackingList().stream().flatMap(Collection::stream).anyMatch(x -> x >= 2);
95+
96+
if (hasSharedPositions) continue;
97+
98+
for (List<Integer> integers : asRobotCounts.getBackingList()) {
99+
integers.forEach(System.out::print);
100+
System.out.println();
101+
}
102+
103+
break;
104+
}
105+
106+
return String.valueOf(seconds);
19107
}
20108
}

src/main/java/dev/jacobandersen/codechallenges/util/Grid.java

Lines changed: 80 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import java.util.stream.Collectors;
99
import java.util.stream.Stream;
1010

11-
public class Grid<T extends Comparable<T>> {
11+
public class Grid<T> {
1212
private final int rows;
1313
private final int cols;
1414
private final List<List<T>> grid;
@@ -27,7 +27,7 @@ public Grid(int rows, int cols, int currentRow, int currentCol, List<List<T>> gr
2727
this.grid = grid;
2828
}
2929

30-
public static <T extends Comparable<T>> Grid<T> create(Stream<String> input, Function<String, List<T>> mapper) {
30+
public static <T> Grid<T> create(Stream<String> input, Function<String, List<T>> mapper) {
3131
final List<List<T>> grid = input.map(mapper).collect(Collectors.toList());
3232
if (!grid.stream().map(List::size).allMatch(size -> grid.get(0).size() == size)) {
3333
throw new IllegalArgumentException("Received grid had rows with varying columns - invalid");
@@ -36,6 +36,18 @@ public static <T extends Comparable<T>> Grid<T> create(Stream<String> input, Fun
3636
return new Grid<>(grid.size(), grid.get(0).size(), grid);
3737
}
3838

39+
public static <T> Grid<T> emptyGrid(int rows, int cols, Supplier<T> initializer) {
40+
final List<List<T>> grid = new ArrayList<>();
41+
for (int i = 0; i < rows; i++) {
42+
grid.add(new ArrayList<>());
43+
for (int j = 0; j < cols; j++) {
44+
grid.get(i).add(initializer.get());
45+
}
46+
}
47+
48+
return new Grid<>(rows, cols, grid);
49+
}
50+
3951
public int getRows() {
4052
return rows;
4153
}
@@ -56,17 +68,44 @@ public Pair<Integer, Integer> getCurrentPos() {
5668
return Pair.of(getCurrentRow(), getCurrentCol());
5769
}
5870

59-
public T get() {
60-
return grid.get(currentRow).get(currentCol);
71+
public Grid<T> set(T value) {
72+
return set(currentRow, currentCol, value);
6173
}
6274

63-
public Grid<T> set(T value) {
64-
grid.get(currentRow).set(currentCol, value);
75+
public Grid<T> set(Pair<Integer, Integer> pos, T value) {
76+
return set(pos.first(), pos.second(), value);
77+
}
78+
79+
public Grid<T> set(int row, int col, T value) {
80+
grid.get(row).set(col, value);
6581
return this;
6682
}
6783

68-
public T get(int row, int col) {
69-
return grid.get(row).get(col);
84+
public Pair<Integer, Integer> locateWrappedPosition(int targetRow, int targetCol) {
85+
int wrappedRow = targetRow;
86+
int wrappedCol = targetCol;
87+
88+
if (wrappedRow < 0) {
89+
wrappedRow = (wrappedRow % rows + rows) % rows;
90+
} else if (wrappedRow >= rows) {
91+
wrappedRow = wrappedRow % rows;
92+
}
93+
94+
if (wrappedCol < 0) {
95+
wrappedCol = (wrappedCol % cols + cols) % cols;
96+
} else if (wrappedCol >= cols) {
97+
wrappedCol = wrappedCol % cols;
98+
}
99+
100+
return Pair.of(wrappedRow, wrappedCol);
101+
}
102+
103+
public T get() {
104+
return get(currentRow, currentCol);
105+
}
106+
107+
public T getOrNull(Pair<Integer, Integer> pos) {
108+
return getOrNull(pos.first(), pos.second());
70109
}
71110

72111
public T getOrNull(int row, int col) {
@@ -77,6 +116,14 @@ public T getOrNull(int row, int col) {
77116
}
78117
}
79118

119+
public T get(Pair<Integer, Integer> pos) {
120+
return get(pos.first(), pos.second());
121+
}
122+
123+
public T get(int row, int col) {
124+
return grid.get(row).get(col);
125+
}
126+
80127
public Grid<T> move(int row, int col) {
81128
if (row < 0 || row >= rows || col < 0 || col >= cols) {
82129
throw new IllegalArgumentException("Tried to move current cell beyond boundaries");
@@ -203,10 +250,6 @@ public <R extends Comparable<R>> Grid<R> map(Function<PositionContext<T>, R> map
203250
return output;
204251
}
205252

206-
public List<List<T>> getBackingList() {
207-
return copy().grid;
208-
}
209-
210253
public Grid<T> copy() {
211254
List<List<T>> copy = new ArrayList<>(rows);
212255

@@ -225,6 +268,31 @@ public boolean contains(Pair<Integer, Integer> position) {
225268
return position.first() >= 0 && position.first() < rows && position.second() >= 0 && position.second() < cols;
226269
}
227270

271+
public List<Grid<T>> getQuadrants() {
272+
int midRow = rows / 2, midCol = cols / 2;
273+
274+
Grid<T> q1 = extractSubgrid(0, midRow, 0, midCol);
275+
Grid<T> q2 = extractSubgrid(0, midRow, midCol + 1, cols);
276+
Grid<T> q3 = extractSubgrid(midRow + 1, rows, 0, midCol);
277+
Grid<T> q4 = extractSubgrid(midRow + 1, rows, midCol + 1, cols);
278+
279+
return List.of(q1, q2, q3, q4);
280+
}
281+
282+
private Grid<T> extractSubgrid(int startRow, int endRow, int startCol, int endCol) {
283+
Grid<T> subgrid = Grid.emptyGrid(endRow - startRow, endCol - startCol, () -> null);
284+
for (int i = startRow; i < endRow; i++) {
285+
for (int j = startCol; j < endCol; j++) {
286+
subgrid.set(i - startRow, j - startCol, get(i, j));
287+
}
288+
}
289+
return subgrid;
290+
}
291+
292+
public List<List<T>> getBackingList() {
293+
return grid;
294+
}
295+
228296
@Override
229297
public String toString() {
230298
StringBuilder builder = new StringBuilder("Grid {\n" +

src/main/java/dev/jacobandersen/codechallenges/util/Pair.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,21 @@
11
package dev.jacobandersen.codechallenges.util;
22

3+
import java.util.function.Function;
4+
35
public record Pair<T, R>(T first, R second) {
46
public static <T, R> Pair<T, R> of(T first, R second) {
57
return new Pair<>(first, second);
68
}
79

10+
public static <T> Pair<T, T> fromStringPair(String pair, Function<String, T> mapper) {
11+
final String[] parts = pair.split(",");
12+
return Pair.of(mapper.apply(parts[0]), mapper.apply(parts[1]));
13+
}
14+
15+
public Pair<R, T> reverse() {
16+
return Pair.of(second(), first());
17+
}
18+
819
public Pair<T, R> copy() {
920
return Pair.of(first, second);
1021
}

0 commit comments

Comments
 (0)