introduce bitloops

This commit is contained in:
mike
2026-01-10 08:45:45 +01:00
parent a3df24e90f
commit d8f51e9136

View File

@@ -447,9 +447,44 @@ public record SwedishGenerator(Rng rng) {
var seen = ctx.seen;
seen.clear();
var stack = ctx.stack;
class Mask {
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));
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;
for (var rci : IT) if (grid.notClue(rci.i())) mask.wall(rci);
return mask.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;
}
Grid randomMask() {
var g = Grid.createEmpty();
for (int placed = 0, guard = 0, idx; placed < TARGET_CLUES && guard < 4000; guard++) {