From 123cdbdc01630fcfa1359a40eb77bf3c0380a9b7 Mon Sep 17 00:00:00 2001 From: mike Date: Mon, 12 Jan 2026 03:52:52 +0100 Subject: [PATCH] introduce bitloops --- src/main/java/puzzle/Export.java | 4 +- src/main/java/puzzle/SwedishGenerator.java | 76 ++++++++++++---------- src/test/java/puzzle/MainTest.java | 4 +- 3 files changed, 47 insertions(+), 37 deletions(-) diff --git a/src/main/java/puzzle/Export.java b/src/main/java/puzzle/Export.java index 71ecdc1..ca24b9c 100644 --- a/src/main/java/puzzle/Export.java +++ b/src/main/java/puzzle/Export.java @@ -58,11 +58,11 @@ public record Export() { static long pack(int r, int c) { return (((long) r) << 32) ^ (c & 0xFFFFFFFFL); } long l1, l2; public boolean get(int bitIndex) { - if (bitIndex < 64) return (l1 & (1L << bitIndex)) != 0L; + if ((bitIndex & 64) == 0) return (l1 & (1L << bitIndex)) != 0L; return (l2 & (1L << (bitIndex & 63))) != 0L; } public void set(int bitIndex) { - if (bitIndex < 64) this.l1 |= 1L << bitIndex; + if ((bitIndex & 64) == 0) this.l1 |= 1L << bitIndex; else this.l2 |= 1L << (bitIndex & 63); } public void clear() { diff --git a/src/main/java/puzzle/SwedishGenerator.java b/src/main/java/puzzle/SwedishGenerator.java index 70f187b..7afbe5c 100644 --- a/src/main/java/puzzle/SwedishGenerator.java +++ b/src/main/java/puzzle/SwedishGenerator.java @@ -57,7 +57,6 @@ public record SwedishGenerator(Rng rng) { static final double SIZED = (double) SIZE;// ~18 static final int TARGET_CLUES = SIZE >> 2; static final int MAX_WORD_LENGTH = C <= R ? C : R; - static final int MAX_WORD_LENGTH7 = MAX_WORD_LENGTH * 7; static final int MAX_WORD_LENGTH_PLUS_ONE = MAX_WORD_LENGTH + 1; static final int MIN_LEN = Config.MIN_LEN; static final int MIN_LEN7 = Config.MIN_LEN * 7; @@ -123,8 +122,8 @@ public record SwedishGenerator(Rng rng) { static final class Context { - final int[] covH = new int[SIZE]; - final int[] covV = new int[SIZE]; + final Bit covH2 = new Bit(); + final Bit covV2 = new Bit(); final int[] cellCount = new int[SIZE]; final int[] stack = new int[SIZE]; final Bit seen = new Bit(); @@ -188,35 +187,32 @@ public record SwedishGenerator(Rng rng) { void setByteAt(int idx, byte ch) { g[idx] = ch; } void setClue(int idx, byte ch) { g[idx] = ch; - if (idx < 64) lo |= (1L << idx); + if ((idx & 64) == 0) lo |= (1L << idx); else hi |= (1L << (idx & 63)); } void clearletter(int idx) { g[idx] = DASH; } void clearClue(int idx) { g[idx] = DASH; - if (idx < 64) lo &= ~(1L << idx); + if ((idx & 64) == 0) lo &= ~(1L << idx); else hi &= ~(1L << (idx & 63)); } static boolean isDigit(byte b) { return (b & B48) == B48; } boolean isDigitAt(int index) { return isDigit(g[index]); } boolean isClue(long index) { - if (index < 64) return ((lo >> index) & 1L) != X; + if ((index & 64) == 0) return ((lo >> index) & 1L) != X; return ((hi >> (index & 63)) & 1L) != X; } boolean isClue(int index) { - if (index < 64) return ((lo >> index) & 1L) != 0; + if ((index & 64) == 0) return ((lo >> index) & 1L) != 0; return ((hi >> (index & 63)) & 1L) != 0; } boolean notClue(long index) { - if (index < 64) return ((lo >> index) & 1L) == X; - return ((hi >> (index & 63)) & 1L) == X; - } - boolean notClue(int index) { - if (index < 64) return ((lo >> index) & 1L) == X; + if ((index & 64) == 0) return ((lo >> index) & 1L) == X; return ((hi >> (index & 63)) & 1L) == X; } + boolean notClue(int index) { return ((index & 64) == 0) ? ((lo >> index) & 1L) == X : ((hi >> (index & 63)) & 1L) == X; } boolean clueless(int idx) { - if (idx < 64) { + if ((idx & 64) == 0) { val test = (1L << idx); if ((test & lo) == X) return false; g[idx] = DASH; @@ -257,6 +253,9 @@ public record SwedishGenerator(Rng rng) { public static record Lemma(int index, long word, byte len) { static int LEMMA_COUNTER = 0; + static long pack(String word) { + return pack(word.getBytes(US_ASCII)); + } static long pack(byte[] b) { long w = 0; for (var i = 0; i < b.length; i++) w |= ((long) b[i] & ~64) << (i * 5); @@ -394,7 +393,7 @@ public record SwedishGenerator(Rng rng) { long packed = nbrs16.path()[clueIdx]; int n = (int) (packed >>> 56) * 7, k, idx; var horiz = Slot.horiz(d) ? covH : covV; - for (k = 0; k < n && k < MAX_WORD_LENGTH7; k += 7) { + for (k = 0; k < n; k += 7) { idx = (int) ((packed >>> (k)) & 0x7F); if (grid.isClue(idx)) break; horiz[idx] += 1; @@ -408,10 +407,12 @@ public record SwedishGenerator(Rng rng) { long maskFitness(Grid grid) { var ctx = CTX.get(); - var covH = ctx.covH; - var covV = ctx.covV; - Arrays.fill(covH, 0, SIZE, 0); - Arrays.fill(covV, 0, SIZE, 0); + var covH = ctx.covH2; + var covV = ctx.covV2; + covH.clear(); + covV.clear(); + /*Arrays.fill(covH, 0, SIZE, 0); + Arrays.fill(covV, 0, SIZE, 0);*/ long lo_cl = grid.lo, hi_cl = grid.hi; long penalty = (((long) Math.abs(grid.clueCount() - TARGET_CLUES)) * 16000L); boolean hasSlots = false; @@ -424,10 +425,10 @@ public record SwedishGenerator(Rng rng) { long packed = nbrs16.path()[clueIdx]; int n = (int) (packed >>> 56) * 7, k, idx; var horiz = Slot.horiz(d) ? covH : covV; - for (k = 0; k < n && k < MAX_WORD_LENGTH7; k += 7) { + for (k = 0; k < n; k += 7) { idx = (int) ((packed >>> (k)) & 0x7F); if (grid.isClue(idx)) break; - horiz[idx] += 1; + horiz.set(idx); } if (k > 0) { hasSlots = true; @@ -470,10 +471,10 @@ public record SwedishGenerator(Rng rng) { int clueIdx = i + Long.numberOfTrailingZeros(bits); var rci = IT[clueIdx]; if ((4 - rci.nbrCount()) + Long.bitCount(rci.n1() & lo_cl) + Long.bitCount(rci.n2() & hi_cl) >= 3) penalty += 400; - var h = covH[clueIdx]; - var v = covV[clueIdx]; - if (h == 0 && v == 0) penalty += 1500; - else if (h > 0 && v > 0) { /* ok */ } else if (h + v == 1) penalty += 200; + var h = covH.get(clueIdx); + var v = covV.get(clueIdx); + if (!h && !v) penalty += 1500; + else if (h && v) { /* ok */ } else if (h | v) penalty += 200; else penalty += 600; } } @@ -523,10 +524,10 @@ public record SwedishGenerator(Rng rng) { if (out.g[i] != ch) { out.g[i] = ch; if (Grid.isDigit(ch)) { - if (i < 64) bo0 |= (1L << i); + if ((i & 64) == 0) bo0 |= (1L << i); else bo1 |= (1L << (i & 63)); } else { - if (i < 64) bo0 &= ~(1L << i); + if ((i & 64) == 0) bo0 &= ~(1L << i); else bo1 &= ~(1L << (i & 63)); } } @@ -615,6 +616,11 @@ public record SwedishGenerator(Rng rng) { //return pop.get(0).grid; return best.grid; } + static int usedCharsInPattern(long p) { + if (p == 0) return 0; + int highestBit = 63 - Long.numberOfLeadingZeros(p); // 0-based + return (highestBit / 5) + 1; + } static long patternForSlot(Grid grid, Slot s) { long p = 0; for (int i = 0, len = s.len(); i < len; i++) { @@ -654,23 +660,27 @@ public record SwedishGenerator(Rng rng) { return true; } - static CandidateInfo candidateInfoForPattern(Context ctx, DictEntry entry, int len) { + static CandidateInfo candidateInfoForPattern(Context ctx, DictEntry entry, int lenb) { var pattern = ctx.pattern; var listBuffer = ctx.intListBuffer; var listCount = 0; IntList tmp; - for (var i = 0; i < len; i++) { + if (pattern == X) { + return new CandidateInfo(null, entry.words.length); + } + /*if (usedCharsInPattern(pattern) > len) { + var abc = usedCharsInPattern(pattern); + System.out.println(abc); + }*/ + for (int i = 0, len = usedCharsInPattern(pattern); i < len; i++) { int val = (int) ((pattern >>> (i * 5)) & 31); if (val != 0) { listBuffer[listCount++] = entry.pos[i][val - 1]; + } else { + //System.out.println("?"); } } - if (listCount == 0) { - //return CANDIDATES[entry.words.length]; - return new CandidateInfo(null, entry.words.length); - } - // Sort constraints by size to optimize intersection for (var i = 0; i < listCount - 1; i++) { for (var j = i + 1; j < listCount; j++) { diff --git a/src/test/java/puzzle/MainTest.java b/src/test/java/puzzle/MainTest.java index fc067d6..319bf50 100644 --- a/src/test/java/puzzle/MainTest.java +++ b/src/test/java/puzzle/MainTest.java @@ -167,8 +167,8 @@ public class MainTest { // Regression baseline for seed search starting at 12347, pop 4, gens 20 Assertions.assertEquals(12348, foundSeed, "Found seed changed"); Assertions.assertEquals(18, res.filled().clueMap().size(), "Number of assigned words changed"); - Assertions.assertEquals(Lemma.pack(new byte[]{ 'L', 'E', 'L', 'I', 'J', 'K', 'S' }), res.filled().clueMap().get(451).word()); - Assertions.assertEquals(73207692597665799L, res.filled().grid().grid().lo); + Assertions.assertEquals(Lemma.pack("VERPATS"), res.filled().clueMap().get(74).word()); + Assertions.assertEquals(301794542151533187L, res.filled().grid().grid().lo); Assertions.assertEquals(193L, res.filled().grid().grid().hi); } @Test