introduce bitloops
This commit is contained in:
@@ -215,7 +215,8 @@ public record Export() {
|
||||
public record WordOut(String word, int[] cell, int startRow, int startCol, char direction, int arrowRow, int arrowCol, boolean isReversed, int complex, String[] clue) {
|
||||
|
||||
public WordOut(long l, int startRow, int startCol, char d, int arrowRow, int arrowCol, boolean isReversed) {
|
||||
this(Lemma.asWord(l), new int[]{ arrowRow, arrowCol, startRow, startCol }, startRow, startCol, d, arrowRow, arrowCol, isReversed, Lemma.simpel(l), Lemma.clue(l));
|
||||
this(Lemma.asWord(l), new int[]{ arrowRow, arrowCol, startRow, startCol }, startRow, startCol, d, arrowRow, arrowCol, isReversed,
|
||||
CsvIndexService.simpel(Lemma.unpackIndex(l)), CsvIndexService.clues(Lemma.unpackIndex(l)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,6 +224,18 @@ public record Export() {
|
||||
|
||||
public record PuzzleResult(Clued clues, Gridded grid, Slotinfo[] slots, FillResult filled) {
|
||||
|
||||
static public long calcSimpel(Slotinfo[] slots) {
|
||||
int k = 0;
|
||||
long simpel = 0L;
|
||||
for (var n = 1; n < slots.length; n++) {
|
||||
if (slots[n].assign().w != X) {
|
||||
k++;
|
||||
simpel += CsvIndexService.simpel(Lemma.unpackIndex(slots[n].assign().w));
|
||||
}
|
||||
}
|
||||
simpel = k == 0 ? 0 : simpel / k;
|
||||
return simpel;
|
||||
}
|
||||
public ExportedPuzzle exportFormatFromFilled(int difficulty, Rewards rewards) {
|
||||
var placed = new ArrayList<Placed>();
|
||||
for (var slot : slots) {
|
||||
|
||||
@@ -58,7 +58,7 @@ public class Main {
|
||||
|
||||
}
|
||||
|
||||
public void main(String[] args) {
|
||||
void main(String[] args) {
|
||||
var csv = Paths.get("nl_score_hints_v3.csv");
|
||||
var idx = Paths.get("nl_score_hints_v3.idx");
|
||||
try {
|
||||
@@ -97,7 +97,7 @@ public class Main {
|
||||
}
|
||||
|
||||
section("Result");
|
||||
res.filled().stats().simplicity = FillResult.calcSimpel(res.slots());
|
||||
res.filled().stats().simplicity = PuzzleResult.calcSimpel(res.slots());
|
||||
info(String.format(Locale.ROOT, "simplicity : %.2f", res.filled().stats().simplicity));
|
||||
|
||||
section("Mask");
|
||||
@@ -206,19 +206,19 @@ public class Main {
|
||||
}
|
||||
|
||||
static void usage() {
|
||||
System.out.println("""
|
||||
Usage:
|
||||
java puzzle.Main [--seed N] [--clues N] [--pop N] [--offspring N] [--gens N] [--tries N] [--words FILE] [--min-simplicity N.N] [--threads N] [--reindex]
|
||||
|
||||
Defaults:
|
||||
--clues 18
|
||||
--pop 40
|
||||
--offspring 60
|
||||
--gens 500
|
||||
--words nl_score_hints.csv
|
||||
--min-simplicity 0 (no limit)
|
||||
--threads %d
|
||||
""".formatted(Math.max(1, Runtime.getRuntime().availableProcessors())));
|
||||
System.out.printf("""
|
||||
Usage:
|
||||
java puzzle.Main [--seed N] [--clues N] [--pop N] [--offspring N] [--gens N] [--tries N] [--words FILE] [--min-simplicity N.N] [--threads N] [--reindex]
|
||||
|
||||
Defaults:
|
||||
--clues 18
|
||||
--pop 40
|
||||
--offspring 60
|
||||
--gens 500
|
||||
--words nl_score_hints.csv
|
||||
--min-simplicity 0 (no limit)
|
||||
--threads %d
|
||||
%n""", Math.max(1, Runtime.getRuntime().availableProcessors()));
|
||||
}
|
||||
|
||||
static Opts parseArgs(String[] argv) {
|
||||
@@ -392,7 +392,7 @@ public class Main {
|
||||
val slotInfo = Masker.scoreSlots(new int[slots.length], slots);
|
||||
var grid = mask.toGrid();
|
||||
var filled = fillMask(rng, slotInfo, grid, multiThreaded);
|
||||
|
||||
|
||||
if (!multiThreaded) {
|
||||
System.out.print("\r" + Strings.padRight("", 120) + "\r");
|
||||
System.out.flush();
|
||||
@@ -401,22 +401,22 @@ public class Main {
|
||||
if (Main.VERBOSE && !multiThreaded) {
|
||||
System.out.printf(Locale.ROOT,
|
||||
"[######################] %d/%d slots | nodes=%d | backtracks=%d | mrv=%d | %.1fs%n",
|
||||
Slotinfo.wordCount(0, slotInfo), slotInfo.length, filled.nodes(), filled.backtracks(), filled.stats().lastMRV(), filled.stats().seconds()
|
||||
);
|
||||
Slotinfo.wordCount(0, slotInfo), slotInfo.length, filled.nodes(), filled.backtracks(), filled.lastMRV(), filled.elapsed() * 0.001
|
||||
);
|
||||
}
|
||||
|
||||
TOTAL_NODES.addAndGet(filled.nodes());
|
||||
TOTAL_BACKTRACKS.addAndGet(filled.backtracks());
|
||||
if (filled.ok()) {
|
||||
val simpel = FillResult.calcSimpel(slotInfo);
|
||||
val simpel = PuzzleResult.calcSimpel(slotInfo);
|
||||
TOTAL_SUCCESS.incrementAndGet();
|
||||
TOTAL_SIMPLICITY.addAndGet((long) (simpel * 100));
|
||||
TOTAL_SIMPLICITY.addAndGet(simpel * 100);
|
||||
}
|
||||
|
||||
var name = Thread.currentThread().getName();
|
||||
var status = filled.ok() ? "SUCCESS" : "FAILED";
|
||||
var simplicity = String.format(Locale.ROOT, "%.2f", filled.stats().simplicity);
|
||||
var nps = (int) (filled.nodes() / Math.max(0.001, filled.stats().seconds));
|
||||
var nps = (int) (filled.nodes() / Math.max(0.001, filled.elapsed() * 0.001));
|
||||
var totalTime = (System.currentTimeMillis() - t0) / 1000.0;
|
||||
|
||||
System.out.printf(Locale.ROOT,
|
||||
|
||||
@@ -91,25 +91,11 @@ public class SwedishGenerator {
|
||||
@Accessors(fluent = true)
|
||||
public static final class FillStats {
|
||||
|
||||
final public double seconds;
|
||||
final public int lastMRV;
|
||||
public double simplicity;
|
||||
public double simplicity;
|
||||
}
|
||||
|
||||
public static record FillResult(boolean ok, long nodes, long backtracks, @Delegate FillStats stats) {
|
||||
public static record FillResult(boolean ok, long nodes, long backtracks, int lastMRV, long elapsed, @Delegate FillStats stats) {
|
||||
|
||||
static public long calcSimpel(Slotinfo[] slots) {
|
||||
int k = 0;
|
||||
long simpel = 0L;
|
||||
for (var n = 1; n < slots.length; n++) {
|
||||
if (slots[n].assign.w != X) {
|
||||
k++;
|
||||
simpel += Lemma.simpel(slots[n].assign.w);
|
||||
}
|
||||
}
|
||||
simpel = k == 0 ? 0 : simpel / k;
|
||||
return simpel;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Rng {
|
||||
@@ -161,8 +147,6 @@ public class SwedishGenerator {
|
||||
}
|
||||
static public long from(int index, String word) { return pack(index, word.getBytes(US_ASCII)); }
|
||||
static byte byteAt(long word, int idx) { return (byte) ((word >>> (idx * 5)) & 0b11111); }
|
||||
static String[] clue(long w) { return CsvIndexService.clues(unpackIndex(w)); }
|
||||
static int simpel(long w) { return CsvIndexService.simpel(unpackIndex(w)); }
|
||||
static int length(long word) { return ((63 - numberOfLeadingZeros(word & LETTER_MASK)) / 5) + 1; }
|
||||
static ThreadLocal<byte[]> BYTES = ThreadLocal.withInitial(() -> new byte[MAX_WORD_LENGTH]);
|
||||
public static String asWord(long word) {
|
||||
@@ -225,59 +209,6 @@ public class SwedishGenerator {
|
||||
}
|
||||
return p;
|
||||
}
|
||||
public 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;
|
||||
if (Slotinfo.increasing(key)) {
|
||||
for (long b = lo & glo; b != X; b &= b - 1) {
|
||||
int idx = numberOfTrailingZeros(b);
|
||||
if (g[idx] != Lemma.byteAt(w, bitCount(lo & ((1L << idx) - 1)))) return false;
|
||||
}
|
||||
int bcLo = bitCount(lo);
|
||||
for (long b = hi & ghi; b != X; b &= b - 1) {
|
||||
int idx = numberOfTrailingZeros(b);
|
||||
if (g[64 | idx] != 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) {
|
||||
int idx = numberOfTrailingZeros(b);
|
||||
g[idx] = Lemma.byteAt(w, bitCount(lo & ((1L << idx) - 1)));
|
||||
}
|
||||
for (long b = maskHi; b != X; b &= b - 1) {
|
||||
int idx = numberOfTrailingZeros(b);
|
||||
g[64 | idx] = Lemma.byteAt(w, bcLo + bitCount(hi & ((1L << idx) - 1)));
|
||||
}
|
||||
grid.lo |= maskLo;
|
||||
grid.hi |= maskHi;
|
||||
}
|
||||
} else {
|
||||
int bcHi = bitCount(hi);
|
||||
for (long b = hi & ghi; b != X; b &= b - 1) {
|
||||
int idx = numberOfTrailingZeros(b);
|
||||
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) {
|
||||
int idx = numberOfTrailingZeros(b);
|
||||
if (g[idx] != 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) {
|
||||
int idx = numberOfTrailingZeros(b);
|
||||
g[64 | idx] = Lemma.byteAt(w, bitCount(hi & ~((1L << idx) | ((1L << idx) - 1))));
|
||||
}
|
||||
for (long b = maskLo; b != X; b &= b - 1) {
|
||||
int idx = numberOfTrailingZeros(b);
|
||||
g[idx] = Lemma.byteAt(w, bcHi + bitCount(lo & ~((1L << idx) | ((1L << idx) - 1))));
|
||||
}
|
||||
grid.lo |= maskLo;
|
||||
grid.hi |= maskHi;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// pattern cannot be X
|
||||
public static int[] candidateInfoForPattern(long[] res, long pattern, long[][] posBitsets, int numLongs) {
|
||||
@@ -503,6 +434,6 @@ public class SwedishGenerator {
|
||||
grid.lo = solver.glo;
|
||||
grid.hi = solver.ghi;
|
||||
|
||||
return new FillResult(ok, solver.nodes, solver.backtracks, new FillStats((System.currentTimeMillis() - t0) / 1000.0, solver.lastMRV));
|
||||
return new FillResult(ok, solver.nodes, solver.backtracks, solver.lastMRV, System.currentTimeMillis() - t0, new FillStats());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user