introduce bitloops
This commit is contained in:
@@ -98,12 +98,12 @@ public record Export() {
|
||||
public Stream<LetterAt> stream(Clues clues) {
|
||||
val stream = Stream.<LetterAt>builder();
|
||||
for (var l = grid.lo & ~clues.lo; l != X; l &= l - 1) stream.accept(LetterAt.from(Long.numberOfTrailingZeros(l), grid.g));
|
||||
for (var h = grid.hi & ~clues.hi; h != X; h &= h - 1) stream.accept(LetterAt.from(64 | Long.numberOfTrailingZeros(h), grid.g));
|
||||
for (var h = grid.hi & ~clues.hi & 0xFF; h != X; h &= h - 1) stream.accept(LetterAt.from(64 | Long.numberOfTrailingZeros(h), grid.g));
|
||||
return stream.build();
|
||||
}
|
||||
public void forEachLetter(Clues clues, LetterVisit visitor) {
|
||||
for (var l = grid.lo & ~clues.lo; l != X; l &= l - 1) visitor.visit(Long.numberOfTrailingZeros(l), grid.g);
|
||||
for (var h = grid.hi & ~clues.hi; h != X; h &= h - 1) visitor.visit(64 | Long.numberOfTrailingZeros(h), grid.g);
|
||||
for (var h = grid.hi & ~clues.hi & 0xFF; h != X; h &= h - 1) visitor.visit(64 | Long.numberOfTrailingZeros(h), grid.g);
|
||||
}
|
||||
public static IntStream walk(byte base, long lo, long hi) {
|
||||
if (Slotinfo.increasing(base)) {
|
||||
@@ -243,7 +243,8 @@ public record Export() {
|
||||
return new ExportedPuzzle(grid.exportGrid(clues.c, _ -> '#', '#'), new WordOut[0], difficulty, rewards);
|
||||
}
|
||||
|
||||
var placed = Arrays.stream(slots).map(slot -> new Placed(slot.assign().w, slot.key(), Gridded.walk((byte) slot.key(), slot.lo(), slot.hi()).toArray())).toArray(Placed[]::new);
|
||||
var placed = Arrays.stream(slots).map(slot -> new Placed(slot.assign().w, slot.key(), Gridded.walk((byte) slot.key(), slot.lo(), slot.hi()).toArray())).toArray(
|
||||
Placed[]::new);
|
||||
|
||||
// 2) bounding box around all word cells + arrow cells, with 1-cell margin
|
||||
int minR = Integer.MAX_VALUE, minC = Integer.MAX_VALUE;
|
||||
|
||||
@@ -47,9 +47,9 @@ public class Main {
|
||||
static int SSIZE = 24;
|
||||
public int seed = (int) (System.nanoTime() ^ System.currentTimeMillis());
|
||||
public int clueSize = SSIZE;
|
||||
public int pop = SSIZE*2;
|
||||
public int offspring = SSIZE*3;
|
||||
public int gens =600;
|
||||
public int pop = SSIZE * 2;
|
||||
public int offspring = SSIZE * 3;
|
||||
public int gens = 600;
|
||||
public String wordsPath = "nl_score_hints_v3.csv";
|
||||
public double minSimplicity = 0; // 0 means no limit
|
||||
public int threads = Math.max(1, Runtime.getRuntime().availableProcessors());
|
||||
@@ -414,8 +414,8 @@ public class Main {
|
||||
if (mask == null) return null;
|
||||
|
||||
val slotInfo = Masker.slots(mask, dict.index());
|
||||
var grid = mask.toGrid();
|
||||
var filled = fillMask(rng, slotInfo, grid, (!Main.VERBOSE || multiThreaded));
|
||||
var grid = Slotinfo.grid(slotInfo);// mask.toGrid();
|
||||
var filled = fillMask(rng, slotInfo, grid, (!Main.VERBOSE || multiThreaded));
|
||||
|
||||
if (!multiThreaded) {
|
||||
System.out.print("\r" + Strings.padRight("", 120) + "\r");
|
||||
|
||||
@@ -14,7 +14,23 @@ import java.util.stream.IntStream;
|
||||
import static java.lang.Long.*;
|
||||
import static puzzle.SwedishGenerator.*;
|
||||
|
||||
public record Masker(Rng rng, int[] stack, Clues cache) {
|
||||
public final class Masker {
|
||||
|
||||
private final Rng rng;
|
||||
private final int[] stack;
|
||||
private final Clues cache;
|
||||
|
||||
private final int[] activeCIdx = new int[SwedishGenerator.SIZE];
|
||||
private final long[] activeSLo = new long[SwedishGenerator.SIZE];
|
||||
private final long[] activeSHi = new long[SwedishGenerator.SIZE];
|
||||
private final long[] adjLo = new long[SwedishGenerator.SIZE];
|
||||
private final long[] adjHi = new long[SwedishGenerator.SIZE];
|
||||
|
||||
public Masker(Rng rng, int[] stack, Clues cache) {
|
||||
this.rng = rng;
|
||||
this.stack = stack;
|
||||
this.cache = cache;
|
||||
}
|
||||
|
||||
public static final int[][] MUTATE_RI = new int[SwedishGenerator.SIZE][625];
|
||||
|
||||
@@ -109,6 +125,8 @@ public record Masker(Rng rng, int[] stack, Clues cache) {
|
||||
long penalty = (((long) Math.abs(grid.clueCount() - clueSize)) * 16000L);
|
||||
boolean hasSlots = false;
|
||||
if (!grid.isValid(2)) return 1_000_000_000L;
|
||||
|
||||
int numClues = 0;
|
||||
for (long bits = lo_cl; bits != X; bits &= bits - 1) {
|
||||
long lsb = bits & -bits;
|
||||
int clueIdx = numberOfTrailingZeros(lsb);
|
||||
@@ -130,6 +148,12 @@ public record Masker(Rng rng, int[] stack, Clues cache) {
|
||||
int msb = 63 - numberOfLeadingZeros(hLo);
|
||||
rLo &= -(1L << msb << 1);
|
||||
}
|
||||
|
||||
activeCIdx[numClues] = clueIdx;
|
||||
activeSLo[numClues] = rLo;
|
||||
activeSHi[numClues] = rHi;
|
||||
numClues++;
|
||||
|
||||
if ((rLo | rHi) != X) {
|
||||
hasSlots = true;
|
||||
if (Slot.horiz(key)) {
|
||||
@@ -167,6 +191,12 @@ public record Masker(Rng rng, int[] stack, Clues cache) {
|
||||
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)) {
|
||||
@@ -185,63 +215,64 @@ public record Masker(Rng rng, int[] stack, Clues cache) {
|
||||
}
|
||||
|
||||
if (!hasSlots) return 1_000_000_000L;
|
||||
long seenLo = X, seenHi = X;
|
||||
|
||||
// loop over beide helften
|
||||
for (int base = 0, size, sp, cur; base <= 64; base += 64) {
|
||||
long clueMask = (base == 0) ? lo_cl : hi_cl;
|
||||
long seenMask = (base == 0) ? seenLo : seenHi;
|
||||
|
||||
// "unseen clues" in deze helft
|
||||
for (long bits = clueMask & ~seenMask, nLo, nHi; bits != X; bits &= bits - 1) {
|
||||
int clueIdx = base | numberOfTrailingZeros(bits);
|
||||
|
||||
// start nieuwe component
|
||||
size = 0;
|
||||
stack[0] = clueIdx;
|
||||
sp = 1;
|
||||
|
||||
// mark seen
|
||||
if ((clueIdx & 64) == 0) seenLo |= 1L << clueIdx;
|
||||
else seenHi |= 1L << (clueIdx & 63);
|
||||
|
||||
// flood fill / bfs
|
||||
while (sp > 0) {
|
||||
cur = stack[--sp];
|
||||
size++;
|
||||
|
||||
// neighbors als 2x long masks
|
||||
nLo = NBR8_PACKED_LO[cur];
|
||||
nHi = NBR8_PACKED_HI[cur];
|
||||
|
||||
// filter: alleen clues, en nog niet seen
|
||||
nLo &= lo_cl & ~seenLo;
|
||||
nHi &= hi_cl & ~seenHi;
|
||||
|
||||
// push lo-neighbors
|
||||
while (nLo != X) {
|
||||
long lsb = nLo & -nLo;
|
||||
int nidx = numberOfTrailingZeros(nLo); // 0..63
|
||||
seenLo |= lsb;
|
||||
|
||||
stack[sp++] = nidx;
|
||||
|
||||
nLo &= nLo - 1;
|
||||
}
|
||||
|
||||
// push hi-neighbors
|
||||
while (nHi != X) {
|
||||
long lsb = nHi & -nHi;
|
||||
int nidx = 64 | numberOfTrailingZeros(nHi); // 64..127
|
||||
seenHi |= lsb;
|
||||
|
||||
stack[sp++] = nidx;
|
||||
|
||||
nHi &= nHi - 1;
|
||||
|
||||
// Connectiviteitscheck
|
||||
for (int i = 0; i < numClues; i++) {
|
||||
adjLo[i] = 0; adjHi[i] = 0;
|
||||
}
|
||||
for (int i = 0; i < numClues; i++) {
|
||||
for (int j = i + 1; j < numClues; j++) {
|
||||
boolean connected = false;
|
||||
// 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 (size >= 2) penalty += (size - 1L) * 120L;
|
||||
if (connected) {
|
||||
if (j < 64) adjLo[i] |= (1L << j);
|
||||
else adjHi[i] |= (1L << (j - 64));
|
||||
if (i < 64) adjLo[j] |= (1L << i);
|
||||
else adjHi[j] |= (1L << (i - 64));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 count = bitCount(reachedLo) + bitCount(reachedHi);
|
||||
if (count < numClues) {
|
||||
penalty += (numClues - count) * 4000;
|
||||
penalty += 20000;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,7 +282,7 @@ public record Masker(Rng rng, int[] stack, Clues cache) {
|
||||
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 += 1500;
|
||||
if (!h && !v) penalty += 15000;
|
||||
else if (h && v) { /* ok */ } else if (((h ? cHLo2 : cVLo2) & (1L << clueIdx)) != X) penalty += 600;
|
||||
else penalty += 200;
|
||||
}
|
||||
@@ -261,7 +292,8 @@ public record Masker(Rng rng, int[] stack, Clues cache) {
|
||||
if ((4 - rci.nbrCount()) + bitCount(rci.n1() & lo_cl) + bitCount(rci.n2() & hi_cl) >= 3) penalty += 400;
|
||||
boolean h = (cHHi & (1L << clueIdx)) != X;
|
||||
boolean v = (cVHi & (1L << clueIdx)) != X;
|
||||
if (!h && !v) penalty += 1500;
|
||||
if (!h && !v)
|
||||
penalty += 15000;
|
||||
else if (h && v) { /* ok */ } else if (((h ? cHHi2 : cVHi2) & (1L << clueIdx)) != X) penalty += 600;
|
||||
else penalty += 200;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public record SwedishGenerator() {
|
||||
public static final int MAX_WORD_LENGTH_PLUS_ONE = MAX_WORD_LENGTH + 1;
|
||||
public static final int MIN_LEN = 3;//Config.MIN_LEN;
|
||||
public static final int MAX_TRIES_PER_SLOT = 700;//Config.MAX_TRIES_PER_SLOT;
|
||||
public static final int STACK_SIZE = 64;
|
||||
public static final int STACK_SIZE = 128;
|
||||
public static final char C_DASH = '\0';
|
||||
public static final byte DASH = (byte) C_DASH;
|
||||
public static final long RANGE_0_SIZE = (long) SIZE_MIN_1 - 0L + 1L;
|
||||
|
||||
Reference in New Issue
Block a user