From e559040321655fd3fa4f213d0c12ef54107fd584 Mon Sep 17 00:00:00 2001 From: mike Date: Sat, 10 Jan 2026 04:25:51 +0100 Subject: [PATCH] introduce bitloops --- pom.xml | 4 +- src/main/generated-sources/puzzle/Config.java | 13 --- src/main/java/puzzle/SwedishGenerator.java | 86 ++++++++----------- 3 files changed, 39 insertions(+), 64 deletions(-) delete mode 100644 src/main/generated-sources/puzzle/Config.java diff --git a/pom.xml b/pom.xml index 42e680c..524f540 100644 --- a/pom.xml +++ b/pom.xml @@ -64,7 +64,7 @@ mike.processor puzzle-processor - 1.1-SNAPSHOT + 1.2-SNAPSHOT provided @@ -104,7 +104,7 @@ mike.processor puzzle-processor - 1.1-SNAPSHOT + 1.2-SNAPSHOT 25 diff --git a/src/main/generated-sources/puzzle/Config.java b/src/main/generated-sources/puzzle/Config.java deleted file mode 100644 index 8d60e3c..0000000 --- a/src/main/generated-sources/puzzle/Config.java +++ /dev/null @@ -1,13 +0,0 @@ -package puzzle; - -/** - * Generated constants from pom.xml during build via templating-maven-plugin. - */ -public final class Config { - public static final int CLUE_SIZE = 4; - public static final int MIN_LEN = 2; - public static final int MAX_TRIES_PER_SLOT = 2000; - public static final int MAX_LEN = 8; - public static final int PUZZLE_ROWS = 8; - public static final int PUZZLE_COLS = 9; -} diff --git a/src/main/java/puzzle/SwedishGenerator.java b/src/main/java/puzzle/SwedishGenerator.java index e09c545..62e91c5 100644 --- a/src/main/java/puzzle/SwedishGenerator.java +++ b/src/main/java/puzzle/SwedishGenerator.java @@ -380,15 +380,22 @@ public record SwedishGenerator(Rng rng) { grid.forEachSlot((key, packedPos, len) -> slots.add(Slot.from(key, packedPos, len))); return slots; } - boolean hasRoomForClue(Grid grid, int idx, nbrs_16 nbrs16) { - int rr = Grid.r(idx) + nbrs16.r(), cc = Grid.c(idx) + nbrs16.c(); - var run = 0; + boolean hasRoomForClue(Grid grid, long packed) { + //long packed = nbrs16.path()[idx]; + int n = (int) (packed >>> 56), k, idx; + for (k = 0; k < n && k < MAX_WORD_LENGTH; ) { + idx = (int) ((packed >>> (k * 7)) & 0x7F); + if (!grid.isLetterAt(idx)) break; + k++; + if (k >= MIN_LEN) return true; + } + /* int rr = Grid.r(idx) + nbrs16.r(), cc = Grid.c(idx) + nbrs16.c(); while (rr >= 0 && rr < R && cc >= 0 && cc < C && (grid.isLetterAt(rr, cc)) && run < MAX_WORD_LENGTH) { run++; rr += nbrs16.dr(); cc += nbrs16.dc(); if (run >= MIN_LEN) return true; - } + }*/ return false; } @@ -409,54 +416,36 @@ public record SwedishGenerator(Rng rng) { while (lo_cl != 0) { int clueIdx = Long.numberOfTrailingZeros(lo_cl); lo_cl &= (lo_cl - 1); - - var d = grid.digitAt(clueIdx); - var nbrs16 = OFFSETS[d]; - int rr = Grid.r(clueIdx) + nbrs16.r(), cc = Grid.c(clueIdx) + nbrs16.c(); - if (rr < 0 || rr >= R || cc < 0 || cc >= C || grid.isDigitAt(rr, cc)) continue; - - long packedPos = 0; - var n = 0; - while (rr >= 0 && rr < R && cc >= 0 && cc < C && n < MAX_WORD_LENGTH) { - if (grid.isDigitAt(rr, cc)) break; - packedPos |= (long) Grid.offset(rr, cc) << (n * 7); - n++; - rr += nbrs16.dr(); - cc += nbrs16.dc(); + var d = grid.digitAt(clueIdx); + var nbrs16 = OFFSETS[d]; + long packed = nbrs16.path()[clueIdx]; + int n = (int) (packed >>> 56), k, idx; + var horiz = Slot.horiz(d) ? covH : covV; + for (k = 0; k < n && k < MAX_WORD_LENGTH; k++) { + idx = (int) ((packed >>> (k * 7)) & 0x7F); + if (grid.isClue(idx)) break; + horiz[idx] += 1; } - if (n == 0) continue; + if (k == 0) continue; hasSlots = true; - if (n < MIN_LEN) { - penalty[0] += 8000; - } - var horiz = Slot.horiz(d) ? covH : covV; - for (var i = 0; i < n; i++) horiz[Slot.offset(packedPos, i)] += 1; + if (k < MIN_LEN) penalty[0] += 8000; } while (hi_cl != 0) { int clueIdx = 64 + Long.numberOfTrailingZeros(hi_cl); hi_cl &= (hi_cl - 1); - - var d = grid.digitAt(clueIdx); - var nbrs16 = OFFSETS[d]; - int rr = Grid.r(clueIdx) + nbrs16.r(), cc = Grid.c(clueIdx) + nbrs16.c(); - if (rr < 0 || rr >= R || cc < 0 || cc >= C || grid.isDigitAt(rr, cc)) continue; - - long packedPos = 0; - var n = 0; - while (rr >= 0 && rr < R && cc >= 0 && cc < C && n < MAX_WORD_LENGTH) { - if (grid.isDigitAt(rr, cc)) break; - packedPos |= (long) Grid.offset(rr, cc) << (n * 7); - n++; - rr += nbrs16.dr(); - cc += nbrs16.dc(); + var d = grid.digitAt(clueIdx); + var nbrs16 = OFFSETS[d]; + long packed = nbrs16.path()[clueIdx]; + int n = (int) (packed >>> 56), k, idx; + var horiz = Slot.horiz(d) ? covH : covV; + for (k = 0; k < n && k < MAX_WORD_LENGTH; k++) { + idx = (int) ((packed >>> (k * 7)) & 0x7F); + if (grid.isClue(idx)) break; + horiz[idx] += 1; } - if (n == 0) continue; + if (k == 0) continue; hasSlots = true; - if (n < MIN_LEN) { - penalty[0] += 8000; - } - var horiz = Slot.horiz(d) ? covH : covV; - for (var i = 0; i < n; i++) horiz[Slot.offset(packedPos, i)] += 1; + if (k < MIN_LEN) penalty[0] += 8000; } if (!hasSlots) return 1_000_000_000L; @@ -510,8 +499,7 @@ public record SwedishGenerator(Rng rng) { h = covH[rci.i()]; v = covV[rci.i()]; if (h == 0 && v == 0) penalty[0] += 1500; - else if (h > 0 && v > 0) { /* ok */ } - else if (h + v == 1) penalty[0] += 200; + else if (h > 0 && v > 0) { /* ok */ } else if (h + v == 1) penalty[0] += 200; else penalty[0] += 600; } return penalty[0]; @@ -525,7 +513,7 @@ public record SwedishGenerator(Rng rng) { if (g.isClue(idx)) continue; var d = OFFSETS[rng.randbyte(1, 4)]; - if (hasRoomForClue(g, idx, d)) { + if (hasRoomForClue(g, d.path()[idx])) { g.setClue(idx, d.dbyte()); placed++; } @@ -545,7 +533,7 @@ public record SwedishGenerator(Rng rng) { if (!g.clueless(ri)) { var d = OFFSETS[rng.randint(1, 4)]; - if (hasRoomForClue(g, ri, d)) g.setClue(ri, d.dbyte()); + if (hasRoomForClue(g, d.path()[ri])) g.setClue(ri, d.dbyte()); } } return g; @@ -557,7 +545,7 @@ public record SwedishGenerator(Rng rng) { var nr = Math.sin(theta); for (var rci : IT) out.setAt(rci.i(), ((rci.r() - CROSS_C) * nc + (rci.c() - CROSS_R) * nr >= 0) ? a.byteAt(rci.i()) : b.byteAt(rci.i())); - for (var rci : IT) if (out.isDigitAt(rci.i()) && !hasRoomForClue(out, rci.i(), OFFSETS[out.digitAt(rci.i())])) out.clearClue(rci.i()); + for (var rci : IT) if (out.isClue(rci.i()) && !hasRoomForClue(out, OFFSETS[out.digitAt(rci.i())].path()[rci.i()])) out.clearClue(rci.i()); return out; }