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,
|
int[] stack,
|
||||||
BitSet seen,
|
BitSet seen,
|
||||||
char[] pattern,
|
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);
|
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());
|
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 first = listBuffer[0];
|
||||||
var cur = first.data();
|
var cur = first.data();
|
||||||
var curLen = first.size();
|
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 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); }
|
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
|
@FunctionalInterface
|
||||||
interface SlotVisitor {
|
interface SlotVisitor {
|
||||||
|
|
||||||
@@ -352,7 +369,7 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff)
|
|||||||
n++;
|
n++;
|
||||||
rr += dr;
|
rr += dr;
|
||||||
cc += dc;
|
cc += dc;
|
||||||
if (n >= 12) break;
|
if (n >= MAX_LEN) break;
|
||||||
}
|
}
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
visitor.visit((r << 8) | (c << 4) | d, packedRs, packedCs, n);
|
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++;
|
n++;
|
||||||
rr += dr;
|
rr += dr;
|
||||||
cc += dc;
|
cc += dc;
|
||||||
if (n >= 12) break;
|
if (n >= MAX_LEN) break;
|
||||||
}
|
}
|
||||||
if (n == 0) continue;
|
if (n == 0) continue;
|
||||||
hasSlots = true;
|
hasSlots = true;
|
||||||
@@ -646,7 +663,6 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff)
|
|||||||
return pop.get(0);
|
return pop.get(0);
|
||||||
}
|
}
|
||||||
record UndoPlace(int ur, int uc, char up) { }
|
record UndoPlace(int ur, int uc, char up) { }
|
||||||
|
|
||||||
// ---------------- Fill (CSP) ----------------
|
// ---------------- Fill (CSP) ----------------
|
||||||
record Undo(UndoPlace[] ur, int n) { }
|
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();
|
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) {
|
static Undo placeWord(Grid grid, Slot s, Lemma w) {
|
||||||
var ur = new UndoPlace[s.len()];
|
var ur = new UndoPlace[s.len()];
|
||||||
var n = 0;
|
var n = 0;
|
||||||
|
|
||||||
for (var i = 0; i < s.len(); i++) {
|
for (var i = 0; i < s.len(); i++) {
|
||||||
int r = s.r(i), c = s.c(i);
|
int r = s.r(i), c = s.c(i);
|
||||||
char cur = grid.getCharAt(r, c);
|
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);
|
return new Undo(ur, n);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
static void undoPlace(Grid grid, Undo u) {
|
static void undoPlace(Grid grid, Undo u) {
|
||||||
for (var i = 0; i < u.n; i++) grid.setCharAt(u.ur[i]);
|
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);
|
return new Pick(best, bestInfo, false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
System.out.println("hit");
|
|
||||||
|
|
||||||
class Solver {
|
class Solver {
|
||||||
|
|
||||||
boolean backtrack() {
|
boolean backtrack(int depth) {
|
||||||
if (Thread.currentThread().isInterrupted()) return false;
|
if (Thread.currentThread().isInterrupted()) return false;
|
||||||
stats.nodes++;
|
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;
|
stats.lastMRV = pick.info.count;
|
||||||
renderProgress.run();
|
renderProgress.run();
|
||||||
|
|
||||||
|
|
||||||
var s = pick.slot;
|
var s = pick.slot;
|
||||||
var k = s.key();
|
var k = s.key();
|
||||||
var entry = dictIndex[s.len()];
|
var entry = dictIndex[s.len()];
|
||||||
var pat = new char[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) {
|
if (pick.info.indices != null && pick.info.indices.length > 0) {
|
||||||
var idxs = pick.info.indices;
|
var idxs = pick.info.indices;
|
||||||
var L = idxs.length;
|
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;
|
if (used.get(w.index())) continue;
|
||||||
|
|
||||||
boolean match = true;
|
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)) {
|
if (pat[i] != C_DASH && pat[i] != w.charAt(i)) {
|
||||||
match = false;
|
match = false;
|
||||||
break;
|
break;
|
||||||
@@ -844,17 +882,17 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff)
|
|||||||
}
|
}
|
||||||
if (!match) continue;
|
if (!match) continue;
|
||||||
|
|
||||||
var undo = placeWord(grid, s, w);
|
int nPlaced = placeWord(grid, s, w, ctx.undoBuffer, undoOffset);
|
||||||
if (undo == null) continue;
|
if (nPlaced < 0) continue;
|
||||||
|
|
||||||
used.set(w.index());
|
used.set(w.index());
|
||||||
assigned.put(k, w);
|
assigned.put(k, w);
|
||||||
|
|
||||||
if (backtrack()) return true;
|
if (backtrack(depth+1)) return true;
|
||||||
|
|
||||||
assigned.remove(k);
|
assigned.remove(k);
|
||||||
used.set(w.index, false);
|
used.set(w.index, false);
|
||||||
undoPlace(grid, undo);
|
undoPlace(grid, ctx.undoBuffer, undoOffset, nPlaced);
|
||||||
}
|
}
|
||||||
stats.backtracks++;
|
stats.backtracks++;
|
||||||
return false;
|
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;
|
if (used.get(w.index())) continue;
|
||||||
|
|
||||||
boolean match = true;
|
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)) {
|
if (pat[i] != C_DASH && pat[i] != w.charAt(i)) {
|
||||||
match = false;
|
match = false;
|
||||||
break;
|
break;
|
||||||
@@ -883,17 +921,17 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff)
|
|||||||
}
|
}
|
||||||
if (!match) continue;
|
if (!match) continue;
|
||||||
|
|
||||||
var undo = placeWord(grid, s, w);
|
int nPlaced = placeWord(grid, s, w, ctx.undoBuffer, undoOffset);
|
||||||
if (undo == null) continue;
|
if (nPlaced < 0) continue;
|
||||||
|
|
||||||
used.set(w.index());
|
used.set(w.index());
|
||||||
assigned.put(k, w);
|
assigned.put(k, w);
|
||||||
|
|
||||||
if (backtrack()) return true;
|
if (backtrack(depth+1)) return true;
|
||||||
|
|
||||||
assigned.remove(k);
|
assigned.remove(k);
|
||||||
used.set(w.index, false);
|
used.set(w.index, false);
|
||||||
undoPlace(grid, undo);
|
undoPlace(grid, ctx.undoBuffer, undoOffset, nPlaced);
|
||||||
}
|
}
|
||||||
|
|
||||||
stats.backtracks++;
|
stats.backtracks++;
|
||||||
@@ -903,7 +941,7 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff)
|
|||||||
|
|
||||||
// initial render (same feel)
|
// initial render (same feel)
|
||||||
renderProgress.run();
|
renderProgress.run();
|
||||||
var ok = new Solver().backtrack();
|
var ok = new Solver().backtrack(0);
|
||||||
// final progress line
|
// final progress line
|
||||||
System.out.print("\r" + padRight("", 120) + "\r");
|
System.out.print("\r" + padRight("", 120) + "\r");
|
||||||
System.out.flush();
|
System.out.flush();
|
||||||
|
|||||||
Reference in New Issue
Block a user