introduce bitloops
This commit is contained in:
16
src/main/generated-sources/puzzle/Config.java
Normal file
16
src/main/generated-sources/puzzle/Config.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package puzzle;
|
||||
|
||||
/**
|
||||
* Generated constants from pom.xml during build via templating-maven-plugin.
|
||||
*/
|
||||
public final class Config {
|
||||
public static final int CLUE_SIZE = 4;
|
||||
public static final int MIN_LEN = 2;
|
||||
public static final int MAX_TRIES_PER_SLOT = 1000;
|
||||
public static final int MAX_LEN = 8;
|
||||
public static final int PUZZLE_ROWS = 8;
|
||||
public static final int PUZZLE_COLS = 9;
|
||||
public static final int PUZZLE_SIZE = PUZZLE_ROWS*PUZZLE_COLS;
|
||||
public static final int MAX_WORD_LENGTH = PUZZLE_ROWS;
|
||||
public static final int MAX_WORD_LENGTH_MIN_1 = PUZZLE_ROWS-1;
|
||||
}
|
||||
@@ -34,7 +34,7 @@ public class Main {
|
||||
@NoArgsConstructor
|
||||
public static class Opts {
|
||||
|
||||
static int SSIZE = 23;
|
||||
static int SSIZE = 20;
|
||||
public int seed = (int) (System.nanoTime() ^ System.currentTimeMillis());
|
||||
public int clueSize = SSIZE;
|
||||
public int pop = SSIZE * 2;
|
||||
|
||||
@@ -28,13 +28,45 @@ public final class Masker {
|
||||
}
|
||||
|
||||
public boolean isValid(Clues c, int minLen) {
|
||||
return c.isValid(minLen, activeSLo, activeSHi);
|
||||
return findOffendingClue(c, minLen) == -1;
|
||||
}
|
||||
|
||||
|
||||
public int findOffendingClue(Clues grid, int minLen) {
|
||||
if (((grid.xlo & grid.rlo) & grid.lo) != X) return numberOfTrailingZeros((grid.xlo & grid.rlo) & grid.lo);
|
||||
if (((grid.xhi & grid.rhi) & grid.hi) != X) return 64 | numberOfTrailingZeros((grid.xhi & grid.rhi) & grid.hi);
|
||||
|
||||
int num = 0;
|
||||
for (long bits = grid.lo; bits != X; bits &= bits - 1) activeCIdx[num++] = numberOfTrailingZeros(bits);
|
||||
for (long bits = grid.hi; bits != X; bits &= bits - 1) activeCIdx[num++] = 64 | numberOfTrailingZeros(bits);
|
||||
|
||||
if (num == 0) return -1;
|
||||
|
||||
int start = rng.randint0_SIZE() % num;
|
||||
int n = 0;
|
||||
for (int i = 0; i < num; i++) {
|
||||
int idx = activeCIdx[(start + i) % num];
|
||||
int dir = grid.getDir(idx);
|
||||
int key = Slot.packSlotKey(idx, dir);
|
||||
long sLo = PATH_LO[key], sHi = PATH_HI[key];
|
||||
long hLo = sLo & grid.lo, hHi = sHi & grid.hi;
|
||||
if (Slotinfo.increasing(key)) {
|
||||
if (hLo != X) { sLo &= (1L << numberOfTrailingZeros(hLo)) - 1; sHi = 0; }
|
||||
else if (hHi != X) { sHi &= (1L << numberOfTrailingZeros(hHi)) - 1; }
|
||||
} else {
|
||||
if (hHi != X) { sHi &= -(1L << (63 - numberOfLeadingZeros(hHi)) << 1); sLo = 0; }
|
||||
else if (hLo != X) { sLo &= -(1L << (63 - numberOfLeadingZeros(hLo)) << 1); }
|
||||
}
|
||||
if (bitCount(sLo) + bitCount(sHi) < minLen) return idx;
|
||||
for (int j = 0; j < n; j++) if (bitCount(sLo & activeSLo[j]) + bitCount(sHi & activeSHi[j]) > 1) return idx;
|
||||
activeSLo[n] = sLo; activeSHi[n] = sHi; n++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void cleanup(Clues c, int minLen) {
|
||||
int guard = 0;
|
||||
while (guard++ < 50) {
|
||||
int offending = c.findOffendingClue(minLen, activeSLo, activeSHi);
|
||||
int offending = findOffendingClue(c, minLen);
|
||||
if (offending == -1) break;
|
||||
if ((offending & 64) == 0) c.clearClueLo(~(1L << offending));
|
||||
else c.clearClueHi(~(1L << (offending & 63)));
|
||||
@@ -199,6 +231,8 @@ public final class Masker {
|
||||
cVHi |= rHi;
|
||||
}
|
||||
if ((bitCount(rLo) + bitCount(rHi)) < MIN_LEN) penalty += 8000;
|
||||
int wordLen = bitCount(rLo) + bitCount(rHi);
|
||||
if (wordLen > 5) penalty += (wordLen - 5) * 2000;
|
||||
} else penalty += 25000;
|
||||
}
|
||||
for (long bits = hi_cl; bits != X; bits &= bits - 1) {
|
||||
@@ -221,12 +255,12 @@ public final class Masker {
|
||||
int msb = 63 - numberOfLeadingZeros(hLo);
|
||||
rLo &= -(1L << msb << 1);
|
||||
}
|
||||
|
||||
|
||||
activeCIdx[numClues] = 64 | clueIdx;
|
||||
activeSLo[numClues] = rLo;
|
||||
activeSHi[numClues] = rHi;
|
||||
numClues++;
|
||||
|
||||
|
||||
if ((rLo | rHi) != X) {
|
||||
hasSlots = true;
|
||||
if (Slot.horiz(key)) {
|
||||
@@ -241,10 +275,22 @@ public final class Masker {
|
||||
cVHi |= rHi;
|
||||
}
|
||||
if ((bitCount(rLo) + bitCount(rHi)) < MIN_LEN) penalty += 8000;
|
||||
int wordLen = bitCount(rLo) + bitCount(rHi);
|
||||
if (wordLen > 5) penalty += (wordLen - 5) * 2000;
|
||||
} else penalty += 25000;
|
||||
}
|
||||
|
||||
if (!hasSlots) return 1_000_000_000L;
|
||||
|
||||
int[] rCount = new int[8];
|
||||
int[] cCount = new int[9];
|
||||
for (int i = 0; i < numClues; i++) {
|
||||
int idx = activeCIdx[i];
|
||||
rCount[idx & 7]++;
|
||||
cCount[idx >> 3]++;
|
||||
}
|
||||
for (int rc : rCount) if (rc < 2) penalty += (2 - rc) * 4000;
|
||||
for (int cc : cCount) if (cc < 2) penalty += (2 - cc) * 4000;
|
||||
|
||||
// Connectiviteitscheck
|
||||
for (int i = 0; i < numClues; i++) {
|
||||
@@ -269,44 +315,56 @@ public final class Masker {
|
||||
}
|
||||
|
||||
if (numClues > 0) {
|
||||
long reachedLo = 1L, reachedHi = 0L;
|
||||
stack[0] = 0;
|
||||
int sp = 1;
|
||||
while (sp > 0) {
|
||||
int cur = stack[--sp];
|
||||
long nLo = adjLo[cur] & ~reachedLo;
|
||||
long nHi = adjHi[cur] & ~reachedHi;
|
||||
while (nLo != 0) {
|
||||
long lsb = nLo & -nLo;
|
||||
int idx = numberOfTrailingZeros(lsb);
|
||||
reachedLo |= lsb;
|
||||
stack[sp++] = idx;
|
||||
nLo &= ~lsb;
|
||||
}
|
||||
while (nHi != 0) {
|
||||
long lsb = nHi & -nHi;
|
||||
int idx = 64 | numberOfTrailingZeros(lsb);
|
||||
reachedHi |= lsb;
|
||||
stack[sp++] = idx;
|
||||
nHi &= ~lsb;
|
||||
int maxReached = 0;
|
||||
long totalReachedLo = 0, totalReachedHi = 0;
|
||||
for (int i = 0; i < numClues; i++) {
|
||||
if (i < 64) { if ((totalReachedLo & (1L << i)) != 0) continue; }
|
||||
else { if ((totalReachedHi & (1L << (i - 64))) != 0) continue; }
|
||||
|
||||
long currentReachedLo = (i < 64) ? (1L << i) : 0;
|
||||
long currentReachedHi = (i >= 64) ? (1L << (i - 64)) : 0;
|
||||
stack[0] = i;
|
||||
int sp = 1;
|
||||
int count = 0;
|
||||
while (sp > 0) {
|
||||
int cur = stack[--sp];
|
||||
count++;
|
||||
long nLo = adjLo[cur] & ~currentReachedLo;
|
||||
long nHi = adjHi[cur] & ~currentReachedHi;
|
||||
while (nLo != 0) {
|
||||
long lsb = nLo & -nLo;
|
||||
int idx = numberOfTrailingZeros(lsb);
|
||||
currentReachedLo |= lsb;
|
||||
stack[sp++] = idx;
|
||||
nLo &= ~lsb;
|
||||
}
|
||||
while (nHi != 0) {
|
||||
long lsb = nHi & -nHi;
|
||||
int idx = 64 | numberOfTrailingZeros(lsb);
|
||||
currentReachedHi |= lsb;
|
||||
stack[sp++] = idx;
|
||||
nHi &= ~lsb;
|
||||
}
|
||||
}
|
||||
if (count > maxReached) maxReached = count;
|
||||
totalReachedLo |= currentReachedLo;
|
||||
totalReachedHi |= currentReachedHi;
|
||||
}
|
||||
int count = bitCount(reachedLo) + bitCount(reachedHi);
|
||||
if (count < numClues) {
|
||||
penalty += (numClues - count) * 4000;
|
||||
if (maxReached < numClues) {
|
||||
penalty += (numClues - maxReached) * 4000;
|
||||
penalty += 20000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (long bits = ~lo_cl & MASK_LO; bits != X; bits &= bits - 1) {
|
||||
int clueIdx = numberOfTrailingZeros(bits);
|
||||
var rci = IT[clueIdx];
|
||||
if ((4 - rci.nbrCount()) + bitCount(rci.n1() & lo_cl) + bitCount(rci.n2() & hi_cl) >= 3) penalty += 400;
|
||||
boolean h = (cHLo & (1L << clueIdx)) != X;
|
||||
boolean v = (cVLo & (1L << clueIdx)) != X;
|
||||
if (!h && !v) penalty += 5000;
|
||||
else if (h && v) { /* ok */ } else if (((h ? cHLo2 : cVLo2) & (1L << clueIdx)) != X) penalty += 600;
|
||||
else penalty += 200;
|
||||
if (!h && !v) penalty += 2000;
|
||||
else if (h && v) { /* ok */ } else if (((h ? cHLo2 : cVLo2) & (1L << clueIdx)) != X) penalty += 1000;
|
||||
else penalty += 1000;
|
||||
}
|
||||
for (long bits = ~hi_cl & MASK_HI; bits != X; bits &= bits - 1) {
|
||||
int clueIdx = numberOfTrailingZeros(bits);
|
||||
@@ -315,11 +373,23 @@ public final class Masker {
|
||||
boolean h = (cHHi & (1L << clueIdx)) != X;
|
||||
boolean v = (cVHi & (1L << clueIdx)) != X;
|
||||
if (!h && !v)
|
||||
penalty += 5000;
|
||||
else if (h && v) { /* ok */ } else if (((h ? cHHi2 : cVHi2) & (1L << clueIdx)) != X) penalty += 600;
|
||||
else penalty += 200;
|
||||
penalty += 2000;
|
||||
else if (h && v) { /* ok */ } else if (((h ? cHHi2 : cVHi2) & (1L << clueIdx)) != X) penalty += 1000;
|
||||
else penalty += 1000;
|
||||
}
|
||||
|
||||
|
||||
long nclLo = ~lo_cl & MASK_LO;
|
||||
long nclHi = ~hi_cl & MASK_HI;
|
||||
long hNbrLo = (nclLo >> 8) | (nclLo << 8) | (nclHi << 56);
|
||||
long hNbrHi = (nclHi >> 8) | (nclLo >> 56);
|
||||
long vNbrLo = ((nclLo & ~0x0101010101010101L) >> 1) | ((nclLo & ~0x8080808080808080L) << 1);
|
||||
long vNbrHi = ((nclHi & ~0x01L) >> 1) | ((nclHi & ~0x80L) << 1);
|
||||
|
||||
penalty += bitCount(nclLo & ~cHLo & hNbrLo) * 800;
|
||||
penalty += bitCount(nclLo & ~cVLo & vNbrLo) * 800;
|
||||
penalty += bitCount(nclHi & ~cHHi & hNbrHi) * 800;
|
||||
penalty += bitCount(nclHi & ~cVHi & vNbrHi) * 800;
|
||||
|
||||
return penalty;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ public record SwedishGenerator() {
|
||||
public static final int MAX_WORD_LENGTH = Config.PUZZLE_ROWS;
|
||||
public static final int MAX_WORD_LENGTH_PLUS_ONE = MAX_WORD_LENGTH + 1;
|
||||
public static final int MIN_LEN = 2;//Neighbors9x8.MIN_LEN;//Config.MIN_LEN;
|
||||
public static final int MAX_TRIES_PER_SLOT = 700;//Config.MAX_TRIES_PER_SLOT;
|
||||
public static final int MAX_TRIES_PER_SLOT = 1200;//Config.MAX_TRIES_PER_SLOT;
|
||||
public static final int STACK_SIZE = 128;
|
||||
public static final long RANGE_0_SIZE = Neighbors9x8.RANGE_0_SIZE;// (long) SIZE_MIN_1 - 0L + 1L
|
||||
public static final long RANGE_0_624 = Neighbors9x8.RANGE_0_624;//624L - 0L + 1L;
|
||||
|
||||
Reference in New Issue
Block a user