introduce bitloops

This commit is contained in:
mike
2026-01-17 16:03:16 +01:00
parent 9bd85c81a3
commit bfa19ec585
18 changed files with 40847 additions and 41296 deletions

View File

@@ -8,6 +8,7 @@ import puzzle.Export.Dicts;
import puzzle.Export.Gridded;
import puzzle.Export.IntListDTO;
import puzzle.Export.LetterVisit.LetterAt;
import puzzle.Masker.Slot;
import java.nio.charset.StandardCharsets;
import java.util.stream.Collectors;
@@ -26,39 +27,39 @@ public class SwedishGeneratorTest {
public static Context get() { return CTX.get(); }
}
static final long TEST = Lemma.from(0, "TEST");
static final long TEST = Lemma.from("TEST");
static final long[] WORDS = new long[]{
Lemma.from(1, "AT"),
Lemma.from(2, "CAT"),
Lemma.from(3, "DOGS"),
Lemma.from(4, "APPLE"),
Lemma.from(5, "APPLY"),
Lemma.from(6, "BANAN"),
Lemma.from(7, "BANANA"),
Lemma.from(8, "BANANAS"),
Lemma.from(9, "BANANASS") // length 8
Lemma.from("AT"),
Lemma.from("CAT"),
Lemma.from("DOGS"),
Lemma.from("APPLE"),
Lemma.from("APPLY"),
Lemma.from("BANAN"),
Lemma.from("BANANA"),
Lemma.from("BANANAS"),
Lemma.from("BANANASS") // length 8
};
static final long l2a = Lemma.from(10, "IN");
static final long l4a = Lemma.from(11, "INER");
static final long l6a = Lemma.from(12, "INEREN");
static final long l7a = Lemma.from(13, "INERENA");
static final long l8a = Lemma.from(14, "INERENAE");
static final long l1 = Lemma.from(15, "APPLE");
static final long l2 = Lemma.from(16, "AXE");
static final long l2a = Lemma.from("IN");
static final long l4a = Lemma.from("INER");
static final long l6a = Lemma.from("INEREN");
static final long l7a = Lemma.from("INERENA");
static final long l8a = Lemma.from("INERENAE");
static final long l1 = Lemma.from("APPLE");
static final long l2 = Lemma.from("AXE");
static final long[] WORDS2 = new long[]{ Lemma.from(17, "IN"),
Lemma.from(18, "APPLE"),
Lemma.from(19, "APPLY"),
Lemma.from(20, "BANAN"),
Lemma.from(21, "INE"),
Lemma.from(22, "INER"),
Lemma.from(23, "INEREN"),
Lemma.from(24, "INERENA"),
Lemma.from(25, "INERENAE") };
static final long ABC = Lemma.from(26, "ABC");
static final long ABD = Lemma.from(27, "ABD");
static final long AZ = Lemma.from(28, "AZ");
static final long AB = Lemma.from(29, "AB");
static final long[] WORDS2 = new long[]{ Lemma.from("IN"),
Lemma.from("APPLE"),
Lemma.from("APPLY"),
Lemma.from("BANAN"),
Lemma.from("INE"),
Lemma.from("INER"),
Lemma.from("INEREN"),
Lemma.from("INERENA"),
Lemma.from("INERENAE") };
static final long ABC = Lemma.from("ABC");
static final long ABD = Lemma.from("ABD");
static final long AZ = Lemma.from("AZ");
static final long AB = Lemma.from("AB");
static final byte LETTER_A = ((byte) 'A') & 31;
static final byte LETTER_B = ((byte) 'B') & 31;
static final byte LETTER_C = ((byte) 'C') & 31;
@@ -139,7 +140,7 @@ public class SwedishGeneratorTest {
@Test
void testPatternForSlotAllLetters() {
var grid = new Gridded(createEmpty());
var key = Masker.Slot.packSlotKey(OFF_0_0, CLUE_RIGHT);
var key = Slot.packSlotKey(OFF_0_0, CLUE_RIGHT);
val clues = Masker.Clues.createEmpty();
clues.setClueLo(IDX_0_0.lo, CLUE_RIGHT);
GridBuilder.placeWord(grid.grid(), grid.grid().g, key, (1L << OFF_0_1) | (1L << OFF_0_2) | (1L << OFF_0_3), 0L, ABC);
@@ -152,9 +153,9 @@ public class SwedishGeneratorTest {
@Test
void testPatternForSlotMixed() {
var grid = createEmpty();
GridBuilder.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_2_0, 0, Lemma.from(0, "C"));
var key = Masker.Slot.packSlotKey(OFF_1_0, CLUE_RIGHT);
GridBuilder.placeWord(grid, grid.g, Slot.packSlotKey(0, CLUE_RIGHT), 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"));
var key = Slot.packSlotKey(OFF_1_0, CLUE_RIGHT);
var pattern = patternForSlot(grid.lo, grid.hi, grid.g, key, 7L, 0L);
assertEquals(14081L, pattern);
}
@@ -162,7 +163,7 @@ public class SwedishGeneratorTest {
@Test
void testPatternForSlotAllDashes() {
var grid = createEmpty();
var key = Masker.Slot.packSlotKey(1 << Masker.Slot.BIT_FOR_DIR, CLUE_RIGHT);
var key = Slot.packSlotKey(1 << Slot.BIT_FOR_DIR, CLUE_RIGHT);
var pattern = patternForSlot(grid.lo, grid.hi, grid.g, key, 7L, 0L);
assertEquals(0L, pattern);
}
@@ -170,8 +171,8 @@ public class SwedishGeneratorTest {
@Test
void testPatternForSlotSingleLetter() {
var grid = createEmpty();
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);
GridBuilder.placeWord(grid, grid.g, Slot.packSlotKey(0, CLUE_RIGHT), 1L << OFF_0_0, 0, Lemma.from("A"));
var key = Slot.packSlotKey(1, CLUE_RIGHT);
var pattern = patternForSlot(grid.lo, grid.hi, grid.g, key, 7L, 0L);
assertEquals(1L, pattern);
}
@@ -196,7 +197,7 @@ public class SwedishGeneratorTest {
@Test
void testGrid() {
var grid = new Gridded(createEmpty());
GridBuilder.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, Slot.packSlotKey(0, CLUE_RIGHT), 1L << OFF_0_0, 0, Lemma.from("A"));
val arr = grid.stream(Masker.Clues.createEmpty()).collect(Collectors.toMap(LetterAt::index, LetterAt::letter));
assertEquals(1, arr.size());
assertEquals(LETTER_A, arr.get(OFF_0_0));
@@ -232,11 +233,11 @@ public class SwedishGeneratorTest {
@Test
void testSlot() {
System.out.println("[DEBUG_LOG] Slot.BIT_FOR_DIR = " + Masker.Slot.BIT_FOR_DIR);
System.out.println("[DEBUG_LOG] Slot.BIT_FOR_DIR = " + Slot.BIT_FOR_DIR);
// key = (r << 8) | (c << 4) | d
var offset = OFF_2_3;
System.out.println("[DEBUG_LOG] Grid.offset(2, 3) = " + offset);
var key = Masker.Slot.packSlotKey(offset, CLUE_DOWN);
var key = Slot.packSlotKey(offset, CLUE_DOWN);
System.out.println("[DEBUG_LOG] key = " + key);
long lo = 0;
// pos 0: (2, 5)
@@ -246,10 +247,10 @@ public class SwedishGeneratorTest {
// pos 2: (4, 5)
lo |= 1L << OFF_4_5;
System.out.println("[DEBUG_LOG] s.dir() = " + Masker.Slot.dir(key));
assertEquals(OFF_2_3, Masker.Slot.clueIndex(key));
assertEquals(CLUE_DOWN, Masker.Slot.dir(key));
assertFalse(Masker.Slot.horiz(key));
System.out.println("[DEBUG_LOG] s.dir() = " + Slot.dir(key));
assertEquals(OFF_2_3, Slot.clueIndex(key));
assertEquals(CLUE_DOWN, Slot.dir(key));
assertFalse(Slot.horiz(key));
var cells = Gridded.walk((byte) key, lo, 0L).toArray();
assertEquals(2, SwedishGenerator.IT[cells[0]].r());
assertEquals(3, SwedishGenerator.IT[cells[1]].r());
@@ -258,8 +259,8 @@ public class SwedishGeneratorTest {
assertEquals(5, SwedishGenerator.IT[cells[1]].c());
assertEquals(5, SwedishGenerator.IT[cells[2]].c());
assertTrue(Masker.Slot.horiz(CLUE_RIGHT)); // right
assertFalse(Masker.Slot.horiz(CLUE_DOWN)); // down
assertTrue(Slot.horiz(CLUE_RIGHT)); // right
assertFalse(Slot.horiz(CLUE_DOWN)); // down
}
static long packPattern(String s) {
@@ -295,9 +296,9 @@ public class SwedishGeneratorTest {
assertEquals(1, slots.length);
var s = slots[0];
assertTrue(Masker.Slot.length(s.lo(), s.hi()) >= 2);
assertEquals(OFF_0_0, Masker.Slot.clueIndex(s.key()));
assertEquals(CLUE_RIGHT, Masker.Slot.dir(s.key()));
assertTrue(Slot.length(s.lo(), s.hi()) >= 2);
assertEquals(OFF_0_0, Slot.clueIndex(s.key()));
assertEquals(CLUE_RIGHT, Slot.dir(s.key()));
}
@Test
@@ -336,7 +337,7 @@ public class SwedishGeneratorTest {
void testPlaceWord() {
var grid = new Gridded(createEmpty());
// Slot at OFF_0_0 length 3, horizontal (right)
var key = Masker.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);
val hi = 0L;
var w1 = ABC;
@@ -362,7 +363,7 @@ public class SwedishGeneratorTest {
// 4. Partial placement then conflict (rollback)
grid = new Gridded(createEmpty());
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
GridBuilder.placeWord(grid.grid(), grid.grid().g, Slot.packSlotKey(0, CLUE_RIGHT), 1L << OFF_0_2, 0, Lemma.from("X")); // Conflict at the end
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));
assertEquals(1, map.size());
@@ -373,7 +374,7 @@ public class SwedishGeneratorTest {
void testBacktrackingHelpers() {
var grid = new Gridded(createEmpty());
// Slot at 0,1 length 2
var key = Masker.Slot.packSlotKey(0, CLUE_RIGHT);
var key = Slot.packSlotKey(0, CLUE_RIGHT);
var lo = (1L << OFF_0_1) | (1L << OFF_0_2);
var w = AZ;
val low = grid.grid().lo;
@@ -401,8 +402,8 @@ public class SwedishGeneratorTest {
assertTrue(Slotinfo.increasing(CLUE_DOWN)); // Down
assertFalse(Slotinfo.increasing(CLUE_UP)); // Up
assertTrue(Slotinfo.increasing(Masker.Slot.packSlotKey(0, CLUE_RIGHT)));
assertFalse(Slotinfo.increasing(Masker.Slot.packSlotKey(0, CLUE_LEFT)));
assertTrue(Slotinfo.increasing(Slot.packSlotKey(0, CLUE_RIGHT)));
assertFalse(Slotinfo.increasing(Slot.packSlotKey(0, CLUE_LEFT)));
// 2. Test slotScore
val counts = new byte[SIZE];