Skip to content

Commit a6e40c6

Browse files
committed
feat: solve day 6
1 parent 60d6958 commit a6e40c6

File tree

6 files changed

+163
-12
lines changed

6 files changed

+163
-12
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
- [Day 3 - Mull It Over](https://github.com/Flashky/advent-of-code-2024/tree/master/src/main/java/com/adventofcode/flashk/day03)
99
- [Day 4 - Ceres Search](https://github.com/Flashky/advent-of-code-2024/tree/master/src/main/java/com/adventofcode/flashk/day04)
1010
- [Day 5 - Print Queue](https://github.com/Flashky/advent-of-code-2024/tree/master/src/main/java/com/adventofcode/flashk/day05)
11-
- [Day 6](https://github.com/Flashky/advent-of-code-2024/tree/master/src/main/java/com/adventofcode/flashk/day06)
11+
- [Day 6 - Guard Gallivant](https://github.com/Flashky/advent-of-code-2024/tree/master/src/main/java/com/adventofcode/flashk/day06)
1212
- [Day 7](https://github.com/Flashky/advent-of-code-2024/tree/master/src/main/java/com/adventofcode/flashk/day07)
1313
- [Day 8](https://github.com/Flashky/advent-of-code-2024/tree/master/src/main/java/com/adventofcode/flashk/day08)
1414
- [Day 9](https://github.com/Flashky/advent-of-code-2024/tree/master/src/main/java/com/adventofcode/flashk/day09)

pom.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,14 @@
6868
<artifactId>commons-math3</artifactId>
6969
<version>3.6.1</version>
7070
</dependency>
71+
<dependency>
72+
<groupId>org.jetbrains</groupId>
73+
<artifactId>annotations</artifactId>
74+
<version>13.0</version>
75+
<scope>compile</scope>
76+
</dependency>
7177

72-
</dependencies>
78+
</dependencies>
7379

7480
<build>
7581
<plugins>
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package com.adventofcode.flashk.day06;
2+
3+
import com.adventofcode.flashk.common.Vector2;
4+
5+
import java.util.HashSet;
6+
import java.util.List;
7+
import java.util.Set;
8+
9+
10+
public class GuardGallivant {
11+
12+
private static final char OBSTACLE = '#';
13+
private static final char OBSTRUCTION = 'O';
14+
private static final char UNVISITED = '.';
15+
private static final char VISITED = 'X';
16+
17+
private final char[][] map;
18+
private final int rows;
19+
private final int cols;
20+
21+
private GuardState initialGuardState;
22+
private Set<GuardState> guardStates = new HashSet<>();
23+
24+
public GuardGallivant(char[][] inputs) {
25+
26+
this.map = inputs;
27+
this.rows = inputs.length;
28+
this.cols = inputs[0].length;
29+
30+
for(int row = 0; row < rows; row++) {
31+
for(int col = 0; col < cols; col++) {
32+
if(inputs[row][col] == '^') {
33+
initialGuardState = new GuardState(new Vector2(col,row), new Vector2(0,-1));
34+
guardStates.add(initialGuardState);
35+
break;
36+
}
37+
}
38+
}
39+
}
40+
41+
public long solveA() {
42+
simulateGuardMovement();
43+
return guardStates.stream().map(GuardState::pos).distinct().count();
44+
45+
}
46+
47+
public long solveB() {
48+
49+
// Obtain first execution guard information
50+
simulateGuardMovement();
51+
List<Vector2> possibleObstructionPositions = guardStates.stream().map(GuardState::pos)
52+
.distinct().filter(pos -> !pos.equals(initialGuardState.pos())).toList();
53+
resetMap();
54+
55+
// Search for loops
56+
long loopCount = 0;
57+
for(Vector2 obstructionPos : possibleObstructionPositions) {
58+
map[obstructionPos.getY()][obstructionPos.getX()] = OBSTRUCTION;
59+
if(simulateGuardMovement()) {
60+
loopCount++;
61+
}
62+
resetMap();
63+
}
64+
65+
return loopCount;
66+
67+
}
68+
69+
private boolean simulateGuardMovement() {
70+
boolean isLoop = false;
71+
Vector2 guardPos = initialGuardState.pos();
72+
Vector2 guardDir = initialGuardState.dir();
73+
74+
Vector2 nextPos;
75+
76+
do {
77+
78+
nextPos = Vector2.transform(guardPos,guardDir);
79+
if(canMove(nextPos)) {
80+
guardPos = nextPos;
81+
GuardState guardState = new GuardState(guardPos, guardDir);
82+
if(guardStates.contains(guardState)) {
83+
isLoop = true;
84+
} else {
85+
guardStates.add(guardState);
86+
map[nextPos.getY()][nextPos.getX()] = VISITED;
87+
}
88+
} else {
89+
guardDir.rotateLeft();
90+
}
91+
92+
} while(!isOutOfBounds(nextPos.getY(), nextPos.getX()) && !isLoop);
93+
94+
return isLoop;
95+
}
96+
97+
private boolean canMove(Vector2 nextPos) {
98+
if(isOutOfBounds(nextPos.getY(), nextPos.getX())) {
99+
return false;
100+
}
101+
102+
return map[nextPos.getY()][nextPos.getX()] != OBSTACLE && map[nextPos.getY()][nextPos.getX()] != OBSTRUCTION;
103+
}
104+
105+
private boolean isOutOfBounds(int row, int col) {
106+
return row < 0 || row >= rows || col < 0 || col >= cols;
107+
}
108+
109+
private void resetMap() {
110+
111+
guardStates = new HashSet<>();
112+
guardStates.add(initialGuardState);
113+
114+
for(int row = 0; row < rows; row++) {
115+
for(int col = 0; col < cols; col++) {
116+
if(map[row][col] != OBSTACLE) {
117+
map[row][col] = UNVISITED;
118+
}
119+
}
120+
}
121+
}
122+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.adventofcode.flashk.day06;
2+
3+
import com.adventofcode.flashk.common.Vector2;
4+
5+
public record GuardState(Vector2 pos, Vector2 dir) {
6+
7+
public Vector2 pos() {
8+
return new Vector2(pos);
9+
}
10+
11+
public Vector2 dir() {
12+
return new Vector2(dir);
13+
}
14+
}

src/test/java/com/adventofcode/flashk/day06/Day06Test.java

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@
1919
import com.adventofcode.flashk.common.test.utils.Timer;
2020
import com.adventofcode.flashk.common.test.utils.Input;
2121

22+
import static org.junit.jupiter.api.Assertions.assertEquals;
23+
2224
@DisplayName(TestDisplayName.DAY_06)
2325
@TestMethodOrder(OrderAnnotation.class)
24-
@Disabled // TODO Remove comment when implemented
2526
public class Day06Test extends PuzzleTest {
2627

2728
private final static String INPUT_FOLDER = TestFolder.DAY_06;
@@ -42,8 +43,10 @@ public void testSolvePart1Sample() {
4243
System.out.print("1 | sample | ");
4344

4445
// Read input file
45-
List<String> inputs = Input.readStringLines(INPUT_FOLDER, TestFilename.INPUT_FILE_SAMPLE);
46-
46+
char[][] inputs = Input.read2DCharArray(INPUT_FOLDER, TestFilename.INPUT_FILE_SAMPLE);
47+
GuardGallivant guardGallivant = new GuardGallivant(inputs);
48+
49+
assertEquals(41,guardGallivant.solveA());
4750
}
4851

4952
@Test
@@ -56,8 +59,10 @@ public void testSolvePart1Input() {
5659
System.out.print("1 | input | ");
5760

5861
// Read input file
59-
List<String> inputs = Input.readStringLines(INPUT_FOLDER, TestFilename.INPUT_FILE);
60-
62+
char[][] inputs = Input.read2DCharArray(INPUT_FOLDER, TestFilename.INPUT_FILE);
63+
GuardGallivant guardGallivant = new GuardGallivant(inputs);
64+
65+
assertEquals(5269,guardGallivant.solveA());
6166
}
6267

6368
@Test
@@ -70,8 +75,10 @@ public void testSolvePart2Sample() {
7075
System.out.print("2 | sample | ");
7176

7277
// Read input file
73-
List<String> inputs = Input.readStringLines(INPUT_FOLDER, TestFilename.INPUT_FILE_SAMPLE);
74-
78+
char[][] inputs = Input.read2DCharArray(INPUT_FOLDER, TestFilename.INPUT_FILE_SAMPLE);
79+
GuardGallivant guardGallivant = new GuardGallivant(inputs);
80+
81+
assertEquals(6,guardGallivant.solveB());
7582
}
7683

7784
@Test
@@ -84,8 +91,10 @@ public void testSolvePart2Input() {
8491
System.out.print("2 | input | ");
8592

8693
// Read input file
87-
List<String> inputs = Input.readStringLines(INPUT_FOLDER, TestFilename.INPUT_FILE);
88-
94+
char[][]inputs = Input.read2DCharArray(INPUT_FOLDER, TestFilename.INPUT_FILE);
95+
GuardGallivant guardGallivant = new GuardGallivant(inputs);
96+
97+
assertEquals(1957,guardGallivant.solveB());
8998
}
9099

91100
}

src/test/resources/inputs

0 commit comments

Comments
 (0)