introduce bitloops
This commit is contained in:
@@ -10,8 +10,8 @@ import puzzle.Masker.Clues;
|
|||||||
import puzzle.SwedishGenerator.FillResult;
|
import puzzle.SwedishGenerator.FillResult;
|
||||||
import puzzle.SwedishGenerator.Grid;
|
import puzzle.SwedishGenerator.Grid;
|
||||||
import puzzle.SwedishGenerator.Slotinfo;
|
import puzzle.SwedishGenerator.Slotinfo;
|
||||||
import static puzzle.Export.Clue.DOWN;
|
import static puzzle.Export.Clue.DOWN0;
|
||||||
import static puzzle.Export.Clue.RIGHT;
|
import static puzzle.Export.Clue.RIGHT1;
|
||||||
import static puzzle.Masker.Clues.createEmpty;
|
import static puzzle.Masker.Clues.createEmpty;
|
||||||
import static puzzle.SwedishGenerator.R;
|
import static puzzle.SwedishGenerator.R;
|
||||||
import static puzzle.SwedishGenerator.Lemma;
|
import static puzzle.SwedishGenerator.Lemma;
|
||||||
@@ -45,14 +45,16 @@ public record Export() {
|
|||||||
static int INDEX(int r, int cols, int c) { return r * cols + c; }
|
static int INDEX(int r, int cols, int c) { return r * cols + c; }
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
enum Clue {
|
enum Clue {
|
||||||
DOWN(CLUE_DOWN, 'B', 'b'),
|
DOWN0(CLUE_DOWN, 'B', 'b'),
|
||||||
RIGHT(CLUE_RIGHT, 'A', 'a'),
|
RIGHT1(CLUE_RIGHT, 'A', 'a'),
|
||||||
UP(CLUE_UP, 'C', 'c'),
|
UP2(CLUE_UP, 'C', 'c'),
|
||||||
LEFT(CLUE_LEFT, 'D', 'd'),
|
LEFT3(CLUE_LEFT, 'D', 'd'),
|
||||||
|
LEFT_TOP4(CLUE_LEFT_TOP, 'E', 'e'),
|
||||||
|
RIGHT_TOP5(CLUE_RIGHT_TOP, 'F', 'f'),
|
||||||
NONE(CLUE_LEFT, '?', '?');
|
NONE(CLUE_LEFT, '?', '?');
|
||||||
final byte dir;
|
final byte dir;
|
||||||
final char slotChar, clueChar;
|
final char slotChar, clueChar;
|
||||||
private static final Clue[] CLUES = new Clue[]{ DOWN, RIGHT, UP, LEFT, NONE, NONE, NONE, NONE, NONE };
|
private static final Clue[] CLUES = new Clue[]{ DOWN0, RIGHT1, UP2, LEFT3, LEFT_TOP4, RIGHT_TOP5, NONE, NONE, NONE };
|
||||||
public static Clue from(int dir) { return CLUES[dir]; }
|
public static Clue from(int dir) { return CLUES[dir]; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,8 +98,8 @@ public record Export() {
|
|||||||
}
|
}
|
||||||
public Stream<ClueAt> stream() {
|
public Stream<ClueAt> stream() {
|
||||||
val stream = Stream.<ClueAt>builder();
|
val stream = Stream.<ClueAt>builder();
|
||||||
for (var l = c.lo & ~c.xlo & ~c.rlo & c.vlo; l != X; l &= l - 1) stream.accept(new ClueAt(Long.numberOfTrailingZeros(l), RIGHT.dir));
|
for (var l = c.lo & ~c.xlo & ~c.rlo & c.vlo; l != X; l &= l - 1) stream.accept(new ClueAt(Long.numberOfTrailingZeros(l), RIGHT1.dir));
|
||||||
for (var l = c.lo & ~c.xlo & ~c.rlo & ~c.vlo; l != X; l &= l - 1) stream.accept(new ClueAt(Long.numberOfTrailingZeros(l), DOWN.dir));
|
for (var l = c.lo & ~c.xlo & ~c.rlo & ~c.vlo; l != X; l &= l - 1) stream.accept(new ClueAt(Long.numberOfTrailingZeros(l), DOWN0.dir));
|
||||||
for (var l = c.lo & ~c.xlo & c.rlo & ~c.vlo; l != X; l &= l - 1) stream.accept(new ClueAt(Long.numberOfTrailingZeros(l), CLUE_UP));
|
for (var l = c.lo & ~c.xlo & c.rlo & ~c.vlo; l != X; l &= l - 1) stream.accept(new ClueAt(Long.numberOfTrailingZeros(l), CLUE_UP));
|
||||||
for (var l = c.lo & ~c.xlo & c.rlo & c.vlo; l != X; l &= l - 1) stream.accept(new ClueAt(Long.numberOfTrailingZeros(l), CLUE_LEFT));
|
for (var l = c.lo & ~c.xlo & c.rlo & c.vlo; l != X; l &= l - 1) stream.accept(new ClueAt(Long.numberOfTrailingZeros(l), CLUE_LEFT));
|
||||||
for (var l = c.lo & c.xlo & ~c.rlo & ~c.vlo; l != X; l &= l - 1) stream.accept(new ClueAt(Long.numberOfTrailingZeros(l), CLUE_LEFT_TOP));
|
for (var l = c.lo & c.xlo & ~c.rlo & ~c.vlo; l != X; l &= l - 1) stream.accept(new ClueAt(Long.numberOfTrailingZeros(l), CLUE_LEFT_TOP));
|
||||||
|
|||||||
@@ -35,24 +35,24 @@ public final class Masker {
|
|||||||
return findOffendingClue(c) == -1;
|
return findOffendingClue(c) == -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int findOffendingClue(Clues grid) {
|
public int findOffendingClue(Clues c) {
|
||||||
if (((grid.xlo & grid.rlo) & grid.lo) != X) return numberOfTrailingZeros((grid.xlo & grid.rlo) & grid.lo);
|
if (((c.xlo & c.rlo) & c.lo) != X) return numberOfTrailingZeros((c.xlo & c.rlo) & c.lo);
|
||||||
if (((grid.xhi & grid.rhi) & grid.hi) != X) return 64 | numberOfTrailingZeros((grid.xhi & grid.rhi) & grid.hi);
|
if (((c.xhi & c.rhi) & c.hi) != X) return 64 | numberOfTrailingZeros((c.xhi & c.rhi) & c.hi);
|
||||||
|
|
||||||
var num = 0;
|
var num = 0;
|
||||||
for (var bits = grid.lo; bits != X; bits &= bits - 1) activeCIdx[num++] = numberOfTrailingZeros(bits);
|
for (var bits = c.lo; bits != X; bits &= bits - 1) activeCIdx[num++] = numberOfTrailingZeros(bits);
|
||||||
for (var bits = grid.hi; bits != X; bits &= bits - 1) activeCIdx[num++] = 64 | numberOfTrailingZeros(bits);
|
for (var bits = c.hi; bits != X; bits &= bits - 1) activeCIdx[num++] = 64 | numberOfTrailingZeros(bits);
|
||||||
|
|
||||||
if (num == 0) return -1;
|
if (num == 0) return -1;
|
||||||
|
|
||||||
var start = rng.randint0_SIZE() % num;
|
var start = rng.randint0_SIZE() % num;
|
||||||
var n = 0;
|
var n = 0;
|
||||||
for (var i = 0; i < num; i++) {
|
for (var i = 0; i < num; i++) {
|
||||||
var idx = activeCIdx[(start + i) % num];
|
var idx = activeCIdx[(start + i) % num];
|
||||||
int dir = grid.getDir(idx);
|
int dir = c.getDir(idx);
|
||||||
var key = Slot.packSlotKey(idx, dir);
|
var key = Slot.packSlotKey(idx, dir);
|
||||||
long sLo = PATH_LO[key], sHi = PATH_HI[key];
|
long sLo = PATH_LO[key], sHi = PATH_HI[key];
|
||||||
long hLo = sLo & grid.lo, hHi = sHi & grid.hi;
|
long hLo = sLo & c.lo, hHi = sHi & c.hi;
|
||||||
if (Slotinfo.increasing(key)) {
|
if (Slotinfo.increasing(key)) {
|
||||||
if (hLo != X) {
|
if (hLo != X) {
|
||||||
sLo &= (1L << numberOfTrailingZeros(hLo)) - 1;
|
sLo &= (1L << numberOfTrailingZeros(hLo)) - 1;
|
||||||
@@ -121,26 +121,26 @@ 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);
|
||||||
}
|
}
|
||||||
private static boolean validSlotRev(long lo, long hi, int min, int key) {
|
private static boolean validSlotRev(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];
|
||||||
// only consider clue cells
|
// only consider clue cells
|
||||||
var hitsLo = rayLo & lo;
|
var hitsLo = rayLo & lo;
|
||||||
var hitsHi = rayHi & hi;
|
var hitsHi = rayHi & hi;
|
||||||
|
|
||||||
if (hitsHi != X) return (Long.bitCount(rayHi & -(1L << 63 - numberOfLeadingZeros(hitsHi) << 1)) >= min);
|
if (hitsHi != X) return (Long.bitCount(rayHi & -(1L << 63 - numberOfLeadingZeros(hitsHi) << 1)) >= SwedishGenerator.MIN_LEN);
|
||||||
else if (hitsLo != X) return (Long.bitCount(rayLo & -(1L << 63 - numberOfLeadingZeros(hitsLo) << 1)) + Long.bitCount(rayHi) >= min);
|
else if (hitsLo != X) return (Long.bitCount(rayLo & -(1L << 63 - numberOfLeadingZeros(hitsLo) << 1)) + Long.bitCount(rayHi) >= SwedishGenerator.MIN_LEN);
|
||||||
else return (Long.bitCount(rayLo) + Long.bitCount(rayHi) >= min);
|
else return (Long.bitCount(rayLo) + Long.bitCount(rayHi) >= SwedishGenerator.MIN_LEN);
|
||||||
}
|
}
|
||||||
private static boolean validSlot(long lo, long hi, int min, 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)) >= min);
|
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)) >= min);
|
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) >= min);
|
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];
|
||||||
@@ -198,10 +198,6 @@ public final class Masker {
|
|||||||
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;
|
||||||
/* if (!isValid(grid, 2)) {
|
|
||||||
throw new RuntimeException("Invalid grid configuration for mask fitness calculation");
|
|
||||||
//return 1_000_000_000L;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
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) {
|
||||||
@@ -653,8 +649,8 @@ public final class Masker {
|
|||||||
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) {
|
||||||
if (Slotinfo.increasing(key)) if (!validSlot(lo, hi, MIN_LEN, key)) return false;
|
if (Slotinfo.increasing(key)) if (!validSlot(lo, hi, key)) return false;
|
||||||
return validSlotRev(lo, hi, MIN_LEN, key);
|
return validSlotRev(lo, hi, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setClueLo(long mask, byte idx) {
|
public void setClueLo(long mask, byte idx) {
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package puzzle;
|
package puzzle;
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.experimental.FieldDefaults;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import puzzle.Export.Clue;
|
||||||
import puzzle.Masker.Clues;
|
import puzzle.Masker.Clues;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
@@ -8,17 +11,36 @@ import static precomp.Const9x8.OFF_0_0;
|
|||||||
import static precomp.Const9x8.OFF_0_1;
|
import static precomp.Const9x8.OFF_0_1;
|
||||||
import static precomp.Const9x8.OFF_1_0;
|
import static precomp.Const9x8.OFF_1_0;
|
||||||
import static precomp.Const9x8.OFF_1_1;
|
import static precomp.Const9x8.OFF_1_1;
|
||||||
|
import static puzzle.CornerClueTest.Cell.r0c1d5;
|
||||||
|
import static puzzle.CornerClueTest.Cell.r0c0d4;
|
||||||
|
|
||||||
public class CornerClueTest {
|
public class CornerClueTest {
|
||||||
|
|
||||||
|
enum Cell {
|
||||||
|
r0c0d4(Clue.LEFT_TOP4, OFF_0_0),
|
||||||
|
r0c1d5(Clue.RIGHT_TOP5, OFF_0_1);
|
||||||
|
final public byte d;
|
||||||
|
final public long mask;
|
||||||
|
final public int index;
|
||||||
|
Cell(Clue d, int off) {
|
||||||
|
this.d = d.dir;
|
||||||
|
this.mask = 1L << off;
|
||||||
|
this.index = off;
|
||||||
|
}
|
||||||
|
public Clues attach(Clues c) {
|
||||||
|
c.setClueLo(mask, d);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
public Clues attach() { return attach(Clues.createEmpty()); }
|
||||||
|
public int dir(Clues clues) { return clues.getDir(index); }
|
||||||
|
}
|
||||||
@Test
|
@Test
|
||||||
void testCornerDownSlot() {
|
void testCornerDownSlot() {
|
||||||
var clues = Clues.createEmpty();
|
|
||||||
// Clue op (0,0), type 4 (Corner Down)
|
|
||||||
var idx = OFF_0_0;
|
|
||||||
clues.setClueLo(1L << idx, (byte) 4);
|
|
||||||
|
|
||||||
assertEquals(4, clues.getDir(idx));
|
var clues = r0c0d4.attach();
|
||||||
|
// Clue op (0,0), type 4 (Corner Down)
|
||||||
|
|
||||||
|
assertEquals(Clue.LEFT_TOP4.dir, r0c0d4.dir(clues));
|
||||||
|
|
||||||
// Controleer of forEachSlot het slot vindt
|
// Controleer of forEachSlot het slot vindt
|
||||||
final var found = new boolean[]{ false };
|
final var found = new boolean[]{ false };
|
||||||
@@ -39,25 +61,16 @@ public class CornerClueTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testCornerDownExtraction() {
|
void testCornerDownExtraction() {
|
||||||
var clues = Clues.createEmpty();
|
var slots = Masker.slots(r0c0d4.attach(), DictData.DICT.index());
|
||||||
clues.setClueLo(1L << OFF_0_0, (byte) 4);
|
|
||||||
|
|
||||||
var dict = DictData.DICT.index();
|
|
||||||
var slots = Masker.slots(clues, dict);
|
|
||||||
|
|
||||||
assertEquals(1, slots.length);
|
assertEquals(1, slots.length);
|
||||||
assertEquals(4, Masker.Slot.dir(slots[0].key()));
|
assertEquals(4, Masker.Slot.dir(slots[0].key()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testCornerDownLeftSlot() {
|
void testCornerDownLeftSlot() {
|
||||||
var clues = Clues.createEmpty();
|
var clues = r0c1d5.attach();
|
||||||
// Clue op (0,1), type 5 (Corner Down Left)
|
|
||||||
// Should result in word starting at (0,0) going down.
|
|
||||||
var idx = OFF_0_1;
|
|
||||||
clues.setClueLo(1L << idx, (byte) 5);
|
|
||||||
|
|
||||||
assertEquals(5, clues.getDir(idx));
|
assertEquals(Clue.RIGHT_TOP5.dir, r0c1d5.dir(clues));
|
||||||
|
|
||||||
// Controleer of forEachSlot het slot vindt
|
// Controleer of forEachSlot het slot vindt
|
||||||
final var found = new boolean[]{ false };
|
final var found = new boolean[]{ false };
|
||||||
@@ -78,13 +91,9 @@ public class CornerClueTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testCornerDownLeftExtraction() {
|
void testCornerDownLeftExtraction() {
|
||||||
var clues = Clues.createEmpty();
|
var slots = Masker.slots(r0c1d5.attach(), DictData.DICT.index());
|
||||||
clues.setClueLo(1L << OFF_0_1, (byte) 5);
|
|
||||||
|
|
||||||
var dict = DictData.DICT.index();
|
|
||||||
var slots = Masker.slots(clues, dict);
|
|
||||||
|
|
||||||
assertEquals(1, slots.length);
|
assertEquals(1, slots.length);
|
||||||
assertEquals(5, Masker.Slot.dir(slots[0].key()));
|
assertEquals(Clue.RIGHT_TOP5.dir, Masker.Slot.dir(slots[0].key()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package puzzle;
|
|||||||
|
|
||||||
import module java.base;
|
import module java.base;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
import org.junit.jupiter.api.Assertions;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import puzzle.Export.Clued;
|
import puzzle.Export.Clued;
|
||||||
import puzzle.Export.Gridded;
|
import puzzle.Export.Gridded;
|
||||||
@@ -21,8 +20,8 @@ import static precomp.Const9x8.OFF_0_1;
|
|||||||
import static precomp.Const9x8.OFF_0_2;
|
import static precomp.Const9x8.OFF_0_2;
|
||||||
import static precomp.Const9x8.OFF_0_3;
|
import static precomp.Const9x8.OFF_0_3;
|
||||||
import static precomp.Const9x8.OFF_0_4;
|
import static precomp.Const9x8.OFF_0_4;
|
||||||
import static puzzle.Export.Clue.LEFT;
|
import static puzzle.Export.Clue.LEFT3;
|
||||||
import static puzzle.Export.Clue.RIGHT;
|
import static puzzle.Export.Clue.RIGHT1;
|
||||||
import static puzzle.SwedishGenerator.C;
|
import static puzzle.SwedishGenerator.C;
|
||||||
import static puzzle.Masker.Clues;
|
import static puzzle.Masker.Clues;
|
||||||
import static puzzle.SwedishGenerator.FillStats;
|
import static puzzle.SwedishGenerator.FillStats;
|
||||||
@@ -37,14 +36,14 @@ public class ExportFormatTest {
|
|||||||
void testExportFormatFromFilled() {
|
void testExportFormatFromFilled() {
|
||||||
val clues = Clues.createEmpty();
|
val clues = Clues.createEmpty();
|
||||||
// Place a RIGHT clue at (0,0)
|
// Place a RIGHT clue at (0,0)
|
||||||
clues.setClueLo(Idx.IDX_0_0.lo, RIGHT.dir);
|
clues.setClueLo(Idx.IDX_0_0.lo, RIGHT1.dir);
|
||||||
// This creates a slot starting at (0,1)
|
// This creates a slot starting at (0,1)
|
||||||
// Terminate the slot at (0,5) with another digit to avoid it extending to MAX_WORD_LENGTH
|
// Terminate the slot at (0,5) with another digit to avoid it extending to MAX_WORD_LENGTH
|
||||||
clues.setClueLo(Idx.IDX_0_5.lo, LEFT.dir);
|
clues.setClueLo(Idx.IDX_0_5.lo, LEFT3.dir);
|
||||||
var grid = new Gridded(clues);
|
var grid = new Gridded(clues);
|
||||||
|
|
||||||
// key = (cellIndex << 2) | (direction)
|
// key = (cellIndex << 2) | (direction)
|
||||||
var key = Slot.packSlotKey(0, RIGHT.dir);
|
var key = Slot.packSlotKey(0, RIGHT1.dir);
|
||||||
var lo = (1L << OFF_0_1) | (1L << OFF_0_2) | (1L << OFF_0_3) | (1L << OFF_0_4);
|
var lo = (1L << OFF_0_1) | (1L << OFF_0_2) | (1L << OFF_0_3) | (1L << OFF_0_4);
|
||||||
|
|
||||||
assertTrue(placeWord(grid.grid(), grid.grid().g, key, lo, 0L, TEST));
|
assertTrue(placeWord(grid.grid(), grid.grid().g, key, lo, 0L, TEST));
|
||||||
|
|||||||
@@ -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.ClueAt;
|
import puzzle.Export.ClueAt;
|
||||||
import puzzle.Export.Clued;
|
import puzzle.Export.Clued;
|
||||||
import puzzle.Export.Gridded;
|
import puzzle.Export.Gridded;
|
||||||
@@ -23,10 +24,10 @@ import static precomp.Const9x8.OFF_1_1;
|
|||||||
import static precomp.Const9x8.OFF_1_2;
|
import static precomp.Const9x8.OFF_1_2;
|
||||||
import static precomp.Const9x8.OFF_2_1;
|
import static precomp.Const9x8.OFF_2_1;
|
||||||
import static precomp.Const9x8.OFF_2_3;
|
import static precomp.Const9x8.OFF_2_3;
|
||||||
import static puzzle.Export.Clue.DOWN;
|
import static puzzle.Export.Clue.DOWN0;
|
||||||
import static puzzle.Export.Clue.LEFT;
|
import static puzzle.Export.Clue.LEFT3;
|
||||||
import static puzzle.Export.Clue.RIGHT;
|
import static puzzle.Export.Clue.RIGHT1;
|
||||||
import static puzzle.Export.Clue.UP;
|
import static puzzle.Export.Clue.UP2;
|
||||||
import static puzzle.SwedishGenerator.Lemma;
|
import static puzzle.SwedishGenerator.Lemma;
|
||||||
import static puzzle.SwedishGenerator.Slotinfo;
|
import static puzzle.SwedishGenerator.Slotinfo;
|
||||||
import static puzzle.SwedishGenerator.fillMask;
|
import static puzzle.SwedishGenerator.fillMask;
|
||||||
@@ -70,11 +71,11 @@ public class MainTest {
|
|||||||
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()).toArray();
|
var cells = Gridded.cellWalk((byte) s.key(), s.lo(), s.hi()).mapToObj(c-> Masker.IT[c]).toArray(rci[]::new);
|
||||||
assertEquals(0, Masker.IT[cells[0]].r());
|
assertEquals(0, cells[0].r());
|
||||||
assertEquals(1, Masker.IT[cells[0]].c());
|
assertEquals(1, cells[0].c());
|
||||||
assertEquals(0, Masker.IT[cells[1]].r());
|
assertEquals(0, cells[1].r());
|
||||||
assertEquals(2, Masker.IT[cells[1]].c());
|
assertEquals(2, cells[1].c());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -125,10 +126,10 @@ public class MainTest {
|
|||||||
Assertions.assertEquals(CLUE_UP, clueMap.get(OFF_2_1));
|
Assertions.assertEquals(CLUE_UP, clueMap.get(OFF_2_1));
|
||||||
|
|
||||||
// Test isLetterAt
|
// Test isLetterAt
|
||||||
Assertions.assertTrue(clues.notClue(OFF_0_0));
|
Assertions.assertFalse(clueMap.containsKey(OFF_0_0));
|
||||||
Assertions.assertTrue(clues.notClue(OFF_1_2));
|
Assertions.assertFalse(clueMap.containsKey(OFF_1_2));
|
||||||
Assertions.assertTrue(clues.notClue(OFF_2_3));
|
Assertions.assertFalse(clueMap.containsKey(OFF_2_3));
|
||||||
Assertions.assertFalse(clues.isClueLo(OFF_1_1));
|
Assertions.assertFalse(clueMap.containsKey(OFF_1_1));
|
||||||
|
|
||||||
// Test isDigitAt
|
// Test isDigitAt
|
||||||
Assertions.assertFalse(clues.isClueLo(OFF_0_0));
|
Assertions.assertFalse(clues.isClueLo(OFF_0_0));
|
||||||
@@ -146,19 +147,19 @@ public class MainTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testCluesDeepCopy() {
|
public void testCluesDeepCopy() {
|
||||||
var clues = new Clued(Masker.Clues.createEmpty());
|
var clues = new Clued(Masker.Clues.createEmpty());
|
||||||
clues.setClueLo(IDX_0_0.lo, RIGHT.dir);
|
clues.setClueLo(IDX_0_0.lo, RIGHT1.dir);
|
||||||
clues.setClueLo(IDX_0_1.lo, UP.dir);
|
clues.setClueLo(IDX_0_1.lo, UP2.dir);
|
||||||
clues.setClueLo(IDX_1_0.lo, LEFT.dir);
|
clues.setClueLo(IDX_1_0.lo, LEFT3.dir);
|
||||||
clues.setClueLo(IDX_1_1.lo, DOWN.dir);
|
clues.setClueLo(IDX_1_1.lo, DOWN0.dir);
|
||||||
|
|
||||||
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));
|
||||||
Assertions.assertEquals(CLUE_RIGHT, clueMap.get(OFF_0_0));
|
Assertions.assertEquals(CLUE_RIGHT, clueMap.get(OFF_0_0));
|
||||||
|
|
||||||
copy.setClueLo(IDX_0_0.lo, DOWN.dir);
|
copy.setClueLo(IDX_0_0.lo, DOWN0.dir);
|
||||||
var copied = copy.stream().collect(Collectors.toMap(ClueAt::index, ClueAt::clue));
|
var copied = copy.stream().collect(Collectors.toMap(ClueAt::index, ClueAt::clue));
|
||||||
Assertions.assertEquals(DOWN.dir, copied.get(OFF_0_0));
|
Assertions.assertEquals(DOWN0.dir, copied.get(OFF_0_0));
|
||||||
Assertions.assertEquals(RIGHT.dir, clueMap.get(OFF_0_0));
|
Assertions.assertEquals(RIGHT1.dir, clueMap.get(OFF_0_0));
|
||||||
}
|
}
|
||||||
@Test
|
@Test
|
||||||
public void testMini() {
|
public void testMini() {
|
||||||
|
|||||||
@@ -13,13 +13,12 @@ import puzzle.Masker.Slot;
|
|||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
import static precomp.Const9x8.*;
|
import static precomp.Const9x8.*;
|
||||||
|
import static precomp.Const9x8.Cell.r0c0d1;
|
||||||
import static puzzle.SwedishGenerator.*;
|
import static puzzle.SwedishGenerator.*;
|
||||||
import static puzzle.SwedishGeneratorTest.Idx.IDX_0_0;
|
import static puzzle.SwedishGeneratorTest.Idx.IDX_0_0;
|
||||||
|
|
||||||
public class SwedishGeneratorTest {
|
public class SwedishGeneratorTest {
|
||||||
|
|
||||||
public static final char C_DASH = '\0';
|
|
||||||
public static final byte DASH = (byte) C_DASH;
|
|
||||||
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) {
|
||||||
|
|
||||||
@@ -137,8 +136,8 @@ public class SwedishGeneratorTest {
|
|||||||
@Test
|
@Test
|
||||||
void testPatternForSlotMixed() {
|
void testPatternForSlotMixed() {
|
||||||
var grid = createEmpty();
|
var grid = createEmpty();
|
||||||
GridBuilder.placeWord(grid, grid.g, Slot.packSlotKey(0, CLUE_RIGHT), 1L << OFF_0_0, 0, Lemma.from("A"));
|
GridBuilder.placeWord(grid, grid.g, r0c0d1.slotKey, 1L << OFF_0_0, 0, Lemma.from("A"));
|
||||||
GridBuilder.placeWord(grid, grid.g, Slot.packSlotKey(0, CLUE_RIGHT), 1L << OFF_2_0, 0, Lemma.from("C"));
|
GridBuilder.placeWord(grid, grid.g, r0c0d1.slotKey, 1L << OFF_2_0, 0, Lemma.from("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);
|
||||||
@@ -155,7 +154,8 @@ public class SwedishGeneratorTest {
|
|||||||
@Test
|
@Test
|
||||||
void testPatternForSlotSingleLetter() {
|
void testPatternForSlotSingleLetter() {
|
||||||
var grid = createEmpty();
|
var grid = createEmpty();
|
||||||
GridBuilder.placeWord(grid, grid.g, Slot.packSlotKey(0, CLUE_RIGHT), 1L << OFF_0_0, 0, Lemma.from("A"));
|
//Slot.packSlotKey(0, CLUE_RIGHT)
|
||||||
|
GridBuilder.placeWord(grid, grid.g, r0c0d1.slotKey, 1L << OFF_0_0, 0, Lemma.from("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);
|
||||||
@@ -189,7 +189,7 @@ public class SwedishGeneratorTest {
|
|||||||
void testGrid() {
|
void testGrid() {
|
||||||
var empty = Clues.createEmpty();
|
var empty = Clues.createEmpty();
|
||||||
var grid = new Gridded(empty);
|
var grid = new Gridded(empty);
|
||||||
GridBuilder.placeWord(grid.grid(), grid.grid().g, Slot.packSlotKey(0, CLUE_RIGHT), 1L << OFF_0_0, 0, Lemma.from("A"));
|
GridBuilder.placeWord(grid.grid(), grid.grid().g, r0c0d1.slotKey, 1L << OFF_0_0, 0, Lemma.from("A"));
|
||||||
val arr = grid.stream(empty).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));
|
||||||
@@ -393,8 +393,8 @@ public class SwedishGeneratorTest {
|
|||||||
grid.grid().lo = low;
|
grid.grid().lo = low;
|
||||||
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(0, map.size());
|
assertEquals(0, map.size());
|
||||||
assertEquals(DASH, map.getOrDefault(OFF_0_1, DASH));
|
assertFalse(map.containsKey(OFF_0_1));
|
||||||
assertEquals(DASH, map.getOrDefault(OFF_0_2, DASH));
|
assertFalse(map.containsKey(OFF_0_2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user