Gather data
This commit is contained in:
@@ -80,9 +80,10 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff)
|
||||
int[] stack,
|
||||
BitSet seen,
|
||||
char[] pattern,
|
||||
IntList[] intListBuffer) {
|
||||
IntList[] intListBuffer,
|
||||
long[] undoBuffer) {
|
||||
|
||||
public Context() { this(new int[256], new int[256], new int[256], new int[256], new BitSet(256), new char[32], new IntList[32]); }
|
||||
public Context() { this(new int[256], new int[256], new int[256], new int[256], new BitSet(256), new char[32], new IntList[32], new long[2048]); }
|
||||
}
|
||||
|
||||
static final ThreadLocal<Context> CTX = ThreadLocal.withInitial(Context::new);
|
||||
@@ -295,6 +296,17 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff)
|
||||
return new CandidateInfo(null, entry.words.size());
|
||||
}
|
||||
|
||||
// Sort constraints by size to optimize intersection
|
||||
for (int i = 0; i < listCount - 1; i++) {
|
||||
for (int j = i + 1; j < listCount; j++) {
|
||||
if (listBuffer[j].size() < listBuffer[i].size()) {
|
||||
var tmp = listBuffer[i];
|
||||
listBuffer[i] = listBuffer[j];
|
||||
listBuffer[j] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var first = listBuffer[0];
|
||||
var cur = first.data();
|
||||
var curLen = first.size();
|
||||
@@ -322,7 +334,12 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff)
|
||||
public static int r(long rs, int i) { return (int) ((rs >> (i << 2)) & 15); }
|
||||
public static int c(long cs, int i) { return (int) ((cs >> (i << 2)) & 15); }
|
||||
}
|
||||
|
||||
static void undoPlace(Grid grid, long[] undoBuffer, int offset, int n) {
|
||||
for (var i = 0; i < n; i++) {
|
||||
long v = undoBuffer[offset + i];
|
||||
grid.setCharAt((int) (v >> 16) & 0xFF, (int) (v >> 8) & 0xFF, (char) (v & 0xFF));
|
||||
}
|
||||
}
|
||||
@FunctionalInterface
|
||||
interface SlotVisitor {
|
||||
|
||||
@@ -352,7 +369,7 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff)
|
||||
n++;
|
||||
rr += dr;
|
||||
cc += dc;
|
||||
if (n >= 12) break;
|
||||
if (n >= MAX_LEN) break;
|
||||
}
|
||||
if (n > 0) {
|
||||
visitor.visit((r << 8) | (c << 4) | d, packedRs, packedCs, n);
|
||||
@@ -419,7 +436,7 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff)
|
||||
n++;
|
||||
rr += dr;
|
||||
cc += dc;
|
||||
if (n >= 12) break;
|
||||
if (n >= MAX_LEN) break;
|
||||
}
|
||||
if (n == 0) continue;
|
||||
hasSlots = true;
|
||||
@@ -646,7 +663,6 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff)
|
||||
return pop.get(0);
|
||||
}
|
||||
record UndoPlace(int ur, int uc, char up) { }
|
||||
|
||||
// ---------------- Fill (CSP) ----------------
|
||||
record Undo(UndoPlace[] ur, int n) { }
|
||||
|
||||
@@ -692,10 +708,32 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff)
|
||||
return cross * 10 + s.len();
|
||||
}
|
||||
|
||||
static int placeWord(Grid grid, Slot s, Lemma w, long[] undoBuffer, int offset) {
|
||||
int n = 0;
|
||||
for (var i = 0; i < s.len(); i++) {
|
||||
int r = s.r(i), c = s.c(i);
|
||||
char cur = grid.getCharAt(r, c);
|
||||
var ch = w.charAt(i);
|
||||
if (cur == C_DASH) {
|
||||
undoBuffer[offset + n] = ((long) r << 16) | ((long) c << 8) | (long) C_DASH;
|
||||
n++;
|
||||
grid.setCharAt(r, c, ch);
|
||||
} else {
|
||||
if (cur != ch) {
|
||||
for (var j = 0; j < n; j++) {
|
||||
long v = undoBuffer[offset + j];
|
||||
grid.setCharAt((int) (v >> 16) & 0xFF, (int) (v >> 8) & 0xFF, (char) (v & 0xFF));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
/*
|
||||
static Undo placeWord(Grid grid, Slot s, Lemma w) {
|
||||
var ur = new UndoPlace[s.len()];
|
||||
var n = 0;
|
||||
|
||||
for (var i = 0; i < s.len(); i++) {
|
||||
int r = s.r(i), c = s.c(i);
|
||||
char cur = grid.getCharAt(r, c);
|
||||
@@ -713,7 +751,7 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff)
|
||||
}
|
||||
}
|
||||
return new Undo(ur, n);
|
||||
}
|
||||
}*/
|
||||
|
||||
static void undoPlace(Grid grid, Undo u) {
|
||||
for (var i = 0; i < u.n; i++) grid.setCharAt(u.ur[i]);
|
||||
@@ -796,11 +834,10 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff)
|
||||
return new Pick(best, bestInfo, false);
|
||||
}
|
||||
};
|
||||
System.out.println("hit");
|
||||
|
||||
class Solver {
|
||||
|
||||
boolean backtrack() {
|
||||
boolean backtrack(int depth) {
|
||||
if (Thread.currentThread().isInterrupted()) return false;
|
||||
stats.nodes++;
|
||||
|
||||
@@ -815,13 +852,14 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff)
|
||||
|
||||
stats.lastMRV = pick.info.count;
|
||||
renderProgress.run();
|
||||
|
||||
|
||||
var s = pick.slot;
|
||||
var k = s.key();
|
||||
var entry = dictIndex[s.len()];
|
||||
var pat = new char[s.len()];
|
||||
patternForSlot(grid, s, pat);
|
||||
|
||||
int patLen = patternForSlot(grid, s, pat);
|
||||
int undoOffset = depth * SIZE;
|
||||
if (pick.info.indices != null && pick.info.indices.length > 0) {
|
||||
var idxs = pick.info.indices;
|
||||
var L = idxs.length;
|
||||
@@ -836,7 +874,7 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff)
|
||||
if (used.get(w.index())) continue;
|
||||
|
||||
boolean match = true;
|
||||
for (var i = 0; i < pat.length; i++) {
|
||||
for (var i = 0; i < patLen; i++) {
|
||||
if (pat[i] != C_DASH && pat[i] != w.charAt(i)) {
|
||||
match = false;
|
||||
break;
|
||||
@@ -844,17 +882,17 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff)
|
||||
}
|
||||
if (!match) continue;
|
||||
|
||||
var undo = placeWord(grid, s, w);
|
||||
if (undo == null) continue;
|
||||
int nPlaced = placeWord(grid, s, w, ctx.undoBuffer, undoOffset);
|
||||
if (nPlaced < 0) continue;
|
||||
|
||||
used.set(w.index());
|
||||
assigned.put(k, w);
|
||||
|
||||
if (backtrack()) return true;
|
||||
if (backtrack(depth+1)) return true;
|
||||
|
||||
assigned.remove(k);
|
||||
used.set(w.index, false);
|
||||
undoPlace(grid, undo);
|
||||
undoPlace(grid, ctx.undoBuffer, undoOffset, nPlaced);
|
||||
}
|
||||
stats.backtracks++;
|
||||
return false;
|
||||
@@ -875,7 +913,7 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff)
|
||||
if (used.get(w.index())) continue;
|
||||
|
||||
boolean match = true;
|
||||
for (var i = 0; i < pat.length; i++) {
|
||||
for (var i = 0; i < patLen; i++) {
|
||||
if (pat[i] != C_DASH && pat[i] != w.charAt(i)) {
|
||||
match = false;
|
||||
break;
|
||||
@@ -883,17 +921,17 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff)
|
||||
}
|
||||
if (!match) continue;
|
||||
|
||||
var undo = placeWord(grid, s, w);
|
||||
if (undo == null) continue;
|
||||
int nPlaced = placeWord(grid, s, w, ctx.undoBuffer, undoOffset);
|
||||
if (nPlaced < 0) continue;
|
||||
|
||||
used.set(w.index());
|
||||
assigned.put(k, w);
|
||||
|
||||
if (backtrack()) return true;
|
||||
if (backtrack(depth+1)) return true;
|
||||
|
||||
assigned.remove(k);
|
||||
used.set(w.index, false);
|
||||
undoPlace(grid, undo);
|
||||
undoPlace(grid, ctx.undoBuffer, undoOffset, nPlaced);
|
||||
}
|
||||
|
||||
stats.backtracks++;
|
||||
@@ -903,7 +941,7 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff)
|
||||
|
||||
// initial render (same feel)
|
||||
renderProgress.run();
|
||||
var ok = new Solver().backtrack();
|
||||
var ok = new Solver().backtrack(0);
|
||||
// final progress line
|
||||
System.out.print("\r" + padRight("", 120) + "\r");
|
||||
System.out.flush();
|
||||
|
||||
Reference in New Issue
Block a user