Day 7 Off-heap
This commit is contained in:
@@ -12,7 +12,11 @@ import java.util.Map;
|
||||
import java.util.concurrent.StructuredTaskScope;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
// This needs about 350.000.000GB RAM to complete
|
||||
public class Main3 {
|
||||
private static final boolean PRINT_TRAVEL = false;
|
||||
private static final boolean PRINT_COMPLETE = false;
|
||||
|
||||
private static final int SKIP_ROWS = 2;
|
||||
private static final long ALIGNMENT = 16;
|
||||
|
||||
@@ -43,15 +47,8 @@ public class Main3 {
|
||||
for(int i = 0; i < SPLITTER_POSITIONS[0].length; i++) {
|
||||
if(SPLITTER_POSITIONS[0][i]) {
|
||||
try(var scope = StructuredTaskScope.open()) {
|
||||
int finalI = i;
|
||||
|
||||
// Left
|
||||
final MemorySegment leftSegment = copyAndSet(initialSegment, arena, 0, i - 1);
|
||||
scope.fork(() -> travel(counter, leftSegment, arena, 2, finalI - 1));
|
||||
|
||||
// Right
|
||||
final MemorySegment rightSegment = copyAndSet(initialSegment, arena, 0, i + 1);
|
||||
scope.fork(() -> travel(counter, rightSegment, arena, 2, finalI + 1));
|
||||
branchLeft(counter, initialSegment, arena, 0, i, scope);
|
||||
branchRight(counter, initialSegment, arena, 0, i, scope);
|
||||
|
||||
scope.join();
|
||||
}
|
||||
@@ -65,39 +62,89 @@ public class Main3 {
|
||||
}
|
||||
|
||||
private static final void travel(AtomicLong counter, MemorySegment current, Arena arena, int row, int column) {
|
||||
if(row >= RELEVANT_ROWS - 1) {
|
||||
if(row >= RELEVANT_ROWS) {
|
||||
counter.incrementAndGet();
|
||||
|
||||
printAsPuzzle(current);
|
||||
|
||||
if(PRINT_COMPLETE) printAsPuzzle(current);
|
||||
return;
|
||||
}
|
||||
|
||||
for(int i = column; i < SPLITTER_POSITIONS[row].length; i++) {
|
||||
int finalI = i;
|
||||
try(var scope = StructuredTaskScope.open()) {
|
||||
if(SPLITTER_POSITIONS[row][i]) {
|
||||
// Left
|
||||
final MemorySegment leftSegment = copyAndSet(current, arena, row, i - 1);
|
||||
scope.fork(() -> travel(counter, leftSegment, arena, row + 2, finalI - 1));
|
||||
try(var scope = StructuredTaskScope.open()) {
|
||||
if(SPLITTER_POSITIONS[row][column]) { // current position is a splitter
|
||||
branchLeft(counter, current, arena, row, column, scope);
|
||||
branchRight(counter, current, arena, row, column, scope);
|
||||
}
|
||||
else { // The cell below the beam is free
|
||||
continueDown(counter, current, arena, row, column, scope);
|
||||
}
|
||||
|
||||
// Right
|
||||
final MemorySegment rightSegment = copyAndSet(current, arena, row, i + 1);
|
||||
scope.fork(() -> travel(counter, rightSegment, arena, row + 2, finalI + 1));
|
||||
}
|
||||
else {
|
||||
// The cell under the beam is free
|
||||
final MemorySegment leftSegment = copyAndSetOnce(current, arena, row + 1, i);
|
||||
scope.fork(() -> travel(counter, leftSegment, arena, row + 1, finalI));
|
||||
}
|
||||
scope.join();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
scope.join();
|
||||
private static void continueDown(AtomicLong counter, MemorySegment current, Arena arena, int row, int column, StructuredTaskScope<?, ?> scope) {
|
||||
final MemorySegment belowSegment = copyAndSetOnce(current, arena, row, column);
|
||||
int freeRow = row + 1;
|
||||
boolean free = isFree(belowSegment, freeRow, column);
|
||||
boolean isSplitter = false; // when we come here first, the down cell is guaranteed to not be a splitter
|
||||
|
||||
return;
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
while(free && !isSplitter) {
|
||||
set(belowSegment, freeRow, column);
|
||||
if(PRINT_TRAVEL) System.out.println("Travel from " + (freeRow - 1) + "|" + column + " to " + freeRow + "|" + column + " (DOWN)");
|
||||
freeRow += 1;
|
||||
|
||||
if(freeRow < SPLITTER_POSITIONS.length) {
|
||||
isSplitter = SPLITTER_POSITIONS[freeRow][column];
|
||||
}
|
||||
else {
|
||||
isSplitter = false;
|
||||
}
|
||||
|
||||
if(freeRow < RELEVANT_ROWS && !isSplitter) {
|
||||
free = isFree(belowSegment, freeRow, column);
|
||||
}
|
||||
else {
|
||||
free = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(freeRow < RELEVANT_ROWS && SPLITTER_POSITIONS[freeRow][column]) {
|
||||
branchLeft(counter, belowSegment, arena, freeRow, column, scope);
|
||||
branchRight(counter, belowSegment, arena, freeRow, column, scope);
|
||||
}
|
||||
else if(freeRow == RELEVANT_ROWS) {
|
||||
counter.incrementAndGet();
|
||||
if(PRINT_COMPLETE) printAsPuzzle(belowSegment);
|
||||
}
|
||||
}
|
||||
|
||||
private static void branchRight(AtomicLong counter, MemorySegment current, Arena arena, int row, int column, StructuredTaskScope<?, ?> scope) {
|
||||
final int newColumn = column + 1;
|
||||
final int newRow = row + 2;
|
||||
final MemorySegment rightSegment = copyAndSet(current, arena, row, newColumn);
|
||||
scope.fork(() -> travel(counter, rightSegment, arena, newRow, newColumn));
|
||||
if(PRINT_TRAVEL) System.out.println("Travel from " + row + "|" + column + " to " + newRow + "|" + newColumn);
|
||||
}
|
||||
|
||||
private static void branchLeft(AtomicLong counter, MemorySegment current, Arena arena, int row, int column, StructuredTaskScope<?, ?> scope) {
|
||||
final int newColumn = column - 1;
|
||||
final int newRow = row + 2;
|
||||
final MemorySegment leftSegment = copyAndSet(current, arena, row, newColumn);
|
||||
scope.fork(() -> travel(counter, leftSegment, arena, newRow, newColumn));
|
||||
if(PRINT_TRAVEL) System.out.println("Travel from " + row + "|" + column + " to " + newRow + "|" + newColumn);
|
||||
}
|
||||
|
||||
private static final boolean isFree(MemorySegment segment, int row, int column) {
|
||||
final long offset = calculateOffset(row, column);
|
||||
final byte current = segment.get(ValueLayout.OfByte.JAVA_BYTE, offset);
|
||||
final byte bit = calculateBit(column);
|
||||
|
||||
return current == 0 || (current & bit) != bit;
|
||||
}
|
||||
|
||||
private static byte calculateBit(int column) {
|
||||
return (byte) (column < 8 ? 7 - column : 7 - (column - ((column / 8) * 8)));
|
||||
}
|
||||
|
||||
private static final MemorySegment copyAndSetOnce(MemorySegment src, Arena arena, int row, int column) {
|
||||
@@ -111,7 +158,10 @@ public class Main3 {
|
||||
private static final MemorySegment copyAndSet(MemorySegment src, Arena arena, int row, int column) {
|
||||
final MemorySegment copy = arena.allocate(src.byteSize(), ALIGNMENT).copyFrom(src);
|
||||
|
||||
// Set the beam in the current row + column
|
||||
set(copy, row, column);
|
||||
|
||||
// and also in the next row (same column) since the row below splitters is always free
|
||||
set(copy, row + 1, column);
|
||||
|
||||
return copy;
|
||||
@@ -120,8 +170,7 @@ public class Main3 {
|
||||
private static final void set(MemorySegment segment, int row, int column) {
|
||||
final long offset = calculateOffset(row, column);
|
||||
final byte current = segment.get(ValueLayout.OfByte.JAVA_BYTE, offset);
|
||||
//final byte bit = (byte) ((byte) 7 - (column - (column / 8)));
|
||||
final byte bit = (byte) (column < 8 ? 7 - column : 7 - (column - ((column / 8) * 8)));
|
||||
final byte bit = calculateBit(column);
|
||||
|
||||
segment.set(ValueLayout.OfByte.JAVA_BYTE, offset, (byte) (current | (1 << bit)));
|
||||
}
|
||||
@@ -161,8 +210,11 @@ public class Main3 {
|
||||
}
|
||||
|
||||
private static final void printAsPuzzle(MemorySegment segment) {
|
||||
printAsPuzzle(segment, new StringBuilder());
|
||||
}
|
||||
|
||||
private static final void printAsPuzzle(MemorySegment segment, StringBuilder sb) {
|
||||
final long size = segment.byteSize();
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
final byte[] bytes = new byte[(int) size];
|
||||
final Map<Integer, List<Byte>> rowMap = new HashMap<>();
|
||||
|
||||
@@ -178,17 +230,17 @@ public class Main3 {
|
||||
final Byte b = bytes[i];
|
||||
|
||||
rowMap.compute(row, (k, v) -> {
|
||||
if(v == null) {
|
||||
List<Byte> value = new ArrayList<>();
|
||||
if(v == null) {
|
||||
List<Byte> value = new ArrayList<>();
|
||||
|
||||
value.add(b);
|
||||
value.add(b);
|
||||
|
||||
return value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
v.add(b);
|
||||
v.add(b);
|
||||
|
||||
return v;
|
||||
return v;
|
||||
});
|
||||
|
||||
if(row != previousRow) {
|
||||
@@ -205,6 +257,8 @@ public class Main3 {
|
||||
|
||||
String str = s.toString();
|
||||
|
||||
sb.append(String.format("%02d ", e.getKey()));
|
||||
|
||||
for(int i = 0; i < str.length(); i++) {
|
||||
boolean isSplitter = false;
|
||||
|
||||
@@ -231,4 +285,4 @@ public class Main3 {
|
||||
|
||||
System.out.println(sb);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user