1
0

Day 7 Off-heap

This commit is contained in:
2025-12-13 00:23:31 +01:00
parent e4de2b844b
commit 2803b323f6

View File

@@ -12,7 +12,11 @@ import java.util.Map;
import java.util.concurrent.StructuredTaskScope; import java.util.concurrent.StructuredTaskScope;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
// This needs about 350.000.000GB RAM to complete
public class Main3 { 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 int SKIP_ROWS = 2;
private static final long ALIGNMENT = 16; private static final long ALIGNMENT = 16;
@@ -43,15 +47,8 @@ public class Main3 {
for(int i = 0; i < SPLITTER_POSITIONS[0].length; i++) { for(int i = 0; i < SPLITTER_POSITIONS[0].length; i++) {
if(SPLITTER_POSITIONS[0][i]) { if(SPLITTER_POSITIONS[0][i]) {
try(var scope = StructuredTaskScope.open()) { try(var scope = StructuredTaskScope.open()) {
int finalI = i; branchLeft(counter, initialSegment, arena, 0, i, scope);
branchRight(counter, initialSegment, arena, 0, i, scope);
// 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));
scope.join(); scope.join();
} }
@@ -65,39 +62,89 @@ public class Main3 {
} }
private static final void travel(AtomicLong counter, MemorySegment current, Arena arena, int row, int column) { 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(); counter.incrementAndGet();
if(PRINT_COMPLETE) printAsPuzzle(current);
printAsPuzzle(current);
return; return;
} }
for(int i = column; i < SPLITTER_POSITIONS[row].length; i++) { try(var scope = StructuredTaskScope.open()) {
int finalI = i; if(SPLITTER_POSITIONS[row][column]) { // current position is a splitter
try(var scope = StructuredTaskScope.open()) { branchLeft(counter, current, arena, row, column, scope);
if(SPLITTER_POSITIONS[row][i]) { branchRight(counter, current, arena, row, column, scope);
// Left }
final MemorySegment leftSegment = copyAndSet(current, arena, row, i - 1); else { // The cell below the beam is free
scope.fork(() -> travel(counter, leftSegment, arena, row + 2, finalI - 1)); continueDown(counter, current, arena, row, column, scope);
}
// Right scope.join();
final MemorySegment rightSegment = copyAndSet(current, arena, row, i + 1); } catch (InterruptedException e) {
scope.fork(() -> travel(counter, rightSegment, arena, row + 2, finalI + 1)); throw new RuntimeException(e);
} }
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(); 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; while(free && !isSplitter) {
} catch (InterruptedException e) { set(belowSegment, freeRow, column);
throw new RuntimeException(e); 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) { 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) { private static final MemorySegment copyAndSet(MemorySegment src, Arena arena, int row, int column) {
final MemorySegment copy = arena.allocate(src.byteSize(), ALIGNMENT).copyFrom(src); final MemorySegment copy = arena.allocate(src.byteSize(), ALIGNMENT).copyFrom(src);
// Set the beam in the current row + column
set(copy, 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); set(copy, row + 1, column);
return copy; return copy;
@@ -120,8 +170,7 @@ public class Main3 {
private static final void set(MemorySegment segment, int row, int column) { private static final void set(MemorySegment segment, int row, int column) {
final long offset = calculateOffset(row, column); final long offset = calculateOffset(row, column);
final byte current = segment.get(ValueLayout.OfByte.JAVA_BYTE, offset); final byte current = segment.get(ValueLayout.OfByte.JAVA_BYTE, offset);
//final byte bit = (byte) ((byte) 7 - (column - (column / 8))); final byte bit = calculateBit(column);
final byte bit = (byte) (column < 8 ? 7 - column : 7 - (column - ((column / 8) * 8)));
segment.set(ValueLayout.OfByte.JAVA_BYTE, offset, (byte) (current | (1 << bit))); 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) { 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 long size = segment.byteSize();
final StringBuilder sb = new StringBuilder();
final byte[] bytes = new byte[(int) size]; final byte[] bytes = new byte[(int) size];
final Map<Integer, List<Byte>> rowMap = new HashMap<>(); final Map<Integer, List<Byte>> rowMap = new HashMap<>();
@@ -178,17 +230,17 @@ public class Main3 {
final Byte b = bytes[i]; final Byte b = bytes[i];
rowMap.compute(row, (k, v) -> { rowMap.compute(row, (k, v) -> {
if(v == null) { if(v == null) {
List<Byte> value = new ArrayList<>(); 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) { if(row != previousRow) {
@@ -205,6 +257,8 @@ public class Main3 {
String str = s.toString(); String str = s.toString();
sb.append(String.format("%02d ", e.getKey()));
for(int i = 0; i < str.length(); i++) { for(int i = 0; i < str.length(); i++) {
boolean isSplitter = false; boolean isSplitter = false;