introduce bitloops
This commit is contained in:
@@ -115,7 +115,7 @@ public record Export() {
|
||||
var sb = new StringBuilder();
|
||||
for (var r = 0; r < R; r++) {
|
||||
if (r > 0) sb.append('\n');
|
||||
for (var c = 0; c < C; c++) sb.append((char) grid.byteAt(Grid.offset(r, c)));
|
||||
for (var c = 0; c < C; c++) sb.append((char) grid.letter32At(Grid.offset(r, c)));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
@@ -137,9 +137,9 @@ public record Export() {
|
||||
for (var c = 0; c < C; c++) {
|
||||
var offset = Grid.offset(r, c);
|
||||
if (grid.isClue(offset)) {
|
||||
sb.append(clueChar.replace(new Cell(grid, offset, grid.byteAt(offset))));
|
||||
sb.append(clueChar.replace(new Cell(grid, offset, grid.letter32At(offset))));
|
||||
} else {
|
||||
sb.append(NOT_CLUE_NOT_LETTER_TO(grid.byteAt(offset), emptyFallback));
|
||||
sb.append(NOT_CLUE_NOT_LETTER_TO(grid.letter32At(offset), emptyFallback));
|
||||
}
|
||||
}
|
||||
out[r] = sb.toString();
|
||||
@@ -227,7 +227,7 @@ public record Export() {
|
||||
for (var p : placed) {
|
||||
for (var c : p.cells) {
|
||||
if (inBounds(c) && g.notClue(c)) {
|
||||
letterAt.put(c, (char) g.byteAt(c));
|
||||
letterAt.put(c, (char) g.letter32At(c));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,14 @@ public record SwedishGenerator(Rng rng, int[] stack) {
|
||||
//72 << 3;
|
||||
static final int CLUE_INDEX_MAX_SIZE = (288 | 3) + 1;
|
||||
static int clamp(int x, int a, int b) { return Math.max(a, Math.min(b, x)); }
|
||||
record Pick(Slot slot, int[] indices, int count) { }
|
||||
@AllArgsConstructor
|
||||
static class Pick {
|
||||
|
||||
Slot slot;
|
||||
int[] indices;
|
||||
int count;
|
||||
}
|
||||
|
||||
// 0b11
|
||||
//0b00
|
||||
// 0b01
|
||||
@@ -282,18 +289,14 @@ public record SwedishGenerator(Rng rng, int[] stack) {
|
||||
|
||||
public Grid(byte[] g) { this(g, 0, 0); }
|
||||
static Grid createEmpty() { return new Grid(new byte[SIZE], X, X); }
|
||||
int digitAt(int index) { return g[index]; }
|
||||
public static int r(int offset) { return offset & 7; }
|
||||
public static int c(int offset) { return offset >>> 3; }
|
||||
static int offset(int r, int c) { return r | (c << 3); }
|
||||
public byte byteAt(int pos) { return g[pos]; }
|
||||
public byte letter32At(int pos) { return g[pos]; }
|
||||
void setLetter(int idx, byte ch) { g[idx] = ch; }
|
||||
void clearletter(int idx) { g[idx] = DASH; }
|
||||
boolean isClue(long index) { return ((index & 64) == 0) ? ((lo >>> index) & 1L) != X : ((hi >>> (index & 63)) & 1L) != X; }
|
||||
boolean isClue(int index) { return ((index & 64) == 0) ? ((lo >>> index) & 1L) != X : ((hi >>> (index & 63)) & 1L) != X; }
|
||||
boolean notClue(long index) { return ((index & 64) == 0) ? ((lo >>> index) & 1L) == X : ((hi >>> (index & 63)) & 1L) == X; }
|
||||
boolean notClue(int index) { return ((index & 64) == 0) ? ((lo >>> index) & 1L) == X : ((hi >>> (index & 63)) & 1L) == X; }
|
||||
int clueCount() { return Long.bitCount(lo) + Long.bitCount(hi); }
|
||||
|
||||
void undoPlace(long maskLo, long maskHi) {
|
||||
for (long b = maskLo; b != 0; b &= b - 1) clearletter(Long.numberOfTrailingZeros(b));
|
||||
@@ -785,7 +788,7 @@ public record SwedishGenerator(Rng rng, int[] stack) {
|
||||
if (s.increasing()) {
|
||||
for (long b = s.lo; b != 0; b &= b - 1, i++) {
|
||||
int idx = Long.numberOfTrailingZeros(b);
|
||||
byte cur = grid.byteAt(idx), ch = Lemma.byteAt(w, i);
|
||||
byte cur = grid.letter32At(idx), ch = Lemma.byteAt(w, i);
|
||||
if (cur == DASH) {
|
||||
maskLo |= (1L << idx);
|
||||
grid.setLetter(idx, ch);
|
||||
@@ -796,7 +799,7 @@ public record SwedishGenerator(Rng rng, int[] stack) {
|
||||
}
|
||||
for (long b = s.hi; b != 0; b &= b - 1, i++) {
|
||||
int idx = 64 | Long.numberOfTrailingZeros(b);
|
||||
byte cur = grid.byteAt(idx), ch = Lemma.byteAt(w, i);
|
||||
byte cur = grid.letter32At(idx), ch = Lemma.byteAt(w, i);
|
||||
if (cur == DASH) {
|
||||
maskHi |= (1L << (idx & 63));
|
||||
grid.setLetter(idx, ch);
|
||||
@@ -809,7 +812,7 @@ public record SwedishGenerator(Rng rng, int[] stack) {
|
||||
for (long b = s.hi; b != 0; i++) {
|
||||
int msb = 63 - Long.numberOfLeadingZeros(b);
|
||||
int idx = 64 | msb;
|
||||
byte cur = grid.byteAt(idx), ch = Lemma.byteAt(w, i);
|
||||
byte cur = grid.letter32At(idx), ch = Lemma.byteAt(w, i);
|
||||
if (cur == DASH) {
|
||||
maskHi |= (1L << msb);
|
||||
grid.setLetter(idx, ch);
|
||||
@@ -822,7 +825,7 @@ public record SwedishGenerator(Rng rng, int[] stack) {
|
||||
for (long b = s.lo; b != 0; i++) {
|
||||
int msb = 63 - Long.numberOfLeadingZeros(b);
|
||||
int idx = msb;
|
||||
byte cur = grid.byteAt(idx), ch = Lemma.byteAt(w, i);
|
||||
byte cur = grid.letter32At(idx), ch = Lemma.byteAt(w, i);
|
||||
if (cur == DASH) {
|
||||
maskLo |= (1L << msb);
|
||||
grid.setLetter(idx, ch);
|
||||
@@ -928,10 +931,12 @@ public record SwedishGenerator(Rng rng, int[] stack) {
|
||||
|
||||
class Solver {
|
||||
|
||||
private final Pick CARRIER = new Pick(null, null, 0);
|
||||
long nodes;
|
||||
long backtracks;
|
||||
int lastMRV;
|
||||
long lastLog = t0;
|
||||
Pick current = CARRIER;
|
||||
void renderProgress() {
|
||||
var now = System.currentTimeMillis();
|
||||
if ((now - lastLog) < LOG_EVERY_MS) return;
|
||||
@@ -953,7 +958,7 @@ public record SwedishGenerator(Rng rng, int[] stack) {
|
||||
System.out.print("\r" + Strings.padRight(msg, 120));
|
||||
System.out.flush();
|
||||
}
|
||||
Pick chooseMRV() {
|
||||
void chooseMRV() {
|
||||
Slot best = null;
|
||||
for (int i = 0, count, count2 = -1, bestScore = -1, n = TOTAL; i < n; i++) {
|
||||
var s = slots[i];
|
||||
@@ -962,7 +967,10 @@ public record SwedishGenerator(Rng rng, int[] stack) {
|
||||
var index = dictIndex[s.length()];
|
||||
count = pattern == X ? index.length : candidateCountForPattern(bitset, pattern, index, s.length());
|
||||
|
||||
if (count == 0) return PICK_NOT_DONE;
|
||||
if (count == 0) {
|
||||
current = PICK_NOT_DONE;
|
||||
return;
|
||||
}
|
||||
if (best == null
|
||||
|| count < count2
|
||||
|| (count == count2 && slotScores[i] > bestScore)) {
|
||||
@@ -973,11 +981,20 @@ public record SwedishGenerator(Rng rng, int[] stack) {
|
||||
}
|
||||
}
|
||||
// Re-calculate for the best slot to get actual indices
|
||||
if (best == null) return PICK_DONE;
|
||||
if (best == null) {
|
||||
current = PICK_DONE;
|
||||
return;
|
||||
}
|
||||
var pattern = patternForSlot(grid, best);
|
||||
var index = dictIndex[best.length()];
|
||||
if (pattern == X) return new Pick(best, null, index.length);
|
||||
return new Pick(best, candidateInfoForPattern(bitset, pattern, index, best.length()), index.length);
|
||||
current = CARRIER;
|
||||
current.slot = best;
|
||||
current.count = index.length;
|
||||
if (pattern == X) {
|
||||
current.indices = null;
|
||||
return;
|
||||
}
|
||||
current.indices = candidateInfoForPattern(bitset, pattern, index, best.length());
|
||||
}
|
||||
boolean backtrack(int depth) {
|
||||
if (Thread.currentThread().isInterrupted()) return false;
|
||||
@@ -985,7 +1002,8 @@ public record SwedishGenerator(Rng rng, int[] stack) {
|
||||
|
||||
if (20_000 > 0 && (System.currentTimeMillis() - t0) > 20_000) return false;
|
||||
|
||||
var pick = chooseMRV();
|
||||
chooseMRV();
|
||||
var pick = current;
|
||||
if (pick == PICK_DONE) return true;
|
||||
if (pick.slot == null) {
|
||||
backtracks++;
|
||||
|
||||
Reference in New Issue
Block a user