From cb2935e0f5139efeea90f06d7c3c9e752a223bc3 Mon Sep 17 00:00:00 2001 From: mike Date: Wed, 14 Jan 2026 10:24:55 +0100 Subject: [PATCH] introduce bitloops --- src/main/java/puzzle/SwedishGenerator.java | 94 +++++++++++----------- 1 file changed, 46 insertions(+), 48 deletions(-) diff --git a/src/main/java/puzzle/SwedishGenerator.java b/src/main/java/puzzle/SwedishGenerator.java index c0ab69a..5068b3a 100644 --- a/src/main/java/puzzle/SwedishGenerator.java +++ b/src/main/java/puzzle/SwedishGenerator.java @@ -789,61 +789,59 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) { return cross * 10 + s.length(); } static boolean placeWord(Grid grid, Slot s, long w, long[] undoBuffer, int offset) { - long maskLo = 0, maskHi = 0; - int i = 0; if (s.increasing()) { - for (long b = s.lo; b != 0; b &= b - 1, i++) { - int idx = Long.numberOfTrailingZeros(b); - byte cur = grid.letter32At(idx), ch = Lemma.byteAt(w, i); - if (cur == DASH) { - maskLo |= (1L << idx); - grid.setLetterLo(idx, ch); - } else if (cur != ch) { - grid.undoPlace(maskLo, maskHi); - return false; - } + for (long b = s.lo & grid.lo; b != 0; b &= b - 1) { + int idx = Long.numberOfTrailingZeros(b); + if (grid.g[idx] != Lemma.byteAt(w, Long.bitCount(s.lo & ((1L << idx) - 1)))) return false; } - for (long b = s.hi; b != 0; b &= b - 1, i++) { - int idx = 64 | Long.numberOfTrailingZeros(b); - byte cur = grid.letter32At(idx), ch = Lemma.byteAt(w, i); - if (cur == DASH) { - maskHi |= (1L << (idx & 63)); - grid.setLetterHi(idx, ch); - } else if (cur != ch) { - grid.undoPlace(maskLo, maskHi); - return false; - } + int bcLo = Long.bitCount(s.lo); + for (long b = s.hi & grid.hi; b != 0; b &= b - 1) { + int idx = Long.numberOfTrailingZeros(b); + if (grid.g[64 | idx] != Lemma.byteAt(w, bcLo + Long.bitCount(s.hi & ((1L << idx) - 1)))) return false; } + + long maskLo = s.lo & ~grid.lo, maskHi = s.hi & ~grid.hi; + if ((maskLo | maskHi) != 0) { + for (long b = maskLo; b != 0; b &= b - 1) { + int idx = Long.numberOfTrailingZeros(b); + grid.g[idx] = Lemma.byteAt(w, Long.bitCount(s.lo & ((1L << idx) - 1))); + } + for (long b = maskHi; b != 0; b &= b - 1) { + int idx = Long.numberOfTrailingZeros(b); + grid.g[64 | idx] = Lemma.byteAt(w, bcLo + Long.bitCount(s.hi & ((1L << idx) - 1))); + } + grid.lo |= maskLo; + grid.hi |= maskHi; + } + undoBuffer[offset << 1] = maskLo; + undoBuffer[(offset << 1) | 1] = maskHi; } else { - for (long b = s.hi; b != 0; i++) { - int msb = 63 - Long.numberOfLeadingZeros(b); - int idx = 64 | msb; - byte cur = grid.letter32At(idx), ch = Lemma.byteAt(w, i); - if (cur == DASH) { - maskHi |= (1L << msb); - grid.setLetterHi(idx, ch); - } else if (cur != ch) { - grid.undoPlace(maskLo, maskHi); - return false; - } - b &= ~(1L << msb); + int bcHi = Long.bitCount(s.hi); + for (long b = s.hi & grid.hi; b != 0; b &= b - 1) { + int idx = Long.numberOfTrailingZeros(b); + if (grid.g[64 | idx] != Lemma.byteAt(w, Long.bitCount(s.hi & ~((1L << idx) | ((1L << idx) - 1))))) return false; } - for (long b = s.lo; b != 0; i++) { - int msb = 63 - Long.numberOfLeadingZeros(b); - int idx = msb; - byte cur = grid.letter32At(idx), ch = Lemma.byteAt(w, i); - if (cur == DASH) { - maskLo |= (1L << msb); - grid.setLetterLo(idx, ch); - } else if (cur != ch) { - grid.undoPlace(maskLo, maskHi); - return false; - } - b &= ~(1L << msb); + for (long b = s.lo & grid.lo; b != 0; b &= b - 1) { + int idx = Long.numberOfTrailingZeros(b); + if (grid.g[idx] != Lemma.byteAt(w, bcHi + Long.bitCount(s.lo & ~((1L << idx) | ((1L << idx) - 1))))) return false; } + + long maskLo = s.lo & ~grid.lo, maskHi = s.hi & ~grid.hi; + if ((maskLo | maskHi) != 0) { + for (long b = maskHi; b != 0; b &= b - 1) { + int idx = Long.numberOfTrailingZeros(b); + grid.g[64 | idx] = Lemma.byteAt(w, Long.bitCount(s.hi & ~((1L << idx) | ((1L << idx) - 1)))); + } + for (long b = maskLo; b != 0; b &= b - 1) { + int idx = Long.numberOfTrailingZeros(b); + grid.g[idx] = Lemma.byteAt(w, bcHi + Long.bitCount(s.lo & ~((1L << idx) | ((1L << idx) - 1)))); + } + grid.lo |= maskLo; + grid.hi |= maskHi; + } + undoBuffer[offset << 1] = maskLo; + undoBuffer[(offset << 1) | 1] = maskHi; } - undoBuffer[offset << 1] = maskLo; - undoBuffer[(offset << 1) | 1] = maskHi; return true; }