Skip to content

Commit 3f4daf0

Browse files
committed
Day 21 WIP
1 parent 58ec721 commit 3f4daf0

File tree

3 files changed

+233
-5
lines changed

3 files changed

+233
-5
lines changed
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
package com.adventofcode.flashk.day21;
2+
3+
import com.adventofcode.flashk.common.Vector2;
4+
import org.apache.commons.lang3.tuple.ImmutablePair;
5+
import org.apache.commons.lang3.tuple.Pair;
6+
7+
import java.util.ArrayDeque;
8+
import java.util.Deque;
9+
import java.util.HashSet;
10+
import java.util.Set;
11+
12+
public class StepCounter {
13+
14+
private static final char ROCK = '#';
15+
private static final char GARDEN_PLOT = '.';
16+
private static final char REACH_TILE = '0';
17+
18+
private char[][] map;
19+
private char[][] solutionsMap;
20+
21+
private int rows;
22+
private int cols;
23+
private int reachableTiles = 0;
24+
private Vector2 start;
25+
26+
public StepCounter(char[][] inputs) {
27+
28+
rows = inputs.length;
29+
cols = inputs[0].length;
30+
map = inputs;
31+
32+
// Find starting position
33+
34+
solutionsMap = new char[rows][];
35+
for(int row = 0; row < rows; row++) {
36+
37+
solutionsMap[row] = new char[cols];
38+
39+
for(int col = 0; col < cols; col++) {
40+
if(map[row][col] == 'S') {
41+
start = new Vector2(col, row);
42+
map[row][col] = GARDEN_PLOT;
43+
}
44+
solutionsMap[row][col] = map[row][col];
45+
46+
}
47+
}
48+
}
49+
50+
public long solveA(int totalSteps) {
51+
52+
// TODO, este algoritmo vale para datos muy pequeños, pero en este caso, la ramificación es muy amplia.
53+
Deque<Pair<Vector2,Integer>> queue = new ArrayDeque<>();
54+
queue.add(ImmutablePair.of(start,0));
55+
56+
while(!queue.isEmpty() && queue.peek().getRight() < totalSteps) {
57+
Pair<Vector2,Integer> positionAndSteps = queue.poll();
58+
59+
Vector2 position = positionAndSteps.getLeft();
60+
int steps = positionAndSteps.getRight();
61+
62+
map[position.getY()][position.getX()] = GARDEN_PLOT;
63+
64+
Set<Pair<Vector2,Integer>> adjacentTiles = getAdjacentTiles(position, steps);
65+
for(Pair<Vector2,Integer> positionAndStep : adjacentTiles) {
66+
position = positionAndStep.getLeft();
67+
map[position.getY()][position.getX()] = REACH_TILE;
68+
queue.add(positionAndStep);
69+
}
70+
}
71+
72+
return countPositions();
73+
}
74+
75+
public long solveADFS(int totalSteps) {
76+
77+
Set<Vector2> reachablePositions = new HashSet<>();
78+
/*
79+
long result = countReachableTiles(start.getY(),start.getX()+1, 1, totalSteps);
80+
result += countReachableTiles(start.getY(), start.getX()-1, 1, totalSteps);
81+
result += countReachableTiles(start.getY()-1, start.getX(), 1, totalSteps);
82+
result += countReachableTiles(start.getY()+1, start.getX(), 1, totalSteps);
83+
84+
return result;
85+
*/
86+
87+
countReachableTiles(start.getY(),start.getX()+1, 1, totalSteps, reachablePositions);
88+
countReachableTiles(start.getY(), start.getX()-1, 1, totalSteps, reachablePositions);
89+
countReachableTiles(start.getY()-1, start.getX(), 1, totalSteps, reachablePositions);
90+
countReachableTiles(start.getY()+1, start.getX(), 1, totalSteps, reachablePositions);
91+
92+
return reachablePositions.size();
93+
}
94+
95+
private void countReachableTiles(int row, int col, int steps, int maxSteps, Set<Vector2> reachablePositions) {
96+
97+
if(!isValid(row, col)) {
98+
return;
99+
}
100+
101+
if(steps == maxSteps) {
102+
reachablePositions.add(new Vector2(col, row));
103+
solutionsMap[row][col] = REACH_TILE;
104+
return;
105+
}
106+
107+
// TODO esta condición está mal
108+
// Es necesario podar ramas que ya hayamos visitado para reducir el árbol de llamadas, pero hay que ver como.
109+
/*if(solutionsMap[row][col] == REACH_TILE) {
110+
return; // Already explored
111+
}*/
112+
113+
if(maxSteps % 2 == 0) {
114+
// Se buscan celdas pares
115+
if(steps % 2 == 0) {
116+
reachablePositions.add(new Vector2(col, row));
117+
solutionsMap[row][col] = REACH_TILE;
118+
}
119+
120+
} else {
121+
// Se buscan celdas impares
122+
if(steps % 2 != 0) {
123+
reachablePositions.add(new Vector2(col, row));
124+
solutionsMap[row][col] = REACH_TILE;
125+
}
126+
}
127+
128+
countReachableTiles(row,col+1, steps+1, maxSteps, reachablePositions);
129+
countReachableTiles(row, col-1, steps+1, maxSteps, reachablePositions);
130+
countReachableTiles(row-1, col, steps+1, maxSteps, reachablePositions);
131+
countReachableTiles(row+1, col, steps+1, maxSteps, reachablePositions);
132+
133+
}
134+
135+
private long countReachableTiles(int row, int col, int steps, int maxSteps) {
136+
137+
if(!isValid(row, col)) {
138+
return 0;
139+
}
140+
141+
if(steps == maxSteps) {
142+
return 1;
143+
}
144+
145+
long result = countReachableTiles(row,col+1, steps+1, maxSteps);
146+
result += countReachableTiles(row, col-1, steps+1, maxSteps);
147+
result += countReachableTiles(row-1, col, steps+1, maxSteps);
148+
result += countReachableTiles(row+1, col, steps+1, maxSteps);
149+
150+
return result;
151+
}
152+
153+
154+
private long countPositions() {
155+
long count = 0;
156+
for(int row = 0; row < rows; row++) {
157+
for(int col = 0; col < cols; col++) {
158+
if(map[row][col] == REACH_TILE) {
159+
count++;
160+
}
161+
}
162+
}
163+
return count;
164+
}
165+
private Set<Pair<Vector2,Integer>> getAdjacentTiles(Vector2 position, int stepCounter) {
166+
167+
Set<Pair<Vector2,Integer>> adjacentTiles = new HashSet<>();
168+
169+
//Vector2 position = positionAndSteps.getLeft();
170+
//int stepCounter = positionAndSteps.getRight() + 1;
171+
172+
// Possible positions
173+
Vector2 left = Vector2.transform(position, Vector2.left());
174+
Vector2 right = Vector2.transform(position, Vector2.right());
175+
Vector2 up = Vector2.transform(position, Vector2.down());
176+
Vector2 down = Vector2.transform(position, Vector2.up());
177+
178+
// Add valid movements to the adjacent set
179+
if(isValid(left)) {
180+
adjacentTiles.add(ImmutablePair.of(left, stepCounter+1));
181+
}
182+
183+
if(isValid(right)) {
184+
adjacentTiles.add(ImmutablePair.of(right, stepCounter+1));
185+
}
186+
187+
if(isValid(up)) {
188+
adjacentTiles.add(ImmutablePair.of(up, stepCounter+1));
189+
}
190+
191+
if(isValid(down)) {
192+
adjacentTiles.add(ImmutablePair.of(down, stepCounter+1));
193+
}
194+
195+
return adjacentTiles;
196+
}
197+
198+
private boolean isValid(Vector2 position) {
199+
return isNotOutOfBounds(position) && map[position.getY()][position.getX()] != ROCK;
200+
}
201+
202+
private boolean isValid(int row, int col) {
203+
// Empty tile that is in limits
204+
// TODO we don't want to repeat movements
205+
return isNotOutOfBounds(row, col) && map[row][col] == GARDEN_PLOT;
206+
}
207+
private boolean isNotOutOfBounds(int row, int col) {
208+
return (row >= 0 && row < rows) && (col >= 0 && col < cols);
209+
}
210+
211+
private boolean isNotOutOfBounds(Vector2 position) {
212+
return (position.getY() >= 0 && position.getY() < rows) && (position.getX() >= 0 && position.getX() < cols);
213+
}
214+
}

