introduce bitloops
This commit is contained in:
@@ -51,7 +51,7 @@ public record Export() {
|
||||
|
||||
public record Clued(@Delegate Clues c) {
|
||||
|
||||
public Clued deepCopyGrid() { return new Clued(new Clues(c.lo, c.hi, c.vlo, c.vhi, c.rlo, c.rhi)); }
|
||||
public Clued deepCopyGrid() { return new Clued(new Clues(c.lo, c.hi, c.vlo, c.vhi, c.rlo, c.rhi, c.xlo, c.xhi)); }
|
||||
String gridToString() {
|
||||
var sb = new StringBuilder(INIT);
|
||||
forEachSlot((s, _, _) -> {
|
||||
@@ -199,7 +199,7 @@ public record Export() {
|
||||
|
||||
record Placed(long lemma, int slotKey, int[] cells) {
|
||||
|
||||
static final char[] DIRECTION = { Placed.VERTICAL, Placed.HORIZONTAL, Placed.VERTICAL, Placed.HORIZONTAL };
|
||||
static final char[] DIRECTION = { Placed.VERTICAL, Placed.HORIZONTAL, Placed.VERTICAL, Placed.HORIZONTAL, Placed.VERTICAL };
|
||||
public static final char HORIZONTAL = 'h';
|
||||
static final char VERTICAL = 'v';
|
||||
public int arrowCol() { return SwedishGenerator.IT[Slot.clueIndex(slotKey)].c(); }
|
||||
|
||||
@@ -130,9 +130,8 @@ public final class Masker {
|
||||
for (long bits = lo_cl; bits != X; bits &= bits - 1) {
|
||||
long lsb = bits & -bits;
|
||||
int clueIdx = numberOfTrailingZeros(lsb);
|
||||
int v = (grid.vlo & lsb) != 0 ? 1 : 0;
|
||||
int r = (grid.rlo & lsb) != 0 ? 1 : 0;
|
||||
int key = Slot.packSlotKey(clueIdx, (r << 1) | v);
|
||||
int dir = grid.getDir(clueIdx);
|
||||
int key = Slot.packSlotKey(clueIdx, dir);
|
||||
long rLo = PATH_LO[key], rHi = PATH_HI[key];
|
||||
long hLo = rLo & lo_cl, hHi = rHi & hi_cl;
|
||||
if (Slotinfo.increasing(key)) {
|
||||
@@ -173,9 +172,8 @@ public final class Masker {
|
||||
for (long bits = hi_cl; bits != X; bits &= bits - 1) {
|
||||
long lsb = bits & -bits;
|
||||
int clueIdx = numberOfTrailingZeros(lsb);
|
||||
int v = (grid.vhi & lsb) != 0 ? 1 : 0;
|
||||
int r = (grid.rhi & lsb) != 0 ? 1 : 0;
|
||||
int key = Slot.packSlotKey(64 | clueIdx, (r << 1) | v);
|
||||
int dir = grid.getDir(64 | clueIdx);
|
||||
int key = Slot.packSlotKey(64 | clueIdx, dir);
|
||||
long rLo = PATH_LO[key], rHi = PATH_HI[key];
|
||||
long hLo = rLo & lo_cl, hHi = rHi & hi_cl;
|
||||
if (Slotinfo.increasing(key)) {
|
||||
@@ -226,15 +224,6 @@ public final class Masker {
|
||||
// 1. Intersectie
|
||||
if (((activeSLo[i] & activeSLo[j]) | (activeSHi[i] & activeSHi[j])) != 0) {
|
||||
connected = true;
|
||||
} else {
|
||||
// 2. 8-naburigheid van clue cells
|
||||
int ci = activeCIdx[i];
|
||||
int cj = activeCIdx[j];
|
||||
if (cj < 64) {
|
||||
if ((NBR8_PACKED_LO[ci] & (1L << cj)) != 0) connected = true;
|
||||
} else {
|
||||
if ((NBR8_PACKED_HI[ci] & (1L << (cj & 63))) != 0) connected = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (connected) {
|
||||
@@ -282,7 +271,7 @@ public final class Masker {
|
||||
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 += 15000;
|
||||
if (!h && !v) penalty += 5000;
|
||||
else if (h && v) { /* ok */ } else if (((h ? cHLo2 : cVLo2) & (1L << clueIdx)) != X) penalty += 600;
|
||||
else penalty += 200;
|
||||
}
|
||||
@@ -293,7 +282,7 @@ public final class Masker {
|
||||
boolean h = (cHHi & (1L << clueIdx)) != X;
|
||||
boolean v = (cVHi & (1L << clueIdx)) != X;
|
||||
if (!h && !v)
|
||||
penalty += 15000;
|
||||
penalty += 5000;
|
||||
else if (h && v) { /* ok */ } else if (((h ? cHHi2 : cVHi2) & (1L << clueIdx)) != X) penalty += 600;
|
||||
else penalty += 200;
|
||||
}
|
||||
@@ -407,7 +396,9 @@ public final class Masker {
|
||||
(a.vlo & ~maskLo) | (other.vlo & maskLo),
|
||||
(a.vhi & ~maskHi) | (other.vhi & maskHi),
|
||||
(a.rlo & ~maskLo) | (other.rlo & maskLo),
|
||||
(a.rhi & ~maskHi) | (other.rhi & maskHi));
|
||||
(a.rhi & ~maskHi) | (other.rhi & maskHi),
|
||||
(a.xlo & ~maskLo) | (other.xlo & maskLo),
|
||||
(a.xhi & ~maskHi) | (other.xhi & maskHi));
|
||||
int guard = 0;
|
||||
while (!c.isValid(MIN_LEN) && guard++ < 3) {
|
||||
for (var l = c.lo & ~c.rlo & ~c.vlo; l != X; l &= l - 1) clearCluesLo(c, numberOfTrailingZeros(l), 0);
|
||||
@@ -513,9 +504,9 @@ public final class Masker {
|
||||
@AllArgsConstructor
|
||||
public static class Clues {
|
||||
|
||||
long lo, hi, vlo, vhi, rlo, rhi;
|
||||
long lo, hi, vlo, vhi, rlo, rhi, xlo, xhi;
|
||||
|
||||
public static Clues createEmpty() { return new Clues(0, 0, 0, 0, 0, 0); }
|
||||
public static Clues createEmpty() { return new Clues(0, 0, 0, 0, 0, 0, 0, 0); }
|
||||
public static Clued parse(String s) {
|
||||
var c = createEmpty();
|
||||
var lines = s.split("\n");
|
||||
@@ -523,7 +514,7 @@ public final class Masker {
|
||||
var line = lines[r];
|
||||
for (int col = 0; col < Math.min(line.length(), C); col++) {
|
||||
char ch = line.charAt(col);
|
||||
if (ch >= '0' && ch <= '3') {
|
||||
if (ch >= '0' && ch <= '4') {
|
||||
int idx = Grid.offset(r, col);
|
||||
byte dir = (byte) (ch - '0');
|
||||
if ((idx & 64) == 0) c.setClueLo(1L << idx, dir);
|
||||
@@ -557,6 +548,8 @@ public final class Masker {
|
||||
else vlo &= ~mask;
|
||||
if ((idx & 2) != 0) rlo |= mask;
|
||||
else rlo &= ~mask;
|
||||
if ((idx & 4) != 0) xlo |= mask;
|
||||
else xlo &= ~mask;
|
||||
}
|
||||
public void setClueHi(long mask, byte idx) {
|
||||
hi |= mask;
|
||||
@@ -564,16 +557,20 @@ public final class Masker {
|
||||
else vhi &= ~mask;
|
||||
if ((idx & 2) != 0) rhi |= mask;
|
||||
else rhi &= ~mask;
|
||||
if ((idx & 4) != 0) xhi |= mask;
|
||||
else xhi &= ~mask;
|
||||
}
|
||||
public void clearClueLo(long mask) {
|
||||
lo &= mask;
|
||||
vlo &= mask;
|
||||
rlo &= mask;
|
||||
xlo &= mask;
|
||||
}
|
||||
public void clearClueHi(long mask) {
|
||||
hi &= mask;
|
||||
vhi &= mask;
|
||||
rhi &= mask;
|
||||
xhi &= mask;
|
||||
}
|
||||
public boolean isClueLo(int index) { return ((lo >>> index) & 1L) != X; }
|
||||
public boolean isClueHi(int index) { return ((hi >>> (index & 63)) & 1L) != X; }
|
||||
@@ -582,8 +579,8 @@ public final class Masker {
|
||||
|
||||
public int clueCount() { return bitCount(lo) + bitCount(hi); }
|
||||
public double similarity(Clues b) {
|
||||
long matchLo = (~(lo ^ b.lo)) & (~lo | (~(vlo ^ b.vlo) & ~(rlo ^ b.rlo)));
|
||||
long matchHi = (~(hi ^ b.hi)) & (~hi | (~(vhi ^ b.vhi) & ~(rhi ^ b.rhi)));
|
||||
long matchLo = (~(lo ^ b.lo)) & (~lo | (~(vlo ^ b.vlo) & ~(rlo ^ b.rlo) & ~(xlo ^ b.xlo)));
|
||||
long matchHi = (~(hi ^ b.hi)) & (~hi | (~(vhi ^ b.vhi) & ~(rhi ^ b.rhi) & ~(xhi ^ b.xhi)));
|
||||
|
||||
return (bitCount(matchLo & MASK_LO) + bitCount(matchHi & MASK_HI)) / SIZED;
|
||||
}
|
||||
@@ -601,14 +598,17 @@ public final class Masker {
|
||||
return v.ok;
|
||||
}
|
||||
public void forEachSlot(SlotVisitor visitor) {
|
||||
for (var l = lo & ~rlo & vlo; l != X; l &= l - 1) processSlot(this, visitor, Slot.packSlotKey(numberOfTrailingZeros(l), 1));
|
||||
for (var l = lo & ~rlo & ~vlo; l != X; l &= l - 1) processSlot(this, visitor, Slot.packSlotKey(numberOfTrailingZeros(l), 0));
|
||||
for (var l = lo & rlo & ~vlo; l != X; l &= l - 1) processSlotRev(this, visitor, Slot.packSlotKey(numberOfTrailingZeros(l), 2));
|
||||
for (var l = lo & rlo & vlo; l != X; l &= l - 1) processSlotRev(this, visitor, Slot.packSlotKey(numberOfTrailingZeros(l), 3));
|
||||
for (var h = hi & ~rhi & vhi; h != X; h &= h - 1) processSlot(this, visitor, Slot.packSlotKey(64 | numberOfTrailingZeros(h), 1));
|
||||
for (var h = hi & ~rhi & ~vhi; h != X; h &= h - 1) processSlot(this, visitor, Slot.packSlotKey(64 | numberOfTrailingZeros(h), 0));
|
||||
for (var h = hi & rhi & ~vhi; h != X; h &= h - 1) processSlotRev(this, visitor, Slot.packSlotKey((64 | numberOfTrailingZeros(h)), 2));
|
||||
for (var h = hi & rhi & vhi; h != X; h &= h - 1) processSlotRev(this, visitor, Slot.packSlotKey((64 | numberOfTrailingZeros(h)), 3));
|
||||
for (var l = lo & ~xlo & ~rlo & vlo; l != X; l &= l - 1) processSlot(this, visitor, Slot.packSlotKey(numberOfTrailingZeros(l), 1));
|
||||
for (var l = lo & ~xlo & ~rlo & ~vlo; l != X; l &= l - 1) processSlot(this, visitor, Slot.packSlotKey(numberOfTrailingZeros(l), 0));
|
||||
for (var l = lo & ~xlo & rlo & ~vlo; l != X; l &= l - 1) processSlotRev(this, visitor, Slot.packSlotKey(numberOfTrailingZeros(l), 2));
|
||||
for (var l = lo & ~xlo & rlo & vlo; l != X; l &= l - 1) processSlotRev(this, visitor, Slot.packSlotKey(numberOfTrailingZeros(l), 3));
|
||||
for (var l = lo & xlo & ~rlo & ~vlo; l != X; l &= l - 1) processSlot(this, visitor, Slot.packSlotKey(numberOfTrailingZeros(l), 4));
|
||||
|
||||
for (var h = hi & ~xhi & ~rhi & vhi; h != X; h &= h - 1) processSlot(this, visitor, Slot.packSlotKey(64 | numberOfTrailingZeros(h), 1));
|
||||
for (var h = hi & ~xhi & ~rhi & ~vhi; h != X; h &= h - 1) processSlot(this, visitor, Slot.packSlotKey(64 | numberOfTrailingZeros(h), 0));
|
||||
for (var h = hi & ~xhi & rhi & ~vhi; h != X; h &= h - 1) processSlotRev(this, visitor, Slot.packSlotKey((64 | numberOfTrailingZeros(h)), 2));
|
||||
for (var h = hi & ~xhi & rhi & vhi; h != X; h &= h - 1) processSlotRev(this, visitor, Slot.packSlotKey((64 | numberOfTrailingZeros(h)), 3));
|
||||
for (var h = hi & xhi & ~rhi & ~vhi; h != X; h &= h - 1) processSlot(this, visitor, Slot.packSlotKey(64 | numberOfTrailingZeros(h), 4));
|
||||
}
|
||||
public Clues from(Clues best) {
|
||||
lo = best.lo;
|
||||
@@ -617,30 +617,34 @@ public final class Masker {
|
||||
vhi = best.vhi;
|
||||
rlo = best.rlo;
|
||||
rhi = best.rhi;
|
||||
xlo = best.xlo;
|
||||
xhi = best.xhi;
|
||||
return this;
|
||||
}
|
||||
public byte getDir(int index) {
|
||||
if ((index & 64) == 0) {
|
||||
int v = (vlo & (1L << index)) != 0 ? 1 : 0;
|
||||
int r = (rlo & (1L << index)) != 0 ? 1 : 0;
|
||||
return (byte) ((r << 1) | v);
|
||||
int x = (xlo & (1L << index)) != 0 ? 1 : 0;
|
||||
return (byte) ((x << 2) | (r << 1) | v);
|
||||
} else {
|
||||
int v = (vhi & (1L << (index & 63))) != 0 ? 1 : 0;
|
||||
int r = (rhi & (1L << (index & 63))) != 0 ? 1 : 0;
|
||||
return (byte) ((r << 1) | v);
|
||||
int x = (xhi & (1L << (index & 63))) != 0 ? 1 : 0;
|
||||
return (byte) ((x << 2) | (r << 1) | v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public record Slot(int key, long lo, long hi, DictEntry entry) {
|
||||
|
||||
static final int BIT_FOR_DIR = 2;
|
||||
static Slot from(int key, long lo, long hi, DictEntry entry) { return new Slot(key, lo, hi, entry); }
|
||||
static final int BIT_FOR_DIR = 3;
|
||||
public static Slot from(int key, long lo, long hi, DictEntry entry) { return new Slot(key, lo, hi, entry); }
|
||||
public static int length(long lo, long hi) { return bitCount(lo) + bitCount(hi); }
|
||||
public static int clueIndex(int key) { return key >>> BIT_FOR_DIR; }
|
||||
public static int dir(int key) { return key & 3; }
|
||||
public static int dir(int key) { return key & 7; }
|
||||
public IntStream walk() { return Gridded.walk((byte) key, lo, hi); }
|
||||
public static boolean horiz(int d) { return (d & 1) != 0; }
|
||||
public static boolean horiz(int d) { return (d & 1) != 0 && (d & 4) == 0; }
|
||||
public static int packSlotKey(int idx, int d) { return (idx << BIT_FOR_DIR) | d; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,12 +76,45 @@ public record SwedishGenerator() {
|
||||
public int count;
|
||||
}
|
||||
|
||||
public static final long[] OFFSETS_D_IDX = Neighbors9x8.OFFSET_D_IDX_0_BASE;
|
||||
public static final long[] OFFSETS_D_IDX;
|
||||
public static final rci[] IT = Neighbors9x8.IT;
|
||||
public static final long[] NBR8_PACKED_LO = Neighbors9x8.NBR8_PACKED_LO;
|
||||
public static final long[] NBR8_PACKED_HI = Neighbors9x8.NBR8_PACKED_HI;
|
||||
public static final long[] PATH_LO = Neighbors9x8.PATH_LO;
|
||||
public static final long[] PATH_HI = Neighbors9x8.PATH_HI;
|
||||
public static final long[] PATH_LO;
|
||||
public static final long[] PATH_HI;
|
||||
|
||||
static {
|
||||
final int NEW_SIZE = SIZE << Masker.Slot.BIT_FOR_DIR;
|
||||
PATH_LO = new long[NEW_SIZE];
|
||||
PATH_HI = new long[NEW_SIZE];
|
||||
OFFSETS_D_IDX = new long[NEW_SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
for (int d = 0; d < 4; d++) {
|
||||
int oldKey = (i << 2) | d;
|
||||
int newKey = (i << Masker.Slot.BIT_FOR_DIR) | d;
|
||||
PATH_LO[newKey] = Neighbors9x8.PATH_LO[oldKey];
|
||||
PATH_HI[newKey] = Neighbors9x8.PATH_HI[oldKey];
|
||||
OFFSETS_D_IDX[newKey] = Neighbors9x8.OFFSET_D_IDX_0_BASE[oldKey];
|
||||
}
|
||||
// Richting 4: Corner Down (Clue op r,c -> Woord op r,c+1 naar beneden)
|
||||
int r = IT[i].r();
|
||||
int c = IT[i].c();
|
||||
int newKey4 = (i << Masker.Slot.BIT_FOR_DIR) | 4;
|
||||
if (c + 1 < C) {
|
||||
long mLo = 0, mHi = 0;
|
||||
for (int ri = r; ri < R; ri++) {
|
||||
int target = Grid.offset(ri, c + 1);
|
||||
if (isLo(target)) mLo |= (1L << target);
|
||||
else mHi |= (1L << (target & 63));
|
||||
}
|
||||
PATH_LO[newKey4] = mLo;
|
||||
PATH_HI[newKey4] = mHi;
|
||||
int first = Grid.offset(r, c + 1);
|
||||
int last = Grid.offset(R - 1, c + 1);
|
||||
OFFSETS_D_IDX[newKey4] = (long)first | ((long)last << 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
public static final Pick PICK_DONE = null;//new Pick(null, null, 0, true);
|
||||
public static final Pick PICK_NOT_DONE = new Pick(null, null, 0);
|
||||
|
||||
@@ -112,13 +145,10 @@ public record SwedishGenerator() {
|
||||
return y;
|
||||
}
|
||||
public byte randint2bitByte() {
|
||||
var b = (byte) (nextU32() & 3);
|
||||
if (b == 3) {
|
||||
return 1;
|
||||
}if (b == 4) {
|
||||
return 2;
|
||||
}
|
||||
return b;
|
||||
int r = nextU32() & 7;
|
||||
if (r < 4) return (byte) r;
|
||||
if (r == 4) return (byte) 4;
|
||||
return (byte) (r % 4);
|
||||
}
|
||||
public <T> T rand(T[] p) { return p[(int) (((nextU32() & 0xFFFFFFFFL) % ((long) p.length /*- 0L*/ /*+ 1L*/)))]; }
|
||||
public <T> T rand(List<T> p) { return p.get((int) (((nextU32() & 0xFFFFFFFFL) % ((long) p.size() /*- 0L*/ /*+ 1L*/)))); }
|
||||
|
||||
Reference in New Issue
Block a user