introduce bitloops

This commit is contained in:
mike
2026-01-12 03:52:52 +01:00
parent 678add4cb9
commit 123cdbdc01
3 changed files with 47 additions and 37 deletions

View File

@@ -57,7 +57,6 @@ public record SwedishGenerator(Rng rng) {
static final double SIZED = (double) SIZE;// ~18
static final int TARGET_CLUES = SIZE >> 2;
static final int MAX_WORD_LENGTH = C <= R ? C : R;
static final int MAX_WORD_LENGTH7 = MAX_WORD_LENGTH * 7;
static final int MAX_WORD_LENGTH_PLUS_ONE = MAX_WORD_LENGTH + 1;
static final int MIN_LEN = Config.MIN_LEN;
static final int MIN_LEN7 = Config.MIN_LEN * 7;
@@ -123,8 +122,8 @@ public record SwedishGenerator(Rng rng) {
static final class Context {
final int[] covH = new int[SIZE];
final int[] covV = new int[SIZE];
final Bit covH2 = new Bit();
final Bit covV2 = new Bit();
final int[] cellCount = new int[SIZE];
final int[] stack = new int[SIZE];
final Bit seen = new Bit();
@@ -188,35 +187,32 @@ public record SwedishGenerator(Rng rng) {
void setByteAt(int idx, byte ch) { g[idx] = ch; }
void setClue(int idx, byte ch) {
g[idx] = ch;
if (idx < 64) lo |= (1L << idx);
if ((idx & 64) == 0) lo |= (1L << idx);
else hi |= (1L << (idx & 63));
}
void clearletter(int idx) { g[idx] = DASH; }
void clearClue(int idx) {
g[idx] = DASH;
if (idx < 64) lo &= ~(1L << idx);
if ((idx & 64) == 0) lo &= ~(1L << idx);
else hi &= ~(1L << (idx & 63));
}
static boolean isDigit(byte b) { return (b & B48) == B48; }
boolean isDigitAt(int index) { return isDigit(g[index]); }
boolean isClue(long index) {
if (index < 64) return ((lo >> index) & 1L) != X;
if ((index & 64) == 0) return ((lo >> index) & 1L) != X;
return ((hi >> (index & 63)) & 1L) != X;
}
boolean isClue(int index) {
if (index < 64) return ((lo >> index) & 1L) != 0;
if ((index & 64) == 0) return ((lo >> index) & 1L) != 0;
return ((hi >> (index & 63)) & 1L) != 0;
}
boolean notClue(long index) {
if (index < 64) return ((lo >> index) & 1L) == X;
return ((hi >> (index & 63)) & 1L) == X;
}
boolean notClue(int index) {
if (index < 64) return ((lo >> index) & 1L) == X;
if ((index & 64) == 0) return ((lo >> index) & 1L) == X;
return ((hi >> (index & 63)) & 1L) == X;
}
boolean notClue(int index) { return ((index & 64) == 0) ? ((lo >> index) & 1L) == X : ((hi >> (index & 63)) & 1L) == X; }
boolean clueless(int idx) {
if (idx < 64) {
if ((idx & 64) == 0) {
val test = (1L << idx);
if ((test & lo) == X) return false;
g[idx] = DASH;
@@ -257,6 +253,9 @@ public record SwedishGenerator(Rng rng) {
public static record Lemma(int index, long word, byte len) {
static int LEMMA_COUNTER = 0;
static long pack(String word) {
return pack(word.getBytes(US_ASCII));
}
static long pack(byte[] b) {
long w = 0;
for (var i = 0; i < b.length; i++) w |= ((long) b[i] & ~64) << (i * 5);
@@ -394,7 +393,7 @@ public record SwedishGenerator(Rng rng) {
long packed = nbrs16.path()[clueIdx];
int n = (int) (packed >>> 56) * 7, k, idx;
var horiz = Slot.horiz(d) ? covH : covV;
for (k = 0; k < n && k < MAX_WORD_LENGTH7; k += 7) {
for (k = 0; k < n; k += 7) {
idx = (int) ((packed >>> (k)) & 0x7F);
if (grid.isClue(idx)) break;
horiz[idx] += 1;
@@ -408,10 +407,12 @@ public record SwedishGenerator(Rng rng) {
long maskFitness(Grid grid) {
var ctx = CTX.get();
var covH = ctx.covH;
var covV = ctx.covV;
Arrays.fill(covH, 0, SIZE, 0);
Arrays.fill(covV, 0, SIZE, 0);
var covH = ctx.covH2;
var covV = ctx.covV2;
covH.clear();
covV.clear();
/*Arrays.fill(covH, 0, SIZE, 0);
Arrays.fill(covV, 0, SIZE, 0);*/
long lo_cl = grid.lo, hi_cl = grid.hi;
long penalty = (((long) Math.abs(grid.clueCount() - TARGET_CLUES)) * 16000L);
boolean hasSlots = false;
@@ -424,10 +425,10 @@ public record SwedishGenerator(Rng rng) {
long packed = nbrs16.path()[clueIdx];
int n = (int) (packed >>> 56) * 7, k, idx;
var horiz = Slot.horiz(d) ? covH : covV;
for (k = 0; k < n && k < MAX_WORD_LENGTH7; k += 7) {
for (k = 0; k < n; k += 7) {
idx = (int) ((packed >>> (k)) & 0x7F);
if (grid.isClue(idx)) break;
horiz[idx] += 1;
horiz.set(idx);
}
if (k > 0) {
hasSlots = true;
@@ -470,10 +471,10 @@ public record SwedishGenerator(Rng rng) {
int clueIdx = i + Long.numberOfTrailingZeros(bits);
var rci = IT[clueIdx];
if ((4 - rci.nbrCount()) + Long.bitCount(rci.n1() & lo_cl) + Long.bitCount(rci.n2() & hi_cl) >= 3) penalty += 400;
var h = covH[clueIdx];
var v = covV[clueIdx];
if (h == 0 && v == 0) penalty += 1500;
else if (h > 0 && v > 0) { /* ok */ } else if (h + v == 1) penalty += 200;
var h = covH.get(clueIdx);
var v = covV.get(clueIdx);
if (!h && !v) penalty += 1500;
else if (h && v) { /* ok */ } else if (h | v) penalty += 200;
else penalty += 600;
}
}
@@ -523,10 +524,10 @@ public record SwedishGenerator(Rng rng) {
if (out.g[i] != ch) {
out.g[i] = ch;
if (Grid.isDigit(ch)) {
if (i < 64) bo0 |= (1L << i);
if ((i & 64) == 0) bo0 |= (1L << i);
else bo1 |= (1L << (i & 63));
} else {
if (i < 64) bo0 &= ~(1L << i);
if ((i & 64) == 0) bo0 &= ~(1L << i);
else bo1 &= ~(1L << (i & 63));
}
}
@@ -615,6 +616,11 @@ public record SwedishGenerator(Rng rng) {
//return pop.get(0).grid;
return best.grid;
}
static int usedCharsInPattern(long p) {
if (p == 0) return 0;
int highestBit = 63 - Long.numberOfLeadingZeros(p); // 0-based
return (highestBit / 5) + 1;
}
static long patternForSlot(Grid grid, Slot s) {
long p = 0;
for (int i = 0, len = s.len(); i < len; i++) {
@@ -654,23 +660,27 @@ public record SwedishGenerator(Rng rng) {
return true;
}
static CandidateInfo candidateInfoForPattern(Context ctx, DictEntry entry, int len) {
static CandidateInfo candidateInfoForPattern(Context ctx, DictEntry entry, int lenb) {
var pattern = ctx.pattern;
var listBuffer = ctx.intListBuffer;
var listCount = 0;
IntList tmp;
for (var i = 0; i < len; i++) {
if (pattern == X) {
return new CandidateInfo(null, entry.words.length);
}
/*if (usedCharsInPattern(pattern) > len) {
var abc = usedCharsInPattern(pattern);
System.out.println(abc);
}*/
for (int i = 0, len = usedCharsInPattern(pattern); i < len; i++) {
int val = (int) ((pattern >>> (i * 5)) & 31);
if (val != 0) {
listBuffer[listCount++] = entry.pos[i][val - 1];
} else {
//System.out.println("?");
}
}
if (listCount == 0) {
//return CANDIDATES[entry.words.length];
return new CandidateInfo(null, entry.words.length);
}
// Sort constraints by size to optimize intersection
for (var i = 0; i < listCount - 1; i++) {
for (var j = i + 1; j < listCount; j++) {