introduce bitloops
This commit is contained in:
@@ -62,14 +62,16 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
static int clamp(int x, int a, int b) { return Math.max(a, Math.min(b, x)); }
|
static int clamp(int x, int a, int b) { return Math.max(a, Math.min(b, x)); }
|
||||||
record Pick(Slot slot, CandidateInfo info, boolean done) { }
|
record Pick(Slot slot, CandidateInfo info, boolean done) { }
|
||||||
|
|
||||||
static final byte B0 = (byte) 0;
|
static final byte B0 = (byte) 0;
|
||||||
static final byte B64 = (byte) 64;
|
static final byte B64 = (byte) 64;
|
||||||
static final byte B48 = (byte) 48;
|
static final byte B48 = (byte) 48;
|
||||||
static final long[] OFFSETS_D_IDX = Neighbors9x8.OFFSET_D_IDX;
|
static final long[] OFFSETS_D_IDX = Neighbors9x8.OFFSET_D_IDX;
|
||||||
static final rci[] IT = Neighbors9x8.IT;
|
static final rci[] IT = Neighbors9x8.IT;
|
||||||
static final int[][] MUTATE_RI = new int[SIZE][625];
|
static final int[][] MUTATE_RI = new int[SIZE][625];
|
||||||
static final long[] NBR8_PACKED_LO = Neighbors9x8.NBR8_PACKED_LO;
|
static final long[] NBR8_PACKED_LO = Neighbors9x8.NBR8_PACKED_LO;
|
||||||
static final long[] NBR8_PACKED_HI = Neighbors9x8.NBR8_PACKED_HI;
|
static final long[] NBR8_PACKED_HI = Neighbors9x8.NBR8_PACKED_HI;
|
||||||
|
static final long[] PATH_LO = Neighbors9x8.PATH_LO;
|
||||||
|
static final long[] PATH_HI = Neighbors9x8.PATH_HI;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
for (int i = 0; i < SIZE; i++) {
|
for (int i = 0; i < SIZE; i++) {
|
||||||
@@ -305,10 +307,10 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static record Slot(int key, long packedPos) {
|
static record Slot(int key, long packedPos, long packedPoslo, long packedPoshi) {
|
||||||
|
|
||||||
static final int BIT_FOR_DIR = 3;
|
static final int BIT_FOR_DIR = 3;
|
||||||
static Slot from(int key, long packedPos, int len) { return new Slot(key, packedPos | ((long) len << 56)); }
|
static Slot from(int key, long packedPos, int len) { return new Slot(key, packedPos | ((long) len << 56), 0L, 0L); }
|
||||||
void undoPlace(Grid grid, int mask) { for (int i = 0, len = len(); i < len; i++) if ((mask & (1L << i)) != 0) grid.clearletter(pos(i)); }
|
void undoPlace(Grid grid, int mask) { for (int i = 0, len = len(); i < len; i++) if ((mask & (1L << i)) != 0) grid.clearletter(pos(i)); }
|
||||||
public int len() { return (int) (packedPos >>> 56); }
|
public int len() { return (int) (packedPos >>> 56); }
|
||||||
public int clueR() { return Grid.r((key >>> BIT_FOR_DIR)); }
|
public int clueR() { return Grid.r((key >>> BIT_FOR_DIR)); }
|
||||||
@@ -322,6 +324,56 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
public static int packSlotDir(int idx, int d) { return (idx << BIT_FOR_DIR) | d; }
|
public static int packSlotDir(int idx, int d) { return (idx << BIT_FOR_DIR) | d; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface SlotVisitor2 {
|
||||||
|
|
||||||
|
void visitMasks(int slotDir, long loMask, long hiMask);
|
||||||
|
}
|
||||||
|
private static void processSlot(Grid grid, SlotVisitor2 visitor, int idx) {
|
||||||
|
int d = grid.digitAt(idx); // 1..4
|
||||||
|
int di = d - 1; // 0..3
|
||||||
|
int key = (idx << 2) | di;
|
||||||
|
|
||||||
|
long rayLo = PATH_LO[key];
|
||||||
|
long rayHi = PATH_HI[key];
|
||||||
|
|
||||||
|
// only consider clue cells
|
||||||
|
long hitsLo = rayLo & grid.lo;
|
||||||
|
long hitsHi = rayHi & grid.hi;
|
||||||
|
|
||||||
|
// slice ray to stop before first clue, depending on direction monotonicity
|
||||||
|
// right/down => increasing indices; up/left => decreasing indices
|
||||||
|
boolean increasing = (d == 2 || d == 3);
|
||||||
|
|
||||||
|
if (increasing) {
|
||||||
|
// first clue is lowest index among hits (lo first, then hi)
|
||||||
|
if (hitsLo != 0) {
|
||||||
|
long stop = 1L << Long.numberOfTrailingZeros(hitsLo);
|
||||||
|
rayLo &= (stop - 1);
|
||||||
|
rayHi = 0; // any hi is beyond the stop
|
||||||
|
} else if (hitsHi != 0) {
|
||||||
|
long stop = 1L << Long.numberOfTrailingZeros(hitsHi);
|
||||||
|
// keep all lo (lo indices are < any hi index), but cut hi below stop
|
||||||
|
rayHi &= (stop - 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// first clue is highest index among hits (hi first, then lo)
|
||||||
|
if (hitsHi != 0) {
|
||||||
|
int msb = 63 - Long.numberOfLeadingZeros(hitsHi);
|
||||||
|
long stop = 1L << msb;
|
||||||
|
rayHi &= ~((stop << 1) - 1); // keep bits > stop
|
||||||
|
rayLo = 0; // lo indices are below stop
|
||||||
|
} else if (hitsLo != 0) {
|
||||||
|
int msb = 63 - Long.numberOfLeadingZeros(hitsLo);
|
||||||
|
long stop = 1L << msb;
|
||||||
|
rayLo &= ~((stop << 1) - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rayLo | rayHi) != 0) {
|
||||||
|
visitor.visitMasks(Slot.packSlotDir(idx, d), rayLo, rayHi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void processSlot(Grid grid, SlotVisitor visitor, int idx) {
|
private static void processSlot(Grid grid, SlotVisitor visitor, int idx) {
|
||||||
var d = grid.digitAt(idx);
|
var d = grid.digitAt(idx);
|
||||||
var packed = OFFSETS_D_IDX[(d - 1) | (idx << 2)];
|
var packed = OFFSETS_D_IDX[(d - 1) | (idx << 2)];
|
||||||
@@ -462,7 +514,7 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
for (int placed = 0, guard = 0, idx; placed < TARGET_CLUES && guard < 4000; guard++) {
|
for (int placed = 0, guard = 0, idx; placed < TARGET_CLUES && guard < 4000; guard++) {
|
||||||
idx = rng.randint(0, SIZE_MIN_1);
|
idx = rng.randint(0, SIZE_MIN_1);
|
||||||
if (g.isClue(idx)) continue;
|
if (g.isClue(idx)) continue;
|
||||||
int d_idx = rng.randint2bit();
|
int d_idx = rng.randint2bit();
|
||||||
val packed = OFFSETS_D_IDX[d_idx | idx << 2];
|
val packed = OFFSETS_D_IDX[d_idx | idx << 2];
|
||||||
if (g.hasRoomForClue(packed)) {
|
if (g.hasRoomForClue(packed)) {
|
||||||
g.setClue(idx, (byte) (1 + (d_idx | 48)));
|
g.setClue(idx, (byte) (1 + (d_idx | 48)));
|
||||||
@@ -472,13 +524,13 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
return g;
|
return g;
|
||||||
}
|
}
|
||||||
Grid mutate(Grid grid) {
|
Grid mutate(Grid grid) {
|
||||||
var g = grid.deepCopyGrid();
|
var g = grid.deepCopyGrid();
|
||||||
int ri;
|
int ri;
|
||||||
var bytes = MUTATE_RI[rng.randint(0, SIZE_MIN_1)];
|
var bytes = MUTATE_RI[rng.randint(0, SIZE_MIN_1)];
|
||||||
for (var k = 0; k < 4; k++) {
|
for (var k = 0; k < 4; k++) {
|
||||||
ri = bytes[rng.randint(0, 624)];
|
ri = bytes[rng.randint(0, 624)];
|
||||||
if (!g.clueless(ri)) {
|
if (!g.clueless(ri)) {
|
||||||
int d_idx = rng.randint2bit();
|
int d_idx = rng.randint2bit();
|
||||||
val packed = OFFSETS_D_IDX[d_idx | ri << 2];
|
val packed = OFFSETS_D_IDX[d_idx | ri << 2];
|
||||||
if (g.hasRoomForClue(packed)) g.setClue(ri, (byte) (1 + (d_idx | 48)));
|
if (g.hasRoomForClue(packed)) g.setClue(ri, (byte) (1 + (d_idx | 48)));
|
||||||
}
|
}
|
||||||
@@ -587,8 +639,6 @@ public record SwedishGenerator(Rng rng) {
|
|||||||
var x = pop.get(i);
|
var x = pop.get(i);
|
||||||
if (x.fit() < best.fit()) best = x;
|
if (x.fit() < best.fit()) best = x;
|
||||||
}
|
}
|
||||||
//pop.sort(Comparator.comparingLong(GridAndFit::fit));
|
|
||||||
//return pop.get(0).grid;
|
|
||||||
return best.grid;
|
return best.grid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user