introduce bitloops
This commit is contained in:
@@ -335,10 +335,13 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static record Slotinfo(int key, long lo, long hi, int score, DictEntry entry) {
|
static class Assign {
|
||||||
|
|
||||||
|
long w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static record Slotinfo(int key, long lo, long hi, int score, Assign assign, DictEntry entry) { }
|
||||||
|
|
||||||
static record Slot(int key, long lo, long hi, DictEntry entry) {
|
static record Slot(int key, long lo, long hi, DictEntry entry) {
|
||||||
|
|
||||||
static final int BIT_FOR_DIR = 2;
|
static final int BIT_FOR_DIR = 2;
|
||||||
@@ -725,11 +728,39 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
}
|
}
|
||||||
return best.grid;
|
return best.grid;
|
||||||
}
|
}
|
||||||
|
static long patternForSlot2(final long glo, final long ghi, final byte[] g, final int key, final long lo, final long hi) {
|
||||||
static long patternForSlot(final long glo, final long ghi, final byte[] g, final int key, final long lo, final long hi) {
|
if (((lo & glo) | (hi & ghi)) == X) return 0;
|
||||||
if (((lo & glo) | (hi & ghi)) == X) {
|
long p = 0;
|
||||||
return 0;
|
int n = 0;
|
||||||
|
if (Slot.increasing(key)) {
|
||||||
|
for (long b = lo & glo; b != X; b &= b - 1) {
|
||||||
|
int idx = numberOfTrailingZeros(b);
|
||||||
|
int i = bitCount(lo & ((1L << idx) - 1));
|
||||||
|
p |= ((long) (i * 26 + g[idx])) << (n++ << 3);
|
||||||
}
|
}
|
||||||
|
int offset = bitCount(lo);
|
||||||
|
for (long b = hi & ghi; b != X; b &= b - 1) {
|
||||||
|
int idx = numberOfTrailingZeros(b);
|
||||||
|
int i = offset + bitCount(hi & ((1L << idx) - 1));
|
||||||
|
p |= ((long) (i * 26 + g[64 | idx])) << (n++ << 3);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int offset = bitCount(hi);
|
||||||
|
for (long b = hi & ghi; b != X; b &= b - 1) {
|
||||||
|
int idx = numberOfTrailingZeros(b);
|
||||||
|
int i = bitCount(hi & ~((1L << idx) | ((1L << idx) - 1)));
|
||||||
|
p |= ((long) (i * 26 + g[64 | idx])) << (n++ << 3);
|
||||||
|
}
|
||||||
|
for (long b = lo & glo; b != X; b &= b - 1) {
|
||||||
|
int idx = numberOfTrailingZeros(b);
|
||||||
|
int i = offset + bitCount(lo & ~((1L << idx) | ((1L << idx) - 1)));
|
||||||
|
p |= ((long) (i * 26 + g[idx])) << (n++ << 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
static long patternForSlot(final long glo, final long ghi, final byte[] g, final int key, final long lo, final long hi) {
|
||||||
|
if (((lo & glo) | (hi & ghi)) == X) return 0;
|
||||||
long p = 0;
|
long p = 0;
|
||||||
if (Slot.increasing(key)) {
|
if (Slot.increasing(key)) {
|
||||||
for (long b = lo & glo; b != X; b &= b - 1) {
|
for (long b = lo & glo; b != X; b &= b - 1) {
|
||||||
@@ -819,34 +850,20 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int[] candidateInfoForPattern(long[] res, long pattern, long[][] posBitsets, int numLongs) {
|
static int[] candidateInfoForPattern(long[] res, long pattern, long[][] posBitsets, int numLongs) {
|
||||||
boolean first = true;
|
System.arraycopy(posBitsets[(int) (pattern & 0xFF) - 1], 0, res, 0, numLongs);
|
||||||
|
for (long p = pattern >>> 8; p != X; p >>>= 8) {
|
||||||
for (long p = pattern; p != X; ) {
|
long[] bs = posBitsets[(int) (p & 0xFF) - 1];
|
||||||
int combined = (int) (p & 0xFF);
|
|
||||||
if (combined != X) {
|
|
||||||
long[] bs = posBitsets[combined - 1];
|
|
||||||
if (first) {
|
|
||||||
System.arraycopy(bs, 0, res, 0, numLongs);
|
|
||||||
first = false;
|
|
||||||
} else {
|
|
||||||
for (int k = 0; k < numLongs; k++) res[k] &= bs[k];
|
for (int k = 0; k < numLongs; k++) res[k] &= bs[k];
|
||||||
}
|
}
|
||||||
p >>>= 8;
|
|
||||||
} else {
|
|
||||||
p >>>= (numberOfTrailingZeros(p) & ~7);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (int k = 0; k < numLongs; k++) count += bitCount(res[k]);
|
for (int k = 0; k < numLongs; k++) count += bitCount(res[k]);
|
||||||
|
|
||||||
int[] indices = new int[count];
|
int[] indices = new int[count];
|
||||||
int ki = 0;
|
for (int k = 0, ki = 0; k < numLongs; k++) {
|
||||||
for (int k = 0; k < numLongs; k++) {
|
|
||||||
long w = res[k];
|
long w = res[k];
|
||||||
while (w != X) {
|
while (w != X) {
|
||||||
int t = numberOfTrailingZeros(w);
|
indices[ki++] = (k << 6) | numberOfTrailingZeros(w);
|
||||||
indices[ki++] = (k << 6) | t;
|
|
||||||
w &= w - 1;
|
w &= w - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -855,23 +872,11 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int candidateCountForPattern(final long[] res, final long pattern, final long[][] posBitsets, final int numLongs) {
|
static int candidateCountForPattern(final long[] res, final long pattern, final long[][] posBitsets, final int numLongs) {
|
||||||
boolean first = true;
|
System.arraycopy(posBitsets[(int) (pattern & 0xFF) - 1], 0, res, 0, numLongs);
|
||||||
|
for (long p = pattern >>> 8; p != X; p >>>= 8) {
|
||||||
for (long p = pattern; p != X; ) {
|
long[] bs = posBitsets[(int) (p & 0xFF) - 1];
|
||||||
int combined = (int) (p & 0xFF);
|
|
||||||
if (combined != X) {
|
|
||||||
long[] bs = posBitsets[combined - 1];
|
|
||||||
if (first) {
|
|
||||||
System.arraycopy(bs, 0, res, 0, numLongs);
|
|
||||||
first = false;
|
|
||||||
} else {
|
|
||||||
for (int k = 0; k < numLongs; k++) res[k] &= bs[k];
|
for (int k = 0; k < numLongs; k++) res[k] &= bs[k];
|
||||||
}
|
}
|
||||||
p >>>= 8;
|
|
||||||
} else {
|
|
||||||
p >>>= (numberOfTrailingZeros(p) & ~7);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (int k = 0; k < numLongs; k++) count += bitCount(res[k]);
|
for (int k = 0; k < numLongs; k++) count += bitCount(res[k]);
|
||||||
@@ -888,7 +893,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
for (int i = 0; i < slots.length; i++) {
|
for (int i = 0; i < slots.length; i++) {
|
||||||
var slot = slots[i];
|
var slot = slots[i];
|
||||||
slotScores[i] = slotScore(count, slot.lo, slot.hi);
|
slotScores[i] = slotScore(count, slot.lo, slot.hi);
|
||||||
slotInfo[i] = new Slotinfo(slot.key, slot.lo, slot.hi, slotScores[i], slot.entry);
|
slotInfo[i] = new Slotinfo(slot.key, slot.lo, slot.hi, slotScores[i], new Assign(), slot.entry);
|
||||||
}
|
}
|
||||||
return slotInfo;
|
return slotInfo;
|
||||||
}
|
}
|
||||||
@@ -897,7 +902,6 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
final boolean multiThreaded) {
|
final boolean multiThreaded) {
|
||||||
val NO_LOG = (!Main.VERBOSE || multiThreaded);
|
val NO_LOG = (!Main.VERBOSE || multiThreaded);
|
||||||
val used = new long[2048];
|
val used = new long[2048];
|
||||||
val assigned = new long[CLUE_INDEX_MAX_SIZE];
|
|
||||||
val bitset = new long[2500];
|
val bitset = new long[2500];
|
||||||
val g = grid.g;
|
val g = grid.g;
|
||||||
val TOTAL = slots.length;
|
val TOTAL = slots.length;
|
||||||
@@ -915,8 +919,8 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
if ((now - lastLog) < LOG_EVERY_MS) return;
|
if ((now - lastLog) < LOG_EVERY_MS) return;
|
||||||
lastLog = (now);
|
lastLog = (now);
|
||||||
var done = 0;
|
var done = 0;
|
||||||
for (var lemma : assigned) {
|
for (var lemma : slots) {
|
||||||
if (lemma != X) done++;
|
if (lemma.assign.w != X) done++;
|
||||||
}
|
}
|
||||||
var pct = (TOTAL == 0) ? 100 : (int) Math.floor((done / (double) TOTAL) * 100);
|
var pct = (TOTAL == 0) ? 100 : (int) Math.floor((done / (double) TOTAL) * 100);
|
||||||
var filled = Math.min(BAR_LEN, (int) Math.floor((pct / 100.0) * BAR_LEN));
|
var filled = Math.min(BAR_LEN, (int) Math.floor((pct / 100.0) * BAR_LEN));
|
||||||
@@ -964,11 +968,11 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
void chooseMRV() {
|
void chooseMRV() {
|
||||||
Slotinfo best = null;
|
SwedishGenerator.Slotinfo best = null;
|
||||||
for (int i = 0, count, count2 = -1, bestScore = -1, n = TOTAL; i < n; i++) {
|
for (int i = 0, count, count2 = -1, bestScore = -1, n = TOTAL; i < n; i++) {
|
||||||
var s = slots[i];
|
var s = slots[i];
|
||||||
if (assigned[s.key] != X) continue;
|
if (s.assign.w != X) continue;
|
||||||
var pattern = patternForSlot(glo, ghi, g, s.key, s.lo, s.hi);
|
var pattern = patternForSlot2(glo, ghi, g, s.key, s.lo, s.hi);
|
||||||
var index = s.entry;
|
var index = s.entry;
|
||||||
count = pattern == X ? index.length : candidateCountForPattern(bitset, pattern, index.posBitsets, index.numlong);
|
count = pattern == X ? index.length : candidateCountForPattern(bitset, pattern, index.posBitsets, index.numlong);
|
||||||
|
|
||||||
@@ -990,7 +994,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
current = PICK_DONE;
|
current = PICK_DONE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var pattern = patternForSlot(glo, ghi, g, best.key, best.lo, best.hi);
|
var pattern = patternForSlot2(glo, ghi, g, best.key, best.lo, best.hi);
|
||||||
var index = best.entry;
|
var index = best.entry;
|
||||||
current = CARRIER;
|
current = CARRIER;
|
||||||
current.slot = best;
|
current.slot = best;
|
||||||
@@ -1032,9 +1036,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
for (var t = 0; t < tries; t++) {
|
for (var t = 0; t < tries; t++) {
|
||||||
var r = rng.nextFloat();
|
var r = rng.nextFloat();
|
||||||
//int idxInArray = rng.biasedIndexPow3(L - 1);
|
//int idxInArray = rng.biasedIndexPow3(L - 1);
|
||||||
int idxInArray = (int) (r * r * r * (L - 1));
|
var w = entry.words[idxs[(int) (r * r * r * (L - 1))]];
|
||||||
var idx = idxs[idxInArray];
|
|
||||||
var w = entry.words[idx];
|
|
||||||
var lemIdx = Lemma.unpackIndex(w);
|
var lemIdx = Lemma.unpackIndex(w);
|
||||||
if (Bit1029.get(used, lemIdx)) continue;
|
if (Bit1029.get(used, lemIdx)) continue;
|
||||||
low = glo;
|
low = glo;
|
||||||
@@ -1042,11 +1044,11 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
if (!placeWord(k, slo, shi, w)) continue;
|
if (!placeWord(k, slo, shi, w)) continue;
|
||||||
|
|
||||||
Bit1029.set(used, lemIdx);
|
Bit1029.set(used, lemIdx);
|
||||||
assigned[k] = w;
|
//assigned[k] = w;
|
||||||
|
s.assign.w = w;
|
||||||
if (backtrack(depth + 1)) return true;
|
if (backtrack(depth + 1)) return true;
|
||||||
|
s.assign.w = X;
|
||||||
assigned[k] = X;
|
//assigned[k] = X;
|
||||||
Bit1029.clear(used, lemIdx);
|
Bit1029.clear(used, lemIdx);
|
||||||
glo = low;
|
glo = low;
|
||||||
ghi = top;
|
ghi = top;
|
||||||
@@ -1060,8 +1062,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
var tries = Math.min(MAX_TRIES_PER_SLOT, N);
|
var tries = Math.min(MAX_TRIES_PER_SLOT, N);
|
||||||
for (var t = 0; t < tries; t++) {
|
for (var t = 0; t < tries; t++) {
|
||||||
double r = rng.nextFloat();
|
double r = rng.nextFloat();
|
||||||
int idxInArray = (int) (r * r * r * (N - 1));
|
var w = entry.words[(int) (r * r * r * (N - 1))];
|
||||||
var w = entry.words[idxInArray];
|
|
||||||
var lemIdx = Lemma.unpackIndex(w);
|
var lemIdx = Lemma.unpackIndex(w);
|
||||||
if (Bit1029.get(used, lemIdx)) continue;
|
if (Bit1029.get(used, lemIdx)) continue;
|
||||||
low = glo;
|
low = glo;
|
||||||
@@ -1069,11 +1070,12 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
if (!placeWord(k, slo, shi, w)) continue;
|
if (!placeWord(k, slo, shi, w)) continue;
|
||||||
|
|
||||||
Bit1029.set(used, lemIdx);
|
Bit1029.set(used, lemIdx);
|
||||||
assigned[k] = w;
|
s.assign.w = w;
|
||||||
|
//assigned[k] = w;
|
||||||
|
|
||||||
if (backtrack(depth + 1)) return true;
|
if (backtrack(depth + 1)) return true;
|
||||||
|
s.assign.w = X;
|
||||||
assigned[k] = X;
|
//assigned[k] = X;
|
||||||
Bit1029.clear(used, lemIdx);
|
Bit1029.clear(used, lemIdx);
|
||||||
glo = low;
|
glo = low;
|
||||||
ghi = top;
|
ghi = top;
|
||||||
@@ -1091,6 +1093,8 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
// final progress line
|
// final progress line
|
||||||
grid.lo = solver.glo;
|
grid.lo = solver.glo;
|
||||||
grid.hi = solver.ghi;
|
grid.hi = solver.ghi;
|
||||||
|
val assigned = new long[CLUE_INDEX_MAX_SIZE];
|
||||||
|
Arrays.stream(slots).forEach(s -> assigned[s.key] = s.assign.w);
|
||||||
var res = new FillResult(ok, new Gridded(grid), assigned,
|
var res = new FillResult(ok, new Gridded(grid), assigned,
|
||||||
new FillStats(solver.nodes, solver.backtracks, (System.currentTimeMillis() - t0) / 1000.0, solver.lastMRV));
|
new FillStats(solver.nodes, solver.backtracks, (System.currentTimeMillis() - t0) / 1000.0, solver.lastMRV));
|
||||||
if (!multiThreaded) {
|
if (!multiThreaded) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package puzzle;
|
|||||||
|
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import puzzle.Export.ClueAt;
|
import puzzle.Export.ClueAt;
|
||||||
import puzzle.Export.Clued;
|
import puzzle.Export.Clued;
|
||||||
|
|||||||
Reference in New Issue
Block a user