introduce bitloops
This commit is contained in:
@@ -388,8 +388,8 @@ public class Main {
|
|||||||
var swe = new SwedishGenerator(rng, new int[STACK_SIZE], Clues.createEmpty());
|
var swe = new SwedishGenerator(rng, new int[STACK_SIZE], Clues.createEmpty());
|
||||||
var mask = swe.generateMask(opts.clueSize, opts.pop, opts.gens, opts.offspring);
|
var mask = swe.generateMask(opts.clueSize, opts.pop, opts.gens, opts.offspring);
|
||||||
if (mask == null) return null;
|
if (mask == null) return null;
|
||||||
|
val multiThreaded = Thread.currentThread().getName().contains("pool");
|
||||||
var filled = fillMask(rng, extractSlots(mask, dict.index()), mask.toGrid());
|
var filled = fillMask(rng, extractSlots(mask, dict.index()), mask.toGrid(), multiThreaded);
|
||||||
|
|
||||||
TOTAL_NODES.addAndGet(filled.stats().nodes);
|
TOTAL_NODES.addAndGet(filled.stats().nodes);
|
||||||
TOTAL_BACKTRACKS.addAndGet(filled.stats().backtracks);
|
TOTAL_BACKTRACKS.addAndGet(filled.stats().backtracks);
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ import java.util.Arrays;
|
|||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
import static java.lang.Long.*;
|
||||||
|
import static java.lang.Long.numberOfTrailingZeros;
|
||||||
import static java.nio.charset.StandardCharsets.US_ASCII;
|
import static java.nio.charset.StandardCharsets.US_ASCII;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -142,8 +144,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
stats.simplicity = k == 0 ? 0 : stats.simplicity / k;
|
stats.simplicity = k == 0 ? 0 : stats.simplicity / k;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public int wordCount() {
|
public int wordCount(int k) {
|
||||||
int k = 0;
|
|
||||||
for (var n = 1; n < clueMap.length; n++) if (clueMap[n] != X) k++;
|
for (var n = 1; n < clueMap.length; n++) if (clueMap[n] != X) k++;
|
||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
@@ -220,23 +221,23 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
public boolean notClue(long index) { return ((index & 64) == 0) ? ((lo >>> index) & 1L) == X : ((hi >>> (index & 63)) & 1L) == X; }
|
public boolean notClue(long index) { return ((index & 64) == 0) ? ((lo >>> index) & 1L) == X : ((hi >>> (index & 63)) & 1L) == X; }
|
||||||
public boolean notClue(int index) { return ((index & 64) == 0) ? ((lo >>> index) & 1L) == X : ((hi >>> (index & 63)) & 1L) == X; }
|
public boolean notClue(int index) { return ((index & 64) == 0) ? ((lo >>> index) & 1L) == X : ((hi >>> (index & 63)) & 1L) == X; }
|
||||||
|
|
||||||
public int clueCount() { return Long.bitCount(lo) + Long.bitCount(hi); }
|
public int clueCount() { return bitCount(lo) + bitCount(hi); }
|
||||||
public double similarity(Clues b) {
|
public double similarity(Clues b) {
|
||||||
long matchLo = (~(lo ^ b.lo)) & (~lo | (~(vlo ^ b.vlo) & ~(rlo ^ b.rlo)));
|
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 matchHi = (~(hi ^ b.hi)) & (~hi | (~(vhi ^ b.vhi) & ~(rhi ^ b.rhi)));
|
||||||
|
|
||||||
return (Long.bitCount(matchLo & MASK_LO) + Long.bitCount(matchHi & MASK_HI)) / SIZED;
|
return (bitCount(matchLo & MASK_LO) + bitCount(matchHi & MASK_HI)) / SIZED;
|
||||||
}
|
}
|
||||||
public Grid toGrid() { return new Grid(new byte[SIZE], lo, hi); }
|
public Grid toGrid() { return new Grid(new byte[SIZE], lo, hi); }
|
||||||
public void forEachSlot(SlotVisitor visitor) {
|
public void forEachSlot(SlotVisitor visitor) {
|
||||||
for (var l = lo & ~rlo & vlo; l != X; l &= l - 1) processSlot(this, visitor, Slot.packSlotKey(Long.numberOfTrailingZeros(l), 1));
|
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(Long.numberOfTrailingZeros(l), 0));
|
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(Long.numberOfTrailingZeros(l), 2));
|
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(Long.numberOfTrailingZeros(l), 3));
|
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 | Long.numberOfTrailingZeros(h), 1));
|
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 | Long.numberOfTrailingZeros(h), 0));
|
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 | Long.numberOfTrailingZeros(h)), 2));
|
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 | Long.numberOfTrailingZeros(h)), 3));
|
for (var h = hi & rhi & vhi; h != X; h &= h - 1) processSlotRev(this, visitor, Slot.packSlotKey((64 | numberOfTrailingZeros(h)), 3));
|
||||||
}
|
}
|
||||||
public Clues from(Clues best) {
|
public Clues from(Clues best) {
|
||||||
lo = best.lo;
|
lo = best.lo;
|
||||||
@@ -275,7 +276,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
static byte byteAt(long word, int idx) { return (byte) ((word >>> (idx * 5)) & 0b11111); }
|
static byte byteAt(long word, int idx) { return (byte) ((word >>> (idx * 5)) & 0b11111); }
|
||||||
static String[] clue(long w) { return CsvIndexService.clues(unpackIndex(w)); }
|
static String[] clue(long w) { return CsvIndexService.clues(unpackIndex(w)); }
|
||||||
static int simpel(long w) { return CsvIndexService.simpel(unpackIndex(w)); }
|
static int simpel(long w) { return CsvIndexService.simpel(unpackIndex(w)); }
|
||||||
static int length(long word) { return ((63 - Long.numberOfLeadingZeros(word & LETTER_MASK)) / 5) + 1; }
|
static int length(long word) { return ((63 - numberOfLeadingZeros(word & LETTER_MASK)) / 5) + 1; }
|
||||||
static ThreadLocal<byte[]> BYTES = ThreadLocal.withInitial(() -> new byte[MAX_WORD_LENGTH]);
|
static ThreadLocal<byte[]> BYTES = ThreadLocal.withInitial(() -> new byte[MAX_WORD_LENGTH]);
|
||||||
public static String asWord(long word) {
|
public static String asWord(long word) {
|
||||||
val len = Lemma.length(word);
|
val len = Lemma.length(word);
|
||||||
@@ -338,7 +339,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
|
|
||||||
static final int BIT_FOR_DIR = 2;
|
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 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 Long.bitCount(lo) + Long.bitCount(hi); }
|
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 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 & 3; }
|
||||||
public static boolean increasing(int dir) { return (dir & 2) == 0; }
|
public static boolean increasing(int dir) { return (dir & 2) == 0; }
|
||||||
@@ -357,12 +358,12 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
long hitsHi = rayHi & c.hi;
|
long hitsHi = rayHi & c.hi;
|
||||||
|
|
||||||
if (hitsHi != X) {
|
if (hitsHi != X) {
|
||||||
int msb = 63 - Long.numberOfLeadingZeros(hitsHi);
|
int msb = 63 - numberOfLeadingZeros(hitsHi);
|
||||||
long stop = 1L << msb;
|
long stop = 1L << msb;
|
||||||
rayHi &= ~((stop << 1) - 1); // keep bits > stop
|
rayHi &= ~((stop << 1) - 1); // keep bits > stop
|
||||||
rayLo = 0; // lo indices are below stop
|
rayLo = 0; // lo indices are below stop
|
||||||
} else if (hitsLo != X) {
|
} else if (hitsLo != X) {
|
||||||
int msb = 63 - Long.numberOfLeadingZeros(hitsLo);
|
int msb = 63 - numberOfLeadingZeros(hitsLo);
|
||||||
long stop = 1L << msb;
|
long stop = 1L << msb;
|
||||||
rayLo &= ~((stop << 1) - 1);
|
rayLo &= ~((stop << 1) - 1);
|
||||||
}
|
}
|
||||||
@@ -376,11 +377,11 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
long hitsHi = rayHi & c.hi;
|
long hitsHi = rayHi & c.hi;
|
||||||
|
|
||||||
if (hitsLo != X) {
|
if (hitsLo != X) {
|
||||||
long stop = 1L << Long.numberOfTrailingZeros(hitsLo);
|
long stop = 1L << numberOfTrailingZeros(hitsLo);
|
||||||
rayLo &= (stop - 1);
|
rayLo &= (stop - 1);
|
||||||
rayHi = 0; // any hi is beyond the stop
|
rayHi = 0; // any hi is beyond the stop
|
||||||
} else if (hitsHi != X) {
|
} else if (hitsHi != X) {
|
||||||
long stop = 1L << Long.numberOfTrailingZeros(hitsHi);
|
long stop = 1L << numberOfTrailingZeros(hitsHi);
|
||||||
// keep all lo (lo indices are < any hi index), but cut hi below stop
|
// keep all lo (lo indices are < any hi index), but cut hi below stop
|
||||||
rayHi &= (stop - 1);
|
rayHi &= (stop - 1);
|
||||||
}
|
}
|
||||||
@@ -405,7 +406,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
|
|
||||||
for (long bits = lo_cl; bits != X; bits &= bits - 1) {
|
for (long bits = lo_cl; bits != X; bits &= bits - 1) {
|
||||||
long lsb = bits & -bits;
|
long lsb = bits & -bits;
|
||||||
int clueIdx = Long.numberOfTrailingZeros(lsb);
|
int clueIdx = numberOfTrailingZeros(lsb);
|
||||||
int v = (grid.vlo & lsb) != 0 ? 1 : 0;
|
int v = (grid.vlo & lsb) != 0 ? 1 : 0;
|
||||||
int r = (grid.rlo & lsb) != 0 ? 1 : 0;
|
int r = (grid.rlo & lsb) != 0 ? 1 : 0;
|
||||||
int key = Slot.packSlotKey(clueIdx, (r << 1) | v);
|
int key = Slot.packSlotKey(clueIdx, (r << 1) | v);
|
||||||
@@ -413,16 +414,16 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
long hLo = rLo & lo_cl, hHi = rHi & hi_cl;
|
long hLo = rLo & lo_cl, hHi = rHi & hi_cl;
|
||||||
if (Slot.increasing(key)) {
|
if (Slot.increasing(key)) {
|
||||||
if (hLo != X) {
|
if (hLo != X) {
|
||||||
rLo &= ((1L << Long.numberOfTrailingZeros(hLo)) - 1);
|
rLo &= ((1L << numberOfTrailingZeros(hLo)) - 1);
|
||||||
rHi = 0;
|
rHi = 0;
|
||||||
} else if (hHi != X) { rHi &= ((1L << Long.numberOfTrailingZeros(hHi)) - 1); }
|
} else if (hHi != X) { rHi &= ((1L << numberOfTrailingZeros(hHi)) - 1); }
|
||||||
} else {
|
} else {
|
||||||
if (hHi != X) {
|
if (hHi != X) {
|
||||||
int msb = 63 - Long.numberOfLeadingZeros(hHi);
|
int msb = 63 - numberOfLeadingZeros(hHi);
|
||||||
rHi &= ~((1L << msb << 1) - 1);
|
rHi &= ~((1L << msb << 1) - 1);
|
||||||
rLo = 0;
|
rLo = 0;
|
||||||
} else if (hLo != X) {
|
} else if (hLo != X) {
|
||||||
int msb = 63 - Long.numberOfLeadingZeros(hLo);
|
int msb = 63 - numberOfLeadingZeros(hLo);
|
||||||
rLo &= ~((1L << msb << 1) - 1);
|
rLo &= ~((1L << msb << 1) - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -435,14 +436,14 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
cVLo |= rLo;
|
cVLo |= rLo;
|
||||||
cVHi |= rHi;
|
cVHi |= rHi;
|
||||||
}
|
}
|
||||||
if ((Long.bitCount(rLo) + Long.bitCount(rHi)) < MIN_LEN) penalty += 8000;
|
if ((bitCount(rLo) + bitCount(rHi)) < MIN_LEN) penalty += 8000;
|
||||||
} else {
|
} else {
|
||||||
penalty += 25000;
|
penalty += 25000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (long bits = hi_cl; bits != X; bits &= bits - 1) {
|
for (long bits = hi_cl; bits != X; bits &= bits - 1) {
|
||||||
long lsb = bits & -bits;
|
long lsb = bits & -bits;
|
||||||
int clueIdx = Long.numberOfTrailingZeros(lsb);
|
int clueIdx = numberOfTrailingZeros(lsb);
|
||||||
int v = (grid.vhi & lsb) != 0 ? 1 : 0;
|
int v = (grid.vhi & lsb) != 0 ? 1 : 0;
|
||||||
int r = (grid.rhi & lsb) != 0 ? 1 : 0;
|
int r = (grid.rhi & lsb) != 0 ? 1 : 0;
|
||||||
int key = Slot.packSlotKey(64 | clueIdx, (r << 1) | v);
|
int key = Slot.packSlotKey(64 | clueIdx, (r << 1) | v);
|
||||||
@@ -450,16 +451,16 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
long hLo = rLo & lo_cl, hHi = rHi & hi_cl;
|
long hLo = rLo & lo_cl, hHi = rHi & hi_cl;
|
||||||
if (Slot.increasing(key)) {
|
if (Slot.increasing(key)) {
|
||||||
if (hLo != X) {
|
if (hLo != X) {
|
||||||
rLo &= ((1L << Long.numberOfTrailingZeros(hLo)) - 1);
|
rLo &= ((1L << numberOfTrailingZeros(hLo)) - 1);
|
||||||
rHi = 0;
|
rHi = 0;
|
||||||
} else if (hHi != X) { rHi &= ((1L << Long.numberOfTrailingZeros(hHi)) - 1); }
|
} else if (hHi != X) { rHi &= ((1L << numberOfTrailingZeros(hHi)) - 1); }
|
||||||
} else {
|
} else {
|
||||||
if (hHi != X) {
|
if (hHi != X) {
|
||||||
int msb = 63 - Long.numberOfLeadingZeros(hHi);
|
int msb = 63 - numberOfLeadingZeros(hHi);
|
||||||
rHi &= ~((1L << msb << 1) - 1);
|
rHi &= ~((1L << msb << 1) - 1);
|
||||||
rLo = 0;
|
rLo = 0;
|
||||||
} else if (hLo != X) {
|
} else if (hLo != X) {
|
||||||
int msb = 63 - Long.numberOfLeadingZeros(hLo);
|
int msb = 63 - numberOfLeadingZeros(hLo);
|
||||||
rLo &= ~((1L << msb << 1) - 1);
|
rLo &= ~((1L << msb << 1) - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -472,7 +473,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
cVLo |= rLo;
|
cVLo |= rLo;
|
||||||
cVHi |= rHi;
|
cVHi |= rHi;
|
||||||
}
|
}
|
||||||
if ((Long.bitCount(rLo) + Long.bitCount(rHi)) < MIN_LEN) penalty += 8000;
|
if ((bitCount(rLo) + bitCount(rHi)) < MIN_LEN) penalty += 8000;
|
||||||
} else {
|
} else {
|
||||||
penalty += 25000;
|
penalty += 25000;
|
||||||
}
|
}
|
||||||
@@ -488,7 +489,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
|
|
||||||
// "unseen clues" in deze helft
|
// "unseen clues" in deze helft
|
||||||
for (long bits = clueMask & ~seenMask, nLo, nHi; bits != X; bits &= bits - 1) {
|
for (long bits = clueMask & ~seenMask, nLo, nHi; bits != X; bits &= bits - 1) {
|
||||||
int clueIdx = base | Long.numberOfTrailingZeros(bits);
|
int clueIdx = base | numberOfTrailingZeros(bits);
|
||||||
|
|
||||||
// start nieuwe component
|
// start nieuwe component
|
||||||
size = 0;
|
size = 0;
|
||||||
@@ -515,7 +516,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
// push lo-neighbors
|
// push lo-neighbors
|
||||||
while (nLo != X) {
|
while (nLo != X) {
|
||||||
long lsb = nLo & -nLo;
|
long lsb = nLo & -nLo;
|
||||||
int nidx = Long.numberOfTrailingZeros(nLo); // 0..63
|
int nidx = numberOfTrailingZeros(nLo); // 0..63
|
||||||
seenLo |= lsb;
|
seenLo |= lsb;
|
||||||
|
|
||||||
stack[sp++] = nidx;
|
stack[sp++] = nidx;
|
||||||
@@ -526,7 +527,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
// push hi-neighbors
|
// push hi-neighbors
|
||||||
while (nHi != X) {
|
while (nHi != X) {
|
||||||
long lsb = nHi & -nHi;
|
long lsb = nHi & -nHi;
|
||||||
int nidx = 64 | Long.numberOfTrailingZeros(nHi); // 64..127
|
int nidx = 64 | numberOfTrailingZeros(nHi); // 64..127
|
||||||
seenHi |= lsb;
|
seenHi |= lsb;
|
||||||
|
|
||||||
stack[sp++] = nidx;
|
stack[sp++] = nidx;
|
||||||
@@ -540,9 +541,9 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (long bits = ~lo_cl; bits != X; bits &= bits - 1) {
|
for (long bits = ~lo_cl; bits != X; bits &= bits - 1) {
|
||||||
int clueIdx = Long.numberOfTrailingZeros(bits);
|
int clueIdx = 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()) + bitCount(rci.n1() & lo_cl) + bitCount(rci.n2() & hi_cl) >= 3) penalty += 400;
|
||||||
boolean h = (cHLo & (1L << clueIdx)) != X;
|
boolean h = (cHLo & (1L << clueIdx)) != X;
|
||||||
boolean v = (cVLo & (1L << clueIdx)) != X;
|
boolean v = (cVLo & (1L << clueIdx)) != X;
|
||||||
if (!h && !v) penalty += 1500;
|
if (!h && !v) penalty += 1500;
|
||||||
@@ -550,9 +551,9 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
else penalty += 600;
|
else penalty += 600;
|
||||||
}
|
}
|
||||||
for (long bits = ~hi_cl & 0xFFL; bits != X; bits &= bits - 1) {
|
for (long bits = ~hi_cl & 0xFFL; bits != X; bits &= bits - 1) {
|
||||||
int clueIdx = Long.numberOfTrailingZeros(bits);
|
int clueIdx = numberOfTrailingZeros(bits);
|
||||||
var rci = IT[64 | clueIdx];
|
var rci = IT[64 | clueIdx];
|
||||||
if ((4 - rci.nbrCount()) + Long.bitCount(rci.n1() & lo_cl) + Long.bitCount(rci.n2() & hi_cl) >= 3) penalty += 400;
|
if ((4 - rci.nbrCount()) + bitCount(rci.n1() & lo_cl) + bitCount(rci.n2() & hi_cl) >= 3) penalty += 400;
|
||||||
boolean h = (cHHi & (1L << clueIdx)) != X;
|
boolean h = (cHHi & (1L << clueIdx)) != X;
|
||||||
boolean v = (cVHi & (1L << clueIdx)) != X;
|
boolean v = (cVHi & (1L << clueIdx)) != X;
|
||||||
if (!h && !v) penalty += 1500;
|
if (!h && !v) penalty += 1500;
|
||||||
@@ -629,14 +630,14 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
(a.rlo & ~maskLo) | (other.rlo & maskLo),
|
(a.rlo & ~maskLo) | (other.rlo & maskLo),
|
||||||
(a.rhi & ~maskHi) | (other.rhi & maskHi));
|
(a.rhi & ~maskHi) | (other.rhi & maskHi));
|
||||||
|
|
||||||
for (var l = c.lo & ~c.rlo & ~c.vlo; l != X; l &= l - 1) clearCluesLo(c, Long.numberOfTrailingZeros(l), 0);
|
for (var l = c.lo & ~c.rlo & ~c.vlo; l != X; l &= l - 1) clearCluesLo(c, numberOfTrailingZeros(l), 0);
|
||||||
for (var l = c.lo & ~c.rlo & c.vlo; l != X; l &= l - 1) clearCluesLo(c, Long.numberOfTrailingZeros(l), 1);
|
for (var l = c.lo & ~c.rlo & c.vlo; l != X; l &= l - 1) clearCluesLo(c, numberOfTrailingZeros(l), 1);
|
||||||
for (var l = c.lo & c.rlo & ~c.vlo; l != X; l &= l - 1) clearCluesLo(c, Long.numberOfTrailingZeros(l), 2);
|
for (var l = c.lo & c.rlo & ~c.vlo; l != X; l &= l - 1) clearCluesLo(c, numberOfTrailingZeros(l), 2);
|
||||||
for (var l = c.lo & c.rlo & c.vlo; l != X; l &= l - 1) clearCluesLo(c, Long.numberOfTrailingZeros(l), 3);
|
for (var l = c.lo & c.rlo & c.vlo; l != X; l &= l - 1) clearCluesLo(c, numberOfTrailingZeros(l), 3);
|
||||||
for (var h = c.hi & ~c.rhi & ~c.vhi; h != X; h &= h - 1) clearCluesHi(c, Long.numberOfTrailingZeros(h), 0);
|
for (var h = c.hi & ~c.rhi & ~c.vhi; h != X; h &= h - 1) clearCluesHi(c, numberOfTrailingZeros(h), 0);
|
||||||
for (var h = c.hi & ~c.rhi & c.vhi; h != X; h &= h - 1) clearCluesHi(c, Long.numberOfTrailingZeros(h), 1);
|
for (var h = c.hi & ~c.rhi & c.vhi; h != X; h &= h - 1) clearCluesHi(c, numberOfTrailingZeros(h), 1);
|
||||||
for (var h = c.hi & c.rhi & ~c.vhi; h != X; h &= h - 1) clearCluesHi(c, (Long.numberOfTrailingZeros(h)), 2);
|
for (var h = c.hi & c.rhi & ~c.vhi; h != X; h &= h - 1) clearCluesHi(c, (numberOfTrailingZeros(h)), 2);
|
||||||
for (var h = c.hi & c.rhi & ~c.vhi; h != X; h &= h - 1) clearCluesHi(c, (Long.numberOfTrailingZeros(h)), 3);
|
for (var h = c.hi & c.rhi & ~c.vhi; h != X; h &= h - 1) clearCluesHi(c, (numberOfTrailingZeros(h)), 3);
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
public static void clearCluesLo(Clues out, int idx, int d) { if (!out.hasRoomForClue(OFFSETS_D_IDX[Slot.packSlotKey(idx, d)])) out.clearClueLo(~(1L << idx)); }
|
public static void clearCluesLo(Clues out, int idx, int d) { if (!out.hasRoomForClue(OFFSETS_D_IDX[Slot.packSlotKey(idx, d)])) out.clearClueLo(~(1L << idx)); }
|
||||||
@@ -728,26 +729,26 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
long p = 0;
|
long p = 0;
|
||||||
if (Slot.increasing(key)) {
|
if (Slot.increasing(key)) {
|
||||||
for (long b = lo & glo; b != X; b &= b - 1) {
|
for (long b = lo & glo; b != X; b &= b - 1) {
|
||||||
int idx = Long.numberOfTrailingZeros(b);
|
int idx = numberOfTrailingZeros(b);
|
||||||
int i = Long.bitCount(lo & ((1L << idx) - 1));
|
int i = bitCount(lo & ((1L << idx) - 1));
|
||||||
p |= ((long) (i * 26 + g[idx])) << (i << 3);
|
p |= ((long) (i * 26 + g[idx])) << (i << 3);
|
||||||
}
|
}
|
||||||
int offset = Long.bitCount(lo);
|
int offset = bitCount(lo);
|
||||||
for (long b = hi & ghi; b != X; b &= b - 1) {
|
for (long b = hi & ghi; b != X; b &= b - 1) {
|
||||||
int idx = Long.numberOfTrailingZeros(b);
|
int idx = numberOfTrailingZeros(b);
|
||||||
int i = offset + Long.bitCount(hi & ((1L << idx) - 1));
|
int i = offset + bitCount(hi & ((1L << idx) - 1));
|
||||||
p |= ((long) (i * 26 + g[64 | idx])) << (i << 3);
|
p |= ((long) (i * 26 + g[64 | idx])) << (i << 3);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int offset = Long.bitCount(hi);
|
int offset = bitCount(hi);
|
||||||
for (long b = hi & ghi; b != X; b &= b - 1) {
|
for (long b = hi & ghi; b != X; b &= b - 1) {
|
||||||
int idx = Long.numberOfTrailingZeros(b);
|
int idx = numberOfTrailingZeros(b);
|
||||||
int i = Long.bitCount(hi & ~((1L << idx) | ((1L << idx) - 1)));
|
int i = bitCount(hi & ~((1L << idx) | ((1L << idx) - 1)));
|
||||||
p |= ((long) (i * 26 + g[64 | idx])) << (i << 3);
|
p |= ((long) (i * 26 + g[64 | idx])) << (i << 3);
|
||||||
}
|
}
|
||||||
for (long b = lo & glo; b != X; b &= b - 1) {
|
for (long b = lo & glo; b != X; b &= b - 1) {
|
||||||
int idx = Long.numberOfTrailingZeros(b);
|
int idx = numberOfTrailingZeros(b);
|
||||||
int i = offset + Long.bitCount(lo & ~((1L << idx) | ((1L << idx) - 1)));
|
int i = offset + bitCount(lo & ~((1L << idx) | ((1L << idx) - 1)));
|
||||||
p |= ((long) (i * 26 + g[idx])) << (i << 3);
|
p |= ((long) (i * 26 + g[idx])) << (i << 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -755,56 +756,56 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
}
|
}
|
||||||
static int slotScore(byte[] count, long lo, long hi) {
|
static int slotScore(byte[] count, long lo, long hi) {
|
||||||
int cross = 0;
|
int cross = 0;
|
||||||
for (long b = lo; b != X; b &= b - 1) cross += (count[Long.numberOfTrailingZeros(b)] - 1);
|
for (long b = lo; b != X; b &= b - 1) cross += (count[numberOfTrailingZeros(b)] - 1);
|
||||||
for (long b = hi; b != X; b &= b - 1) cross += (count[64 | Long.numberOfTrailingZeros(b)] - 1);
|
for (long b = hi; b != X; b &= b - 1) cross += (count[64 | numberOfTrailingZeros(b)] - 1);
|
||||||
return cross * 10 + Slot.length(lo, hi);
|
return cross * 10 + Slot.length(lo, hi);
|
||||||
}
|
}
|
||||||
static boolean placeWord(final Grid grid, final byte[] g, final int key, final long lo, final long hi, final long w) {
|
static boolean placeWord(final Grid grid, final byte[] g, final int key, final long lo, final long hi, final long w) {
|
||||||
final long glo = grid.lo, ghi = grid.hi;
|
final long glo = grid.lo, ghi = grid.hi;
|
||||||
if (Slot.increasing(key)) {
|
if (Slot.increasing(key)) {
|
||||||
for (long b = lo & glo; b != X; b &= b - 1) {
|
for (long b = lo & glo; b != X; b &= b - 1) {
|
||||||
int idx = Long.numberOfTrailingZeros(b);
|
int idx = numberOfTrailingZeros(b);
|
||||||
if (g[idx] != Lemma.byteAt(w, Long.bitCount(lo & ((1L << idx) - 1)))) return false;
|
if (g[idx] != Lemma.byteAt(w, bitCount(lo & ((1L << idx) - 1)))) return false;
|
||||||
}
|
}
|
||||||
int bcLo = Long.bitCount(lo);
|
int bcLo = bitCount(lo);
|
||||||
for (long b = hi & ghi; b != X; b &= b - 1) {
|
for (long b = hi & ghi; b != X; b &= b - 1) {
|
||||||
int idx = Long.numberOfTrailingZeros(b);
|
int idx = numberOfTrailingZeros(b);
|
||||||
if (g[64 | idx] != Lemma.byteAt(w, bcLo + Long.bitCount(hi & ((1L << idx) - 1)))) return false;
|
if (g[64 | idx] != Lemma.byteAt(w, bcLo + bitCount(hi & ((1L << idx) - 1)))) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
long maskLo = lo & ~glo, maskHi = hi & ~ghi;
|
long maskLo = lo & ~glo, maskHi = hi & ~ghi;
|
||||||
if ((maskLo | maskHi) != X) {
|
if ((maskLo | maskHi) != X) {
|
||||||
for (long b = maskLo; b != X; b &= b - 1) {
|
for (long b = maskLo; b != X; b &= b - 1) {
|
||||||
int idx = Long.numberOfTrailingZeros(b);
|
int idx = numberOfTrailingZeros(b);
|
||||||
g[idx] = Lemma.byteAt(w, Long.bitCount(lo & ((1L << idx) - 1)));
|
g[idx] = Lemma.byteAt(w, bitCount(lo & ((1L << idx) - 1)));
|
||||||
}
|
}
|
||||||
for (long b = maskHi; b != X; b &= b - 1) {
|
for (long b = maskHi; b != X; b &= b - 1) {
|
||||||
int idx = Long.numberOfTrailingZeros(b);
|
int idx = numberOfTrailingZeros(b);
|
||||||
g[64 | idx] = Lemma.byteAt(w, bcLo + Long.bitCount(hi & ((1L << idx) - 1)));
|
g[64 | idx] = Lemma.byteAt(w, bcLo + bitCount(hi & ((1L << idx) - 1)));
|
||||||
}
|
}
|
||||||
grid.lo |= maskLo;
|
grid.lo |= maskLo;
|
||||||
grid.hi |= maskHi;
|
grid.hi |= maskHi;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int bcHi = Long.bitCount(hi);
|
int bcHi = bitCount(hi);
|
||||||
for (long b = hi & ghi; b != X; b &= b - 1) {
|
for (long b = hi & ghi; b != X; b &= b - 1) {
|
||||||
int idx = Long.numberOfTrailingZeros(b);
|
int idx = numberOfTrailingZeros(b);
|
||||||
if (g[64 | idx] != Lemma.byteAt(w, Long.bitCount(hi & ~((1L << idx) | ((1L << idx) - 1))))) return false;
|
if (g[64 | idx] != Lemma.byteAt(w, bitCount(hi & ~((1L << idx) | ((1L << idx) - 1))))) return false;
|
||||||
}
|
}
|
||||||
for (long b = lo & glo; b != X; b &= b - 1) {
|
for (long b = lo & glo; b != X; b &= b - 1) {
|
||||||
int idx = Long.numberOfTrailingZeros(b);
|
int idx = numberOfTrailingZeros(b);
|
||||||
if (g[idx] != Lemma.byteAt(w, bcHi + Long.bitCount(lo & ~((1L << idx) | ((1L << idx) - 1))))) return false;
|
if (g[idx] != Lemma.byteAt(w, bcHi + bitCount(lo & ~((1L << idx) | ((1L << idx) - 1))))) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
long maskLo = lo & ~glo, maskHi = hi & ~ghi;
|
long maskLo = lo & ~glo, maskHi = hi & ~ghi;
|
||||||
if ((maskLo | maskHi) != X) {
|
if ((maskLo | maskHi) != X) {
|
||||||
for (long b = maskHi; b != X; b &= b - 1) {
|
for (long b = maskHi; b != X; b &= b - 1) {
|
||||||
int idx = Long.numberOfTrailingZeros(b);
|
int idx = numberOfTrailingZeros(b);
|
||||||
g[64 | idx] = Lemma.byteAt(w, Long.bitCount(hi & ~((1L << idx) | ((1L << idx) - 1))));
|
g[64 | idx] = Lemma.byteAt(w, bitCount(hi & ~((1L << idx) | ((1L << idx) - 1))));
|
||||||
}
|
}
|
||||||
for (long b = maskLo; b != X; b &= b - 1) {
|
for (long b = maskLo; b != X; b &= b - 1) {
|
||||||
int idx = Long.numberOfTrailingZeros(b);
|
int idx = numberOfTrailingZeros(b);
|
||||||
g[idx] = Lemma.byteAt(w, bcHi + Long.bitCount(lo & ~((1L << idx) | ((1L << idx) - 1))));
|
g[idx] = Lemma.byteAt(w, bcHi + bitCount(lo & ~((1L << idx) | ((1L << idx) - 1))));
|
||||||
}
|
}
|
||||||
grid.lo |= maskLo;
|
grid.lo |= maskLo;
|
||||||
grid.hi |= maskHi;
|
grid.hi |= maskHi;
|
||||||
@@ -828,19 +829,19 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
}
|
}
|
||||||
p >>>= 8;
|
p >>>= 8;
|
||||||
} else {
|
} else {
|
||||||
p >>>= (Long.numberOfTrailingZeros(p) & ~7);
|
p >>>= (numberOfTrailingZeros(p) & ~7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (int k = 0; k < numLongs; k++) count += Long.bitCount(res[k]);
|
for (int k = 0; k < numLongs; k++) count += bitCount(res[k]);
|
||||||
|
|
||||||
int[] indices = new int[count];
|
int[] indices = new int[count];
|
||||||
int ki = 0;
|
int ki = 0;
|
||||||
for (int k = 0; k < numLongs; k++) {
|
for (int k = 0; k < numLongs; k++) {
|
||||||
long w = res[k];
|
long w = res[k];
|
||||||
while (w != X) {
|
while (w != X) {
|
||||||
int t = Long.numberOfTrailingZeros(w);
|
int t = numberOfTrailingZeros(w);
|
||||||
indices[ki++] = (k << 6) | t;
|
indices[ki++] = (k << 6) | t;
|
||||||
w &= w - 1;
|
w &= w - 1;
|
||||||
}
|
}
|
||||||
@@ -864,20 +865,20 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
}
|
}
|
||||||
p >>>= 8;
|
p >>>= 8;
|
||||||
} else {
|
} else {
|
||||||
p >>>= (Long.numberOfTrailingZeros(p) & ~7);
|
p >>>= (numberOfTrailingZeros(p) & ~7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (int k = 0; k < numLongs; k++) count += Long.bitCount(res[k]);
|
for (int k = 0; k < numLongs; k++) count += bitCount(res[k]);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scoreSlots(int[] slotScores, Slot[] slots) {
|
static void scoreSlots(int[] slotScores, Slot[] slots) {
|
||||||
val count = new byte[SIZE];
|
val count = new byte[SIZE];
|
||||||
for (var s : slots) {
|
for (var s : slots) {
|
||||||
for (long b = s.lo; b != X; b &= b - 1) count[Long.numberOfTrailingZeros(b)]++;
|
for (long b = s.lo; b != X; b &= b - 1) count[numberOfTrailingZeros(b)]++;
|
||||||
for (long b = s.hi; b != X; b &= b - 1) count[64 | Long.numberOfTrailingZeros(b)]++;
|
for (long b = s.hi; b != X; b &= b - 1) count[64 | numberOfTrailingZeros(b)]++;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < slots.length; i++) {
|
for (int i = 0; i < slots.length; i++) {
|
||||||
var slot = slots[i];
|
var slot = slots[i];
|
||||||
@@ -885,14 +886,13 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
public static FillResult fillMask(Rng rng, Slot[] slots, Grid mask) {
|
public static FillResult fillMask(final Rng rng,final Slot[] slots,final Grid mask, final boolean multiThreaded) {
|
||||||
val multiThreaded = Thread.currentThread().getName().contains("pool");
|
val NO_LOG = (!Main.VERBOSE || multiThreaded);
|
||||||
val NO_LOG = (!Main.VERBOSE || multiThreaded);
|
val grid = mask;
|
||||||
val grid = mask;
|
val used = new long[2048];
|
||||||
val used = new long[2048];
|
val assigned = new long[CLUE_INDEX_MAX_SIZE];
|
||||||
val assigned = new long[CLUE_INDEX_MAX_SIZE];
|
val bitset = new long[2500];
|
||||||
val bitset = new long[2500];
|
val g = grid.g;
|
||||||
val g = grid.g;
|
|
||||||
|
|
||||||
val TOTAL = slots.length;
|
val TOTAL = slots.length;
|
||||||
val slotScores = new int[TOTAL];
|
val slotScores = new int[TOTAL];
|
||||||
@@ -907,7 +907,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
long nodes;
|
long nodes;
|
||||||
long backtracks;
|
long backtracks;
|
||||||
int lastMRV;
|
int lastMRV;
|
||||||
long lastLog = t0;
|
long lastLog = t0, glo = grid.lo, ghi = grid.hi;
|
||||||
Pick current = CARRIER;
|
Pick current = CARRIER;
|
||||||
void renderProgress() {
|
void renderProgress() {
|
||||||
var now = System.currentTimeMillis();
|
var now = System.currentTimeMillis();
|
||||||
@@ -930,12 +930,44 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
System.out.print("\r" + Strings.padRight(msg, 120));
|
System.out.print("\r" + Strings.padRight(msg, 120));
|
||||||
System.out.flush();
|
System.out.flush();
|
||||||
}
|
}
|
||||||
|
boolean placeWord(final int key, final long lo, final long hi, final long w) {
|
||||||
|
int idx;
|
||||||
|
if (Slot.increasing(key)) {
|
||||||
|
for (long b = lo & glo; b != X; b &= b - 1) if (g[idx = numberOfTrailingZeros(b)] != Lemma.byteAt(w, bitCount(lo & ((1L << idx) - 1)))) return false;
|
||||||
|
int bcLo = bitCount(lo);
|
||||||
|
for (long b = hi & ghi; b != X; b &= b - 1)
|
||||||
|
if (g[64 | (idx = numberOfTrailingZeros(b))] != Lemma.byteAt(w, bcLo + bitCount(hi & ((1L << idx) - 1)))) return false;
|
||||||
|
|
||||||
|
long maskLo = lo & ~glo, maskHi = hi & ~ghi;
|
||||||
|
if ((maskLo | maskHi) != X) {
|
||||||
|
for (long b = maskLo; b != X; b &= b - 1) g[idx = idx = numberOfTrailingZeros(b)] = Lemma.byteAt(w, bitCount(lo & ((1L << idx) - 1)));
|
||||||
|
for (long b = maskHi; b != X; b &= b - 1) g[64 | (idx = numberOfTrailingZeros(b))] = Lemma.byteAt(w, bcLo + bitCount(hi & ((1L << idx) - 1)));
|
||||||
|
glo |= maskLo;
|
||||||
|
ghi |= maskHi;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int bcHi = bitCount(hi);
|
||||||
|
for (long b = hi & ghi; b != X; b &= b - 1)
|
||||||
|
if (g[64 | (idx = numberOfTrailingZeros(b))] != Lemma.byteAt(w, bitCount(hi & ~((1L << idx) | ((1L << idx) - 1))))) return false;
|
||||||
|
for (long b = lo & glo; b != X; b &= b - 1)
|
||||||
|
if (g[idx = numberOfTrailingZeros(b)] != Lemma.byteAt(w, bcHi + bitCount(lo & ~((1L << idx) | ((1L << idx) - 1))))) return false;
|
||||||
|
|
||||||
|
long maskLo = lo & ~glo, maskHi = hi & ~ghi;
|
||||||
|
if ((maskLo | maskHi) != X) {
|
||||||
|
for (long b = maskHi; b != X; b &= b - 1) g[64 | (idx = numberOfTrailingZeros(b))] = Lemma.byteAt(w, bitCount(hi & ~((1L << idx) | ((1L << idx) - 1))));
|
||||||
|
for (long b = maskLo; b != X; b &= b - 1) g[idx = numberOfTrailingZeros(b)] = Lemma.byteAt(w, bcHi + bitCount(lo & ~((1L << idx) | ((1L << idx) - 1))));
|
||||||
|
glo |= maskLo;
|
||||||
|
ghi |= maskHi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
void chooseMRV() {
|
void chooseMRV() {
|
||||||
Slot best = null;
|
Slot best = null;
|
||||||
for (int i = 0, count, count2 = -1, bestScore = -1, n = TOTAL; i < n; i++) {
|
for (int i = 0, count, count2 = -1, bestScore = -1, n = TOTAL; i < n; i++) {
|
||||||
var s = slots[i];
|
var s = slots[i];
|
||||||
if (assigned[s.key] != X) continue;
|
if (assigned[s.key] != X) continue;
|
||||||
var pattern = patternForSlot(grid.lo, grid.hi, g, s.key, s.lo, s.hi);
|
var pattern = patternForSlot(glo, ghi, g, s.key, s.lo, s.hi);
|
||||||
var index = s.entry;
|
var index = s.entry;
|
||||||
count = pattern == X ? index.length : candidateCountForPattern(bitset, pattern, index.posBitsets, index.numlong);
|
count = pattern == X ? index.length : candidateCountForPattern(bitset, pattern, index.posBitsets, index.numlong);
|
||||||
|
|
||||||
@@ -957,7 +989,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
current = PICK_DONE;
|
current = PICK_DONE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var pattern = patternForSlot(grid.lo, grid.hi, g, best.key, best.lo, best.hi);
|
var pattern = patternForSlot(glo, ghi, g, best.key, best.lo, best.hi);
|
||||||
var index = best.entry;
|
var index = best.entry;
|
||||||
current = CARRIER;
|
current = CARRIER;
|
||||||
current.slot = best;
|
current.slot = best;
|
||||||
@@ -1004,9 +1036,9 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
var w = entry.words[idx];
|
var w = entry.words[idx];
|
||||||
var lemIdx = Lemma.unpackIndex(w);
|
var lemIdx = Lemma.unpackIndex(w);
|
||||||
if (Bit1029.get(used, lemIdx)) continue;
|
if (Bit1029.get(used, lemIdx)) continue;
|
||||||
low = grid.lo;
|
low = glo;
|
||||||
top = grid.hi;
|
top = ghi;
|
||||||
if (!placeWord(grid, g, k, slo, shi, w)) continue;
|
if (!placeWord(k, slo, shi, w)) continue;
|
||||||
|
|
||||||
Bit1029.set(used, lemIdx);
|
Bit1029.set(used, lemIdx);
|
||||||
assigned[k] = w;
|
assigned[k] = w;
|
||||||
@@ -1015,8 +1047,8 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
|
|
||||||
assigned[k] = X;
|
assigned[k] = X;
|
||||||
Bit1029.clear(used, lemIdx);
|
Bit1029.clear(used, lemIdx);
|
||||||
grid.lo = low;
|
glo = low;
|
||||||
grid.hi = top;
|
ghi = top;
|
||||||
}
|
}
|
||||||
backtracks++;
|
backtracks++;
|
||||||
return false;
|
return false;
|
||||||
@@ -1031,9 +1063,9 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
var w = entry.words[idxInArray];
|
var w = entry.words[idxInArray];
|
||||||
var lemIdx = Lemma.unpackIndex(w);
|
var lemIdx = Lemma.unpackIndex(w);
|
||||||
if (Bit1029.get(used, lemIdx)) continue;
|
if (Bit1029.get(used, lemIdx)) continue;
|
||||||
low = grid.lo;
|
low = glo;
|
||||||
top = grid.hi;
|
top = ghi;
|
||||||
if (!placeWord(grid, g, k, slo, shi, w)) continue;
|
if (!placeWord(k, slo, shi, w)) continue;
|
||||||
|
|
||||||
Bit1029.set(used, lemIdx);
|
Bit1029.set(used, lemIdx);
|
||||||
assigned[k] = w;
|
assigned[k] = w;
|
||||||
@@ -1042,8 +1074,8 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
|
|
||||||
assigned[k] = X;
|
assigned[k] = X;
|
||||||
Bit1029.clear(used, lemIdx);
|
Bit1029.clear(used, lemIdx);
|
||||||
grid.lo = low;
|
glo = low;
|
||||||
grid.hi = top;
|
ghi = top;
|
||||||
}
|
}
|
||||||
|
|
||||||
backtracks++;
|
backtracks++;
|
||||||
@@ -1056,7 +1088,8 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
if (!NO_LOG) solver.renderProgress();
|
if (!NO_LOG) solver.renderProgress();
|
||||||
var ok = solver.backtrack(0);
|
var ok = solver.backtrack(0);
|
||||||
// final progress line
|
// final progress line
|
||||||
|
grid.lo = solver.glo;
|
||||||
|
grid.hi = solver.ghi;
|
||||||
var res = new FillResult(ok, new Gridded(grid), assigned,
|
var res = new FillResult(ok, new Gridded(grid), assigned,
|
||||||
new FillStats(solver.nodes, solver.backtracks, (System.currentTimeMillis() - t0) / 1000.0, solver.lastMRV));
|
new FillStats(solver.nodes, solver.backtracks, (System.currentTimeMillis() - t0) / 1000.0, solver.lastMRV));
|
||||||
if (!multiThreaded) {
|
if (!multiThreaded) {
|
||||||
@@ -1068,7 +1101,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
System.out.println(
|
System.out.println(
|
||||||
String.format(Locale.ROOT,
|
String.format(Locale.ROOT,
|
||||||
"[######################] %d/%d slots | nodes=%d | backtracks=%d | mrv=%d | %.1fs",
|
"[######################] %d/%d slots | nodes=%d | backtracks=%d | mrv=%d | %.1fs",
|
||||||
res.wordCount(), TOTAL, res.nodes(), res.backtracks(), res.lastMRV(), res.seconds()
|
res.wordCount(0), TOTAL, res.nodes(), res.backtracks(), res.lastMRV(), res.seconds()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -180,9 +180,9 @@ public class MainTest {
|
|||||||
128L,
|
128L,
|
||||||
422762372923520L,
|
422762372923520L,
|
||||||
192L);
|
192L);
|
||||||
var filled = fillMask(rng, extractSlots(mask, dict.index()), mask.toGrid());
|
var filled = fillMask(rng, extractSlots(mask, dict.index()), mask.toGrid(), false);
|
||||||
Assertions.assertTrue(filled.ok(), "Puzzle generation failed (not ok)");
|
Assertions.assertTrue(filled.ok(), "Puzzle generation failed (not ok)");
|
||||||
Assertions.assertEquals(18, filled.wordCount(), "Number of assigned words changed");
|
Assertions.assertEquals(18, filled.wordCount(0), "Number of assigned words changed");
|
||||||
Assertions.assertEquals("SLEDE", Lemma.asWord(filled.clueMap()[282]));
|
Assertions.assertEquals("SLEDE", Lemma.asWord(filled.clueMap()[282]));
|
||||||
Assertions.assertEquals(-1L, filled.grid().grid().lo);
|
Assertions.assertEquals(-1L, filled.grid().grid().lo);
|
||||||
Assertions.assertEquals(255L, filled.grid().grid().hi);
|
Assertions.assertEquals(255L, filled.grid().grid().hi);
|
||||||
@@ -201,7 +201,7 @@ public class MainTest {
|
|||||||
foundSeed = seed;
|
foundSeed = seed;
|
||||||
System.out.println("[DEBUG_LOG] Seed found: " + seed);
|
System.out.println("[DEBUG_LOG] Seed found: " + seed);
|
||||||
System.out.println("[DEBUG_LOG] Simplicity: " + res.filled().stats().simplicity);
|
System.out.println("[DEBUG_LOG] Simplicity: " + res.filled().stats().simplicity);
|
||||||
System.out.println("[DEBUG_LOG] ClueMap Size: " + res.filled().wordCount());
|
System.out.println("[DEBUG_LOG] ClueMap Size: " + res.filled().wordCount(0));
|
||||||
System.out.println("[DEBUG_LOG] Grid:");
|
System.out.println("[DEBUG_LOG] Grid:");
|
||||||
System.out.println(res.filled().grid().renderHuman(res.clues().c()));
|
System.out.println(res.filled().grid().renderHuman(res.clues().c()));
|
||||||
System.out.println(res.filled().grid().gridToString(res.clues().c()));
|
System.out.println(res.filled().grid().gridToString(res.clues().c()));
|
||||||
@@ -214,15 +214,8 @@ public class MainTest {
|
|||||||
Assertions.assertTrue(res.filled().ok(), "Puzzle generation failed (not ok)");
|
Assertions.assertTrue(res.filled().ok(), "Puzzle generation failed (not ok)");
|
||||||
Assertions.assertEquals(12348, foundSeed, "Found seed changed");
|
Assertions.assertEquals(12348, foundSeed, "Found seed changed");
|
||||||
}
|
}
|
||||||
boolean isLetter(byte b) { return (b & 64) != 0; }
|
boolean isLetter(byte b) { return (b & 64) != 0; }
|
||||||
@Test
|
@Test public void testIsLetterA() { assertTrue(isLetter((byte) 'A')); }
|
||||||
public void testIsLetterA() {
|
@Test public void testIsLetterZ() { assertTrue(isLetter((byte) 'Z')); }
|
||||||
assertTrue(isLetter((byte) 'A'));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIsLetterZ() {
|
|
||||||
assertTrue(isLetter((byte) 'Z'));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user