From 60b7509bf69cdb28b18c1bb20a9c0df9b3605f7e Mon Sep 17 00:00:00 2001 From: mike Date: Fri, 16 Jan 2026 23:48:36 +0100 Subject: [PATCH] introduce bitloops --- src/main/java/puzzle/SwedishGenerator.java | 42 ++++++++++------------ 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/src/main/java/puzzle/SwedishGenerator.java b/src/main/java/puzzle/SwedishGenerator.java index 5a44e12..194dc1c 100644 --- a/src/main/java/puzzle/SwedishGenerator.java +++ b/src/main/java/puzzle/SwedishGenerator.java @@ -205,7 +205,6 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) { if ((idx & 2) != 0) rhi |= mask; else rhi &= ~mask; } - int digitAtLo(int idx) { return (int) ((((rlo >>> idx) & 1L) << 1) | ((vlo >>> idx) & 1L)); } void clearClueLo(long mask) { lo &= mask; vlo &= mask; @@ -229,7 +228,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) { return (Long.bitCount(matchLo & MASK_LO) + Long.bitCount(matchHi & MASK_HI)) / SIZED; } public Grid toGrid() { return new Grid(new byte[SIZE], lo, hi); } - public void forEachSlot(SwedishGenerator.SlotVisitor visitor) { + public void forEachSlot(SlotVisitor visitor) { for (var l = lo & ~rlo & vlo; l != X; l &= l - 1) processSlot(this, visitor, Slot.packSlotKey(Long.numberOfTrailingZeros(l), 1)); for (var l = lo & ~rlo & ~vlo; l != X; l &= l - 1) processSlot(this, visitor, Slot.packSlotKey(Long.numberOfTrailingZeros(l), 0)); for (var l = lo & rlo & ~vlo; l != X; l &= l - 1) processSlotRev(this, visitor, Slot.packSlotKey(Long.numberOfTrailingZeros(l), 2)); @@ -277,7 +276,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) { static String[] clue(long w) { return CsvIndexService.clues(unpackIndex(w)); } static int simpel(long w) { return CsvIndexService.simpel(unpackIndex(w)); } static int length(long word) { return ((63 - Long.numberOfLeadingZeros(word & LETTER_MASK)) / 5) + 1; } - static ThreadLocal BYTES = ThreadLocal.withInitial(() -> new byte[SwedishGenerator.MAX_WORD_LENGTH]); + static ThreadLocal BYTES = ThreadLocal.withInitial(() -> new byte[MAX_WORD_LENGTH]); public static String asWord(long word) { val len = Lemma.length(word); var b = BYTES.get();//new byte[Lemma.length(word)]; @@ -370,7 +369,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) { visitor.visit(key, rayLo, rayHi); } - private static void processSlot(Clues c, SwedishGenerator.SlotVisitor visitor, int key) { + private static void processSlot(Clues c, SlotVisitor visitor, int key) { long rayLo = PATH_LO[key]; long rayHi = PATH_HI[key]; long hitsLo = rayLo & c.lo; @@ -589,10 +588,9 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) { return g; } static boolean isLo(int n) { return (n & 64) == 0; } - Clues mutate(SwedishGenerator.Clues c) { - int ri; + Clues mutate(Clues c) { var bytes = MUTATE_RI[rng.randint0_SIZE()]; - for (var k = 0; k < 4; k++) { + for (int k = 0, ri; k < 4; k++) { ri = bytes[rng.randint0_624()]; if (isLo(ri)) { if (!c.cluelessLo(ri)) { @@ -631,22 +629,18 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) { (a.rlo & ~maskLo) | (other.rlo & maskLo), (a.rhi & ~maskHi) | (other.rhi & maskHi)); - // for (var lo = c.lo; lo != X; lo &= lo - 1L) clearCluesLo(c, Long.numberOfTrailingZeros(lo)); - // for (var hi = c.hi; hi != X; hi &= hi - 1L) clearCluesHi(c, Long.numberOfTrailingZeros(hi)); - - for (var l = c.lo & ~c.rlo & ~c.vlo ; l != X; l &= l - 1) clearCluesLo(c,Long.numberOfTrailingZeros(l), 0); - for (var l = c.lo & ~c.rlo & c.vlo ; l != X; l &= l - 1) clearCluesLo(c,Long.numberOfTrailingZeros(l), 1); - for (var l = c.lo & c.rlo & ~c.vlo ; l != X; l &= l - 1) clearCluesLo(c,Long.numberOfTrailingZeros(l), 2); - for (var l = c.lo & c.rlo & c.vlo ; l != X; l &= l - 1) clearCluesLo(c,Long.numberOfTrailingZeros(l), 3); - for (var h = c.hi & ~c.rhi & ~c.vhi ; h != X; h &= h - 1) clearCluesHi(c, Long.numberOfTrailingZeros(h), 0); - for (var h = c.hi & ~c.rhi & c.vhi ; h != X; h &= h - 1) clearCluesHi(c, Long.numberOfTrailingZeros(h), 1); - for (var h = c.hi & c.rhi & ~c.vhi ; h != X; h &= h - 1) clearCluesHi(c,( Long.numberOfTrailingZeros(h)), 2); - for (var h = c.hi & c.rhi & ~c.vhi ; h != X; h &= h - 1) clearCluesHi(c,( Long.numberOfTrailingZeros(h)), 3); + for (var l = c.lo & ~c.rlo & ~c.vlo; l != X; l &= l - 1) clearCluesLo(c, Long.numberOfTrailingZeros(l), 0); + for (var l = c.lo & ~c.rlo & c.vlo; l != X; l &= l - 1) clearCluesLo(c, Long.numberOfTrailingZeros(l), 1); + for (var l = c.lo & c.rlo & ~c.vlo; l != X; l &= l - 1) clearCluesLo(c, Long.numberOfTrailingZeros(l), 2); + for (var l = c.lo & c.rlo & c.vlo; l != X; l &= l - 1) clearCluesLo(c, Long.numberOfTrailingZeros(l), 3); + for (var h = c.hi & ~c.rhi & ~c.vhi; h != X; h &= h - 1) clearCluesHi(c, Long.numberOfTrailingZeros(h), 0); + for (var h = c.hi & ~c.rhi & c.vhi; h != X; h &= h - 1) clearCluesHi(c, Long.numberOfTrailingZeros(h), 1); + for (var h = c.hi & c.rhi & ~c.vhi; h != X; h &= h - 1) clearCluesHi(c, (Long.numberOfTrailingZeros(h)), 2); + for (var h = c.hi & c.rhi & ~c.vhi; h != X; h &= h - 1) clearCluesHi(c, (Long.numberOfTrailingZeros(h)), 3); return c; } - public static void clearCluesLo(Clues out, int idx) { if (!out.hasRoomForClue(OFFSETS_D_IDX[Slot.packSlotKey(idx, out.digitAtLo(idx))])) out.clearClueLo(~(1L << idx)); } - public static void clearCluesLo(Clues out, int idx,int d) { if (!out.hasRoomForClue(OFFSETS_D_IDX[Slot.packSlotKey(idx, d)])) out.clearClueLo(~(1L << idx)); } - public static void clearCluesHi(Clues out, int idx,int d) { if (!out.hasRoomForClue(OFFSETS_D_IDX[Slot.packSlotKey(64 | idx, d)])) out.clearClueHi(~(1L << idx)); } + public static void clearCluesLo(Clues out, int idx, int d) { if (!out.hasRoomForClue(OFFSETS_D_IDX[Slot.packSlotKey(idx, d)])) out.clearClueLo(~(1L << idx)); } + public static void clearCluesHi(Clues out, int idx, int d) { if (!out.hasRoomForClue(OFFSETS_D_IDX[Slot.packSlotKey(64 | idx, d)])) out.clearClueHi(~(1L << idx)); } Clues hillclimb(Clues start, int clue_size, int limit) { var best = start; @@ -891,7 +885,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) { } } - public static SwedishGenerator.FillResult fillMask(Rng rng, Slot[] slots, Grid mask) { + public static FillResult fillMask(Rng rng, Slot[] slots, Grid mask) { val multiThreaded = Thread.currentThread().getName().contains("pool"); val NO_LOG = (!Main.VERBOSE || multiThreaded); val grid = mask; @@ -909,7 +903,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) { class Solver { - private final SwedishGenerator.Pick CARRIER = new Pick(null, null, 0); + private final Pick CARRIER = new Pick(null, null, 0); long nodes; long backtracks; int lastMRV; @@ -1064,7 +1058,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) { // final progress line var res = new FillResult(ok, new Gridded(grid), assigned, - new SwedishGenerator.FillStats(solver.nodes, solver.backtracks, (System.currentTimeMillis() - t0) / 1000.0, solver.lastMRV)); + new FillStats(solver.nodes, solver.backtracks, (System.currentTimeMillis() - t0) / 1000.0, solver.lastMRV)); if (!multiThreaded) { System.out.print("\r" + Strings.padRight("", 120) + "\r"); System.out.flush();