diff --git a/src/main/java/puzzle/SwedishGenerator.java b/src/main/java/puzzle/SwedishGenerator.java index 97faf96..ccfb8fe 100644 --- a/src/main/java/puzzle/SwedishGenerator.java +++ b/src/main/java/puzzle/SwedishGenerator.java @@ -447,9 +447,44 @@ public record SwedishGenerator(Rng rng) { var seen = ctx.seen; seen.clear(); var stack = ctx.stack; - - for (var lo = grid.bo[0]; lo != 0; lo &= lo - 1) penalty += clueStackPenalty(seen, stack, grid, Long.numberOfTrailingZeros(lo)); - for (var hi = grid.bo[1]; hi != 0; hi &= hi - 1) penalty += clueStackPenalty(seen, stack, grid, 64 + Long.numberOfTrailingZeros(hi)); + class Mask { + + long penalty; + Mask(long pen) { this.penalty = pen; } + void clueStackPenalty(int clueIdx) { + if (seen.get(clueIdx)) ; + var sp = 0; + stack[sp++] = clueIdx; + seen.set(clueIdx); + var size = 0; + + while (sp > 0) { + var p = stack[--sp]; + size++; + long packed = Neighbors9x8.NBR8_PACKED[p]; + int n = (int) (packed >>> 56); + for (int k = 0; k < n; k++) { + int nidx = (int) ((packed >>> (k * 7)) & 0x7F); + if (seen.get(nidx) || grid.notClue(nidx)) continue; + seen.set(nidx); + stack[sp++] = nidx; + } + } + if (size >= 2) this.penalty += ((size - 1L) * 120L); + } + void wall(rci rci) { + if ((4 - rci.nbrCount()) + Long.bitCount(rci.n1() & grid.bo[0]) + Long.bitCount(rci.n2() & grid.bo[1]) >= 3) this.penalty += 400; + var h = covH[rci.i()]; + var v = covV[rci.i()]; + if (h == 0 && v == 0) this.penalty += 1500; + else if (h > 0 && v > 0) { /* ok */ } else if (h + v == 1) penalty += 200; + else this.penalty += 600; + } + + } + val mask = new Mask(penalty); + for (var lo = grid.bo[0]; lo != 0; lo &= lo - 1) mask.clueStackPenalty(Long.numberOfTrailingZeros(lo)); + for (var hi = grid.bo[1]; hi != 0; hi &= hi - 1) mask.clueStackPenalty(64 + Long.numberOfTrailingZeros(hi)); // dead-end-ish letter cell (3+ walls) int walls, wc, wr; @@ -463,39 +498,10 @@ public record SwedishGenerator(Rng rng) { } if (walls >= 3) penalty[0] += 400; }*/ - int h, v; - for (var rci : IT) { - if (grid.isClue(rci.i())) continue; - if ((4 - rci.nbrCount()) + Long.bitCount(rci.n1() & grid.bo[0]) + Long.bitCount(rci.n2() & grid.bo[1]) >= 3) penalty += 400; - h = covH[rci.i()]; - v = covV[rci.i()]; - if (h == 0 && v == 0) penalty += 1500; - else if (h > 0 && v > 0) { /* ok */ } else if (h + v == 1) penalty += 200; - else penalty += 600; - } - return penalty; - } - static long clueStackPenalty(Bit seen, int[] stack, Grid grid, int clueIdx) { - if (seen.get(clueIdx)) return 0; - var sp = 0; - stack[sp++] = clueIdx; - seen.set(clueIdx); - var size = 0; - - while (sp > 0) { - var p = stack[--sp]; - size++; - long packed = Neighbors9x8.NBR8_PACKED[p]; - int n = (int) (packed >>> 56); - for (int k = 0; k < n; k++) { - int nidx = (int) ((packed >>> (k * 7)) & 0x7F); - if (seen.get(nidx) || grid.notClue(nidx)) continue; - seen.set(nidx); - stack[sp++] = nidx; - } - } - return (size >= 2) ? (size - 1L) * 120L : 0; + for (var rci : IT) if (grid.notClue(rci.i())) mask.wall(rci); + return mask.penalty; } + Grid randomMask() { var g = Grid.createEmpty(); for (int placed = 0, guard = 0, idx; placed < TARGET_CLUES && guard < 4000; guard++) {