introduce bitloops

This commit is contained in:
mike
2026-01-21 00:09:37 +01:00
parent 46b2bb04dc
commit 78f72a024e
11 changed files with 516 additions and 546 deletions

View File

@@ -28,16 +28,16 @@ public class PerformanceTest {
// 1. Stress test Clue Generation (Mask Generation)
System.out.println("[DEBUG_LOG] --- Mask Generation Performance ---");
int[] clueSizes = { 20, 25, 30 };
var arr = new Clues[3];
int c = 0;
for (int size : clueSizes) {
long t0 = System.currentTimeMillis();
val masker = new Masker(rng, new int[SwedishGenerator.STACK_SIZE], Masker.Clues.createEmpty());
var clueSizes = new int[]{ 20, 25, 30 };
var arr = new Clues[3];
var c = 0;
for (var size : clueSizes) {
var t0 = System.currentTimeMillis();
val masker = new Masker(rng, new int[SwedishGenerator.STACK_SIZE], Masker.Clues.createEmpty());
// Increased population and generations for stress
arr[c++] = masker.generateMask(size, 200, 100, 50);
long t1 = System.currentTimeMillis();
double duration = (t1 - t0) / 1000.0;
var t1 = System.currentTimeMillis();
var duration = (t1 - t0) / 1000.0;
System.out.printf(Locale.ROOT, "[DEBUG_LOG] Size %d (pop=200, gen=100): %.3fs%n", size, duration);
// Basic sanity check: should not take forever
assertTrue(duration < 10.0, "Mask generation took too long for size " + size);
@@ -46,16 +46,16 @@ public class PerformanceTest {
// 2. Stress test Word Filler
System.out.println("[DEBUG_LOG] \n--- Word Filler Performance ---");
c = 0;
for (int size : clueSizes) {
for (var size : clueSizes) {
long t0 = System.currentTimeMillis();
var t0 = System.currentTimeMillis();
// Try to fill multiple times to get a better average
int iterations = 10;
var iterations = 10;
long totalNodes = 0;
long totalBacktracks = 0;
int successCount = 0;
var successCount = 0;
for (int i = 0; i < iterations; i++) {
for (var i = 0; i < iterations; i++) {
val slotInfo = Masker.slots(arr[c], EN);
val result = fillMask(rng, slotInfo, Slotinfo.grid(slotInfo));
if (result.ok()) successCount++;
@@ -63,8 +63,8 @@ public class PerformanceTest {
totalBacktracks += result.backtracks();
}
c++;
long t1 = System.currentTimeMillis();
double totalDuration = (t1 - t0) / 1000.0;
var t1 = System.currentTimeMillis();
var totalDuration = (t1 - t0) / 1000.0;
System.out.printf(Locale.ROOT, "[DEBUG_LOG] Size %d: %d/%d SUCCESS | avg nodes=%d | avg backtracks=%d | total time=%.3fs%n",
size, successCount, iterations, totalNodes / iterations, totalBacktracks / iterations, totalDuration);
@@ -74,14 +74,14 @@ public class PerformanceTest {
void testIncrementalComplexity() {
// Use the complex mask from Main.java
String maskStr = "1 0000\n" +
"1 \n" +
"00 01 \n" +
" 1 \n" +
" 1 \n" +
" 2 1 \n" +
" 1 \n" +
"221 22\n";
var maskStr = "1 0000\n" +
"1 \n" +
"00 01 \n" +
" 1 \n" +
" 1 \n" +
" 2 1 \n" +
" 1 \n" +
"221 22\n";
val mask = Clued.parse(maskStr);
val allSlots = Masker.slots(mask.c(), DICT900.index());
//mask.toGrid()
@@ -89,7 +89,7 @@ public class PerformanceTest {
System.out.println("[DEBUG_LOG] Full Slot Layout:");
visualizeSlots(allSlots);
for (int i = 10; i <= allSlots.length; i++) {
for (var i = 10; i <= allSlots.length; i++) {
val subset = Arrays.copyOf(allSlots, i);
// Arrays.sort(subset, Comparator.comparingInt(Slotinfo::score));
System.out.printf("[DEBUG_LOG] Testing with first %d slots%n of %s", i, allSlots.length);
@@ -115,15 +115,15 @@ public class PerformanceTest {
}
private void measureFill(Rng rng, Slotinfo[] slots, String label) {
long t0 = System.currentTimeMillis();
int iterations = 1;
var t0 = System.currentTimeMillis();
var iterations = 1;
long totalNodes = 0;
long totalBacktracks = 0;
int successCount = 0;
var successCount = 0;
for (int i = 0; i < iterations; i++) {
for (var i = 0; i < iterations; i++) {
// Reset assignments for each iteration
for (Slotinfo s : slots) s.assign().w = 0;
for (var s : slots) s.assign().w = 0;
val result = fillMask(rng, slots, Slotinfo.grid(slots));
if (result.ok()) {
@@ -132,8 +132,8 @@ public class PerformanceTest {
totalNodes += result.nodes();
totalBacktracks += result.backtracks();
}
long t1 = System.currentTimeMillis();
double totalDuration = (t1 - t0) / 1000.0;
var t1 = System.currentTimeMillis();
var totalDuration = (t1 - t0) / 1000.0;
System.out.printf(Locale.ROOT, "[DEBUG_LOG] %s: %d/%d SUCCESS | avg nodes=%d | avg backtracks=%d | total time=%.3fs%n",
label, successCount, iterations, totalNodes / iterations, totalBacktracks / iterations, totalDuration);
@@ -141,28 +141,28 @@ public class PerformanceTest {
}
private void visualizeSlots(Slotinfo[] slots) {
int R = SwedishGenerator.R;
int C = SwedishGenerator.C;
char[][] display = new char[R][C];
for (int r = 0; r < R; r++) Arrays.fill(display[r], ' ');
var R = SwedishGenerator.R;
var C = SwedishGenerator.C;
var display = new char[R][C];
for (var r = 0; r < R; r++) Arrays.fill(display[r], ' ');
for (Slotinfo slot : slots) {
int key = slot.key();
Clue dir = Clue.from(Masker.Slot.dir(key));
int clueIdx = Masker.Slot.clueIndex(key);
for (var slot : slots) {
var key = slot.key();
var dir = Clue.from(Masker.Slot.dir(key));
var clueIdx = Masker.Slot.clueIndex(key);
int cr = Masker.IT[clueIdx].r();
int cc = Masker.IT[clueIdx].c();
var cr = Masker.IT[clueIdx].r();
var cc = Masker.IT[clueIdx].c();
// User requested: aAAAA for a four letter to RIGHT clue slot.
// SwedishGenerator: 1=RIGHT, 0=DOWN, 2=UP, 3=LEFT
char clueChar = dir.clueChar;
char slotChar = dir.slotChar;
var clueChar = dir.clueChar;
var slotChar = dir.slotChar;
display[cr][cc] = clueChar;
Gridded.cellWalk((byte) slot.key(), slot.lo(), slot.hi()).forEach(idx -> {
int r = Masker.IT[idx].r();
int c = Masker.IT[idx].c();
var r = Masker.IT[idx].r();
var c = Masker.IT[idx].c();
if (display[r][c] == ' ' || (display[r][c] >= 'A' && display[r][c] <= 'D')) {
if (display[r][c] != ' ' && display[r][c] != slotChar) {
display[r][c] = '+'; // Intersection
@@ -173,7 +173,7 @@ public class PerformanceTest {
});
}
for (int r = 0; r < R; r++) {
for (var r = 0; r < R; r++) {
System.out.println("[DEBUG_LOG] " + new String(display[r]));
}
}