introduce bitloops
This commit is contained in:
@@ -58,11 +58,11 @@ public record Export() {
|
|||||||
static long pack(int r, int c) { return (((long) r) << 32) ^ (c & 0xFFFFFFFFL); }
|
static long pack(int r, int c) { return (((long) r) << 32) ^ (c & 0xFFFFFFFFL); }
|
||||||
long l1, l2;
|
long l1, l2;
|
||||||
public boolean get(int bitIndex) {
|
public boolean get(int bitIndex) {
|
||||||
if (bitIndex < 64) return (l1 & (1L << bitIndex)) != 0L;
|
if ((bitIndex & 64) == 0) return (l1 & (1L << bitIndex)) != 0L;
|
||||||
return (l2 & (1L << (bitIndex & 63))) != 0L;
|
return (l2 & (1L << (bitIndex & 63))) != 0L;
|
||||||
}
|
}
|
||||||
public void set(int bitIndex) {
|
public void set(int bitIndex) {
|
||||||
if (bitIndex < 64) this.l1 |= 1L << bitIndex;
|
if ((bitIndex & 64) == 0) this.l1 |= 1L << bitIndex;
|
||||||
else this.l2 |= 1L << (bitIndex & 63);
|
else this.l2 |= 1L << (bitIndex & 63);
|
||||||
}
|
}
|
||||||
public void clear() {
|
public void clear() {
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
static final double SIZED = (double) SIZE;// ~18
|
static final double SIZED = (double) SIZE;// ~18
|
||||||
static final int TARGET_CLUES = SIZE >> 2;
|
static final int TARGET_CLUES = SIZE >> 2;
|
||||||
static final int MAX_WORD_LENGTH = C <= R ? C : R;
|
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 MAX_WORD_LENGTH_PLUS_ONE = MAX_WORD_LENGTH + 1;
|
||||||
static final int MIN_LEN = Config.MIN_LEN;
|
static final int MIN_LEN = Config.MIN_LEN;
|
||||||
static final int MIN_LEN7 = Config.MIN_LEN * 7;
|
static final int MIN_LEN7 = Config.MIN_LEN * 7;
|
||||||
@@ -123,8 +122,8 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
|
|
||||||
static final class Context {
|
static final class Context {
|
||||||
|
|
||||||
final int[] covH = new int[SIZE];
|
final Bit covH2 = new Bit();
|
||||||
final int[] covV = new int[SIZE];
|
final Bit covV2 = new Bit();
|
||||||
final int[] cellCount = new int[SIZE];
|
final int[] cellCount = new int[SIZE];
|
||||||
final int[] stack = new int[SIZE];
|
final int[] stack = new int[SIZE];
|
||||||
final Bit seen = new Bit();
|
final Bit seen = new Bit();
|
||||||
@@ -188,35 +187,32 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
void setByteAt(int idx, byte ch) { g[idx] = ch; }
|
void setByteAt(int idx, byte ch) { g[idx] = ch; }
|
||||||
void setClue(int idx, byte ch) {
|
void setClue(int idx, byte ch) {
|
||||||
g[idx] = ch;
|
g[idx] = ch;
|
||||||
if (idx < 64) lo |= (1L << idx);
|
if ((idx & 64) == 0) lo |= (1L << idx);
|
||||||
else hi |= (1L << (idx & 63));
|
else hi |= (1L << (idx & 63));
|
||||||
}
|
}
|
||||||
void clearletter(int idx) { g[idx] = DASH; }
|
void clearletter(int idx) { g[idx] = DASH; }
|
||||||
void clearClue(int idx) {
|
void clearClue(int idx) {
|
||||||
g[idx] = DASH;
|
g[idx] = DASH;
|
||||||
if (idx < 64) lo &= ~(1L << idx);
|
if ((idx & 64) == 0) lo &= ~(1L << idx);
|
||||||
else hi &= ~(1L << (idx & 63));
|
else hi &= ~(1L << (idx & 63));
|
||||||
}
|
}
|
||||||
static boolean isDigit(byte b) { return (b & B48) == B48; }
|
static boolean isDigit(byte b) { return (b & B48) == B48; }
|
||||||
boolean isDigitAt(int index) { return isDigit(g[index]); }
|
boolean isDigitAt(int index) { return isDigit(g[index]); }
|
||||||
boolean isClue(long 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;
|
return ((hi >> (index & 63)) & 1L) != X;
|
||||||
}
|
}
|
||||||
boolean isClue(int index) {
|
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;
|
return ((hi >> (index & 63)) & 1L) != 0;
|
||||||
}
|
}
|
||||||
boolean notClue(long index) {
|
boolean notClue(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 notClue(int index) {
|
|
||||||
if (index < 64) return ((lo >> index) & 1L) == X;
|
|
||||||
return ((hi >> (index & 63)) & 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) {
|
boolean clueless(int idx) {
|
||||||
if (idx < 64) {
|
if ((idx & 64) == 0) {
|
||||||
val test = (1L << idx);
|
val test = (1L << idx);
|
||||||
if ((test & lo) == X) return false;
|
if ((test & lo) == X) return false;
|
||||||
g[idx] = DASH;
|
g[idx] = DASH;
|
||||||
@@ -257,6 +253,9 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
public static record Lemma(int index, long word, byte len) {
|
public static record Lemma(int index, long word, byte len) {
|
||||||
|
|
||||||
static int LEMMA_COUNTER = 0;
|
static int LEMMA_COUNTER = 0;
|
||||||
|
static long pack(String word) {
|
||||||
|
return pack(word.getBytes(US_ASCII));
|
||||||
|
}
|
||||||
static long pack(byte[] b) {
|
static long pack(byte[] b) {
|
||||||
long w = 0;
|
long w = 0;
|
||||||
for (var i = 0; i < b.length; i++) w |= ((long) b[i] & ~64) << (i * 5);
|
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];
|
long packed = nbrs16.path()[clueIdx];
|
||||||
int n = (int) (packed >>> 56) * 7, k, idx;
|
int n = (int) (packed >>> 56) * 7, k, idx;
|
||||||
var horiz = Slot.horiz(d) ? covH : covV;
|
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);
|
idx = (int) ((packed >>> (k)) & 0x7F);
|
||||||
if (grid.isClue(idx)) break;
|
if (grid.isClue(idx)) break;
|
||||||
horiz[idx] += 1;
|
horiz[idx] += 1;
|
||||||
@@ -408,10 +407,12 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
|
|
||||||
long maskFitness(Grid grid) {
|
long maskFitness(Grid grid) {
|
||||||
var ctx = CTX.get();
|
var ctx = CTX.get();
|
||||||
var covH = ctx.covH;
|
var covH = ctx.covH2;
|
||||||
var covV = ctx.covV;
|
var covV = ctx.covV2;
|
||||||
Arrays.fill(covH, 0, SIZE, 0);
|
covH.clear();
|
||||||
Arrays.fill(covV, 0, SIZE, 0);
|
covV.clear();
|
||||||
|
/*Arrays.fill(covH, 0, SIZE, 0);
|
||||||
|
Arrays.fill(covV, 0, SIZE, 0);*/
|
||||||
long lo_cl = grid.lo, hi_cl = grid.hi;
|
long lo_cl = grid.lo, hi_cl = grid.hi;
|
||||||
long penalty = (((long) Math.abs(grid.clueCount() - TARGET_CLUES)) * 16000L);
|
long penalty = (((long) Math.abs(grid.clueCount() - TARGET_CLUES)) * 16000L);
|
||||||
boolean hasSlots = false;
|
boolean hasSlots = false;
|
||||||
@@ -424,10 +425,10 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
long packed = nbrs16.path()[clueIdx];
|
long packed = nbrs16.path()[clueIdx];
|
||||||
int n = (int) (packed >>> 56) * 7, k, idx;
|
int n = (int) (packed >>> 56) * 7, k, idx;
|
||||||
var horiz = Slot.horiz(d) ? covH : covV;
|
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);
|
idx = (int) ((packed >>> (k)) & 0x7F);
|
||||||
if (grid.isClue(idx)) break;
|
if (grid.isClue(idx)) break;
|
||||||
horiz[idx] += 1;
|
horiz.set(idx);
|
||||||
}
|
}
|
||||||
if (k > 0) {
|
if (k > 0) {
|
||||||
hasSlots = true;
|
hasSlots = true;
|
||||||
@@ -470,10 +471,10 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
int clueIdx = i + Long.numberOfTrailingZeros(bits);
|
int clueIdx = i + Long.numberOfTrailingZeros(bits);
|
||||||
var rci = IT[clueIdx];
|
var rci = IT[clueIdx];
|
||||||
if ((4 - rci.nbrCount()) + Long.bitCount(rci.n1() & lo_cl) + Long.bitCount(rci.n2() & hi_cl) >= 3) penalty += 400;
|
if ((4 - rci.nbrCount()) + Long.bitCount(rci.n1() & lo_cl) + Long.bitCount(rci.n2() & hi_cl) >= 3) penalty += 400;
|
||||||
var h = covH[clueIdx];
|
var h = covH.get(clueIdx);
|
||||||
var v = covV[clueIdx];
|
var v = covV.get(clueIdx);
|
||||||
if (h == 0 && v == 0) penalty += 1500;
|
if (!h && !v) penalty += 1500;
|
||||||
else if (h > 0 && v > 0) { /* ok */ } else if (h + v == 1) penalty += 200;
|
else if (h && v) { /* ok */ } else if (h | v) penalty += 200;
|
||||||
else penalty += 600;
|
else penalty += 600;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -523,10 +524,10 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
if (out.g[i] != ch) {
|
if (out.g[i] != ch) {
|
||||||
out.g[i] = ch;
|
out.g[i] = ch;
|
||||||
if (Grid.isDigit(ch)) {
|
if (Grid.isDigit(ch)) {
|
||||||
if (i < 64) bo0 |= (1L << i);
|
if ((i & 64) == 0) bo0 |= (1L << i);
|
||||||
else bo1 |= (1L << (i & 63));
|
else bo1 |= (1L << (i & 63));
|
||||||
} else {
|
} else {
|
||||||
if (i < 64) bo0 &= ~(1L << i);
|
if ((i & 64) == 0) bo0 &= ~(1L << i);
|
||||||
else bo1 &= ~(1L << (i & 63));
|
else bo1 &= ~(1L << (i & 63));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -615,6 +616,11 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
//return pop.get(0).grid;
|
//return pop.get(0).grid;
|
||||||
return best.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) {
|
static long patternForSlot(Grid grid, Slot s) {
|
||||||
long p = 0;
|
long p = 0;
|
||||||
for (int i = 0, len = s.len(); i < len; i++) {
|
for (int i = 0, len = s.len(); i < len; i++) {
|
||||||
@@ -654,23 +660,27 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
return true;
|
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 pattern = ctx.pattern;
|
||||||
var listBuffer = ctx.intListBuffer;
|
var listBuffer = ctx.intListBuffer;
|
||||||
var listCount = 0;
|
var listCount = 0;
|
||||||
IntList tmp;
|
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);
|
int val = (int) ((pattern >>> (i * 5)) & 31);
|
||||||
if (val != 0) {
|
if (val != 0) {
|
||||||
listBuffer[listCount++] = entry.pos[i][val - 1];
|
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
|
// Sort constraints by size to optimize intersection
|
||||||
for (var i = 0; i < listCount - 1; i++) {
|
for (var i = 0; i < listCount - 1; i++) {
|
||||||
for (var j = i + 1; j < listCount; j++) {
|
for (var j = i + 1; j < listCount; j++) {
|
||||||
|
|||||||
@@ -167,8 +167,8 @@ public class MainTest {
|
|||||||
// Regression baseline for seed search starting at 12347, pop 4, gens 20
|
// Regression baseline for seed search starting at 12347, pop 4, gens 20
|
||||||
Assertions.assertEquals(12348, foundSeed, "Found seed changed");
|
Assertions.assertEquals(12348, foundSeed, "Found seed changed");
|
||||||
Assertions.assertEquals(18, res.filled().clueMap().size(), "Number of assigned words changed");
|
Assertions.assertEquals(18, res.filled().clueMap().size(), "Number of assigned words changed");
|
||||||
Assertions.assertEquals(Lemma.pack(new byte[]{ 'L', 'E', 'L', 'I', 'J', 'K', 'S' }), res.filled().clueMap().get(451).word());
|
Assertions.assertEquals(Lemma.pack("VERPATS"), res.filled().clueMap().get(74).word());
|
||||||
Assertions.assertEquals(73207692597665799L, res.filled().grid().grid().lo);
|
Assertions.assertEquals(301794542151533187L, res.filled().grid().grid().lo);
|
||||||
Assertions.assertEquals(193L, res.filled().grid().grid().hi);
|
Assertions.assertEquals(193L, res.filled().grid().grid().hi);
|
||||||
}
|
}
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user