This commit is contained in:
mike
2026-01-23 20:33:36 +01:00
parent fa3e8ef1ed
commit 73192f5905
8 changed files with 132 additions and 116 deletions

View File

@@ -3,27 +3,28 @@ package puzzle;
import module java.base;
import anno.GenerateShapedCopies;
import anno.Shaped;
import lombok.AllArgsConstructor;
import lombok.experimental.Delegate;
import lombok.val;
import precomp.Const9x8;
import puzzle.Meta.ShardLem;
import puzzle.Replacar.Rell;
import puzzle.Riddle.ExportedPuzzle;
import puzzle.Riddle.Placed;
import puzzle.Riddle.Rewards;
import puzzle.Riddle.Vestigium;
import puzzle.Riddle.WordOut;
import puzzle.SwedishGenerator.FillResult;
import puzzle.SwedishGenerator.Grid;
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_NONE;
import static precomp.Const9x8.CLUE_RIGHT1;
import static precomp.Const9x8.CLUE_RIGHT_TOP5;
import static precomp.Const9x8.CLUE_UP2;
import static puzzle.Export.Clue.DOWN0;
import static puzzle.Export.Clue.RIGHT1;
import static puzzle.Riddle.Clue.DOWN0;
import static puzzle.Riddle.Clue.RIGHT1;
import static puzzle.Clues.createEmpty;
import static puzzle.Masker.Slot;
import static puzzle.SwedishGenerator.Lemma;
import static puzzle.SwedishGenerator.X;
@GenerateShapedCopies(
@@ -47,22 +48,6 @@ public record Export() {
static int INDEX_ROW(int idx) { return idx % R; }
static int INDEX_COL(int idx) { return idx / R; }
static int INDEX(int r, int cols, int c) { return r * cols + c; }
@AllArgsConstructor
enum Clue {
DOWN0(CLUE_DOWN0, 'B', 'b'),
RIGHT1(CLUE_RIGHT1, 'A', 'a'),
UP2(CLUE_UP2, 'C', 'c'),
LEFT3(CLUE_LEFT3, 'D', 'd'),
LEFT_TOP4(CLUE_LEFT_TOP4, 'E', 'e'),
RIGHT_TOP5(CLUE_RIGHT_TOP5, 'F', 'f'),
NONE(CLUE_NONE, '?', '?');
final byte dir;
final char slotChar, clueChar;
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 record Vestigium(int index, int clue) { }
public record Signa(@Delegate Clues c) {
@@ -83,13 +68,13 @@ public record Export() {
public Signa deepCopyGrid() { return new Signa(new Clues(c.lo, c.hi, c.vlo, c.vhi, c.rlo, c.rhi, c.xlo, c.xhi)); }
String gridToString() {
var sb = new StringBuilder(INIT_GRID_OUTPUT);
stream().forEach(v -> sb.setCharAt(INDEX(INDEX_ROW(v.index), C + 1, INDEX_COL(v.index)), CLUE_CHAR(v.clue)));
stream().forEach(v -> sb.setCharAt(INDEX(INDEX_ROW(v.index()), C + 1, INDEX_COL(v.index())), CLUE_CHAR(v.clue())));
return sb.toString();
}
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), RIGHT1.dir));
for (var l = c.lo & ~c.xlo & ~c.rlo & ~c.vlo; l != X; l &= l - 1) stream.accept(new Vestigium(Long.numberOfTrailingZeros(l), DOWN0.dir));
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));
@@ -114,7 +99,7 @@ public record Export() {
public @Delegate Stream<Lettrix> stream() {
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 h = grid.hi & MASK_HI & ~cl.hi; h != X; h &= h - 1) stream.accept(Lettrix.from(64 | Long.numberOfTrailingZeros(h), grid.g));
for (var h = grid.hi & MASK_HI & ~cl.hi; h != X; h &= h - 1) stream.accept(Lettrix.from(HI(Long.numberOfTrailingZeros(h)), grid.g));
return stream.build();
}
public String[] exportGrid(Slotinfo[] slots, Replacar clueChar, char emptyFallback) {
@@ -179,56 +164,6 @@ public record Export() {
}
record Placed(long lemma, int slotKey, rci[] cells) {
public static final char HORIZONTAL = 'h';
static final char VERTICAL = 'v';
static final char[] DIRECTION = { Placed.VERTICAL, Placed.HORIZONTAL, Placed.VERTICAL, Placed.HORIZONTAL, Placed.VERTICAL, Placed.VERTICAL };
public int arrowCol() { return cells[0].c(); }
public int arrowRow() { return cells[0].r(); }
public int startRow() { return cells[1].r(); }
public int startCol() { return cells[1].c(); }
public boolean isReversed() { return !Slotinfo.increasing(slotKey); }
public char direction() { return DIRECTION[Slot.dir(slotKey)]; }
}
public record Rewards(int coins, int stars, int hints) { }
public record WordOut(String word, int[] cell, int startRow, int startCol, char direction, int arrowRow, int arrowCol, boolean isReversed, int complex, String[] clue) {
record ShaLemma(String word, @Delegate ShardLem rec) { }
private static ShaLemma lookup(long w, byte[] bytes) {
try {
val rec = Meta.lookupSilent(w);
System.out.println("\nQuery: w=" + w + " -> i=" + rec.mmap());
var word1 = Lemma.asWord(w, bytes);
System.out.println(" word=" + word1 + "\n" + " simpel=" + rec.simpel() + "\n" + " clues=" + Arrays.toString(rec.clues()));
return new ShaLemma(word1, rec);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static long reverse(long w) {
int L = Lemma.unpackSize(w) + 1;
long letters = w & Lemma.LETTER_MASK;
long rev = 0;
for (int i = 0; i < L; i++) {
long letter = (letters >>> (5 * i)) & 31;
rev |= (letter << (5 * (L - 1 - i)));
}
return (w & ~Lemma.LETTER_MASK) | rev;
}
public WordOut(long l, int startRow, int startCol, char d, int arrowRow, int arrowCol, boolean isReversed, byte[] bytes) {
val meta = lookup(isReversed ? reverse(l) : l, bytes);
this(meta.word, new int[]{ arrowRow, arrowCol, startRow, startCol }, startRow, startCol, d, arrowRow, arrowCol, isReversed,
meta.simpel(), meta.clues());
}
}
public record ExportedPuzzle(String[] grid, WordOut[] words, int difficulty, Rewards rewards) { }
public record PuzzleResult(Signa clues, Puzzle grid, Slotinfo[] slots, FillResult filled) {
public String cluesGridToString() {
@@ -264,7 +199,7 @@ public record Export() {
int maxR = Integer.MIN_VALUE, maxC = Integer.MIN_VALUE;
for (var rc : placed) {
for (var it : rc.cells) {
for (var it : rc.cells()) {
minR = Math.min(minR, it.r());
minC = Math.min(minC, it.c());
maxR = Math.max(maxR, it.r());
@@ -292,7 +227,7 @@ public record Export() {
val bytes = BYTES.get();
var wordsOut = Arrays.stream(placed).map(p -> new WordOut(
p.lemma,
p.lemma(),
p.startRow() - MINR,
p.startCol() - MINC,
p.direction(),
@@ -300,7 +235,7 @@ public record Export() {
p.arrowCol() - MINC,
p.isReversed(), bytes
)).toArray(WordOut[]::new);
var total = 0.0001d + Arrays.stream(wordsOut).mapToDouble(WordOut::complex).sum();
var total = 0.0001d + Arrays.stream(wordsOut).mapToDouble(Riddle.WordOut::complex).sum();
return new ExportedPuzzle(grid, wordsOut, (int) (total / wordsOut.length), rewards);
}

View File

@@ -9,6 +9,9 @@ import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.val;
import puzzle.Riddle.ExportedPuzzle;
import puzzle.Riddle.Rewards;
import puzzle.Riddle.WordOut;
import puzzle.SwedishGenerator.Rng;
import static puzzle.Export.*;

View File

@@ -47,6 +47,9 @@ public final class Masker {
this.stack = stack;
this.cache = cache;
}
public Clues cache(Clues clues){
return cache.from(clues);
}
public static boolean isLo(int n) { return (n & 64) == 0; }
public static double similarity(Clues a, Clues b) {
var matchLo = (~(a.lo ^ b.lo)) & (~a.lo | (~(a.vlo ^ b.vlo) & ~(a.rlo ^ b.rlo) & ~(a.xlo ^ b.xlo)));

View File

@@ -0,0 +1,86 @@
package puzzle;
import lombok.AllArgsConstructor;
import lombok.experimental.Delegate;
import lombok.val;
import puzzle.Masker.Slot;
import puzzle.Meta.ShardLem;
import puzzle.SwedishGenerator.Lemma;
import puzzle.SwedishGenerator.Slotinfo;
import java.util.Arrays;
import static precomp.Const9x8.CLUE_DOWN0;
import static precomp.Const9x8.CLUE_LEFT3;
import static precomp.Const9x8.CLUE_LEFT_TOP4;
import static precomp.Const9x8.CLUE_NONE;
import static precomp.Const9x8.CLUE_RIGHT1;
import static precomp.Const9x8.CLUE_RIGHT_TOP5;
import static precomp.Const9x8.CLUE_UP2;
public class Riddle {
@AllArgsConstructor
enum Clue {
DOWN0(CLUE_DOWN0, 'B', 'b'),
RIGHT1(CLUE_RIGHT1, 'A', 'a'),
UP2(CLUE_UP2, 'C', 'c'),
LEFT3(CLUE_LEFT3, 'D', 'd'),
LEFT_TOP4(CLUE_LEFT_TOP4, 'E', 'e'),
RIGHT_TOP5(CLUE_RIGHT_TOP5, 'F', 'f'),
NONE(CLUE_NONE, '?', '?');
final byte dir;
final char slotChar, clueChar;
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 record Vestigium(int index, int clue) { }
record Placed(long lemma, int slotKey, rci[] cells) {
public static final char HORIZONTAL = 'h';
static final char VERTICAL = 'v';
static final char[] DIRECTION = { Placed.VERTICAL, Placed.HORIZONTAL, Placed.VERTICAL, Placed.HORIZONTAL, Placed.VERTICAL, Placed.VERTICAL };
public int arrowCol() { return cells[0].c(); }
public int arrowRow() { return cells[0].r(); }
public int startRow() { return cells[1].r(); }
public int startCol() { return cells[1].c(); }
public boolean isReversed() { return !Slotinfo.increasing(slotKey); }
public char direction() { return DIRECTION[Slot.dir(slotKey)]; }
}
public record ExportedPuzzle(String[] grid, WordOut[] words, int difficulty, Rewards rewards) { }
public record Rewards(int coins, int stars, int hints) { }
public record WordOut(String word, int[] cell, int startRow, int startCol, char direction, int arrowRow, int arrowCol, boolean isReversed, int complex, String[] clue) {
record ShaLemma(String word, @Delegate ShardLem rec) { }
private static ShaLemma lookup(long w, byte[] bytes) {
try {
val rec = Meta.lookupSilent(w);
System.out.println("\nQuery: w=" + w + " -> i=" + rec.mmap());
var word1 = Lemma.asWord(w, bytes);
System.out.println(" word=" + word1 + "\n" + " simpel=" + rec.simpel() + "\n" + " clues=" + Arrays.toString(rec.clues()));
return new ShaLemma(word1, rec);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static long reverse(long w) {
int L = Lemma.unpackSize(w) + 1;
long letters = w & Lemma.LETTER_MASK;
long rev = 0;
for (int i = 0; i < L; i++) {
long letter = (letters >>> (5 * i)) & 31;
rev |= (letter << (5 * (L - 1 - i)));
}
return (w & ~Lemma.LETTER_MASK) | rev;
}
public WordOut(long l, int startRow, int startCol, char d, int arrowRow, int arrowCol, boolean isReversed, byte[] bytes) {
val meta = lookup(isReversed ? reverse(l) : l, bytes);
this(meta.word, new int[]{ arrowRow, arrowCol, startRow, startCol }, startRow, startCol, d, arrowRow, arrowCol, isReversed,
meta.simpel(), meta.clues());
}
}
}

View File

@@ -5,12 +5,11 @@ import anno.DictGen;
import lombok.val;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import puzzle.Export.Vestigium;
import puzzle.Export.Signa;
import puzzle.Export.Puzzle;
import puzzle.Export.Lettrix;
import puzzle.Export.PuzzleResult;
import puzzle.Export.Rewards;
import puzzle.Riddle.Rewards;
import puzzle.Main.Opts;
import puzzle.SwedishGenerator.Rng;
import puzzle.dict950.DictData950;
@@ -20,7 +19,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static precomp.Const9x8.*;
import static precomp.Const9x8.Cell.*;
import static puzzle.Export.Clue.*;
import static puzzle.Riddle.Clue.*;
import static puzzle.LemmaData.AB;
import static puzzle.LemmaData.AZ;
import static puzzle.SwedishGenerator.Lemma;
@@ -104,7 +103,7 @@ public class MainTest {
val map = grid.collect(Collectors.toMap(Lettrix::index, Lettrix::letter));
Assertions.assertEquals(LETTER_A, map.get(OFF_1_1));
Assertions.assertEquals(LETTER_Z, map.get(OFF_0_1));
var clueMap = clues.stream().collect(Collectors.toMap(Vestigium::index, Vestigium::clue));
var clueMap = clues.stream().collect(Collectors.toMap(Riddle.Vestigium::index, Riddle.Vestigium::clue));
Assertions.assertEquals(1, clueMap.size());
Assertions.assertEquals(UP2.dir, clueMap.get(OFF_2_1));
@@ -117,7 +116,7 @@ public class MainTest {
// Test isDigitAt
Assertions.assertFalse(clues.isClueLo(OFF_0_0));
Assertions.assertTrue(clues.isClueLo(OFF_2_1));
clueMap = clues.stream().collect(Collectors.toMap(Vestigium::index, Vestigium::clue));
clueMap = clues.stream().collect(Collectors.toMap(Riddle.Vestigium::index, Riddle.Vestigium::clue));
Assertions.assertEquals(UP2.dir, clueMap.get(OFF_2_1));
Assertions.assertFalse(clues.isClueLo(OFF_2_3));
Assertions.assertFalse(clues.isClueLo(OFF_1_1));
@@ -132,11 +131,11 @@ public class MainTest {
var clues = Signa.of(r0c0d1, r0c1d2, r1c0d3, r1c1d0);
var copy = clues.deepCopyGrid();
var clueMap = clues.stream().collect(Collectors.toMap(Vestigium::index, Vestigium::clue));
var clueMap = clues.stream().collect(Collectors.toMap(Riddle.Vestigium::index, Riddle.Vestigium::clue));
Assertions.assertEquals(RIGHT1.dir, clueMap.get(OFF_0_0));
copy.setClue(r0c0d0);
var copied = copy.stream().collect(Collectors.toMap(Vestigium::index, Vestigium::clue));
var copied = copy.stream().collect(Collectors.toMap(Riddle.Vestigium::index, Riddle.Vestigium::clue));
Assertions.assertEquals(DOWN0.dir, copied.get(OFF_0_0));
Assertions.assertEquals(RIGHT1.dir, clueMap.get(OFF_0_0));
}
@@ -158,7 +157,7 @@ public class MainTest {
r7c0d2, r7c1d2, r7c2d2, r7c8d3
);
Assertions.assertEquals(20, mask.clueCount());
val map = mask.stream().collect(Collectors.toMap(Vestigium::index, Vestigium::clue));
val map = mask.stream().collect(Collectors.toMap(Riddle.Vestigium::index, Riddle.Vestigium::clue));
Assertions.assertEquals(20, map.size());
var slots = Masker.slots(mask.c(), DictData950.DICT950.index(), DictData950.DICT950.reversed());
// var filled = fillMask(rng, slotInfo, grid, false);

View File

@@ -4,9 +4,8 @@ import lombok.val;
import org.junit.jupiter.api.Test;
import puzzle.Export.Signa;
import puzzle.Export.Puzzle;
import puzzle.Export.Placed;
import puzzle.Export.PuzzleResult;
import puzzle.Export.Rewards;
import puzzle.Riddle.Rewards;
import puzzle.SwedishGenerator.Assign;
import puzzle.SwedishGenerator.FillResult;
import puzzle.SwedishGenerator.Lemma;
@@ -27,10 +26,13 @@ import static puzzle.Masker.STACK_SIZE;
public class MarkerTest {
private static Masker emptyMasker() {
return new Masker(new Rng(42), new int[STACK_SIZE], Clues.createEmpty());
}
@Test
void testValidRandomMask() {
var rng = new Rng(42);
var masker = new Masker(rng, new int[STACK_SIZE], Clues.createEmpty());
var masker = emptyMasker();
for (var i = 0; i < 200; i++) {
for (var j = 19; j < 24; j++) {
var clues = masker.randomMask(j);
@@ -40,15 +42,13 @@ public class MarkerTest {
}
@Test
void testValidMutate() {
var rng = new Rng(42);
var cache = Clues.createEmpty();
var masker = new Masker(rng, new int[STACK_SIZE], cache);
var masker = emptyMasker();
var sim = 0.0;
var simCount = 0.0;
for (var i = 0; i < 200; i++) {
for (var j = 19; j < 24; j++) {
var clues = masker.randomMask(j);
val orig = cache.from(clues);
val orig = masker.cache(clues);
simCount++;
masker.mutate(clues);
sim += Masker.similarity(orig, clues);
@@ -59,9 +59,7 @@ public class MarkerTest {
}
@Test
void testCross() {
var rng = new Rng(42);
var cache = Clues.createEmpty();
var masker = new Masker(rng, new int[STACK_SIZE], cache);
var masker = emptyMasker();
var sim = 0.0;
var simCount = 0.0;
for (var i = 0; i < 200; i++) {
@@ -97,7 +95,7 @@ public class MarkerTest {
@Test
void testIsValid() {
var masker = new Masker(new Rng(42), new int[STACK_SIZE], Clues.createEmpty());
var masker = emptyMasker();
assertTrue(masker.isValid(Clues.createEmpty()));
// Valid clue: Right from (0,0) in 9x8 grid. Length is 8.
@@ -132,7 +130,7 @@ public class MarkerTest {
@Test
void testIntersectionConstraint() {
var masker = new Masker(new Rng(42), new int[STACK_SIZE], Clues.createEmpty());
var masker = emptyMasker();
// 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)
// Intersection is exactly 1 cell (0,2). Valid.
@@ -152,7 +150,7 @@ public class MarkerTest {
@Test
void testInvalidDirectionBits() {
var masker = new Masker(new Rng(42), new int[STACK_SIZE], Clues.createEmpty());
var masker = emptyMasker();
var g = Clues.createEmpty();
// Dir 6 (x=1, r=1, v=0) is invalid
g.setClueLo(1L << 0, (byte) 6);
@@ -165,8 +163,7 @@ public class MarkerTest {
}
@Test
void testConnectivityPenalty() {
var rng = new Rng(42);
var masker = new Masker(rng, new int[STACK_SIZE], Clues.createEmpty());
var masker = emptyMasker();
// 1. Maak een masker met één component van clues (bijv. 2 clues die elkaar kruisen)
var singleComp = Clues.createEmpty().setClue(r0c0d1).setClue(r2c2d2);
@@ -209,8 +206,7 @@ public class MarkerTest {
@Test
void testCornerClueConnectivity() {
var rng = new Rng(42);
var masker = new Masker(rng, new int[STACK_SIZE], Clues.createEmpty());
var masker = emptyMasker();
// Clue A: (2,0) Right. Slot: (2,1), (2,2), (2,3), ...
// Clue B: (1,2) Corner Down. Word starts at (1,3) en gaat omlaag: (1,3), (2,3), (3,3)...
@@ -316,7 +312,7 @@ public class MarkerTest {
assertEquals(1, exported.words().length);
var w = exported.words()[0];
assertEquals("TEST", w.word());
assertEquals(Placed.HORIZONTAL, w.direction());
assertEquals(Riddle.Placed.HORIZONTAL, w.direction());
// The bounding box should include (0,0) for the arrow and (0,1)-(0,4) for the word.
// minR=0, maxR=0, minC=0, maxC=4

View File

@@ -5,7 +5,6 @@ import anno.DictGen;
import anno.Dictionaries;
import lombok.val;
import org.junit.jupiter.api.Test;
import puzzle.Export.Clue;
import puzzle.Export.Signa;
import puzzle.Export.Puzzle;
import puzzle.SwedishGenerator.Rng;
@@ -173,7 +172,7 @@ public class PerformanceTest {
for (var slot : slots) {
var key = slot.key();
var dir = Clue.from(Masker.Slot.dir(key));
var dir = Riddle.Clue.from(Masker.Slot.dir(key));
var clueIdx = Masker.Slot.clueIndex(key);
var cr = Masker.IT[clueIdx].r();

View File

@@ -6,15 +6,10 @@ import gen.Test123X_Neighbors9x8;
import lombok.val;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import puzzle.Export.Puzzle;
import puzzle.Export.PuzzleResult;
import puzzle.Export.Rewards;
import puzzle.Export.Signa;
import puzzle.Export.Vestigium;
import puzzle.Riddle.Rewards;
import puzzle.SwedishGenerator.Rng;
import puzzle.dict800.DictData800;
import puzzle.dict800_4.DictData800_4;
import java.util.Arrays;
import java.util.stream.Collectors;
import static precomp.Const3x4.Cell.r0c0d4;
import static precomp.Const3x4.Cell.r0c2d0;
@@ -42,7 +37,7 @@ public class TestDuplication {
r2c0d1,
r3c0d1);
Assertions.assertEquals(5, mask.clueCount());
val map = mask.stream().collect(Collectors.toMap(Vestigium::index, Vestigium::clue));
val map = mask.stream().collect(Collectors.toMap(Riddle.Vestigium::index, Riddle.Vestigium::clue));
Assertions.assertEquals(5, map.size());
var slots = Masker_Neighbors3x4.slots(mask.c(), DictData800_4.DICT800);
var grid = Masker_Neighbors3x4.grid(slots);
@@ -53,7 +48,7 @@ public class TestDuplication {
var result = new ExportX_Const3x4.PuzzleResult(new ExportX_Const3x4.Signa(mask.c()), grid1, slots, filled);
if (filled.ok()) {
System.out.println(filled);
val res = result.exportFormatFromFilled(new ExportX_Const3x4.Rewards(0, 0, 0), Masker_Neighbors3x4.IT);
val res = result.exportFormatFromFilled(new Rewards(0, 0, 0), Masker_Neighbors3x4.IT);
System.out.println(String.join("\n", res.grid()));
}
}