Skip to content

Commit 82fb6ff

Browse files
committed
Improve year 2022 day12
1 parent e9cfd21 commit 82fb6ff

File tree

4 files changed

+62
-15
lines changed

4 files changed

+62
-15
lines changed

lib/src/main/java/dev/linl33/adventofcode/lib/graph/GraphUtil.java

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
import dev.linl33.adventofcode.lib.function.BiIntConsumer;
44
import dev.linl33.adventofcode.lib.point.Point;
5+
import jdk.incubator.vector.IntVector;
6+
import jdk.incubator.vector.VectorOperators;
7+
import jdk.incubator.vector.VectorSpecies;
58
import org.apache.logging.log4j.LogManager;
69
import org.apache.logging.log4j.Logger;
710
import org.jetbrains.annotations.NotNull;
@@ -10,6 +13,8 @@
1013
import java.util.function.*;
1114

1215
public final class GraphUtil {
16+
private static final VectorSpecies<Integer> SPECIES = IntVector.SPECIES_PREFERRED;
17+
1318
private static final Logger LOGGER = LogManager.getLogger(GraphUtil.class);
1419

1520
public static <T> Optional<GraphPath<T>> aStar(T start, T end, Function<T, ? extends Collection<T>> neighborsFunc) {
@@ -158,7 +163,8 @@ private static <R> R aStarIntInternal(int start,
158163
Arrays.fill(gScore, Integer.MAX_VALUE);
159164
gScore[start] = 0;
160165

161-
var openSetFScore = new int[size];
166+
var alignedSize = Math.ceilDiv(size, SPECIES.length()) * SPECIES.length();
167+
var openSetFScore = new int[alignedSize];
162168
Arrays.fill(openSetFScore, Integer.MAX_VALUE);
163169
openSetFScore[start] = heuristic.applyAsInt(start);
164170

@@ -172,12 +178,22 @@ private static <R> R aStarIntInternal(int start,
172178

173179
while (openSetCounter > 0) {
174180
if (!hasMin) {
175-
minFScore = Integer.MAX_VALUE;
181+
var minVector = (IntVector) SPECIES.fromArray(openSetFScore, 0);
182+
for (int i = SPECIES.length(); i < alignedSize; i += SPECIES.length()) {
183+
var next = SPECIES.fromArray(openSetFScore, i);
184+
minVector = minVector.min(next);
185+
}
186+
187+
minFScore = minVector.reduceLanes(VectorOperators.MIN);
188+
minVector = (IntVector) SPECIES.broadcast(minFScore);
176189

177-
for (int i = 0; i < openSetFScore.length; i++) {
178-
if (openSetFScore[i] < minFScore) {
179-
minFScore = openSetFScore[i];
180-
minNode = i;
190+
for (int i = 0; i < alignedSize; i += SPECIES.length()) {
191+
var next = SPECIES.fromArray(openSetFScore, i);
192+
var eqMask = next.compare(VectorOperators.EQ, minVector);
193+
var eqIdx = eqMask.firstTrue();
194+
if (eqIdx != SPECIES.length()) {
195+
minNode = i + eqIdx;
196+
break;
181197
}
182198
}
183199
}

lib/src/main/java/module-info.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
requires static org.jetbrains.annotations;
33
requires org.apache.logging.log4j;
44

5+
requires jdk.incubator.vector;
6+
57
exports dev.linl33.adventofcode.lib;
68
exports dev.linl33.adventofcode.lib.benchmark;
79
exports dev.linl33.adventofcode.lib.function;

year2022/src/main/java/dev/linl33/adventofcode/year2022/Day12.java

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
import dev.linl33.adventofcode.lib.graph.GraphUtil;
44
import dev.linl33.adventofcode.lib.grid.RowArrayGrid;
5+
import jdk.incubator.vector.ShortVector;
6+
import jdk.incubator.vector.VectorOperators;
7+
import jdk.incubator.vector.VectorSpecies;
58
import org.jetbrains.annotations.NotNull;
69

710
import java.io.BufferedReader;
@@ -10,6 +13,8 @@
1013
import java.util.function.IntUnaryOperator;
1114

1215
public class Day12 extends AdventSolution2022<Integer, Integer> {
16+
private static final VectorSpecies<Short> SPECIES = ShortVector.SPECIES_PREFERRED;
17+
1318
private static final int POTENTIAL_ENDPOINTS_MAX = 100;
1419

1520
public static void main(String[] args) {
@@ -32,13 +37,23 @@ private static int calculatePathLength(@NotNull BufferedReader reader, boolean f
3237

3338
var start = 0;
3439
var end = 0;
40+
var startFound = false;
41+
var endFound = false;
3542
for (int i = 0; i < gridBackingArray.length; i++) {
3643
if (gridBackingArray[i] == 'E') {
3744
gridBackingArray[i] = 'z';
3845
end = i + 1;
46+
47+
if ((endFound = true) && startFound) {
48+
break;
49+
}
3950
} else if (gridBackingArray[i] == 'S') {
4051
gridBackingArray[i] = 'a';
4152
start = i + 1;
53+
54+
if ((startFound = true) && endFound) {
55+
break;
56+
}
4257
}
4358
}
4459

@@ -63,7 +78,7 @@ private static int calculatePathLength(@NotNull BufferedReader reader, boolean f
6378
return (heuristicCache[p + 1] = Math.abs(pathEndX - x) + Math.abs(pathEndY - y));
6479
};
6580
} else {
66-
var potentialEndpoints = new int[POTENTIAL_ENDPOINTS_MAX * 2];
81+
var potentialEndpoints = new short[POTENTIAL_ENDPOINTS_MAX * 2];
6782
var potentialEndpointsCount = 0;
6883

6984
gridLoop:
@@ -92,14 +107,21 @@ private static int calculatePathLength(@NotNull BufferedReader reader, boolean f
92107
// if its lowest elevation is 'c' then it's inaccessible
93108
// if its highest elevation is 'a' then it has a neighbor with a shorter path
94109
if (grid.get(x2, y2) == 'b') {
95-
potentialEndpoints[potentialEndpointsCount++] = x;
96-
potentialEndpoints[potentialEndpointsCount++] = y;
110+
potentialEndpoints[potentialEndpointsCount] = (short) x;
111+
potentialEndpoints[potentialEndpointsCount + POTENTIAL_ENDPOINTS_MAX] = (short) y;
112+
potentialEndpointsCount++;
97113
continue gridLoop;
98114
}
99115
}
100116
}
101117
}
102118

119+
var alignedLength = Math.ceilDiv(potentialEndpointsCount, SPECIES.length()) * SPECIES.length();
120+
if (potentialEndpointsCount % SPECIES.length() != 0) {
121+
Arrays.fill(potentialEndpoints, potentialEndpointsCount, alignedLength, (short) (grid.width() * 2));
122+
Arrays.fill(potentialEndpoints, potentialEndpointsCount + POTENTIAL_ENDPOINTS_MAX, alignedLength + POTENTIAL_ENDPOINTS_MAX, (short) (grid.height() * 2));
123+
}
124+
103125
var finalPotentialEndpointsCount = potentialEndpointsCount;
104126
heuristic = p -> {
105127
if (heuristicCache[p] != 0) {
@@ -110,15 +132,20 @@ private static int calculatePathLength(@NotNull BufferedReader reader, boolean f
110132
var x = p % grid.width();
111133
var y = p / grid.width();
112134

113-
var min = Integer.MAX_VALUE;
114-
for (int i = 0; i < finalPotentialEndpointsCount; i += 2) {
115-
var pathEndX = potentialEndpoints[i];
116-
var pathEndY = potentialEndpoints[i + 1];
135+
var xVector = (ShortVector) SPECIES.broadcast(x);
136+
var yVector = (ShortVector) SPECIES.broadcast(y);
137+
var minVector = (ShortVector) SPECIES.broadcast(Short.MAX_VALUE);
138+
139+
for (int i = 0; i < alignedLength; i += SPECIES.length()) {
140+
var pathX = (ShortVector) SPECIES.fromArray(potentialEndpoints, i);
141+
var pathY = (ShortVector) SPECIES.fromArray(potentialEndpoints, i + finalPotentialEndpointsCount);
117142

118-
var manhattanDistance = Math.abs(pathEndX - x) + Math.abs(pathEndY - y);
119-
min = Math.min(min, manhattanDistance);
143+
pathX = xVector.sub(pathX).abs();
144+
pathY = yVector.sub(pathY).abs();
145+
minVector = minVector.min(pathX.add(pathY));
120146
}
121147

148+
var min = minVector.reduceLanes(VectorOperators.MIN);
122149
return (heuristicCache[p + 1] = min);
123150
};
124151
}

year2022/src/main/java/module-info.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
requires static org.apache.logging.log4j.core;
77
requires static org.jetbrains.annotations;
88

9+
requires jdk.incubator.vector;
10+
911
exports dev.linl33.adventofcode.year2022 to dev.linl33.adventofcode.year2022.test;
1012

1113
opens dev.linl33.adventofcode.year2022 to dev.linl33.adventofcode.lib, dev.linl33.adventofcode.jmh;

0 commit comments

Comments
 (0)