introduce bitloops

This commit is contained in:
mike
2026-01-21 00:56:18 +01:00
parent 78f72a024e
commit 92a736aa0a
7 changed files with 108 additions and 110 deletions

View File

@@ -4,6 +4,7 @@ import module java.base;
import lombok.val;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import precomp.Neighbors9x8.rci;
import puzzle.Export.Clued;
import puzzle.Export.Gridded;
import puzzle.DictJavaGeneratorMulti.DictEntryDTO.IntListDTO;
@@ -37,6 +38,9 @@ import static puzzle.SwedishGenerator.*;
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); }
record Context(long[] bitset) {
@@ -86,11 +90,9 @@ public class SwedishGeneratorTest {
@Test
void testPatternForSlotAllLetters() {
var key = r0c0d1.slotKey;
val clues = Clued.of(r0c0d1);
var grid = new Gridded(clues);
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));
var grid = new Gridded(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);
val map = grid.collect(Collectors.toMap(LetterAt::index, LetterAt::letter));
assertEquals(LETTER_A, map.get(OFF_0_1));
assertEquals(LETTER_B, map.get(OFF_0_2));
assertEquals(LETTER_C, map.get(OFF_0_3));
@@ -99,8 +101,8 @@ public class SwedishGeneratorTest {
@Test
void testPatternForSlotMixed() {
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_2_0, 0, Lemma.from("C"));
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, WORD_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);
@@ -118,7 +120,7 @@ public class SwedishGeneratorTest {
void testPatternForSlotSingleLetter() {
var grid = createEmpty();
//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 pattern = patternForSlot(grid.lo, grid.hi, grid.g, key, 7L, 0L);
assertEquals(1L, pattern);
@@ -150,10 +152,9 @@ public class SwedishGeneratorTest {
@Test
void testGrid() {
var empty = Clues.createEmpty();
var grid = new Gridded(empty);
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));
var grid = new Gridded(Clues.createEmpty());
GridBuilder.placeWord(grid.grid(), grid.grid().g, r0c0d1.slotKey, 1L << OFF_0_0, 0, WORD_A);
val arr = grid.collect(Collectors.toMap(LetterAt::index, LetterAt::letter));
assertEquals(1, arr.size());
assertEquals(LETTER_A, arr.get(OFF_0_0));
}
@@ -213,13 +214,13 @@ public class SwedishGeneratorTest {
assertEquals(OFF_2_3, Slot.clueIndex(key));
assertEquals(CLUE_DOWN, Slot.dir(key));
assertFalse(Slot.horiz(key));
var cells = Gridded.cellWalk((byte) key, lo, 0L).toArray();
assertEquals(2, Masker.IT[cells[0]].r());
assertEquals(3, Masker.IT[cells[1]].r());
assertEquals(4, Masker.IT[cells[2]].r());
assertEquals(5, Masker.IT[cells[0]].c());
assertEquals(5, Masker.IT[cells[1]].c());
assertEquals(5, Masker.IT[cells[2]].c());
var cells = Gridded.cellWalk((byte) key, lo, 0L).mapToObj(i -> Masker.IT[i]).toArray(rci[]::new);
assertEquals(2, cells[0].r());
assertEquals(3, cells[1].r());
assertEquals(4, cells[2].r());
assertEquals(5, cells[0].c());
assertEquals(5, cells[1].c());
assertEquals(5, cells[2].c());
assertTrue(Slot.horiz(CLUE_RIGHT)); // right
assertFalse(Slot.horiz(CLUE_DOWN)); // down
@@ -251,9 +252,8 @@ public class SwedishGeneratorTest {
@Test
void testForEachSlotAndExtractSlots() {
// 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 slots = Masker.extractSlots(clues, dict.index());
var slots = Masker.extractSlots(Clued.of(r0c0d1).c(), dict.index());
assertEquals(1, slots.length);
var s = slots[0];
@@ -296,8 +296,7 @@ public class SwedishGeneratorTest {
@Test
void testPlaceWord() {
var empty = Clues.createEmpty();
var grid = new Gridded(empty);
var grid = new Gridded(Clues.createEmpty());
// Slot at OFF_0_0 length 3, horizontal (right)
var key = Slot.packSlotKey(0, CLUE_RIGHT);
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
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(LETTER_A, map.get(OFF_0_0));
assertEquals(LETTER_B, map.get(OFF_0_1));
@@ -318,7 +317,7 @@ public class SwedishGeneratorTest {
// 3. Conflict: place "ABD" where "ABC" is
assertFalse(GridBuilder.placeWord(grid.grid(), grid.grid().g, key, lo, hi, ABD));
// 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(LETTER_A, map.get(OFF_0_0));
assertEquals(LETTER_B, map.get(OFF_0_1));
@@ -326,17 +325,16 @@ public class SwedishGeneratorTest {
// 4. Partial placement then conflict (rollback)
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));
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(LETTER_X, map.get(OFF_0_2));
}
@Test
void testBacktrackingHelpers() {
var clues = Clues.createEmpty();
var grid = new Gridded(clues);
var grid = new Gridded(Clues.createEmpty());
// Slot at 0,1 length 2
var key = Slot.packSlotKey(0, CLUE_RIGHT);
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);
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(LETTER_A, map.get(OFF_0_1));
assertEquals(LETTER_Z, map.get(OFF_0_2));
grid.grid().hi = top;
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());
assertFalse(map.containsKey(OFF_0_1));
assertFalse(map.containsKey(OFF_0_2));