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 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) {
|
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) {
|
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) {
|
public ExportedPuzzle exportFormatFromFilled(int difficulty, Rewards rewards) {
|
||||||
var placed = new ArrayList<Placed>();
|
var placed = new ArrayList<Placed>();
|
||||||
for (var slot : slots) {
|
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 csv = Paths.get("nl_score_hints_v3.csv");
|
||||||
var idx = Paths.get("nl_score_hints_v3.idx");
|
var idx = Paths.get("nl_score_hints_v3.idx");
|
||||||
try {
|
try {
|
||||||
@@ -97,7 +97,7 @@ public class Main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
section("Result");
|
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));
|
info(String.format(Locale.ROOT, "simplicity : %.2f", res.filled().stats().simplicity));
|
||||||
|
|
||||||
section("Mask");
|
section("Mask");
|
||||||
@@ -206,7 +206,7 @@ public class Main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void usage() {
|
static void usage() {
|
||||||
System.out.println("""
|
System.out.printf("""
|
||||||
Usage:
|
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]
|
java puzzle.Main [--seed N] [--clues N] [--pop N] [--offspring N] [--gens N] [--tries N] [--words FILE] [--min-simplicity N.N] [--threads N] [--reindex]
|
||||||
|
|
||||||
@@ -218,7 +218,7 @@ public class Main {
|
|||||||
--words nl_score_hints.csv
|
--words nl_score_hints.csv
|
||||||
--min-simplicity 0 (no limit)
|
--min-simplicity 0 (no limit)
|
||||||
--threads %d
|
--threads %d
|
||||||
""".formatted(Math.max(1, Runtime.getRuntime().availableProcessors())));
|
%n""", Math.max(1, Runtime.getRuntime().availableProcessors()));
|
||||||
}
|
}
|
||||||
|
|
||||||
static Opts parseArgs(String[] argv) {
|
static Opts parseArgs(String[] argv) {
|
||||||
@@ -401,22 +401,22 @@ public class Main {
|
|||||||
if (Main.VERBOSE && !multiThreaded) {
|
if (Main.VERBOSE && !multiThreaded) {
|
||||||
System.out.printf(Locale.ROOT,
|
System.out.printf(Locale.ROOT,
|
||||||
"[######################] %d/%d slots | nodes=%d | backtracks=%d | mrv=%d | %.1fs%n",
|
"[######################] %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_NODES.addAndGet(filled.nodes());
|
||||||
TOTAL_BACKTRACKS.addAndGet(filled.backtracks());
|
TOTAL_BACKTRACKS.addAndGet(filled.backtracks());
|
||||||
if (filled.ok()) {
|
if (filled.ok()) {
|
||||||
val simpel = FillResult.calcSimpel(slotInfo);
|
val simpel = PuzzleResult.calcSimpel(slotInfo);
|
||||||
TOTAL_SUCCESS.incrementAndGet();
|
TOTAL_SUCCESS.incrementAndGet();
|
||||||
TOTAL_SIMPLICITY.addAndGet((long) (simpel * 100));
|
TOTAL_SIMPLICITY.addAndGet(simpel * 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
var name = Thread.currentThread().getName();
|
var name = Thread.currentThread().getName();
|
||||||
var status = filled.ok() ? "SUCCESS" : "FAILED";
|
var status = filled.ok() ? "SUCCESS" : "FAILED";
|
||||||
var simplicity = String.format(Locale.ROOT, "%.2f", filled.stats().simplicity);
|
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;
|
var totalTime = (System.currentTimeMillis() - t0) / 1000.0;
|
||||||
|
|
||||||
System.out.printf(Locale.ROOT,
|
System.out.printf(Locale.ROOT,
|
||||||
|
|||||||
@@ -91,25 +91,11 @@ public class SwedishGenerator {
|
|||||||
@Accessors(fluent = true)
|
@Accessors(fluent = true)
|
||||||
public static final class FillStats {
|
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 {
|
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 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 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 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) {
|
||||||
@@ -225,59 +209,6 @@ public class SwedishGenerator {
|
|||||||
}
|
}
|
||||||
return p;
|
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
|
/// pattern cannot be X
|
||||||
public static int[] candidateInfoForPattern(long[] res, long pattern, long[][] posBitsets, int numLongs) {
|
public static int[] candidateInfoForPattern(long[] res, long pattern, long[][] posBitsets, int numLongs) {
|
||||||
@@ -503,6 +434,6 @@ public class SwedishGenerator {
|
|||||||
grid.lo = solver.glo;
|
grid.lo = solver.glo;
|
||||||
grid.hi = solver.ghi;
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import static puzzle.Masker.Clues;
|
|||||||
import static puzzle.SwedishGenerator.FillStats;
|
import static puzzle.SwedishGenerator.FillStats;
|
||||||
import static puzzle.SwedishGenerator.R;
|
import static puzzle.SwedishGenerator.R;
|
||||||
import static puzzle.Masker.Slot;
|
import static puzzle.Masker.Slot;
|
||||||
import static puzzle.SwedishGenerator.placeWord;
|
import static puzzle.GridBuilder.placeWord;
|
||||||
import static puzzle.SwedishGeneratorTest.OFF_0_1;
|
import static puzzle.SwedishGeneratorTest.OFF_0_1;
|
||||||
import static puzzle.SwedishGeneratorTest.OFF_0_2;
|
import static puzzle.SwedishGeneratorTest.OFF_0_2;
|
||||||
import static puzzle.SwedishGeneratorTest.OFF_0_3;
|
import static puzzle.SwedishGeneratorTest.OFF_0_3;
|
||||||
@@ -67,7 +67,7 @@ public class ExportFormatTest {
|
|||||||
|
|
||||||
assertTrue(placeWord(grid.grid(), grid.grid().g, key, lo, 0L, TEST));
|
assertTrue(placeWord(grid.grid(), grid.grid().g, key, lo, 0L, TEST));
|
||||||
|
|
||||||
var fillResult = new FillResult(true, 0, 0, new FillStats(0, 0));
|
var fillResult = new FillResult(true, 0, 0, 0, 0, new FillStats());
|
||||||
var puzzleResult = new PuzzleResult(new Clued(clues), grid, new Slotinfo[]{
|
var puzzleResult = new PuzzleResult(new Clued(clues), grid, new Slotinfo[]{
|
||||||
new Slotinfo(key, lo, 0L, 0, new Assign(TEST), null)
|
new Slotinfo(key, lo, 0L, 0, new Assign(TEST), null)
|
||||||
}, fillResult);
|
}, fillResult);
|
||||||
@@ -109,7 +109,7 @@ public class ExportFormatTest {
|
|||||||
void testExportFormatEmpty() {
|
void testExportFormatEmpty() {
|
||||||
var grid = SwedishGeneratorTest.createEmpty();
|
var grid = SwedishGeneratorTest.createEmpty();
|
||||||
val clues = Clues.createEmpty();
|
val clues = Clues.createEmpty();
|
||||||
var fillResult = new FillResult(true, 0, 0, new FillStats(0, 0));
|
var fillResult = new FillResult(true, 0, 0, 0, 0, new FillStats());
|
||||||
var puzzleResult = new PuzzleResult(new Clued(clues), new Gridded(grid), new Slotinfo[0], fillResult);
|
var puzzleResult = new PuzzleResult(new Clued(clues), new Gridded(grid), new Slotinfo[0], fillResult);
|
||||||
|
|
||||||
var exported = puzzleResult.exportFormatFromFilled(1, new Rewards(0, 0, 0));
|
var exported = puzzleResult.exportFormatFromFilled(1, new Rewards(0, 0, 0));
|
||||||
|
|||||||
63
src/test/java/puzzle/GridBuilder.java
Normal file
63
src/test/java/puzzle/GridBuilder.java
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package puzzle;
|
||||||
|
|
||||||
|
import puzzle.SwedishGenerator.Grid;
|
||||||
|
import puzzle.SwedishGenerator.Lemma;
|
||||||
|
import puzzle.SwedishGenerator.Slotinfo;
|
||||||
|
import static java.lang.Long.bitCount;
|
||||||
|
import static java.lang.Long.numberOfTrailingZeros;
|
||||||
|
public class GridBuilder {
|
||||||
|
|
||||||
|
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 != SwedishGenerator.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 != SwedishGenerator.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) != SwedishGenerator.X) {
|
||||||
|
for (long b = maskLo; b != SwedishGenerator.X; b &= b - 1) {
|
||||||
|
int idx = numberOfTrailingZeros(b);
|
||||||
|
g[idx] = Lemma.byteAt(w, bitCount(lo & ((1L << idx) - 1)));
|
||||||
|
}
|
||||||
|
for (long b = maskHi; b != SwedishGenerator.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 != SwedishGenerator.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 != SwedishGenerator.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) != SwedishGenerator.X) {
|
||||||
|
for (long b = maskHi; b != SwedishGenerator.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 != SwedishGenerator.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -52,7 +52,7 @@ public class MainTest {
|
|||||||
clues.setClueLo(IDX_0_0.lo, CLUE_RIGHT);
|
clues.setClueLo(IDX_0_0.lo, CLUE_RIGHT);
|
||||||
var grid = new Gridded(clues.toGrid());
|
var grid = new Gridded(clues.toGrid());
|
||||||
val g = grid.grid().g;
|
val g = grid.grid().g;
|
||||||
placeWord(grid.grid(), g, key, (1L << OFF_0_1) | (1L << OFF_0_2), 0, AB);
|
GridBuilder.placeWord(grid.grid(), g, key, (1L << OFF_0_1) | (1L << OFF_0_2), 0, AB);
|
||||||
|
|
||||||
var slots = Masker.extractSlots(clues, dict.index());
|
var slots = Masker.extractSlots(clues, dict.index());
|
||||||
assertEquals(1, slots.length);
|
assertEquals(1, slots.length);
|
||||||
@@ -102,7 +102,7 @@ public class MainTest {
|
|||||||
var grid = new Gridded(clues.toGrid());
|
var grid = new Gridded(clues.toGrid());
|
||||||
|
|
||||||
// Test set/get
|
// Test set/get
|
||||||
placeWord(grid.grid(), grid.grid().g, key, (1L << OFF_1_1) | (1L << OFF_0_1), 0, AZ);
|
GridBuilder.placeWord(grid.grid(), grid.grid().g, key, (1L << OFF_1_1) | (1L << OFF_0_1), 0, AZ);
|
||||||
val map = grid.stream(clues.c()).collect(Collectors.toMap(LetterAt::index, LetterAt::letter));
|
val map = grid.stream(clues.c()).collect(Collectors.toMap(LetterAt::index, LetterAt::letter));
|
||||||
Assertions.assertEquals(LETTER_A, map.get(OFF_1_1));
|
Assertions.assertEquals(LETTER_A, map.get(OFF_1_1));
|
||||||
Assertions.assertEquals(LETTER_Z, map.get(OFF_0_1));
|
Assertions.assertEquals(LETTER_Z, map.get(OFF_0_1));
|
||||||
@@ -172,6 +172,17 @@ public class MainTest {
|
|||||||
Assertions.assertEquals(RESULT, test, "Found seed changed");
|
Assertions.assertEquals(RESULT, test, "Found seed changed");
|
||||||
}
|
}
|
||||||
@Test
|
@Test
|
||||||
|
void testFiller2() {
|
||||||
|
val mask = "1 000000\n" +
|
||||||
|
"1 \n" +
|
||||||
|
"1 \n" +
|
||||||
|
"3 3 \n" +
|
||||||
|
"3 0 3 \n" +
|
||||||
|
"3 \n" +
|
||||||
|
"3 \n" +
|
||||||
|
"222 3";
|
||||||
|
}
|
||||||
|
@Test
|
||||||
void testFiller() {
|
void testFiller() {
|
||||||
val rng = new Rng(-343913721);
|
val rng = new Rng(-343913721);
|
||||||
val mask = new Clues(
|
val mask = new Clues(
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ public class SwedishGeneratorTest {
|
|||||||
var key = Masker.Slot.packSlotKey(OFF_0_0, CLUE_RIGHT);
|
var key = Masker.Slot.packSlotKey(OFF_0_0, CLUE_RIGHT);
|
||||||
val clues = Masker.Clues.createEmpty();
|
val clues = Masker.Clues.createEmpty();
|
||||||
clues.setClueLo(IDX_0_0.lo, CLUE_RIGHT);
|
clues.setClueLo(IDX_0_0.lo, CLUE_RIGHT);
|
||||||
placeWord(grid.grid(), grid.grid().g, key, (1L << OFF_0_1) | (1L << OFF_0_2) | (1L << OFF_0_3), 0L, ABC);
|
GridBuilder.placeWord(grid.grid(), grid.grid().g, key, (1L << OFF_0_1) | (1L << OFF_0_2) | (1L << OFF_0_3), 0L, ABC);
|
||||||
val map = grid.stream(clues).collect(Collectors.toMap(LetterAt::index, LetterAt::letter));
|
val map = grid.stream(clues).collect(Collectors.toMap(LetterAt::index, LetterAt::letter));
|
||||||
assertEquals(LETTER_A, map.get(OFF_0_1));
|
assertEquals(LETTER_A, map.get(OFF_0_1));
|
||||||
assertEquals(LETTER_B, map.get(OFF_0_2));
|
assertEquals(LETTER_B, map.get(OFF_0_2));
|
||||||
@@ -152,8 +152,8 @@ public class SwedishGeneratorTest {
|
|||||||
@Test
|
@Test
|
||||||
void testPatternForSlotMixed() {
|
void testPatternForSlotMixed() {
|
||||||
var grid = createEmpty();
|
var grid = createEmpty();
|
||||||
placeWord(grid, grid.g, Masker.Slot.packSlotKey(0, CLUE_RIGHT), 1L << OFF_0_0, 0, Lemma.from(0, "A"));
|
GridBuilder.placeWord(grid, grid.g, Masker.Slot.packSlotKey(0, CLUE_RIGHT), 1L << OFF_0_0, 0, Lemma.from(0, "A"));
|
||||||
placeWord(grid, grid.g, Masker.Slot.packSlotKey(0, CLUE_RIGHT), 1L << OFF_2_0, 0, Lemma.from(0, "C"));
|
GridBuilder.placeWord(grid, grid.g, Masker.Slot.packSlotKey(0, CLUE_RIGHT), 1L << OFF_2_0, 0, Lemma.from(0, "C"));
|
||||||
var key = Masker.Slot.packSlotKey(OFF_1_0, CLUE_RIGHT);
|
var key = Masker.Slot.packSlotKey(OFF_1_0, CLUE_RIGHT);
|
||||||
var pattern = patternForSlot(grid.lo, grid.hi, grid.g, key, 7L, 0L);
|
var pattern = patternForSlot(grid.lo, grid.hi, grid.g, key, 7L, 0L);
|
||||||
assertEquals(14081L, pattern);
|
assertEquals(14081L, pattern);
|
||||||
@@ -170,7 +170,7 @@ public class SwedishGeneratorTest {
|
|||||||
@Test
|
@Test
|
||||||
void testPatternForSlotSingleLetter() {
|
void testPatternForSlotSingleLetter() {
|
||||||
var grid = createEmpty();
|
var grid = createEmpty();
|
||||||
placeWord(grid, grid.g, Masker.Slot.packSlotKey(0, CLUE_RIGHT), 1L << OFF_0_0, 0, Lemma.from(0, "A"));
|
GridBuilder.placeWord(grid, grid.g, Masker.Slot.packSlotKey(0, CLUE_RIGHT), 1L << OFF_0_0, 0, Lemma.from(0, "A"));
|
||||||
var key = Masker.Slot.packSlotKey(1, CLUE_RIGHT);
|
var key = Masker.Slot.packSlotKey(1, CLUE_RIGHT);
|
||||||
var pattern = patternForSlot(grid.lo, grid.hi, grid.g, key, 7L, 0L);
|
var pattern = patternForSlot(grid.lo, grid.hi, grid.g, key, 7L, 0L);
|
||||||
assertEquals(1L, pattern);
|
assertEquals(1L, pattern);
|
||||||
@@ -196,7 +196,7 @@ public class SwedishGeneratorTest {
|
|||||||
@Test
|
@Test
|
||||||
void testGrid() {
|
void testGrid() {
|
||||||
var grid = new Gridded(createEmpty());
|
var grid = new Gridded(createEmpty());
|
||||||
placeWord(grid.grid(), grid.grid().g, Masker.Slot.packSlotKey(0, CLUE_RIGHT), 1L << OFF_0_0, 0, Lemma.from(0, "A"));
|
GridBuilder.placeWord(grid.grid(), grid.grid().g, Masker.Slot.packSlotKey(0, CLUE_RIGHT), 1L << OFF_0_0, 0, Lemma.from(0, "A"));
|
||||||
val arr = grid.stream(Masker.Clues.createEmpty()).collect(Collectors.toMap(LetterAt::index, LetterAt::letter));
|
val arr = grid.stream(Masker.Clues.createEmpty()).collect(Collectors.toMap(LetterAt::index, LetterAt::letter));
|
||||||
assertEquals(1, arr.size());
|
assertEquals(1, arr.size());
|
||||||
assertEquals(LETTER_A, arr.get(OFF_0_0));
|
assertEquals(LETTER_A, arr.get(OFF_0_0));
|
||||||
@@ -342,7 +342,7 @@ public class SwedishGeneratorTest {
|
|||||||
var w1 = ABC;
|
var w1 = ABC;
|
||||||
|
|
||||||
// 1. Successful placement in empty grid
|
// 1. Successful placement in empty grid
|
||||||
assertTrue(placeWord(grid.grid(), grid.grid().g, key, lo, hi, w1));
|
assertTrue(GridBuilder.placeWord(grid.grid(), grid.grid().g, key, lo, hi, w1));
|
||||||
var map = grid.stream(Masker.Clues.createEmpty()).collect(Collectors.toMap(LetterAt::index, LetterAt::letter));
|
var map = grid.stream(Masker.Clues.createEmpty()).collect(Collectors.toMap(LetterAt::index, LetterAt::letter));
|
||||||
assertEquals(3, map.size());
|
assertEquals(3, map.size());
|
||||||
assertEquals(LETTER_A, map.get(OFF_0_0));
|
assertEquals(LETTER_A, map.get(OFF_0_0));
|
||||||
@@ -350,9 +350,9 @@ public class SwedishGeneratorTest {
|
|||||||
assertEquals(LETTER_C, map.get(OFF_0_2));
|
assertEquals(LETTER_C, map.get(OFF_0_2));
|
||||||
|
|
||||||
// 2. Successful placement with partial overlap (same characters)
|
// 2. Successful placement with partial overlap (same characters)
|
||||||
assertTrue(placeWord(grid.grid(), grid.grid().g, key, lo, hi, w1));
|
assertTrue(GridBuilder.placeWord(grid.grid(), grid.grid().g, key, lo, hi, w1));
|
||||||
// 3. Conflict: place "ABD" where "ABC" is
|
// 3. Conflict: place "ABD" where "ABC" is
|
||||||
assertFalse(placeWord(grid.grid(), grid.grid().g, key, lo, hi, ABD));
|
assertFalse(GridBuilder.placeWord(grid.grid(), grid.grid().g, key, lo, hi, ABD));
|
||||||
// Verify grid is unchanged (still "ABC")
|
// Verify grid is unchanged (still "ABC")
|
||||||
map = grid.stream(Masker.Clues.createEmpty()).collect(Collectors.toMap(LetterAt::index, LetterAt::letter));
|
map = grid.stream(Masker.Clues.createEmpty()).collect(Collectors.toMap(LetterAt::index, LetterAt::letter));
|
||||||
assertEquals(3, map.size());
|
assertEquals(3, map.size());
|
||||||
@@ -362,8 +362,8 @@ public class SwedishGeneratorTest {
|
|||||||
|
|
||||||
// 4. Partial placement then conflict (rollback)
|
// 4. Partial placement then conflict (rollback)
|
||||||
grid = new Gridded(createEmpty());
|
grid = new Gridded(createEmpty());
|
||||||
placeWord(grid.grid(), grid.grid().g, Masker.Slot.packSlotKey(0, CLUE_RIGHT), 1L << OFF_0_2, 0, Lemma.from(0, "X")); // Conflict at the end
|
GridBuilder.placeWord(grid.grid(), grid.grid().g, Masker.Slot.packSlotKey(0, CLUE_RIGHT), 1L << OFF_0_2, 0, Lemma.from(0, "X")); // Conflict at the end
|
||||||
assertFalse(placeWord(grid.grid(), grid.grid().g, key, lo, hi, w1));
|
assertFalse(GridBuilder.placeWord(grid.grid(), grid.grid().g, key, lo, hi, w1));
|
||||||
map = grid.stream(Masker.Clues.createEmpty()).collect(Collectors.toMap(LetterAt::index, LetterAt::letter));
|
map = grid.stream(Masker.Clues.createEmpty()).collect(Collectors.toMap(LetterAt::index, LetterAt::letter));
|
||||||
assertEquals(1, map.size());
|
assertEquals(1, map.size());
|
||||||
assertEquals(LETTER_X, map.get(OFF_0_2));
|
assertEquals(LETTER_X, map.get(OFF_0_2));
|
||||||
@@ -378,7 +378,7 @@ public class SwedishGeneratorTest {
|
|||||||
var w = AZ;
|
var w = AZ;
|
||||||
val low = grid.grid().lo;
|
val low = grid.grid().lo;
|
||||||
val top = grid.grid().hi;
|
val top = grid.grid().hi;
|
||||||
var placed = placeWord(grid.grid(), grid.grid().g, key, lo, 0L, w);
|
var placed = GridBuilder.placeWord(grid.grid(), grid.grid().g, key, lo, 0L, w);
|
||||||
assertTrue(placed);
|
assertTrue(placed);
|
||||||
var map = grid.stream(Masker.Clues.createEmpty()).collect(Collectors.toMap(LetterAt::index, LetterAt::letter));
|
var map = grid.stream(Masker.Clues.createEmpty()).collect(Collectors.toMap(LetterAt::index, LetterAt::letter));
|
||||||
assertEquals(2, map.size());
|
assertEquals(2, map.size());
|
||||||
|
|||||||
Reference in New Issue
Block a user