From 93628f9b4eccfd2a1b629c573e7c499160e6f788 Mon Sep 17 00:00:00 2001 From: mike Date: Mon, 12 Jan 2026 04:27:46 +0100 Subject: [PATCH] introduce bitloops --- src/main/java/puzzle/SwedishGenerator.java | 91 ++++++++++++++++++---- 1 file changed, 74 insertions(+), 17 deletions(-) diff --git a/src/main/java/puzzle/SwedishGenerator.java b/src/main/java/puzzle/SwedishGenerator.java index 7afbe5c..bcc5f9c 100644 --- a/src/main/java/puzzle/SwedishGenerator.java +++ b/src/main/java/puzzle/SwedishGenerator.java @@ -70,18 +70,19 @@ public record SwedishGenerator(Rng rng) { static int clamp(int x, int a, int b) { return Math.max(a, Math.min(b, x)); } record Pick(Slot slot, CandidateInfo info, boolean done) { } - static final byte B0 = (byte) 0; - static final byte B64 = (byte) 64; - static final byte B48 = (byte) 48; + static final byte B0 = (byte) 0; + static final byte B64 = (byte) 64; + static final byte B48 = (byte) 48; // Directions for '1'..'6' - static final nbrs_16[] OFFSETS = Neighbors9x8.OFFSETS; - static final nbrs_16[] OFFSETS_FOUR = Neighbors9x8.OFFSETS_FOUR; - static final nbrs_8[] nbrs8 = Neighbors9x8.nbrs8; - static final nbrs_8[] nbrs4 = Neighbors9x8.nbrs4; - static final rci[] IT = Neighbors9x8.IT; - static final long[] INBR8_PACKEDT = Neighbors9x8.NBR8_PACKED; - static final int[][] MUTATE_RI = new int[SIZE][625]; - static final long[] NBR8_PACKED = Neighbors9x8.NBR8_PACKED; + static final nbrs_16[] OFFSETS = Neighbors9x8.OFFSETS; + static final nbrs_16[] OFFSETS_FOUR = Neighbors9x8.OFFSETS_FOUR; + static final nbrs_8[] nbrs8 = Neighbors9x8.nbrs8; + static final nbrs_8[] nbrs4 = Neighbors9x8.nbrs4; + static final rci[] IT = Neighbors9x8.IT; + static final long[] INBR8_PACKEDT = Neighbors9x8.NBR8_PACKED; + static final int[][] MUTATE_RI = new int[SIZE][625]; + static final long[] NBR8_PACKED_LO = Neighbors9x8.NBR8_PACKED_LO; + static final long[] NBR8_PACKED_HI = Neighbors9x8.NBR8_PACKED_HI; static { for (int i = 0; i < SIZE; i++) { @@ -441,11 +442,67 @@ public record SwedishGenerator(Rng rng) { if (!hasSlots) return 1_000_000_000L; - var seen = ctx.seen; - var stack = ctx.stack; - seen.clear(); - - for (int i = 0; i < 65; i += 64) { + var stack = ctx.stack; + long seenLo = 0L, seenHi = 0L; + +// loop over beide helften + for (int base = 0; base <= 64; base += 64) { + long clueMask = (base == 0) ? lo_cl : hi_cl; + long seenMask = (base == 0) ? seenLo : seenHi; + + // "unseen clues" in deze helft + for (long bits = clueMask & ~seenMask; bits != 0L; bits &= bits - 1) { + int clueIdx = base + Long.numberOfTrailingZeros(bits); + + // start nieuwe component + int size = 0; + int sp = 0; + stack[sp++] = clueIdx; + + // mark seen + if (clueIdx < 64) seenLo |= 1L << clueIdx; + else seenHi |= 1L << (clueIdx - 64); + + // flood fill / bfs + while (sp > 0) { + int cur = stack[--sp]; + size++; + + // neighbors als 2x long masks + long nLo = NBR8_PACKED_LO[cur]; + long nHi = NBR8_PACKED_HI[cur]; + + // filter: alleen clues, en nog niet seen + nLo &= lo_cl & ~seenLo; + nHi &= hi_cl & ~seenHi; + + // push lo-neighbors + while (nLo != 0L) { + long lsb = nLo & -nLo; + int nidx = Long.numberOfTrailingZeros(nLo); // 0..63 + seenLo |= lsb; + + stack[sp++] = nidx; + + nLo &= nLo - 1; + } + + // push hi-neighbors + while (nHi != 0L) { + long lsb = nHi & -nHi; + int nidx = 64 + Long.numberOfTrailingZeros(nHi); // 64..127 + seenHi |= lsb; + + stack[sp++] = nidx; + + nHi &= nHi - 1; + } + } + + if (size >= 2) penalty += (size - 1L) * 120L; + } + } + /*for (int i = 0; i < 65; i += 64) { for (long bits = (i == 0 ? lo_cl : hi_cl); bits != X; bits &= bits - 1) { int clueIdx = i + Long.numberOfTrailingZeros(bits); if (seen.get(clueIdx)) continue; @@ -463,7 +520,7 @@ public record SwedishGenerator(Rng rng) { } if (size >= 2) penalty += ((size - 1L) * 120L); } - } + }*/ for (int i = 0; i < 65; i += 64) { long bits = (i == 0 ? ~lo_cl : (~hi_cl & 0xFFL));