introduce bitloops
This commit is contained in:
@@ -70,15 +70,10 @@ public record Export() {
|
|||||||
|
|
||||||
public record Clued(@Delegate Clues c) {
|
public record Clued(@Delegate Clues c) {
|
||||||
|
|
||||||
public static Clues create(Cell... cell) {
|
public static Clued of(Cell... cells) {
|
||||||
var empty = createEmpty();
|
|
||||||
for (var cell1 : cell) empty.setClue(cell1);
|
|
||||||
return empty;
|
|
||||||
}
|
|
||||||
public static Clues of(Cell... cells) {
|
|
||||||
var c = createEmpty();
|
var c = createEmpty();
|
||||||
for (var cell : cells) c.setClue(cell);
|
for (var cell : cells) c.setClue(cell);
|
||||||
return c;
|
return new Clued(c);
|
||||||
}
|
}
|
||||||
public Clued deepCopyGrid() { return new Clued(new Clues(c.lo, c.hi, c.vlo, c.vhi, c.rlo, c.rhi, c.xlo, c.xhi)); }
|
public Clued deepCopyGrid() { return new Clued(new Clues(c.lo, c.hi, c.vlo, c.vhi, c.rlo, c.rhi, c.xlo, c.xhi)); }
|
||||||
public static Clued parse(String s) {
|
public static Clued parse(String s) {
|
||||||
@@ -125,6 +120,9 @@ public record Export() {
|
|||||||
|
|
||||||
return stream.build();
|
return stream.build();
|
||||||
}
|
}
|
||||||
|
public Slotinfo[] slots() {
|
||||||
|
return Masker.slots(c, DictData.DICT.index());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
@@ -143,13 +141,15 @@ public record Export() {
|
|||||||
default void visit(int index, byte[] letters) { visit(index, letters[index]); }
|
default void visit(int index, byte[] letters) { visit(index, letters[index]); }
|
||||||
}
|
}
|
||||||
|
|
||||||
record Gridded(@Delegate Grid grid, Clues cl) {
|
record Gridded(@Delegate Grid grid, Clues cl)
|
||||||
|
implements Stream<LetterAt> {
|
||||||
|
|
||||||
public Gridded(Clues clues) { this(clues.toGrid(), clues); }
|
public Gridded(Clues clues) { this(clues.toGrid(), clues); }
|
||||||
public Stream<LetterAt> stream(Clues clues) {
|
public Gridded(Clued clues) { this(clues.toGrid(), clues.c); }
|
||||||
|
public @Delegate Stream<LetterAt> stream() {
|
||||||
val stream = Stream.<LetterAt>builder();
|
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 l = grid.lo & ~cl.lo; l != X; l &= l - 1) stream.accept(LetterAt.from(Long.numberOfTrailingZeros(l), 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));
|
for (var h = grid.hi & ~cl.hi & 0xFF; h != X; h &= h - 1) stream.accept(LetterAt.from(64 | Long.numberOfTrailingZeros(h), grid.g));
|
||||||
return stream.build();
|
return stream.build();
|
||||||
}
|
}
|
||||||
String gridToString(Clues clues) {
|
String gridToString(Clues clues) {
|
||||||
@@ -161,7 +161,7 @@ public record Export() {
|
|||||||
val dir = Slot.dir(s);
|
val dir = Slot.dir(s);
|
||||||
sb.setCharAt(r * (C + 1) + c, (char) (dir | 48));
|
sb.setCharAt(r * (C + 1) + c, (char) (dir | 48));
|
||||||
});
|
});
|
||||||
stream(clues).forEach((l) -> sb.setCharAt(l.index(C + 1), l.human()));
|
stream().forEach((l) -> sb.setCharAt(l.index(C + 1), l.human()));
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
public String[] exportGrid(Clues clues, Replacar clueChar, char emptyFallback) {
|
public String[] exportGrid(Clues clues, Replacar clueChar, char emptyFallback) {
|
||||||
@@ -173,7 +173,7 @@ public record Export() {
|
|||||||
val dir = Slot.dir(s);
|
val dir = Slot.dir(s);
|
||||||
sb.setCharAt(r * (C + 1) + c, clueChar.replace(new Rell(grid, clues, idx, (byte) (dir | 48))));
|
sb.setCharAt(r * (C + 1) + c, clueChar.replace(new Rell(grid, clues, idx, (byte) (dir | 48))));
|
||||||
});
|
});
|
||||||
stream(clues).forEach((l) -> sb.setCharAt(l.index(C + 1), l.human()));
|
stream().forEach((l) -> sb.setCharAt(l.index(C + 1), l.human()));
|
||||||
return sb.toString().replaceAll(" ", "" + emptyFallback).split("\n");
|
return sb.toString().replaceAll(" ", "" + emptyFallback).split("\n");
|
||||||
}
|
}
|
||||||
public static IntStream cellWalk(byte base, long lo, long hi) {
|
public static IntStream cellWalk(byte base, long lo, long hi) {
|
||||||
@@ -291,7 +291,7 @@ public record Export() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3) map of only used letter cells (everything else becomes '#')
|
// 3) map of only used letter cells (everything else becomes '#')
|
||||||
var map = grid.stream(clues.c()).collect(Collectors.toMap(LetterAt::index, LetterAt::human));
|
var map = grid.stream().collect(Collectors.toMap(LetterAt::index, LetterAt::human));
|
||||||
// 4) render gridv2 over cropped bounds (out-of-bounds become '#')
|
// 4) render gridv2 over cropped bounds (out-of-bounds become '#')
|
||||||
var gridv2 = new String[Math.max(0, maxR - minR + 1)];
|
var gridv2 = new String[Math.max(0, maxR - minR + 1)];
|
||||||
for (int r = minR, i = 0; r <= maxR; r++, i++) {
|
for (int r = minR, i = 0; r <= maxR; r++, i++) {
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ public class Main {
|
|||||||
section("Words");
|
section("Words");
|
||||||
printWordsTable(exported.words());
|
printWordsTable(exported.words());
|
||||||
|
|
||||||
section("Gridv2");
|
section("Grid");
|
||||||
for (var row : exported.grid()) System.out.println(" " + row);
|
for (var row : exported.grid()) System.out.println(" " + row);
|
||||||
|
|
||||||
var theme = "algemeen";
|
var theme = "algemeen";
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package puzzle;
|
|||||||
|
|
||||||
import module java.base;
|
import module java.base;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
import precomp.Neighbors9x8;
|
import precomp.Neighbors9x8;
|
||||||
import precomp.Neighbors9x8.rci;
|
import precomp.Neighbors9x8.rci;
|
||||||
@@ -15,11 +17,11 @@ public final class Masker {
|
|||||||
private final Rng rng;
|
private final Rng rng;
|
||||||
private final int[] stack;
|
private final int[] stack;
|
||||||
private final Clues cache;
|
private final Clues cache;
|
||||||
private final int[] activeCIdx = new int[SwedishGenerator.SIZE];
|
private final int[] activeCIdx = new int[Neighbors9x8.SIZE];
|
||||||
private final long[] activeSLo = new long[SwedishGenerator.SIZE];
|
private final long[] activeSLo = new long[Neighbors9x8.SIZE];
|
||||||
private final long[] activeSHi = new long[SwedishGenerator.SIZE];
|
private final long[] activeSHi = new long[Neighbors9x8.SIZE];
|
||||||
private final long[] adjLo = new long[SwedishGenerator.SIZE];
|
private final long[] adjLo = new long[Neighbors9x8.SIZE];
|
||||||
private final long[] adjHi = new long[SwedishGenerator.SIZE];
|
private final long[] adjHi = new long[Neighbors9x8.SIZE];
|
||||||
private final int[] rCount = new int[8];
|
private final int[] rCount = new int[8];
|
||||||
private final int[] cCount = new int[9];
|
private final int[] cCount = new int[9];
|
||||||
private static final long[] NBR_LO = Neighbors9x8.NBR_LO;
|
private static final long[] NBR_LO = Neighbors9x8.NBR_LO;
|
||||||
@@ -133,20 +135,20 @@ public final class Masker {
|
|||||||
else return (Long.bitCount(rayLo) + Long.bitCount(rayHi) >= SwedishGenerator.MIN_LEN);
|
else return (Long.bitCount(rayLo) + Long.bitCount(rayHi) >= SwedishGenerator.MIN_LEN);
|
||||||
}
|
}
|
||||||
private static boolean validSlot(long lo, long hi, int key) {
|
private static boolean validSlot(long lo, long hi, int key) {
|
||||||
var rayLo = PATH_LO[key];
|
var rayLo = PATH_LO[key];
|
||||||
var rayHi = PATH_HI[key];
|
var rayHi = PATH_HI[key];
|
||||||
var hitsLo = rayLo & lo;
|
var hitsLo = rayLo & lo;
|
||||||
var hitsHi = rayHi & hi;
|
var hitsHi = rayHi & hi;
|
||||||
|
|
||||||
if (hitsLo != X) return (Long.bitCount(rayLo & ((1L << numberOfTrailingZeros(hitsLo)) - 1)) >= SwedishGenerator.MIN_LEN);
|
if (hitsLo != X) return (Long.bitCount(rayLo & ((1L << numberOfTrailingZeros(hitsLo)) - 1)) >= SwedishGenerator.MIN_LEN);
|
||||||
else if (hitsHi != X) return (Long.bitCount(rayLo) + Long.bitCount(rayHi & ((1L << numberOfTrailingZeros(hitsHi)) - 1)) >= SwedishGenerator.MIN_LEN);
|
else if (hitsHi != X) return (Long.bitCount(rayLo) + Long.bitCount(rayHi & ((1L << numberOfTrailingZeros(hitsHi)) - 1)) >= SwedishGenerator.MIN_LEN);
|
||||||
else return (Long.bitCount(rayLo) + Long.bitCount(rayHi) >= SwedishGenerator.MIN_LEN);
|
else return (Long.bitCount(rayLo) + Long.bitCount(rayHi) >= SwedishGenerator.MIN_LEN);
|
||||||
}
|
}
|
||||||
private static void processSlot(Clues c, SlotVisitor visitor, int key) {
|
private static void processSlot(Clues c, SlotVisitor visitor, int key) {
|
||||||
var rayLo = PATH_LO[key];
|
var rayLo = PATH_LO[key];
|
||||||
var rayHi = PATH_HI[key];
|
var rayHi = PATH_HI[key];
|
||||||
var hitsLo = rayLo & c.lo;
|
var hitsLo = rayLo & c.lo;
|
||||||
var hitsHi = rayHi & c.hi;
|
var hitsHi = rayHi & c.hi;
|
||||||
|
|
||||||
if (hitsLo != X) {
|
if (hitsLo != X) {
|
||||||
var stop = 1L << numberOfTrailingZeros(hitsLo);
|
var stop = 1L << numberOfTrailingZeros(hitsLo);
|
||||||
@@ -159,9 +161,9 @@ public final class Masker {
|
|||||||
if (Long.bitCount(rayLo) + Long.bitCount(rayHi) >= MIN_LEN)
|
if (Long.bitCount(rayLo) + Long.bitCount(rayHi) >= MIN_LEN)
|
||||||
visitor.visit(key, rayLo, rayHi);
|
visitor.visit(key, rayLo, rayHi);
|
||||||
}
|
}
|
||||||
public static Slot[] extractSlots(Clues grid, DictEntry[] index) {
|
public static Slot[] extractSlots(Clues c, DictEntry[] index) {
|
||||||
var slots = new ArrayList<Slot>(grid.clueCount());
|
var slots = new ArrayList<Slot>(c.clueCount());
|
||||||
grid.forEachSlot((key, lo, hi) -> slots.add(Slot.from(key, lo, hi, index[Slot.length(lo, hi)])));
|
c.forEachSlot((key, lo, hi) -> slots.add(Slot.from(key, lo, hi, index[Slot.length(lo, hi)])));
|
||||||
return slots.toArray(Slot[]::new);
|
return slots.toArray(Slot[]::new);
|
||||||
}
|
}
|
||||||
public static Slotinfo[] slots(Clues mask, DictEntry[] index) {
|
public static Slotinfo[] slots(Clues mask, DictEntry[] index) {
|
||||||
@@ -193,19 +195,19 @@ public final class Masker {
|
|||||||
|
|
||||||
public long maskFitness(final Clues grid, int clueSize) {
|
public long maskFitness(final Clues grid, int clueSize) {
|
||||||
|
|
||||||
long cHLo = 0L, cHHi = 0L, cVLo = 0L, cVHi = 0L;
|
long cHLo = 0L, cHHi = 0L, cVLo = 0L, cVHi = 0L;
|
||||||
long cHLo2 = 0L, cHHi2 = 0L, cVLo2 = 0L, cVHi2 = 0L;
|
long cHLo2 = 0L, cHHi2 = 0L, cVLo2 = 0L, cVHi2 = 0L;
|
||||||
long lo_cl = grid.lo, hi_cl = grid.hi;
|
long lo_cl = grid.lo, hi_cl = grid.hi;
|
||||||
var penalty = (((long) Math.abs(grid.clueCount() - clueSize)) * 16000L);
|
var penalty = (((long) Math.abs(grid.clueCount() - clueSize)) * 16000L);
|
||||||
var hasSlots = false;
|
var hasSlots = false;
|
||||||
|
|
||||||
var numClues = 0;
|
var numClues = 0;
|
||||||
for (var bits = lo_cl; bits != X; bits &= bits - 1) {
|
for (var bits = lo_cl; bits != X; bits &= bits - 1) {
|
||||||
var lsb = bits & -bits;
|
var lsb = bits & -bits;
|
||||||
var clueIdx = numberOfTrailingZeros(lsb);
|
var clueIdx = numberOfTrailingZeros(lsb);
|
||||||
int dir = grid.getDir(clueIdx);
|
int dir = grid.getDir(clueIdx);
|
||||||
var key = Slot.packSlotKey(clueIdx, dir);
|
var key = Slot.packSlotKey(clueIdx, dir);
|
||||||
long rLo = PATH_LO[key], rHi = PATH_HI[key];
|
long rLo = PATH_LO[key], rHi = PATH_HI[key];
|
||||||
long hLo = rLo & lo_cl, hHi = rHi & hi_cl;
|
long hLo = rLo & lo_cl, hHi = rHi & hi_cl;
|
||||||
if (Slotinfo.increasing(key)) {
|
if (Slotinfo.increasing(key)) {
|
||||||
if (hLo != X) {
|
if (hLo != X) {
|
||||||
@@ -245,11 +247,11 @@ public final class Masker {
|
|||||||
} else penalty += 25000;
|
} else penalty += 25000;
|
||||||
}
|
}
|
||||||
for (var bits = hi_cl; bits != X; bits &= bits - 1) {
|
for (var bits = hi_cl; bits != X; bits &= bits - 1) {
|
||||||
var lsb = bits & -bits;
|
var lsb = bits & -bits;
|
||||||
var clueIdx = numberOfTrailingZeros(lsb);
|
var clueIdx = numberOfTrailingZeros(lsb);
|
||||||
int dir = grid.getDir(64 | clueIdx);
|
int dir = grid.getDir(64 | clueIdx);
|
||||||
var key = Slot.packSlotKey(64 | clueIdx, dir);
|
var key = Slot.packSlotKey(64 | clueIdx, dir);
|
||||||
long rLo = PATH_LO[key], rHi = PATH_HI[key];
|
long rLo = PATH_LO[key], rHi = PATH_HI[key];
|
||||||
long hLo = rLo & lo_cl, hHi = rHi & hi_cl;
|
long hLo = rLo & lo_cl, hHi = rHi & hi_cl;
|
||||||
if (Slotinfo.increasing(key)) {
|
if (Slotinfo.increasing(key)) {
|
||||||
if (hLo != X) {
|
if (hLo != X) {
|
||||||
@@ -588,9 +590,9 @@ public final class Masker {
|
|||||||
var childCount = 0;
|
var childCount = 0;
|
||||||
for (var k = 0; k < offspring; k++) {
|
for (var k = 0; k < offspring; k++) {
|
||||||
if (Thread.currentThread().isInterrupted()) break;
|
if (Thread.currentThread().isInterrupted()) break;
|
||||||
var p1 = rng.rand(pop);
|
var p1 = rng.rand(pop);
|
||||||
var p2 = rng.rand(pop);
|
var p2 = rng.rand(pop);
|
||||||
var child = crossover(p1.grid, p2.grid);
|
var child = crossover(p1.grid, p2.grid);
|
||||||
children[k] = new GridAndFit(hillclimb(child, clueSize, 70));
|
children[k] = new GridAndFit(hillclimb(child, clueSize, 70));
|
||||||
childCount++;
|
childCount++;
|
||||||
}
|
}
|
||||||
@@ -641,11 +643,14 @@ public final class Masker {
|
|||||||
}
|
}
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
@FunctionalInterface public interface SlotVisitor { void visit(int key, long lo, long hi); }
|
@FunctionalInterface public interface SlotVisitor { void visit(int key, long lo, long hi); }
|
||||||
|
sealed interface BitPop permits Clues { long hi(); long lo(); }
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public static class Clues {
|
@Accessors(fluent = true)
|
||||||
|
public static final class Clues
|
||||||
|
implements BitPop {
|
||||||
|
|
||||||
long lo, hi, vlo, vhi, rlo, rhi, xlo, xhi;
|
@Getter long lo, hi, vlo, vhi, rlo, rhi, xlo, xhi;
|
||||||
public static Clues createEmpty() { return new Clues(0, 0, 0, 0, 0, 0, 0, 0); }
|
public static Clues createEmpty() { return new Clues(0, 0, 0, 0, 0, 0, 0, 0); }
|
||||||
|
|
||||||
public boolean hasRoomForClue(int key) {
|
public boolean hasRoomForClue(int key) {
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ public record SwedishGenerator() {
|
|||||||
public static final long MASK_HI = Neighbors9x8.MASK_HI;//(1L << (SIZE - 64)) - 1;
|
public static final long MASK_HI = Neighbors9x8.MASK_HI;//(1L << (SIZE - 64)) - 1;
|
||||||
public static final int MAX_WORD_LENGTH = Config.PUZZLE_ROWS;
|
public static final int MAX_WORD_LENGTH = Config.PUZZLE_ROWS;
|
||||||
public static final int MAX_WORD_LENGTH_PLUS_ONE = MAX_WORD_LENGTH + 1;
|
public static final int MAX_WORD_LENGTH_PLUS_ONE = MAX_WORD_LENGTH + 1;
|
||||||
public static final int MIN_LEN = 2;//Neighbors9x8.MIN_LEN;//Config.MIN_LEN;
|
public static final int MIN_LEN = Neighbors9x8.MIN_LEN;//Config.MIN_LEN;
|
||||||
public static final int MAX_TRIES_PER_SLOT = 500;//Config.MAX_TRIES_PER_SLOT;
|
public static final int MAX_TRIES_PER_SLOT = 500;//Config.MAX_TRIES_PER_SLOT;
|
||||||
public static final int STACK_SIZE = 128;
|
public static final int STACK_SIZE = 128;
|
||||||
public static final long RANGE_0_SIZE = Neighbors9x8.RANGE_0_SIZE;// (long) SIZE_MIN_1 - 0L + 1L
|
public static final long RANGE_0_SIZE = Neighbors9x8.RANGE_0_SIZE;// (long) SIZE_MIN_1 - 0L + 1L
|
||||||
@@ -117,7 +117,7 @@ public record SwedishGenerator() {
|
|||||||
static int unpackIndex(long w) { return (int) (w >>> 40); }
|
static int unpackIndex(long w) { return (int) (w >>> 40); }
|
||||||
static int unpackShardIndex(long w) { return (int) (w >>> 43); }
|
static int unpackShardIndex(long w) { return (int) (w >>> 43); }
|
||||||
static int unpackSize(long w) { return (int) (w >>> 40) & 7; }
|
static int unpackSize(long w) { return (int) (w >>> 40) & 7; }
|
||||||
static int unpackLetters(long w) { return (int) (w & LETTER_MASK); }
|
static int unpackLetters(long w) { return (int) (w & LETTER_MASK); }
|
||||||
static long pack43(long w) {
|
static long pack43(long w) {
|
||||||
return w & INDEX_MASK;
|
return w & INDEX_MASK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,17 +43,16 @@ public class MainTest {
|
|||||||
}};
|
}};
|
||||||
@Test
|
@Test
|
||||||
void testExtractSlots() {
|
void testExtractSlots() {
|
||||||
var clues = Clued.of(r0c0d1);
|
var clues = Clued.of(r0c0d1);
|
||||||
val key = r0c0d1.slotKey;
|
var grid = new Gridded(clues);
|
||||||
var grid = new Gridded(clues);
|
val g = grid.grid().g;
|
||||||
val g = grid.grid().g;
|
GridBuilder.placeWord(grid.grid(), g, r0c0d1.slotKey, (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, DictData.DICT.index());
|
var slots = clues.slots();
|
||||||
assertEquals(1, slots.length);
|
assertEquals(1, slots.length);
|
||||||
var s = slots[0];
|
var s = slots[0];
|
||||||
assertEquals(8, Masker.Slot.length(s.lo(), s.hi()));
|
assertEquals(8, Masker.Slot.length(s.lo(), s.hi()));
|
||||||
var cells = Gridded.cellWalk((byte) s.key(), s.lo(), s.hi()).mapToObj(c-> Masker.IT[c]).toArray(rci[]::new);
|
var cells = Gridded.cellWalk((byte) s.key(), s.lo(), s.hi()).mapToObj(c -> Masker.IT[c]).toArray(rci[]::new);
|
||||||
assertEquals(0, cells[0].r());
|
assertEquals(0, cells[0].r());
|
||||||
assertEquals(1, cells[0].c());
|
assertEquals(1, cells[0].c());
|
||||||
assertEquals(0, cells[1].r());
|
assertEquals(0, cells[1].r());
|
||||||
@@ -71,9 +70,8 @@ public class MainTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testForEachSlot() {
|
void testForEachSlot() {
|
||||||
var clues = Clued.of(r0c0d1);
|
|
||||||
var count = new AtomicInteger(0);
|
var count = new AtomicInteger(0);
|
||||||
clues.forEachSlot((key, lo, hi) -> {
|
Clued.of(r0c0d1).forEachSlot((key, lo, hi) -> {
|
||||||
count.incrementAndGet();
|
count.incrementAndGet();
|
||||||
assertEquals(8, Long.bitCount(lo) + Long.bitCount(hi));
|
assertEquals(8, Long.bitCount(lo) + Long.bitCount(hi));
|
||||||
assertEquals(0, Masker.IT[Long.numberOfTrailingZeros(lo)].r());
|
assertEquals(0, Masker.IT[Long.numberOfTrailingZeros(lo)].r());
|
||||||
@@ -92,13 +90,12 @@ public class MainTest {
|
|||||||
}
|
}
|
||||||
@Test
|
@Test
|
||||||
public void testGridBasics() {
|
public void testGridBasics() {
|
||||||
var clues = new Clued(Clued.of(r2c1d2));
|
var clues = Clued.of(r2c1d2);
|
||||||
val key = r2c1d2.slotKey;
|
var grid = new Gridded(clues);
|
||||||
var grid = new Gridded(clues.c());
|
|
||||||
|
|
||||||
// Test set/get
|
// Test set/get
|
||||||
GridBuilder.placeWord(grid.grid(), grid.grid().g, key, (1L << OFF_1_1) | (1L << OFF_0_1), 0, AZ);
|
GridBuilder.placeWord(grid.grid(), grid.grid().g, r2c1d2.slotKey, (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.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));
|
||||||
var clueMap = clues.stream().collect(Collectors.toMap(ClueAt::index, ClueAt::clue));
|
var clueMap = clues.stream().collect(Collectors.toMap(ClueAt::index, ClueAt::clue));
|
||||||
@@ -126,7 +123,7 @@ public class MainTest {
|
|||||||
}
|
}
|
||||||
@Test
|
@Test
|
||||||
public void testCluesDeepCopy() {
|
public void testCluesDeepCopy() {
|
||||||
var clues = new Clued(Clued.of(r0c0d1, r0c1d2, r1c0d3, r1c1d0));
|
var clues = Clued.of(r0c0d1, r0c1d2, r1c0d3, r1c1d0);
|
||||||
|
|
||||||
var copy = clues.deepCopyGrid();
|
var copy = clues.deepCopyGrid();
|
||||||
var clueMap = clues.stream().collect(Collectors.toMap(ClueAt::index, ClueAt::clue));
|
var clueMap = clues.stream().collect(Collectors.toMap(ClueAt::index, ClueAt::clue));
|
||||||
@@ -139,12 +136,10 @@ public class MainTest {
|
|||||||
}
|
}
|
||||||
@Test
|
@Test
|
||||||
public void testMini() {
|
public void testMini() {
|
||||||
var clues = Clued.of(r1c1d3);
|
Assertions.assertTrue(Clued.of(r1c1d3).isClueLo(OFF_1_1));
|
||||||
Assertions.assertTrue(clues.isClueLo(OFF_1_1));
|
|
||||||
}
|
}
|
||||||
@Test
|
@Test
|
||||||
void testFiller2() {
|
void testFiller2() {
|
||||||
val rng = new Rng(-343913721);
|
|
||||||
val mask = Clued.parse(
|
val mask = Clued.parse(
|
||||||
"1 000000\n" +
|
"1 000000\n" +
|
||||||
"1 \n" +
|
"1 \n" +
|
||||||
@@ -157,7 +152,7 @@ public class MainTest {
|
|||||||
Assertions.assertEquals(20, mask.clueCount());
|
Assertions.assertEquals(20, mask.clueCount());
|
||||||
val map = mask.stream().collect(Collectors.toMap(ClueAt::index, ClueAt::clue));
|
val map = mask.stream().collect(Collectors.toMap(ClueAt::index, ClueAt::clue));
|
||||||
Assertions.assertEquals(20, map.size());
|
Assertions.assertEquals(20, map.size());
|
||||||
var slots = Masker.slots(mask.c(), DictData.DICT.index());
|
var slots = mask.slots();
|
||||||
// var filled = fillMask(rng, slotInfo, grid, false);
|
// var filled = fillMask(rng, slotInfo, grid, false);
|
||||||
// val res = new PuzzleResult(new Clued(mask), new Gridded(grid), slotInfo, filled).exportFormatFromFilled(0, new Rewards(0, 0, 0));
|
// val res = new PuzzleResult(new Clued(mask), new Gridded(grid), slotInfo, filled).exportFormatFromFilled(0, new Rewards(0, 0, 0));
|
||||||
}
|
}
|
||||||
@@ -173,7 +168,7 @@ public class MainTest {
|
|||||||
" 1 \n" +
|
" 1 \n" +
|
||||||
" 1 2\n" +
|
" 1 2\n" +
|
||||||
"21 22 3");
|
"21 22 3");
|
||||||
var slotInfo = Masker.slots(mask.c(), DictData.DICT.index());
|
var slotInfo = mask.slots();
|
||||||
var grid = Slotinfo.grid(slotInfo);
|
var grid = Slotinfo.grid(slotInfo);
|
||||||
var filled = fillMask(rng, slotInfo, grid);
|
var filled = fillMask(rng, slotInfo, grid);
|
||||||
Assertions.assertTrue(filled.ok(), "Puzzle generation failed (not ok)");
|
Assertions.assertTrue(filled.ok(), "Puzzle generation failed (not ok)");
|
||||||
|
|||||||
@@ -79,15 +79,15 @@ public class MarkerTest {
|
|||||||
}
|
}
|
||||||
@Test
|
@Test
|
||||||
void testSimilarity() {
|
void testSimilarity() {
|
||||||
var a = Clued.of(r0c0d1, r2c1d0);
|
var a = Clued.of(r0c0d1, r2c1d0).c();
|
||||||
var b = Clued.of(r0c0d1, r2c1d0);
|
var b = Clued.of(r0c0d1, r2c1d0).c();
|
||||||
|
|
||||||
// Identity
|
// Identity
|
||||||
assertEquals(1.0, a.similarity(b), 0.001);
|
assertEquals(1.0, a.similarity(b), 0.001);
|
||||||
|
|
||||||
// Different direction
|
// Different direction
|
||||||
var c = Clued.of(r0c0d0, r2c1d0);
|
var c = Clued.of(r0c0d0, r2c1d0);
|
||||||
assertTrue(a.similarity(c) < 1.0);
|
assertTrue(a.similarity(c.c()) < 1.0);
|
||||||
|
|
||||||
// Completely different
|
// Completely different
|
||||||
var d = Clues.createEmpty();
|
var d = Clues.createEmpty();
|
||||||
@@ -102,10 +102,10 @@ public class MarkerTest {
|
|||||||
assertTrue(masker.isValid(Clues.createEmpty()));
|
assertTrue(masker.isValid(Clues.createEmpty()));
|
||||||
|
|
||||||
// Valid clue: Right from (0,0) in 9x8 grid. Length is 8.
|
// Valid clue: Right from (0,0) in 9x8 grid. Length is 8.
|
||||||
assertTrue(masker.isValid(Clued.of(r0c0d1)));
|
assertTrue(masker.isValid(Clued.of(r0c0d1).c()));
|
||||||
|
|
||||||
// Invalid clue: Right from (0,7) in 9x8 grid. Length is 1 (too short if MIN_LEN >= 2).
|
// Invalid clue: Right from (0,7) in 9x8 grid. Length is 1 (too short if MIN_LEN >= 2).
|
||||||
assertFalse(masker.isValid(Clued.of(r0c7d1)));
|
assertFalse(masker.isValid(Clued.of(r0c7d1).c()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -137,18 +137,18 @@ public class MarkerTest {
|
|||||||
// Clue 1: (0,0) Right. Slot cells: (0,1), (0,2), (0,3), (0,4), (0,5), (0,6), (0,7), (0,8)
|
// Clue 1: (0,0) Right. Slot cells: (0,1), (0,2), (0,3), (0,4), (0,5), (0,6), (0,7), (0,8)
|
||||||
// Clue 2: (1,2) Up. Slot cells: (0,2)
|
// Clue 2: (1,2) Up. Slot cells: (0,2)
|
||||||
// Intersection is exactly 1 cell (0,2). Valid.
|
// Intersection is exactly 1 cell (0,2). Valid.
|
||||||
assertTrue(masker.isValid(Clued.of(r0c0d1, r2c2d2)));
|
assertTrue(masker.isValid(Clued.of(r0c0d1, r2c2d2).c()));
|
||||||
|
|
||||||
// Clue 3: (1,1) Right. Slot cells: (1,2), (1,3), ...
|
// Clue 3: (1,1) Right. Slot cells: (1,2), (1,3), ...
|
||||||
// No intersection with Clue 1 or 2. Valid.
|
// No intersection with Clue 1 or 2. Valid.
|
||||||
assertTrue(masker.isValid(Clued.of(r0c0d1, r2c2d2, r1c1d1)));
|
assertTrue(masker.isValid(Clued.of(r0c0d1, r2c2d2, r1c1d1).c()));
|
||||||
|
|
||||||
// Now create a violation: two slots sharing 2 cells.
|
// Now create a violation: two slots sharing 2 cells.
|
||||||
// We can do this with Corner Down and another clue.
|
// We can do this with Corner Down and another clue.
|
||||||
// Clue A: (0,0) Corner Down. Starts at (0,1) goes down: (0,1), (1,1), (2,1), (3,1), ...
|
// Clue A: (0,0) Corner Down. Starts at (0,1) goes down: (0,1), (1,1), (2,1), (3,1), ...
|
||||||
// Clue B: (0,2) Corner Down Left. Starts at (0,1) goes down: (0,1), (1,1), (2,1), ...
|
// Clue B: (0,2) Corner Down Left. Starts at (0,1) goes down: (0,1), (1,1), (2,1), ...
|
||||||
// They share MANY cells starting from (0,1).
|
// They share MANY cells starting from (0,1).
|
||||||
assertFalse(masker.isValid(Clued.of(r0c0d4, r0c2d5)));
|
assertFalse(masker.isValid(Clued.of(r0c0d4, r0c2d5).c()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -256,7 +256,7 @@ public class MarkerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testCornerDownExtraction() {
|
void testCornerDownExtraction() {
|
||||||
var slots = Masker.slots(Clued.of(r0c0d4), DictData.DICT.index());
|
var slots = Masker.slots(Clued.of(r0c0d4).c(), DictData.DICT.index());
|
||||||
assertEquals(1, slots.length);
|
assertEquals(1, slots.length);
|
||||||
assertEquals(r0c0d4.d, Masker.Slot.dir(slots[0].key()));
|
assertEquals(r0c0d4.d, Masker.Slot.dir(slots[0].key()));
|
||||||
}
|
}
|
||||||
@@ -286,7 +286,7 @@ public class MarkerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testCornerDownLeftExtraction() {
|
void testCornerDownLeftExtraction() {
|
||||||
var slots = Masker.slots(Clued.of(r0c1d5), DictData.DICT.index());
|
var slots = Clued.of(r0c1d5).slots();
|
||||||
|
|
||||||
assertEquals(1, slots.length);
|
assertEquals(1, slots.length);
|
||||||
assertEquals(r0c1d5.d, Masker.Slot.dir(slots[0].key()));
|
assertEquals(r0c1d5.d, Masker.Slot.dir(slots[0].key()));
|
||||||
@@ -303,7 +303,7 @@ public class MarkerTest {
|
|||||||
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, 0, 0, new FillStats());
|
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(clues, grid, new Slotinfo[]{
|
||||||
new Slotinfo(key, lo, 0L, 0, new Assign(TEST), null, 0)
|
new Slotinfo(key, lo, 0L, 0, new Assign(TEST), null, 0)
|
||||||
}, fillResult);
|
}, fillResult);
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import module java.base;
|
|||||||
import lombok.val;
|
import lombok.val;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import precomp.Neighbors9x8.rci;
|
||||||
import puzzle.Export.Clued;
|
import puzzle.Export.Clued;
|
||||||
import puzzle.Export.Gridded;
|
import puzzle.Export.Gridded;
|
||||||
import puzzle.DictJavaGeneratorMulti.DictEntryDTO.IntListDTO;
|
import puzzle.DictJavaGeneratorMulti.DictEntryDTO.IntListDTO;
|
||||||
@@ -37,6 +38,9 @@ import static puzzle.SwedishGenerator.*;
|
|||||||
|
|
||||||
public class SwedishGeneratorTest {
|
public class SwedishGeneratorTest {
|
||||||
|
|
||||||
|
public static final long WORD_A = Lemma.from("A");
|
||||||
|
public static final long WORD_C = Lemma.from("C");
|
||||||
|
public static final long WORD_X = Lemma.from("X");
|
||||||
static Grid createEmpty() { return new Grid(new byte[SIZE], X, X); }
|
static Grid createEmpty() { return new Grid(new byte[SIZE], X, X); }
|
||||||
record Context(long[] bitset) {
|
record Context(long[] bitset) {
|
||||||
|
|
||||||
@@ -86,11 +90,9 @@ public class SwedishGeneratorTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testPatternForSlotAllLetters() {
|
void testPatternForSlotAllLetters() {
|
||||||
var key = r0c0d1.slotKey;
|
var grid = new Gridded(Clued.of(r0c0d1));
|
||||||
val clues = Clued.of(r0c0d1);
|
GridBuilder.placeWord(grid.grid(), grid.grid().g, r0c0d1.slotKey, (1L << OFF_0_1) | (1L << OFF_0_2) | (1L << OFF_0_3), 0L, ABC);
|
||||||
var grid = new Gridded(clues);
|
val map = grid.collect(Collectors.toMap(LetterAt::index, LetterAt::letter));
|
||||||
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));
|
|
||||||
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));
|
||||||
assertEquals(LETTER_C, map.get(OFF_0_3));
|
assertEquals(LETTER_C, map.get(OFF_0_3));
|
||||||
@@ -99,8 +101,8 @@ public class SwedishGeneratorTest {
|
|||||||
@Test
|
@Test
|
||||||
void testPatternForSlotMixed() {
|
void testPatternForSlotMixed() {
|
||||||
var grid = createEmpty();
|
var grid = createEmpty();
|
||||||
GridBuilder.placeWord(grid, grid.g, r0c0d1.slotKey, 1L << OFF_0_0, 0, Lemma.from("A"));
|
GridBuilder.placeWord(grid, grid.g, r0c0d1.slotKey, 1L << OFF_0_0, 0, WORD_A);
|
||||||
GridBuilder.placeWord(grid, grid.g, r0c0d1.slotKey, 1L << OFF_2_0, 0, Lemma.from("C"));
|
GridBuilder.placeWord(grid, grid.g, r0c0d1.slotKey, 1L << OFF_2_0, 0, WORD_C);
|
||||||
var key = Slot.packSlotKey(OFF_1_0, CLUE_RIGHT);
|
var key = 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);
|
||||||
@@ -118,7 +120,7 @@ public class SwedishGeneratorTest {
|
|||||||
void testPatternForSlotSingleLetter() {
|
void testPatternForSlotSingleLetter() {
|
||||||
var grid = createEmpty();
|
var grid = createEmpty();
|
||||||
//Slot.packSlotKey(0, CLUE_RIGHT)
|
//Slot.packSlotKey(0, CLUE_RIGHT)
|
||||||
GridBuilder.placeWord(grid, grid.g, r0c0d1.slotKey, 1L << OFF_0_0, 0, Lemma.from("A"));
|
GridBuilder.placeWord(grid, grid.g, r0c0d1.slotKey, 1L << OFF_0_0, 0, WORD_A);
|
||||||
var key = Slot.packSlotKey(1, CLUE_RIGHT);
|
var key = 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);
|
||||||
@@ -150,10 +152,9 @@ public class SwedishGeneratorTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testGrid() {
|
void testGrid() {
|
||||||
var empty = Clues.createEmpty();
|
var grid = new Gridded(Clues.createEmpty());
|
||||||
var grid = new Gridded(empty);
|
GridBuilder.placeWord(grid.grid(), grid.grid().g, r0c0d1.slotKey, 1L << OFF_0_0, 0, WORD_A);
|
||||||
GridBuilder.placeWord(grid.grid(), grid.grid().g, r0c0d1.slotKey, 1L << OFF_0_0, 0, Lemma.from("A"));
|
val arr = grid.collect(Collectors.toMap(LetterAt::index, LetterAt::letter));
|
||||||
val arr = grid.stream(empty).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));
|
||||||
}
|
}
|
||||||
@@ -213,13 +214,13 @@ public class SwedishGeneratorTest {
|
|||||||
assertEquals(OFF_2_3, Slot.clueIndex(key));
|
assertEquals(OFF_2_3, Slot.clueIndex(key));
|
||||||
assertEquals(CLUE_DOWN, Slot.dir(key));
|
assertEquals(CLUE_DOWN, Slot.dir(key));
|
||||||
assertFalse(Slot.horiz(key));
|
assertFalse(Slot.horiz(key));
|
||||||
var cells = Gridded.cellWalk((byte) key, lo, 0L).toArray();
|
var cells = Gridded.cellWalk((byte) key, lo, 0L).mapToObj(i -> Masker.IT[i]).toArray(rci[]::new);
|
||||||
assertEquals(2, Masker.IT[cells[0]].r());
|
assertEquals(2, cells[0].r());
|
||||||
assertEquals(3, Masker.IT[cells[1]].r());
|
assertEquals(3, cells[1].r());
|
||||||
assertEquals(4, Masker.IT[cells[2]].r());
|
assertEquals(4, cells[2].r());
|
||||||
assertEquals(5, Masker.IT[cells[0]].c());
|
assertEquals(5, cells[0].c());
|
||||||
assertEquals(5, Masker.IT[cells[1]].c());
|
assertEquals(5, cells[1].c());
|
||||||
assertEquals(5, Masker.IT[cells[2]].c());
|
assertEquals(5, cells[2].c());
|
||||||
|
|
||||||
assertTrue(Slot.horiz(CLUE_RIGHT)); // right
|
assertTrue(Slot.horiz(CLUE_RIGHT)); // right
|
||||||
assertFalse(Slot.horiz(CLUE_DOWN)); // down
|
assertFalse(Slot.horiz(CLUE_DOWN)); // down
|
||||||
@@ -251,9 +252,8 @@ public class SwedishGeneratorTest {
|
|||||||
@Test
|
@Test
|
||||||
void testForEachSlotAndExtractSlots() {
|
void testForEachSlotAndExtractSlots() {
|
||||||
// This should detect a slot starting at 0,1 with length 2 (0,1 and 0,2)
|
// This should detect a slot starting at 0,1 with length 2 (0,1 and 0,2)
|
||||||
var clues = Clued.of(r0c0d1);
|
|
||||||
var dict = DictJavaGeneratorMulti.Dicts.makeDict(WORDS2);
|
var dict = DictJavaGeneratorMulti.Dicts.makeDict(WORDS2);
|
||||||
var slots = Masker.extractSlots(clues, dict.index());
|
var slots = Masker.extractSlots(Clued.of(r0c0d1).c(), dict.index());
|
||||||
assertEquals(1, slots.length);
|
assertEquals(1, slots.length);
|
||||||
var s = slots[0];
|
var s = slots[0];
|
||||||
|
|
||||||
@@ -296,8 +296,7 @@ public class SwedishGeneratorTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testPlaceWord() {
|
void testPlaceWord() {
|
||||||
var empty = Clues.createEmpty();
|
var grid = new Gridded(Clues.createEmpty());
|
||||||
var grid = new Gridded(empty);
|
|
||||||
// Slot at OFF_0_0 length 3, horizontal (right)
|
// Slot at OFF_0_0 length 3, horizontal (right)
|
||||||
var key = Slot.packSlotKey(0, CLUE_RIGHT);
|
var key = Slot.packSlotKey(0, CLUE_RIGHT);
|
||||||
var lo = (1L << OFF_0_0) | (1L << OFF_0_1) | (1L << OFF_0_2);
|
var lo = (1L << OFF_0_0) | (1L << OFF_0_1) | (1L << OFF_0_2);
|
||||||
@@ -307,7 +306,7 @@ public class SwedishGeneratorTest {
|
|||||||
// 1. Successful placement in empty grid
|
// 1. Successful placement in empty grid
|
||||||
assertTrue(GridBuilder.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(empty).collect(Collectors.toMap(LetterAt::index, LetterAt::letter));
|
var map = grid.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));
|
||||||
assertEquals(LETTER_B, map.get(OFF_0_1));
|
assertEquals(LETTER_B, map.get(OFF_0_1));
|
||||||
@@ -318,7 +317,7 @@ public class SwedishGeneratorTest {
|
|||||||
// 3. Conflict: place "ABD" where "ABC" is
|
// 3. Conflict: place "ABD" where "ABC" is
|
||||||
assertFalse(GridBuilder.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.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));
|
||||||
assertEquals(LETTER_B, map.get(OFF_0_1));
|
assertEquals(LETTER_B, map.get(OFF_0_1));
|
||||||
@@ -326,17 +325,16 @@ public class SwedishGeneratorTest {
|
|||||||
|
|
||||||
// 4. Partial placement then conflict (rollback)
|
// 4. Partial placement then conflict (rollback)
|
||||||
grid = new Gridded(Clues.createEmpty());
|
grid = new Gridded(Clues.createEmpty());
|
||||||
GridBuilder.placeWord(grid.grid(), grid.grid().g, Slot.packSlotKey(0, CLUE_RIGHT), 1L << OFF_0_2, 0, Lemma.from("X")); // Conflict at the end
|
GridBuilder.placeWord(grid.grid(), grid.grid().g, Slot.packSlotKey(0, CLUE_RIGHT), 1L << OFF_0_2, 0, WORD_X); // Conflict at the end
|
||||||
assertFalse(GridBuilder.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().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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testBacktrackingHelpers() {
|
void testBacktrackingHelpers() {
|
||||||
var clues = Clues.createEmpty();
|
var grid = new Gridded(Clues.createEmpty());
|
||||||
var grid = new Gridded(clues);
|
|
||||||
// Slot at 0,1 length 2
|
// Slot at 0,1 length 2
|
||||||
var key = Slot.packSlotKey(0, CLUE_RIGHT);
|
var key = Slot.packSlotKey(0, CLUE_RIGHT);
|
||||||
var lo = (1L << OFF_0_1) | (1L << OFF_0_2);
|
var lo = (1L << OFF_0_1) | (1L << OFF_0_2);
|
||||||
@@ -346,14 +344,14 @@ public class SwedishGeneratorTest {
|
|||||||
var placed = GridBuilder.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(clues).collect(Collectors.toMap(LetterAt::index, LetterAt::letter));
|
var map = grid.collect(Collectors.toMap(LetterAt::index, LetterAt::letter));
|
||||||
assertEquals(2, map.size());
|
assertEquals(2, map.size());
|
||||||
assertEquals(LETTER_A, map.get(OFF_0_1));
|
assertEquals(LETTER_A, map.get(OFF_0_1));
|
||||||
assertEquals(LETTER_Z, map.get(OFF_0_2));
|
assertEquals(LETTER_Z, map.get(OFF_0_2));
|
||||||
|
|
||||||
grid.grid().hi = top;
|
grid.grid().hi = top;
|
||||||
grid.grid().lo = low;
|
grid.grid().lo = low;
|
||||||
map = grid.stream(Masker.Clues.createEmpty()).collect(Collectors.toMap(LetterAt::index, LetterAt::letter));
|
map = grid.collect(Collectors.toMap(LetterAt::index, LetterAt::letter));
|
||||||
assertEquals(0, map.size());
|
assertEquals(0, map.size());
|
||||||
assertFalse(map.containsKey(OFF_0_1));
|
assertFalse(map.containsKey(OFF_0_1));
|
||||||
assertFalse(map.containsKey(OFF_0_2));
|
assertFalse(map.containsKey(OFF_0_2));
|
||||||
|
|||||||
Reference in New Issue
Block a user