src/test/java/com/adventofcode/flashk/day21/Day21Test.java

Lines changed: 18 additions & 4 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_21)
2325
@TestMethodOrder(OrderAnnotation.class)
24-
@Disabled // TODO Remove comment when implemented
2526
public class Day21Test extends PuzzleTest {
2627

2728
private final static String INPUT_FOLDER = TestFolder.DAY_21;
@@ -42,7 +43,15 @@ 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+
char[][] inputs = Input.read2DCharArray(INPUT_FOLDER, TestFilename.INPUT_FILE_SAMPLE);
47+
48+
StepCounter stepCounter = new StepCounter(inputs);
49+
long result = stepCounter.solveADFS(1);
50+
51+
assertEquals(2, result);
52+
53+
result = stepCounter.solveADFS(6); // 6 para el ejemplo
54+
assertEquals(16, result);
4655

4756
}
4857

@@ -56,8 +65,13 @@ public void testSolvePart1Input() {
5665
System.out.print("1 | input | ");
5766

5867
// Read input file
59-
List<String> inputs = Input.readStringLines(INPUT_FOLDER, TestFilename.INPUT_FILE);
60-
68+
char[][] inputs = Input.read2DCharArray(INPUT_FOLDER, TestFilename.INPUT_FILE);
69+
70+
StepCounter stepCounter = new StepCounter(inputs);
71+
long result = stepCounter.solveADFS(64);
72+
73+
System.out.println("R: "+result);
74+
6175
}
6276

6377
@Test

src/test/resources/inputs

0 commit comments

Comments
 (0)