This commit is contained in:
mike
2026-01-23 22:17:13 +01:00
parent d9b565301f
commit 282ec56f19
8 changed files with 95 additions and 98 deletions

View File

@@ -10,20 +10,12 @@ import puzzle.Riddle.ClueSign;
import puzzle.Riddle.ExportedPuzzle; import puzzle.Riddle.ExportedPuzzle;
import puzzle.Riddle.Placed; import puzzle.Riddle.Placed;
import puzzle.Riddle.Rewards; import puzzle.Riddle.Rewards;
import puzzle.Riddle.Vestigium; import puzzle.Riddle.Signa;
import puzzle.Riddle.WordOut; import puzzle.Riddle.WordOut;
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 precomp.Const9x8.CLUE_DOWN0;
import static precomp.Const9x8.CLUE_LEFT3;
import static precomp.Const9x8.CLUE_LEFT_TOP4;
import static precomp.Const9x8.CLUE_RIGHT1;
import static precomp.Const9x8.CLUE_RIGHT_TOP5;
import static precomp.Const9x8.CLUE_UP2;
import static puzzle.Clues.createEmpty;
import static puzzle.Masker.Slot; import static puzzle.Masker.Slot;
import static puzzle.Masker.isLo;
import static puzzle.SwedishGenerator.X; import static puzzle.SwedishGenerator.X;
@GenerateShapedCopies( @GenerateShapedCopies(
@@ -33,22 +25,22 @@ import static puzzle.SwedishGenerator.X;
) )
public record Export() { public record Export() {
public static final ThreadLocal<byte[]> BYTES = ThreadLocal.withInitial(() -> new byte[8]); public record ExportTemplates(byte[] table, byte[] dashTable, byte[] wordBytes) { }
@Shaped static final String INIT_GRID_OUTPUT = Const9x8.INIT_GRID_OUTPUT;
@Shaped static final int R = Const9x8.R;
@Shaped static final int C = Const9x8.C;
@Shaped static final byte[] INIT_GRID_OUTPUT_ARR = Const9x8.INIT_GRID_OUTPUT_ARR;
@Shaped static final byte[] INIT_GRID_OUTPUT_DASH_ARR = Const9x8.INIT_GRID_OUTPUT_DASH_ARR;
@Shaped static final long MASK_HI = Const9x8.MASK_HI;
@Shaped static final long MASK_LO = Const9x8.MASK_LO;
static int HI(int in) { return in | 64; } @Shaped static final int R = Const9x8.R;
static byte LETTER(int in) { return (byte) (in | 64); } @Shaped static final int C = Const9x8.C;
static byte CLUE_CHAR(int s) { return (byte) (s | 48); } @Shaped static final byte[] INIT_GRID_OUTPUT_ARR = Const9x8.INIT_GRID_OUTPUT_ARR;
static int INDEX_ROW(int idx) { return idx % R; } @Shaped static final byte[] INIT_GRID_OUTPUT_DASH_ARR = Const9x8.INIT_GRID_OUTPUT_DASH_ARR;
static int INDEX_COL(int idx) { return idx / R; } @Shaped static final long MASK_HI = Const9x8.MASK_HI;
static int INDEX(int r, int cols, int c) { return r * cols + c; } @Shaped static final long MASK_LO = Const9x8.MASK_LO;
static int INDEX(int idx, int cols) { return INDEX_ROW(idx) * cols + INDEX_COL(idx); } public static final ThreadLocal<ExportTemplates> BYTES = ThreadLocal.withInitial(
() -> new ExportTemplates(INIT_GRID_OUTPUT_ARR, INIT_GRID_OUTPUT_DASH_ARR, new byte[8]));
static int HI(int in) { return in | 64; }
static byte LETTER(int in) { return (byte) (in | 64); }
static byte CLUE_CHAR(int s) { return (byte) (s | 48); }
static int INDEX_ROW(int idx) { return idx % R; }
static int INDEX_COL(int idx) { return idx / R; }
static int INDEX(int idx, int cols) { return INDEX_ROW(idx) * cols + INDEX_COL(idx); }
record Lettrix(int index, byte letter) { record Lettrix(int index, byte letter) {
@@ -59,47 +51,18 @@ public record Export() {
public int index(int cols) { return (row() * cols) + col(); } public int index(int cols) { return (row() * cols) + col(); }
} }
public static String gridToString(Clues clues) { public static String gridToString(Clues clues) {
val chars = INIT_GRID_OUTPUT_ARR.clone(); val chars = BYTES.get().table();
new Signa(clues).forEach(v -> chars[INDEX(v.index(), C + 1)] = CLUE_CHAR(v.clue())); new Signa(clues).forEach(v -> chars[INDEX(v.index(), C + 1)] = CLUE_CHAR(v.clue()));
return new String(chars); val result = new String(chars);
} new Signa(clues).forEach(v -> chars[INDEX(v.index(), C + 1)] = ' ');
public record Signa(@Delegate Clues c) { return result;
public static Signa of(Mask... cells) { return new Signa(createEmpty()).setClue(cells); }
public Signa setClue(Mask... cells) {
for (var cell : cells) {
if (isLo((cell.index()))) setClueLo(cell.lo(), cell.d());
else setClueHi(cell.hi(), cell.d());
}
return this;
}
public Signa deepCopyGrid() { return new Signa(new Clues(c.lo, c.hi, c.vlo, c.vhi, c.rlo, c.rhi, c.xlo, c.xhi)); }
@Delegate public Stream<Vestigium> stream() {
val stream = Stream.<Vestigium>builder();
for (var l = c.lo & ~c.xlo & ~c.rlo & c.vlo; l != X; l &= l - 1) stream.accept(new Vestigium(Long.numberOfTrailingZeros(l), CLUE_RIGHT1));
for (var l = c.lo & ~c.xlo & ~c.rlo & ~c.vlo; l != X; l &= l - 1) stream.accept(new Vestigium(Long.numberOfTrailingZeros(l), CLUE_DOWN0));
for (var l = c.lo & ~c.xlo & c.rlo & ~c.vlo; l != X; l &= l - 1) stream.accept(new Vestigium(Long.numberOfTrailingZeros(l), CLUE_UP2));
for (var l = c.lo & ~c.xlo & c.rlo & c.vlo; l != X; l &= l - 1) stream.accept(new Vestigium(Long.numberOfTrailingZeros(l), CLUE_LEFT3));
for (var l = c.lo & c.xlo & ~c.rlo & ~c.vlo; l != X; l &= l - 1) stream.accept(new Vestigium(Long.numberOfTrailingZeros(l), CLUE_LEFT_TOP4));
for (var l = c.lo & c.xlo & ~c.rlo & c.vlo; l != X; l &= l - 1) stream.accept(new Vestigium(Long.numberOfTrailingZeros(l), CLUE_RIGHT_TOP5));
for (var h = c.hi & ~c.xhi & ~c.rhi & c.vhi; h != X; h &= h - 1) stream.accept(new Vestigium(HI(Long.numberOfTrailingZeros(h)), CLUE_RIGHT1));
for (var h = c.hi & ~c.xhi & ~c.rhi & ~c.vhi; h != X; h &= h - 1) stream.accept(new Vestigium(HI(Long.numberOfTrailingZeros(h)), CLUE_DOWN0));
for (var h = c.hi & ~c.xhi & c.rhi & ~c.vhi; h != X; h &= h - 1) stream.accept(new Vestigium(HI(Long.numberOfTrailingZeros(h)), CLUE_UP2));
for (var h = c.hi & ~c.xhi & c.rhi & c.vhi; h != X; h &= h - 1) stream.accept(new Vestigium(HI(Long.numberOfTrailingZeros(h)), CLUE_LEFT3));
for (var h = c.hi & c.xhi & ~c.rhi & ~c.vhi; h != X; h &= h - 1) stream.accept(new Vestigium(HI(Long.numberOfTrailingZeros(h)), CLUE_LEFT_TOP4));
for (var h = c.hi & c.xhi & ~c.rhi & c.vhi; h != X; h &= h - 1) stream.accept(new Vestigium(HI(Long.numberOfTrailingZeros(h)), CLUE_RIGHT_TOP5));
return stream.build();
}
} }
record Puzzle(@Delegate Grid grid, Clues cl) record Puzzle(@Delegate Grid grid, Clues cl)
implements Stream<Lettrix> { implements Stream<Lettrix> {
public Puzzle(Clues clues) { this(Masker.toGrid(clues), clues); } public Puzzle(Clues clues) { this(Masker.toGrid(clues), clues); }
public Puzzle(Signa clues) { this(clues.c); } public Puzzle(Signa clues) { this(clues.c()); }
public @Delegate Stream<Lettrix> stream() { public @Delegate Stream<Lettrix> stream() {
val stream = Stream.<Lettrix>builder(); val stream = Stream.<Lettrix>builder();
for (var l = grid.lo & MASK_LO & ~cl.lo; l != X; l &= l - 1) stream.accept(Lettrix.from(Long.numberOfTrailingZeros(l), grid.g)); for (var l = grid.lo & MASK_LO & ~cl.lo; l != X; l &= l - 1) stream.accept(Lettrix.from(Long.numberOfTrailingZeros(l), grid.g));
@@ -116,7 +79,7 @@ public record Export() {
puzzle.stream().forEach((l) -> sb[l.index(C + 1)] = l.human()); puzzle.stream().forEach((l) -> sb[l.index(C + 1)] = l.human());
return new String(sb); return new String(sb);
} }
public String cluesGridToString() { return gridToString(clues.c); } public String cluesGridToString() { return gridToString(clues.c()); }
public String gridRenderHuman() { return String.join("\n", exportGrid(_ -> (byte) ' ', INIT_GRID_OUTPUT_DASH_ARR).split("\n")); } public String gridRenderHuman() { return String.join("\n", exportGrid(_ -> (byte) ' ', INIT_GRID_OUTPUT_DASH_ARR).split("\n")); }
public String gridGridToString() { return exportGrid(d1 -> d1, INIT_GRID_OUTPUT_ARR); } public String gridGridToString() { return exportGrid(d1 -> d1, INIT_GRID_OUTPUT_ARR); }
public ExportedPuzzle exportFormatFromFilled(Rewards rewards, rci[] rcis) { public ExportedPuzzle exportFormatFromFilled(Rewards rewards, rci[] rcis) {
@@ -159,7 +122,7 @@ public record Export() {
var grid = new String(template).split("\n"); var grid = new String(template).split("\n");
// 5) words output with cropped coordinates // 5) words output with cropped coordinates
val bytes = BYTES.get(); val bytes = BYTES.get().wordBytes();
var wordsOut = Arrays.stream(placed).map(p -> new WordOut( var wordsOut = Arrays.stream(placed).map(p -> new WordOut(
p.lemma(), p.lemma(),
p.startRow() - MINR, p.startRow() - MINR,

View File

@@ -15,7 +15,7 @@ import puzzle.Riddle.WordOut;
import puzzle.SwedishGenerator.Rng; import puzzle.SwedishGenerator.Rng;
import static puzzle.Export.Puzzle; import static puzzle.Export.Puzzle;
import static puzzle.Export.PuzzleResult; import static puzzle.Export.PuzzleResult;
import static puzzle.Export.Signa; import static puzzle.Riddle.Signa;
import static puzzle.SwedishGenerator.Dict; import static puzzle.SwedishGenerator.Dict;
import static puzzle.SwedishGenerator.Slotinfo; import static puzzle.SwedishGenerator.Slotinfo;
import static puzzle.SwedishGenerator.fillMask; import static puzzle.SwedishGenerator.fillMask;

View File

@@ -10,6 +10,7 @@ import puzzle.SwedishGenerator.Slotinfo;
import java.util.Arrays; import java.util.Arrays;
import java.util.function.IntSupplier; import java.util.function.IntSupplier;
import java.util.stream.IntStream; import java.util.stream.IntStream;
import java.util.stream.Stream;
import static precomp.Const9x8.CLUE_DOWN0; import static precomp.Const9x8.CLUE_DOWN0;
import static precomp.Const9x8.CLUE_LEFT3; import static precomp.Const9x8.CLUE_LEFT3;
import static precomp.Const9x8.CLUE_LEFT_TOP4; import static precomp.Const9x8.CLUE_LEFT_TOP4;
@@ -17,6 +18,9 @@ import static precomp.Const9x8.CLUE_NONE;
import static precomp.Const9x8.CLUE_RIGHT1; import static precomp.Const9x8.CLUE_RIGHT1;
import static precomp.Const9x8.CLUE_RIGHT_TOP5; import static precomp.Const9x8.CLUE_RIGHT_TOP5;
import static precomp.Const9x8.CLUE_UP2; import static precomp.Const9x8.CLUE_UP2;
import static puzzle.Clues.createEmpty;
import static puzzle.Masker.isLo;
import static puzzle.SwedishGenerator.X;
public class Riddle { public class Riddle {
public static IntStream cellWalk(int base, long lo, long hi) { public static IntStream cellWalk(int base, long lo, long hi) {
@@ -138,4 +142,36 @@ public class Riddle {
byte replace(byte data); byte replace(byte data);
} }
public record Signa(@Delegate Clues c) {
public static Signa of(Mask... cells) { return new Signa(createEmpty()).setClue(cells); }
public Signa setClue(Mask... cells) {
for (var cell : cells) {
if (isLo((cell.index()))) setClueLo(cell.lo(), cell.d());
else setClueHi(cell.hi(), cell.d());
}
return this;
}
public Signa deepCopyGrid() { return new Signa(new Clues(c.lo, c.hi, c.vlo, c.vhi, c.rlo, c.rhi, c.xlo, c.xhi)); }
@Delegate public Stream<Vestigium> stream() {
val stream = Stream.<Vestigium>builder();
for (var l = c.lo & ~c.xlo & ~c.rlo & c.vlo; l != X; l &= l - 1) stream.accept(new Vestigium(Long.numberOfTrailingZeros(l), CLUE_RIGHT1));
for (var l = c.lo & ~c.xlo & ~c.rlo & ~c.vlo; l != X; l &= l - 1) stream.accept(new Vestigium(Long.numberOfTrailingZeros(l), CLUE_DOWN0));
for (var l = c.lo & ~c.xlo & c.rlo & ~c.vlo; l != X; l &= l - 1) stream.accept(new Vestigium(Long.numberOfTrailingZeros(l), CLUE_UP2));
for (var l = c.lo & ~c.xlo & c.rlo & c.vlo; l != X; l &= l - 1) stream.accept(new Vestigium(Long.numberOfTrailingZeros(l), CLUE_LEFT3));
for (var l = c.lo & c.xlo & ~c.rlo & ~c.vlo; l != X; l &= l - 1) stream.accept(new Vestigium(Long.numberOfTrailingZeros(l), CLUE_LEFT_TOP4));
for (var l = c.lo & c.xlo & ~c.rlo & c.vlo; l != X; l &= l - 1) stream.accept(new Vestigium(Long.numberOfTrailingZeros(l), CLUE_RIGHT_TOP5));
for (var h = c.hi & ~c.xhi & ~c.rhi & c.vhi; h != X; h &= h - 1) stream.accept(new Vestigium(Export.HI(Long.numberOfTrailingZeros(h)), CLUE_RIGHT1));
for (var h = c.hi & ~c.xhi & ~c.rhi & ~c.vhi; h != X; h &= h - 1) stream.accept(new Vestigium(Export.HI(Long.numberOfTrailingZeros(h)), CLUE_DOWN0));
for (var h = c.hi & ~c.xhi & c.rhi & ~c.vhi; h != X; h &= h - 1) stream.accept(new Vestigium(Export.HI(Long.numberOfTrailingZeros(h)), CLUE_UP2));
for (var h = c.hi & ~c.xhi & c.rhi & c.vhi; h != X; h &= h - 1) stream.accept(new Vestigium(Export.HI(Long.numberOfTrailingZeros(h)), CLUE_LEFT3));
for (var h = c.hi & c.xhi & ~c.rhi & ~c.vhi; h != X; h &= h - 1) stream.accept(new Vestigium(Export.HI(Long.numberOfTrailingZeros(h)), CLUE_LEFT_TOP4));
for (var h = c.hi & c.xhi & ~c.rhi & c.vhi; h != X; h &= h - 1) stream.accept(new Vestigium(Export.HI(Long.numberOfTrailingZeros(h)), CLUE_RIGHT_TOP5));
return stream.build();
}
}
} }

View File

@@ -8,7 +8,6 @@ import org.junit.jupiter.api.Test;
import puzzle.Export.Lettrix; import puzzle.Export.Lettrix;
import puzzle.Export.Puzzle; import puzzle.Export.Puzzle;
import puzzle.Export.PuzzleResult; import puzzle.Export.PuzzleResult;
import puzzle.Export.Signa;
import puzzle.Main.Opts; import puzzle.Main.Opts;
import puzzle.Riddle.Rewards; import puzzle.Riddle.Rewards;
import puzzle.SwedishGenerator.Rng; import puzzle.SwedishGenerator.Rng;
@@ -97,7 +96,7 @@ public class MainTest {
}}; }};
@Test @Test
void testExtractSlots() { void testExtractSlots() {
var clues = Signa.of(r0c0d1); var clues = Riddle.Signa.of(r0c0d1);
var grid = new Puzzle(clues); var grid = new Puzzle(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, r0c0d1.slotKey, (1L << OFF_0_1) | (1L << OFF_0_2), 0, AB);
@@ -125,7 +124,7 @@ public class MainTest {
@Test @Test
void testForEachSlot() { void testForEachSlot() {
var count = new AtomicInteger(0); var count = new AtomicInteger(0);
Masker.forEachSlot(Signa.of(r0c0d1).c(), (key, lo, hi) -> { Masker.forEachSlot(Riddle.Signa.of(r0c0d1).c(), (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());
@@ -144,7 +143,7 @@ public class MainTest {
} }
@Test @Test
public void testGridBasics() { public void testGridBasics() {
var clues = Signa.of(r2c1d2); var clues = Riddle.Signa.of(r2c1d2);
var grid = new Puzzle(clues); var grid = new Puzzle(clues);
r1c1.or(r0c1).lo(); r1c1.or(r0c1).lo();
// Test set/get // Test set/get
@@ -177,7 +176,7 @@ public class MainTest {
} }
@Test @Test
public void testCluesDeepCopy() { public void testCluesDeepCopy() {
var clues = Signa.of(r0c0d1, r0c1d2, r1c0d3, r1c1d0); var clues = Riddle.Signa.of(r0c0d1, r0c1d2, r1c0d3, r1c1d0);
var copy = clues.deepCopyGrid(); var copy = clues.deepCopyGrid();
var clueMap = clues.stream().collect(Collectors.toMap(Riddle.Vestigium::index, Riddle.Vestigium::clue)); var clueMap = clues.stream().collect(Collectors.toMap(Riddle.Vestigium::index, Riddle.Vestigium::clue));
@@ -190,11 +189,11 @@ public class MainTest {
} }
@Test @Test
public void testMini() { public void testMini() {
Assertions.assertTrue(Signa.of(r1c1d3).isClueLo(OFF_1_1)); Assertions.assertTrue(Riddle.Signa.of(r1c1d3).isClueLo(OFF_1_1));
} }
@Test @Test
void testFiller2() { void testFiller2() {
var mask = Signa.of( var mask = Riddle.Signa.of(
r0c0d1, r0c0d1,
r0c3d0, r0c4d0, r0c5d0, r0c6d0, r0c7d0, r0c8d0, r0c3d0, r0c4d0, r0c5d0, r0c6d0, r0c7d0, r0c8d0,
r1c0d1, r1c0d1,
@@ -204,7 +203,7 @@ public class MainTest {
r5c0d3, r5c0d3,
r6c0d3, r6c0d3,
r7c0d2, r7c1d2, r7c2d2, r7c8d3 r7c0d2, r7c1d2, r7c2d2, r7c8d3
); );
Assertions.assertEquals(20, mask.clueCount()); Assertions.assertEquals(20, mask.clueCount());
val map = mask.stream().collect(Collectors.toMap(Riddle.Vestigium::index, Riddle.Vestigium::clue)); val map = mask.stream().collect(Collectors.toMap(Riddle.Vestigium::index, Riddle.Vestigium::clue));
Assertions.assertEquals(20, map.size()); Assertions.assertEquals(20, map.size());
@@ -216,7 +215,7 @@ public class MainTest {
void testFiller() { void testFiller() {
System.out.println(DictData950.DICT950.index().length); System.out.println(DictData950.DICT950.index().length);
val rng = new Rng(-343913721); val rng = new Rng(-343913721);
var mask = Signa.of( var mask = Riddle.Signa.of(
r0c3d3, r0c6d3, r0c7d0, r0c8d0, r0c3d3, r0c6d3, r0c7d0, r0c8d0,
r1c1d1, r1c1d1,
r2c1d1, r2c1d1,
@@ -225,13 +224,13 @@ public class MainTest {
r5c1d1, r5c1d1,
r6c1d1, r6c8d2, r6c1d1, r6c8d2,
r7c0d2, r7c1d1, r7c4d2, r7c5d2, r7c8d3 r7c0d2, r7c1d1, r7c4d2, r7c5d2, r7c8d3
); );
var slotInfo = Masker.slots(mask.c(), DictData950.DICT950.index(), DictData950.DICT950.reversed()); var slotInfo = Masker.slots(mask.c(), DictData950.DICT950.index(), DictData950.DICT950.reversed());
var grid = Masker.grid(slotInfo); var grid = Masker.grid(slotInfo);
var filled = fillMask(rng, slotInfo, grid.lo, grid.hi, grid.g); var filled = fillMask(rng, slotInfo, grid.lo, grid.hi, grid.g);
Assertions.assertTrue(filled.ok(), "Puzzle generation failed (not ok)"); Assertions.assertTrue(filled.ok(), "Puzzle generation failed (not ok)");
Assertions.assertEquals(17, Slotinfo.wordCount(0, slotInfo), "Number of assigned words changed"); Assertions.assertEquals(17, Slotinfo.wordCount(0, slotInfo), "Number of assigned words changed");
Assertions.assertEquals("BEADEMT", Lemma.asWord(slotInfo[0].assign().w, Export.BYTES.get())); Assertions.assertEquals("BEADEMT", Lemma.asWord(slotInfo[0].assign().w, Export.BYTES.get().wordBytes()));
Assertions.assertEquals(74732156493031040L, grid.lo); Assertions.assertEquals(74732156493031040L, grid.lo);
Assertions.assertEquals(193L, grid.hi); Assertions.assertEquals(193L, grid.hi);
var g = new Puzzle(grid, mask.c()); var g = new Puzzle(grid, mask.c());

View File

@@ -4,7 +4,7 @@ import lombok.val;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import puzzle.Export.Puzzle; import puzzle.Export.Puzzle;
import puzzle.Export.PuzzleResult; import puzzle.Export.PuzzleResult;
import puzzle.Export.Signa; import puzzle.Riddle.Signa;
import puzzle.Riddle.Rewards; import puzzle.Riddle.Rewards;
import puzzle.SwedishGenerator.Assign; import puzzle.SwedishGenerator.Assign;
import puzzle.SwedishGenerator.FillResult; import puzzle.SwedishGenerator.FillResult;
@@ -99,14 +99,14 @@ public class MarkerTest {
} }
@Test @Test
void testSimilarity() { void testSimilarity() {
var a = Signa.of(r0c0d1, r2c1d0).c(); var a = Riddle.Signa.of(r0c0d1, r2c1d0).c();
var b = Signa.of(r0c0d1, r2c1d0).c(); var b = Riddle.Signa.of(r0c0d1, r2c1d0).c();
// Identity // Identity
assertEquals(1.0, Masker.similarity(a, b), 0.001); assertEquals(1.0, Masker.similarity(a, b), 0.001);
// Different direction // Different direction
var c = Signa.of(r0c0d0, r2c1d0); var c = Riddle.Signa.of(r0c0d0, r2c1d0);
assertTrue(Masker.similarity(a, c.c()) < 1.0); assertTrue(Masker.similarity(a, c.c()) < 1.0);
// Completely different // Completely different
@@ -122,10 +122,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(Signa.of(r0c0d1).c())); assertTrue(masker.isValid(Riddle.Signa.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(Signa.of(r0c7d1).c())); assertFalse(masker.isValid(Riddle.Signa.of(r0c7d1).c()));
} }
@Test @Test
@@ -157,18 +157,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(Signa.of(r0c0d1, r2c2d2).c())); assertTrue(masker.isValid(Riddle.Signa.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(Signa.of(r0c0d1, r2c2d2, r1c1d1).c())); assertTrue(masker.isValid(Riddle.Signa.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(Signa.of(r0c0d4, r0c2d5).c())); assertFalse(masker.isValid(Riddle.Signa.of(r0c0d4, r0c2d5).c()));
} }
@Test @Test
@@ -250,7 +250,7 @@ public class MarkerTest {
} }
@Test @Test
void testCornerDownSlot() { void testCornerDownSlot() {
var clues = Signa.of(r0c0d4); var clues = Riddle.Signa.of(r0c0d4);
// Clue op (0,0), type 4 (Corner Down) // Clue op (0,0), type 4 (Corner Down)
assertEquals(r0c0d4.d, clues.getDir(r0c0d4.index)); assertEquals(r0c0d4.d, clues.getDir(r0c0d4.index));
@@ -274,14 +274,14 @@ public class MarkerTest {
@Test @Test
void testCornerDownExtraction() { void testCornerDownExtraction() {
var slots = Masker.slots(Signa.of(r0c0d4).c(), DictData950.DICT950); var slots = Masker.slots(Riddle.Signa.of(r0c0d4).c(), DictData950.DICT950);
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()));
} }
@Test @Test
void testCornerDownLeftSlot() { void testCornerDownLeftSlot() {
var clues = Signa.of(r0c1d5); var clues = Riddle.Signa.of(r0c1d5);
assertEquals(r0c1d5.d, clues.getDir(r0c1d5.index)); assertEquals(r0c1d5.d, clues.getDir(r0c1d5.index));
@@ -304,13 +304,13 @@ public class MarkerTest {
@Test @Test
void testCornerDownLeftExtraction() { void testCornerDownLeftExtraction() {
var slots = Masker.slots(Signa.of(r0c1d5).c(), DictData950.DICT950.index(), DictData950.DICT950.reversed()); var slots = Masker.slots(Riddle.Signa.of(r0c1d5).c(), DictData950.DICT950.index(), DictData950.DICT950.reversed());
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()));
} }
@Test @Test
void testExportFormatFromFilled() { void testExportFormatFromFilled() {
val clues = Signa.of(r0c0d1, r0c5d3); val clues = Riddle.Signa.of(r0c0d1, r0c5d3);
var grid = new Puzzle(clues); var grid = new Puzzle(clues);
// key = (cellIndex << 2) | (direction) // key = (cellIndex << 2) | (direction)
@@ -378,7 +378,7 @@ public class MarkerTest {
@Test @Test
void testShardToClue() { void testShardToClue() {
var bytes = Export.BYTES.get(); var bytes = Export.BYTES.get().wordBytes();
for (var length = 2; length <= 8; length++) { for (var length = 2; length <= 8; length++) {
val entry = DictData950.DICT950.index()[length]; val entry = DictData950.DICT950.index()[length];
if (entry == null) continue; if (entry == null) continue;
@@ -399,7 +399,7 @@ public class MarkerTest {
@Test @Test
void testSpecificWords() { void testSpecificWords() {
// These words are known to be in the CSV and likely in the dictionary // These words are known to be in the CSV and likely in the dictionary
var bytes = Export.BYTES.get(); var bytes = Export.BYTES.get().wordBytes();
var testWords = new String[]{ "EEN", "NAAR", "IEDEREEN" }; var testWords = new String[]{ "EEN", "NAAR", "IEDEREEN" };
for (var wStr : testWords) { for (var wStr : testWords) {
var w = Lemma.from(wStr); var w = Lemma.from(wStr);

View File

@@ -5,7 +5,6 @@ import anno.DictGen;
import anno.Dictionaries; import anno.Dictionaries;
import lombok.val; import lombok.val;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import puzzle.Export.Signa;
import puzzle.SwedishGenerator.Rng; import puzzle.SwedishGenerator.Rng;
import puzzle.SwedishGenerator.Slotinfo; import puzzle.SwedishGenerator.Slotinfo;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -113,7 +112,7 @@ public class PerformanceTest {
void testIncrementalComplexity() { void testIncrementalComplexity() {
// Use the complex mask from Main.java // Use the complex mask from Main.java
var mask = Signa.of( var mask = Riddle.Signa.of(
r0c0d1, r0c5d0, r0c6d0, r0c7d0, r0c8d0, r0c0d1, r0c5d0, r0c6d0, r0c7d0, r0c8d0,
r1c0d1, r1c0d1,
r2c0d0, r2c1d0, r2c3d0, r2c4d1, r2c0d0, r2c1d0, r2c3d0, r2c4d1,
@@ -122,7 +121,7 @@ public class PerformanceTest {
r5c2d2, r5c4d1, r5c2d2, r5c4d1,
r6c2d1, r6c2d1,
r7c0d2, r7c1d2, r7c2d1, r7c7d2, r7c8d2 r7c0d2, r7c1d2, r7c2d1, r7c7d2, r7c8d2
); );
val allSlots = Masker.slots(mask.c(), DICT900); val allSlots = Masker.slots(mask.c(), DICT900);
//mask.toGrid() //mask.toGrid()
System.out.println("[DEBUG_LOG] \n--- Incremental Complexity Test ---"); System.out.println("[DEBUG_LOG] \n--- Incremental Complexity Test ---");
@@ -143,7 +142,7 @@ public class PerformanceTest {
val rng = new Rng(42); val rng = new Rng(42);
// A single horizontal slot at (0,0) // A single horizontal slot at (0,0)
val mask = Signa.of(r0c0d1); val mask = Riddle.Signa.of(r0c0d1);
val slots = Masker.slots(mask.c(), DICT800); val slots = Masker.slots(mask.c(), DICT800);
System.out.println("[DEBUG_LOG] \n--- Single Slot Resolution ---"); System.out.println("[DEBUG_LOG] \n--- Single Slot Resolution ---");

View File

@@ -11,7 +11,7 @@ import precomp.Neighbors9x8;
import puzzle.DictJavaGeneratorMulti.DictEntryDTO.IntListDTO; import puzzle.DictJavaGeneratorMulti.DictEntryDTO.IntListDTO;
import puzzle.Export.Lettrix; import puzzle.Export.Lettrix;
import puzzle.Export.Puzzle; import puzzle.Export.Puzzle;
import puzzle.Export.Signa; import puzzle.Riddle.Signa;
import puzzle.Masker.Slot; import puzzle.Masker.Slot;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -126,7 +126,7 @@ public class SwedishGeneratorTest {
@Test @Test
void testPatternForSlotAllLetters() { void testPatternForSlotAllLetters() {
var grid = new Puzzle(Signa.of(r0c0d1)); var grid = new Puzzle(Riddle.Signa.of(r0c0d1));
GridBuilder.placeWord(grid.grid(), grid.grid().g, r0c0d1.slotKey, r0c1.or(r0c2).or(r0c3).lo(), X, ABC); GridBuilder.placeWord(grid.grid(), grid.grid().g, r0c0d1.slotKey, r0c1.or(r0c2).or(r0c3).lo(), X, ABC);
val map = grid.collect(Collectors.toMap(Lettrix::index, Lettrix::letter)); val map = grid.collect(Collectors.toMap(Lettrix::index, Lettrix::letter));
assertEquals(LETTER_A, map.get(OFF_0_1)); assertEquals(LETTER_A, map.get(OFF_0_1));
@@ -246,7 +246,7 @@ public class SwedishGeneratorTest {
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 dict = DictJavaGeneratorMulti.Dicts.makeDict(WORDS2); var dict = DictJavaGeneratorMulti.Dicts.makeDict(WORDS2);
var slots = Masker.extractSlots(Signa.of(r0c0d1).c(), dict.index(), dict.reversed()); var slots = Masker.extractSlots(Riddle.Signa.of(r0c0d1).c(), dict.index(), dict.reversed());
assertEquals(1, slots.length); assertEquals(1, slots.length);
var s = slots[0]; var s = slots[0];

View File

@@ -6,8 +6,8 @@ import gen.Test123X_Neighbors9x8;
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 puzzle.Export.Signa;
import puzzle.Riddle.Rewards; import puzzle.Riddle.Rewards;
import puzzle.Riddle.Signa;
import puzzle.SwedishGenerator.Rng; import puzzle.SwedishGenerator.Rng;
import puzzle.dict800_4.DictData800_4; import puzzle.dict800_4.DictData800_4;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -31,7 +31,7 @@ public class TestDuplication {
} }
@Test @Test
void testFiller2() { void testFiller2() {
var mask = Signa.of( var mask = Riddle.Signa.of(
r0c0d4, r0c2d0, r0c0d4, r0c2d0,
r1c0d1, r1c0d1,
r2c0d1, r2c0d1,
@@ -45,7 +45,7 @@ public class TestDuplication {
grid.lo = Masker_Neighbors3x4.MASK_LO & ~mask.c().lo; grid.lo = Masker_Neighbors3x4.MASK_LO & ~mask.c().lo;
grid.hi = Masker_Neighbors3x4.MASK_HI & ~mask.c().hi; grid.hi = Masker_Neighbors3x4.MASK_HI & ~mask.c().hi;
var grid1 = new ExportX_Const3x4.Puzzle(grid, mask.c()); var grid1 = new ExportX_Const3x4.Puzzle(grid, mask.c());
var result = new ExportX_Const3x4.PuzzleResult(new ExportX_Const3x4.Signa(mask.c()), grid1, slots, filled); var result = new ExportX_Const3x4.PuzzleResult(new Signa(mask.c()), grid1, slots, filled);
if (filled.ok()) { if (filled.ok()) {
System.out.println(filled); System.out.println(filled);
val res = result.exportFormatFromFilled(new Rewards(0, 0, 0), Masker_Neighbors3x4.IT); val res = result.exportFormatFromFilled(new Rewards(0, 0, 0), Masker_Neighbors3x4.IT);