introduce bitloops
This commit is contained in:
@@ -153,56 +153,55 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
double nextFloat() { return (nextU32() & 0xFFFFFFFFL) / 4294967295.0; }
|
double nextFloat() { return (nextU32() & 0xFFFFFFFFL) / 4294967295.0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
record Grid(byte[] g, long[] bo) {
|
static class Grid {
|
||||||
|
final byte[] g;
|
||||||
|
long bo0, bo1;
|
||||||
|
|
||||||
public Grid(byte[] g) { this(g, new long[2]); }
|
public Grid(byte[] g) { this(g, 0, 0); }
|
||||||
static Grid createEmpty() { return new Grid(new byte[SIZE], new long[2]); }
|
public Grid(byte[] g, long bo0, long bo1) { this.g = g; this.bo0 = bo0; this.bo1 = bo1; }
|
||||||
|
static Grid createEmpty() { return new Grid(new byte[SIZE], 0L, 0L); }
|
||||||
int digitAt(int index) { return g[index] - 48; }
|
int digitAt(int index) { return g[index] - 48; }
|
||||||
public static int r(int offset) { return offset & 7; }
|
public static int r(int offset) { return offset & 7; }
|
||||||
public static int c(int offset) { return offset >>> 3; }
|
public static int c(int offset) { return offset >>> 3; }
|
||||||
static int offset(int r, int c) { return r | (c << 3); }
|
static int offset(int r, int c) { return r | (c << 3); }
|
||||||
Grid deepCopyGrid() { return new Grid(g.clone(), bo.clone()); }
|
Grid deepCopyGrid() { return new Grid(g.clone(), bo0, bo1); }
|
||||||
public byte byteAt(int pos) { return g[pos]; }
|
public byte byteAt(int pos) { return g[pos]; }
|
||||||
void setByteAt(int idx, byte ch) { g[idx] = ch; }
|
void setByteAt(int idx, byte ch) { g[idx] = ch; }
|
||||||
void setClue(int idx, byte ch) {
|
void setClue(int idx, byte ch) {
|
||||||
g[idx] = ch;
|
g[idx] = ch;
|
||||||
if (idx < 64) bo[0] |= (1L << idx);
|
if (idx < 64) bo0 |= (1L << idx);
|
||||||
else bo[1] |= (1L << (idx & 63));
|
else bo1 |= (1L << (idx & 63));
|
||||||
}
|
}
|
||||||
void clear(int idx) { g[idx] = DASH; }
|
void clear(int idx) { g[idx] = DASH; }
|
||||||
void clearClue(int idx) {
|
void clearClue(int idx) {
|
||||||
g[idx] = DASH;
|
g[idx] = DASH;
|
||||||
if (idx < 64) bo[0] &= ~(1L << idx);
|
if (idx < 64) bo0 &= ~(1L << idx);
|
||||||
else bo[1] &= ~(1L << (idx & 63));
|
else bo1 &= ~(1L << (idx & 63));
|
||||||
}
|
}
|
||||||
static boolean isDigit(byte b) { return (b & 48) == 48; }
|
static boolean isDigit(byte b) { return (b & 48) == 48; }
|
||||||
boolean isDigitAt(int index) { return isDigit(g[index]); }
|
boolean isDigitAt(int index) { return isDigit(g[index]); }
|
||||||
boolean isClue(int index) {
|
boolean isClue(int index) {
|
||||||
if (index < 64) {
|
if (index < 64) return ((bo0 >> index) & 1L) != 0;
|
||||||
return ((bo[0] >> index) & 1L) != 0;
|
return ((bo1 >> (index & 63)) & 1L) != 0;
|
||||||
}
|
|
||||||
return ((bo[1] >> (index & 63)) & 1L) != 0;
|
|
||||||
}
|
}
|
||||||
boolean notClue(int index) {
|
boolean notClue(int index) {
|
||||||
if (index < 64) {
|
if (index < 64) return ((bo0 >> index) & 1L) == 0L;
|
||||||
return ((bo[0] >> index) & 1L) == 0L;
|
return ((bo1 >> (index & 63)) & 1L) == 0L;
|
||||||
}
|
|
||||||
return ((bo[1] >> (index & 63)) & 1L) == 0L;
|
|
||||||
}
|
}
|
||||||
boolean clueless(int idx) {
|
boolean clueless(int idx) {
|
||||||
if (idx < 64) {
|
if (idx < 64) {
|
||||||
val test = (1L << idx);
|
val test = (1L << idx);
|
||||||
if ((test & bo[0]) != 0L) {
|
if ((test & bo0) != 0L) {
|
||||||
g[idx] = DASH;
|
g[idx] = DASH;
|
||||||
bo[0] &= ~test;
|
bo0 &= ~test;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
val test = (1L << (idx & 63));
|
val test = (1L << (idx & 63));
|
||||||
if ((test & bo[1]) != 0L) {
|
if ((test & bo1) != 0L) {
|
||||||
g[idx] = DASH;
|
g[idx] = DASH;
|
||||||
bo[1] &= ~test;
|
bo1 &= ~test;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -218,11 +217,11 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
for (int i = 0; i < SIZE; i++) if (g[i] == b.g[i]) same++;
|
for (int i = 0; i < SIZE; i++) if (g[i] == b.g[i]) same++;
|
||||||
return same / SIZED;
|
return same / SIZED;
|
||||||
}
|
}
|
||||||
int clueCount() { return Long.bitCount(bo[0]) + Long.bitCount(bo[1]); }
|
int clueCount() { return Long.bitCount(bo0) + Long.bitCount(bo1); }
|
||||||
|
|
||||||
void forEachSlot(SlotVisitor visitor) {
|
void forEachSlot(SlotVisitor visitor) {
|
||||||
for (var lo = bo[0]; lo != 0L; lo &= lo - 1) processSlot(this, visitor, Long.numberOfTrailingZeros(lo));
|
for (var lo = bo0; lo != 0L; lo &= lo - 1) processSlot(this, visitor, Long.numberOfTrailingZeros(lo));
|
||||||
for (var hi = bo[1]; hi != 0L; hi &= hi - 1) processSlot(this, visitor, 64 + Long.numberOfTrailingZeros(hi));
|
for (var hi = bo1; hi != 0L; hi &= hi - 1) processSlot(this, visitor, 64 + Long.numberOfTrailingZeros(hi));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,6 +333,23 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int intersectSorted(int[] a, int aLen, int[] b, int bLen, int[] out) {
|
static int intersectSorted(int[] a, int aLen, int[] b, int bLen, int[] out) {
|
||||||
|
if (aLen == 0 || bLen == 0) return 0;
|
||||||
|
if (aLen < bLen >>> 4) {
|
||||||
|
int k = 0;
|
||||||
|
for (int i = 0; i < aLen; i++) {
|
||||||
|
int x = a[i];
|
||||||
|
if (Arrays.binarySearch(b, 0, bLen, x) >= 0) out[k++] = x;
|
||||||
|
}
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
if (bLen < aLen >>> 4) {
|
||||||
|
int k = 0;
|
||||||
|
for (int i = 0; i < bLen; i++) {
|
||||||
|
int y = b[i];
|
||||||
|
if (Arrays.binarySearch(a, 0, aLen, y) >= 0) out[k++] = y;
|
||||||
|
}
|
||||||
|
return k;
|
||||||
|
}
|
||||||
int i = 0, j = 0, k = 0, x, y;
|
int i = 0, j = 0, k = 0, x, y;
|
||||||
while (i < aLen && j < bLen) {
|
while (i < aLen && j < bLen) {
|
||||||
x = a[i];
|
x = a[i];
|
||||||
@@ -393,92 +409,78 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
long maskFitness(Grid grid) {
|
long maskFitness(Grid grid) {
|
||||||
|
|
||||||
var ctx = CTX.get();
|
var ctx = CTX.get();
|
||||||
var covH = ctx.covH;
|
var covH = ctx.covH;
|
||||||
var covV = ctx.covV;
|
var covV = ctx.covV;
|
||||||
Arrays.fill(covH, 0, SIZE, 0);
|
Arrays.fill(covH, 0, SIZE, 0);
|
||||||
Arrays.fill(covV, 0, SIZE, 0);
|
Arrays.fill(covV, 0, SIZE, 0);
|
||||||
|
|
||||||
long lo_cl = grid.bo[0], hi_cl = grid.bo[1];
|
long lo_cl = grid.bo0, hi_cl = grid.bo1;
|
||||||
|
long penalty = (((long) Math.abs(grid.clueCount() - TARGET_CLUES)) << 3);
|
||||||
|
boolean hasSlots = false;
|
||||||
|
|
||||||
// clue clustering (8-connected)
|
for (int i = 0; i < 65; i+=64) {
|
||||||
var seen = ctx.seen;
|
for (long bits = (i == 0 ? lo_cl : hi_cl); bits != 0L; bits &= bits - 1) {
|
||||||
var stack = ctx.stack;
|
int clueIdx = i + Long.numberOfTrailingZeros(bits);
|
||||||
class Mask {
|
var d = grid.digitAt(clueIdx);
|
||||||
|
var nbrs16 = OFFSETS[d];
|
||||||
long penalty = (((long) Math.abs(grid.clueCount() - TARGET_CLUES)) << 3);
|
|
||||||
boolean hasSlots = false;
|
|
||||||
void space(int clueIdx) {
|
|
||||||
var d = grid.digitAt(clueIdx);
|
|
||||||
var nbrs16 = OFFSETS[d];
|
|
||||||
long packed = nbrs16.path()[clueIdx];
|
long packed = nbrs16.path()[clueIdx];
|
||||||
int n = (int) (packed >>> 56) * 7, k, idx;
|
int n = (int) (packed >>> 56) * 7, k, idx;
|
||||||
var horiz = Slot.horiz(d) ? covH : covV;
|
var horiz = Slot.horiz(d) ? covH : covV;
|
||||||
for (k = 0; k < n && k < MAX_WORD_LENGTH7; k += 7) {
|
for (k = 0; k < n && k < MAX_WORD_LENGTH7; k += 7) {
|
||||||
idx = (int) ((packed >>> (k)) & 0x7F);
|
idx = (int) ((packed >>> (k)) & 0x7F);
|
||||||
if (grid.isClue(idx)) break;
|
if (grid.isClue(idx)) break;
|
||||||
horiz[idx] += 1;
|
horiz[idx] += 1;
|
||||||
}
|
}
|
||||||
if (k == 0) return;
|
if (k > 0) {
|
||||||
hasSlots = true;
|
hasSlots = true;
|
||||||
if (k < MIN_LEN7) penalty += 8000;
|
if (k < MIN_LEN7) penalty += 8000;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void clueStackPenalty(int clueIdx) {
|
if (!hasSlots) return 1_000_000_000L;
|
||||||
if (seen.get(clueIdx)) return;
|
|
||||||
int size = 0;
|
var seen = ctx.seen;
|
||||||
long packed;
|
var stack = ctx.stack;
|
||||||
|
seen.clear();
|
||||||
|
|
||||||
|
for (int i = 0; i < 65; i+=64) {
|
||||||
|
for (long bits = (i == 0 ? lo_cl : hi_cl); bits != 0L; bits &= bits - 1) {
|
||||||
|
int clueIdx = i + Long.numberOfTrailingZeros(bits);
|
||||||
|
if (seen.get(clueIdx)) continue;
|
||||||
|
int size = 0;
|
||||||
stack[0] = clueIdx;
|
stack[0] = clueIdx;
|
||||||
seen.set(clueIdx);
|
seen.set(clueIdx);
|
||||||
|
for (int sp = 1; sp > 0; size++) {
|
||||||
for (int sp = 1, n, nidx, k; sp > 0; size++) {
|
long packed = Neighbors9x8.NBR8_PACKED[stack[--sp]];
|
||||||
packed = Neighbors9x8.NBR8_PACKED[stack[--sp]];
|
int n = (int) (packed >>> 56) * 7;
|
||||||
n = (int) (packed >>> 56) * 7;
|
for (int k = 0; k < n; k += 7) {
|
||||||
for (k = 0; k < n; k += 7) {
|
int nidx = (int) ((packed >>> k) & 0x7F);
|
||||||
nidx = (int) ((packed >>> k) & 0x7F);
|
|
||||||
if (seen.get(nidx) || grid.notClue(nidx)) continue;
|
if (seen.get(nidx) || grid.notClue(nidx)) continue;
|
||||||
seen.set(nidx);
|
seen.set(nidx);
|
||||||
stack[sp++] = nidx;
|
stack[sp++] = nidx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (size >= 2) this.penalty += ((size - 1L) * 120L);
|
if (size >= 2) penalty += ((size - 1L) * 120L);
|
||||||
}
|
}
|
||||||
void wall(rci rci) {
|
|
||||||
if ((4 - rci.nbrCount()) + Long.bitCount(rci.n1() & lo_cl) + Long.bitCount(rci.n2() & hi_cl) >= 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 space = new Mask();
|
|
||||||
for (var lo = lo_cl; lo != 0L; lo &= lo - 1) space.space(Long.numberOfTrailingZeros(lo));
|
|
||||||
for (var hi = hi_cl; hi != 0L; hi &= hi - 1) space.space(64 + Long.numberOfTrailingZeros(hi));
|
|
||||||
if (!space.hasSlots) return 1_000_000_000L;
|
|
||||||
seen.clear();
|
|
||||||
for (var lo = lo_cl; lo != 0L; lo &= lo - 1) space.clueStackPenalty(Long.numberOfTrailingZeros(lo));
|
|
||||||
for (var hi = hi_cl; hi != 0L; hi &= hi - 1) space.clueStackPenalty(64 + Long.numberOfTrailingZeros(hi));
|
|
||||||
for (var lo = ~lo_cl; lo != 0L; lo &= lo - 1) space.wall(IT[Long.numberOfTrailingZeros(lo)]);
|
|
||||||
for (var hi = ~hi_cl & 0xFFL; hi != 0L; hi &= hi - 1) space.wall(IT[64 + Long.numberOfTrailingZeros(hi)]);
|
|
||||||
|
|
||||||
//for (var rci : IT) if (grid.notClue(rci.i())) space.wall(rci);
|
for (int i = 0; i < 65; i+=64) {
|
||||||
// dead-end-ish letter cell (3+ walls)
|
long bits = (i == 0 ? ~lo_cl : (~hi_cl & 0xFFL));
|
||||||
// int walls, wc, wr;
|
for (; bits != 0L; bits &= bits - 1) {
|
||||||
/* for (var rci : IT) {
|
int idx = i + Long.numberOfTrailingZeros(bits);
|
||||||
if (grid.isDigitAt(rci.i())) continue;
|
var rci = IT[idx];
|
||||||
walls = 0;
|
if ((4 - rci.nbrCount()) + Long.bitCount(rci.n1() & lo_cl) + Long.bitCount(rci.n2() & hi_cl) >= 3) penalty += 400;
|
||||||
for (var d : nbrs4) {
|
var h = covH[idx];
|
||||||
wr = rci.r() + d.r();
|
var v = covV[idx];
|
||||||
wc = rci.c() + d.c();
|
if (h == 0 && v == 0) penalty += 1500;
|
||||||
if (wr < 0 || wr >= R || wc < 0 || wc >= C || grid.isDigitAt(Grid.offset(wr, wc))) walls++;
|
else if (h > 0 && v > 0) { /* ok */ } else if (h + v == 1) penalty += 200;
|
||||||
|
else penalty += 600;
|
||||||
}
|
}
|
||||||
if (walls >= 3) penalty[0] += 400;
|
}
|
||||||
}*/
|
|
||||||
|
|
||||||
return space.penalty;
|
return penalty;
|
||||||
}
|
}
|
||||||
|
|
||||||
Grid randomMask() {
|
Grid randomMask() {
|
||||||
@@ -516,7 +518,7 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
var nc = Math.cos(theta);
|
var nc = Math.cos(theta);
|
||||||
var nr = Math.sin(theta);
|
var nr = Math.sin(theta);
|
||||||
|
|
||||||
long bo0 = out.bo[0], bo1 = out.bo[1];
|
long bo0 = out.bo0, bo1 = out.bo1;
|
||||||
for (var rci : IT) {
|
for (var rci : IT) {
|
||||||
int i = rci.i();
|
int i = rci.i();
|
||||||
if ((rci.cross_r()) * nc + (rci.cross_c()) * nr < 0) {
|
if ((rci.cross_r()) * nc + (rci.cross_c()) * nr < 0) {
|
||||||
@@ -533,10 +535,10 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out.bo[0] = bo0;
|
out.bo0 = bo0;
|
||||||
out.bo[1] = bo1;
|
out.bo1 = bo1;
|
||||||
for (var lo = out.bo[0]; lo != 0L; lo &= lo - 1L) clearClues(out, Long.numberOfTrailingZeros(lo));
|
for (var lo = out.bo0; lo != 0L; lo &= lo - 1L) clearClues(out, Long.numberOfTrailingZeros(lo));
|
||||||
for (var hi = out.bo[1]; hi != 0L; hi &= hi - 1L) clearClues(out, 64 + Long.numberOfTrailingZeros(hi));
|
for (var hi = out.bo1; hi != 0L; hi &= hi - 1L) clearClues(out, 64 + Long.numberOfTrailingZeros(hi));
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
public static void clearClues(Grid out, int idx) { if (!hasRoomForClue(out, OFFSETS[out.digitAt(idx)].path()[idx])) out.clearClue(idx); }
|
public static void clearClues(Grid out, int idx) { if (!hasRoomForClue(out, OFFSETS[out.digitAt(idx)].path()[idx])) out.clearClue(idx); }
|
||||||
@@ -564,10 +566,10 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
class GridAndFit {
|
class GridAndFit {
|
||||||
|
|
||||||
Grid grid;
|
Grid grid;
|
||||||
Long fite;
|
long fite = -1;
|
||||||
GridAndFit(Grid grid) { this.grid = grid; }
|
GridAndFit(Grid grid) { this.grid = grid; }
|
||||||
long fit() {
|
long fit() {
|
||||||
if (fite == null) this.fite = maskFitness(grid);
|
if (fite == -1) this.fite = maskFitness(grid);
|
||||||
return this.fite;
|
return this.fite;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -707,6 +709,9 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
val slots = extractSlots(grid);
|
val slots = extractSlots(grid);
|
||||||
for (var s : slots) for (int i = 0, len = s.len(); i < len; i++) count[s.pos(i)]++;
|
for (var s : slots) for (int i = 0, len = s.len(); i < len; i++) count[s.pos(i)]++;
|
||||||
|
|
||||||
|
val slotScores = new int[slots.size()];
|
||||||
|
for (int i = 0; i < slots.size(); i++) slotScores[i] = slotScore(count, slots.get(i));
|
||||||
|
|
||||||
val t0 = System.currentTimeMillis();
|
val t0 = System.currentTimeMillis();
|
||||||
val stats = new FillStats();
|
val stats = new FillStats();
|
||||||
val TOTAL = slots.size();
|
val TOTAL = slots.size();
|
||||||
@@ -737,8 +742,9 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
Pick chooseMRV() {
|
Pick chooseMRV() {
|
||||||
Slot best = null;
|
Slot best = null;
|
||||||
CandidateInfo bestInfo = null;
|
CandidateInfo bestInfo = null;
|
||||||
int bestSlot = -1;
|
int bestScore = -1;
|
||||||
for (var s : slots) {
|
for (int i = 0, n = slots.size(); i < n; i++) {
|
||||||
|
var s = slots.get(i);
|
||||||
if (assigned.containsKey(s.key())) continue;
|
if (assigned.containsKey(s.key())) continue;
|
||||||
var entry = dictIndex[s.len()];
|
var entry = dictIndex[s.len()];
|
||||||
if (entry == null) return PICK_NOT_DONE;
|
if (entry == null) return PICK_NOT_DONE;
|
||||||
@@ -746,12 +752,11 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
var info = candidateInfoForPattern(ctx, entry, s.len());
|
var info = candidateInfoForPattern(ctx, entry, s.len());
|
||||||
|
|
||||||
if (info.count == 0) return PICK_NOT_DONE;
|
if (info.count == 0) return PICK_NOT_DONE;
|
||||||
var slotScore = -1;
|
|
||||||
if (best == null
|
if (best == null
|
||||||
|| info.count < bestInfo.count
|
|| info.count < bestInfo.count
|
||||||
|| (info.count == bestInfo.count && (slotScore = slotScore(count, s)) > bestSlot)) {
|
|| (info.count == bestInfo.count && slotScores[i] > bestScore)) {
|
||||||
best = s;
|
best = s;
|
||||||
bestSlot = (slotScore != -1) ? slotScore : slotScore(count, s);
|
bestScore = slotScores[i];
|
||||||
if (info.indices != null && (info.indices == ctx.inter1 || info.indices == ctx.inter2)) {
|
if (info.indices != null && (info.indices == ctx.inter1 || info.indices == ctx.inter2)) {
|
||||||
bestInfo = new CandidateInfo(Arrays.copyOf(info.indices, info.count), info.count);
|
bestInfo = new CandidateInfo(Arrays.copyOf(info.indices, info.count), info.count);
|
||||||
} else {
|
} else {
|
||||||
@@ -761,11 +766,8 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (best == null) {
|
if (best == null) return PICK_DONE;
|
||||||
return PICK_DONE;
|
return new Pick(best, bestInfo, false);
|
||||||
} else {
|
|
||||||
return new Pick(best, bestInfo, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
boolean backtrack(int depth) {
|
boolean backtrack(int depth) {
|
||||||
if (Thread.currentThread().isInterrupted()) return false;
|
if (Thread.currentThread().isInterrupted()) return false;
|
||||||
@@ -787,8 +789,7 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
var k = s.key();
|
var k = s.key();
|
||||||
int patLen = s.len();
|
int patLen = s.len();
|
||||||
var entry = dictIndex[patLen];
|
var entry = dictIndex[patLen];
|
||||||
var pat = new byte[patLen];
|
|
||||||
patternForSlot(grid, s, pat);
|
|
||||||
if (info.indices != null && info.indices.length > 0) {
|
if (info.indices != null && info.indices.length > 0) {
|
||||||
var idxs = info.indices;
|
var idxs = info.indices;
|
||||||
var L = idxs.length;
|
var L = idxs.length;
|
||||||
@@ -802,15 +803,7 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
|
|
||||||
if (used.get(w.index())) continue;
|
if (used.get(w.index())) continue;
|
||||||
|
|
||||||
boolean match = true;
|
if (!placeWord(grid, s, w, ctx.undo, depth)) continue;
|
||||||
for (var i = 0; i < patLen; i++) {
|
|
||||||
if (pat[i] != DASH && pat[i] != w.byteAt(i)) {
|
|
||||||
match = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!match || !placeWord(grid, s, w, ctx.undo, depth)) continue;
|
|
||||||
|
|
||||||
used.set(w.index());
|
used.set(w.index());
|
||||||
assigned.put(k, w);
|
assigned.put(k, w);
|
||||||
@@ -818,7 +811,7 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
if (backtrack(depth + 1)) return true;
|
if (backtrack(depth + 1)) return true;
|
||||||
|
|
||||||
assigned.remove(k);
|
assigned.remove(k);
|
||||||
used.clear(w.index);
|
used.clear(w.index());
|
||||||
s.undoPlace(grid, ctx.undo[depth]);
|
s.undoPlace(grid, ctx.undo[depth]);
|
||||||
}
|
}
|
||||||
stats.backtracks++;
|
stats.backtracks++;
|
||||||
@@ -839,14 +832,7 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
|
|
||||||
if (used.get(w.index())) continue;
|
if (used.get(w.index())) continue;
|
||||||
|
|
||||||
boolean match = true;
|
if (!placeWord(grid, s, w, ctx.undo, depth)) continue;
|
||||||
for (var i = 0; i < patLen; i++) {
|
|
||||||
if (pat[i] != DASH && pat[i] != w.byteAt(i)) {
|
|
||||||
match = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!match || !placeWord(grid, s, w, ctx.undo, depth)) continue;
|
|
||||||
|
|
||||||
used.set(w.index());
|
used.set(w.index());
|
||||||
assigned.put(k, w);
|
assigned.put(k, w);
|
||||||
|
|||||||
Reference in New Issue
Block a user