From 7db439a9dcf4f9eb51c8b8bc062ba6eb518d359a Mon Sep 17 00:00:00 2001 From: mike Date: Fri, 23 Jan 2026 11:58:57 +0100 Subject: [PATCH] redo --- src/main/java/puzzle/Export.java | 90 ++++++++++--------- src/main/java/puzzle/Main.java | 4 +- src/main/java/puzzle/Masker.java | 58 ++++++------ src/main/java/puzzle/SwedishGenerator.java | 9 +- src/test/java/puzzle/MainTest.java | 19 ++-- src/test/java/puzzle/PerformanceTest.java | 35 +++++--- .../java/puzzle/SwedishGeneratorTest.java | 10 +-- src/test/java/puzzle/TestDuplication.java | 10 ++- 8 files changed, 129 insertions(+), 106 deletions(-) diff --git a/src/main/java/puzzle/Export.java b/src/main/java/puzzle/Export.java index 443f5f1..1048433 100644 --- a/src/main/java/puzzle/Export.java +++ b/src/main/java/puzzle/Export.java @@ -1,10 +1,11 @@ package puzzle; import module java.base; +import anno.Shaped; import lombok.AllArgsConstructor; import lombok.experimental.Delegate; import lombok.val; -import precomp.Const9x8.Cell; +import precomp.Const9x8; import puzzle.Export.Puzzle.Replacar.Rell; import puzzle.Meta.ShardLem; import puzzle.SwedishGenerator.Dict; @@ -12,14 +13,16 @@ 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.INIT_GRID_OUTPUT; -import static precomp.Const9x8.INIT_GRID_OUTPUT_ARR; +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.Clues.createEmpty; import static puzzle.Masker.Slot; -import static puzzle.Masker.C; import static puzzle.SwedishGenerator.Lemma; import static puzzle.SwedishGenerator.X; @@ -34,26 +37,30 @@ import static puzzle.SwedishGenerator.X; */ public record Export() { - public static final ThreadLocal BYTES = ThreadLocal.withInitial(() -> new byte[8]); - static final byte CLUE_UP = 2; - static final byte CLUE_LEFT = 3; - static final byte CLUE_LEFT_TOP = 4; - static final byte CLUE_RIGHT_TOP = 5; + public static final ThreadLocal BYTES = ThreadLocal.withInitial(() -> new byte[8]); + static final byte CLUE_UP = 2; + static final byte CLUE_LEFT = 3; + static final byte CLUE_LEFT_TOP = 4; + static final byte CLUE_RIGHT_TOP = 5; + @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; static int HI(int in) { return in | 64; } static char LETTER(int in) { return (char) (in | 64); } static char CLUE_CHAR(int s) { return (char) (s | 48); } - static int INDEX_ROW(int idx) { return idx & 7; } - static int INDEX_COL(int idx) { return idx >>> 3; } + 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_UP, 'C', 'c'), - LEFT3(CLUE_LEFT, 'D', 'd'), - LEFT_TOP4(CLUE_LEFT_TOP, 'E', 'e'), - RIGHT_TOP5(CLUE_RIGHT_TOP, 'F', 'f'), - NONE(CLUE_LEFT, '?', '?'); + 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 }; @@ -113,15 +120,15 @@ public record Export() { for (var h = grid.hi & ~cl.hi & 0xFF; h != X; h &= h - 1) stream.accept(Lettrix.from(64 | Long.numberOfTrailingZeros(h), grid.g)); return stream.build(); } - String gridToString() { + String gridToString(Slotinfo[] slots) { var sb = INIT_GRID_OUTPUT_ARR.clone(); - Masker.forEachSlot(cl, (s, _, _) -> { - val idx = Slot.clueIndex(s); + for (var slot : slots) { + val idx = Slot.clueIndex(slot.key()); val r = idx & 7; val c = idx >>> 3; - val dir = Slot.dir(s); + val dir = Slot.dir(slot.key()); sb[r * (C + 1) + c] = (byte) (dir | 48); - }); + } stream().forEach((l) -> sb[l.index(C + 1)] = (byte) l.human()); return new String(sb); } @@ -137,9 +144,9 @@ public record Export() { stream().forEach((l) -> sb[l.index(C + 1)] = (byte) l.human()); return new String(sb).replaceAll(" ", String.valueOf(emptyFallback)).split("\n"); } - public static IntStream cellWalk(byte base, long lo, long hi) { + public static IntStream cellWalk(int base, long lo, long hi) { if (Slotinfo.increasing(base)) { - return IntStream.concat( + return IntStream.concat(IntStream.of(Slot.clueIndex(base)), IntStream.concat( IntStream.generate(new IntSupplier() { long temp = lo; @@ -159,9 +166,9 @@ public record Export() { temp &= temp - 1; return res; } - }).limit(Long.bitCount(hi))); + }).limit(Long.bitCount(hi)))); } else { - return IntStream.concat( + return IntStream.concat(IntStream.of(Slot.clueIndex(base)), IntStream.concat( IntStream.generate(new IntSupplier() { long temp = hi; @@ -181,11 +188,10 @@ public record Export() { temp &= ~(1L << msb); return msb; } - }).limit(Long.bitCount(lo))); + }).limit(Long.bitCount(lo)))); } } - public String renderHuman() { return String.join("\n", exportGrid(_ -> ' ', '#')); } @FunctionalInterface interface Replacar { @@ -195,16 +201,16 @@ public record Export() { } - record Placed(rci[] rcis, long lemma, int slotKey, int[] cells) { + 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 rcis[Slot.clueIndex(slotKey)].c(); } - public int arrowRow() { return rcis[Slot.clueIndex(slotKey)].r(); } - public int startRow() { return rcis[cells[0]].r(); } - public int startCol() { return rcis[cells[0]].c(); } + public int arrowCol() { return cells[0].c()/*rcis[Slot.clueIndex(slotKey)].c()*/; } + public int arrowRow() { return cells[0].r()/*rcis[Slot.clueIndex(slotKey)].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)]; } } @@ -247,31 +253,33 @@ public record Export() { public record PuzzleResult(Signa clues, Puzzle grid, Slotinfo[] slots, FillResult filled) { + public String gridRenderHuman() { + return String.join("\n", grid.exportGrid(_ -> ' ', '#')); + } + public String gridGridToString() { + return grid.gridToString(slots); + } public ExportedPuzzle exportFormatFromFilled(Rewards rewards, rci[] rcis, int bits) { // If nothing placed: return full grid mapped to letters/# only if (slots.length == 0) { return new ExportedPuzzle(grid.exportGrid(_ -> '#', '#'), new WordOut[0], 1, rewards); } - var placed = Arrays.stream(slots).map(slot -> new Placed(rcis, slot.assign().w, slot.key(), Puzzle.cellWalk((byte) slot.key(), slot.lo(), slot.hi()).toArray())).toArray( - Placed[]::new); + var placed = Arrays.stream(slots) + .map(slot -> new Placed(slot.assign().w, slot.key(), Puzzle.cellWalk(slot.key(), slot.lo(), slot.hi()).mapToObj(i -> rcis[i]).toArray(rci[]::new))) + .toArray(Placed[]::new); // 2) bounding box around all word cells + arrow cells, with 1-cell margin int minR = Integer.MAX_VALUE, minC = Integer.MAX_VALUE; int maxR = Integer.MIN_VALUE, maxC = Integer.MIN_VALUE; for (var rc : placed) { - for (var c : rc.cells) { - val it = rcis[c]; + for (var it : rc.cells) { minR = Math.min(minR, it.r()); minC = Math.min(minC, it.c()); maxR = Math.max(maxR, it.r()); maxC = Math.max(maxC, it.c()); } - minR = Math.min(minR, rc.arrowRow()); - minC = Math.min(minC, rc.arrowCol()); - maxR = Math.max(maxR, rc.arrowRow()); - maxC = Math.max(maxC, rc.arrowCol()); } // 3) map of only used letter cells (everything else becomes '#') @@ -299,6 +307,8 @@ public record Export() { var total = 0.0001d + Arrays.stream(wordsOut).mapToDouble(WordOut::complex).sum(); return new ExportedPuzzle(gridv2, wordsOut, (int) (total / wordsOut.length), rewards); } + + } record Lettrix(int index, byte letter) { diff --git a/src/main/java/puzzle/Main.java b/src/main/java/puzzle/Main.java index e8b52ff..b0efbf6 100644 --- a/src/main/java/puzzle/Main.java +++ b/src/main/java/puzzle/Main.java @@ -96,10 +96,10 @@ public class Main { System.out.print(indentLines(res.clues().gridToString())); section("Grid (raw)"); - System.out.print(indentLines(res.grid().gridToString())); + System.out.print(indentLines(res.gridGridToString())); section("Grid (human)"); - System.out.print(indentLines(res.grid().renderHuman())); + System.out.print(indentLines(res.gridRenderHuman())); var exported = res.exportFormatFromFilled(new Rewards(50, 2, 1), Masker.IT, 3); diff --git a/src/main/java/puzzle/Masker.java b/src/main/java/puzzle/Masker.java index f2dbf0c..59a5204 100644 --- a/src/main/java/puzzle/Masker.java +++ b/src/main/java/puzzle/Masker.java @@ -11,35 +11,37 @@ import static puzzle.SwedishGenerator.*; @GenerateShapedCopies( packageName = "puzzle", className = "Masker", - shapes = { "precomp.Neighbors9x8", "precomp.Neighbors4x3" , "precomp.Neighbors3x4" } + shapes = { "precomp.Neighbors9x8", "precomp.Neighbors4x3", "precomp.Neighbors3x4" } ) public final class Masker { - @Shaped public static final int SIZE = Neighbors9x8.SIZE; - @Shaped public static final rci[] IT = Neighbors9x8.IT; - @Shaped public static final long[] PATH_LO = Neighbors9x8.PATH_LO; - @Shaped public static final long[] PATH_HI = Neighbors9x8.PATH_HI; - @Shaped public static final long MASK_LO = Neighbors9x8.MASK_LO; - @Shaped public static final long MASK_HI = Neighbors9x8.MASK_HI;//(1L << (SIZE - 64)) - 1; - @Shaped public static final int MIN_LEN = Neighbors9x8.MIN_LEN;//Config.MIN_LEN; - @Shaped public static final int C = Neighbors9x8.C; - @Shaped public static final int R = Neighbors9x8.R; - @Shaped public static final double SIZED = Neighbors9x8.SIZED;// ~18 - @Shaped private static final long[] NBR_LO = Neighbors9x8.NBR_LO; - @Shaped private static final long[] NBR_HI = Neighbors9x8.NBR_HI; - public static final int[][] MUTATE_RI = new int[SIZE][625]; - private static final boolean VERBOSE = false; - private final int[] activeCIdx = new int[SIZE]; - private final long[] activeSLo = new long[SIZE]; - private final long[] activeSHi = new long[SIZE]; - private final long[] adjLo = new long[SIZE]; - private final long[] adjHi = new long[SIZE]; - private final int[] rCount = new int[R]; - private final int[] cCount = new int[C]; + @Shaped public static final int SIZE = Neighbors9x8.SIZE; + @Shaped public static final rci[] IT = Neighbors9x8.IT; + @Shaped public static final long[] PATH_LO = Neighbors9x8.PATH_LO; + @Shaped public static final long[] PATH_HI = Neighbors9x8.PATH_HI; + @Shaped public static final long MASK_LO = Neighbors9x8.MASK_LO; + @Shaped public static final long RANGE_0_SIZE = Neighbors9x8.RANGE_0_SIZE; + @Shaped public static final long RANGE_0_624 = Neighbors9x8.RANGE_0_624; + @Shaped public static final long MASK_HI = Neighbors9x8.MASK_HI;//(1L << (SIZE - 64)) - 1; + @Shaped public static final int MIN_LEN = Neighbors9x8.MIN_LEN;//Config.MIN_LEN; + @Shaped public static final int C = Neighbors9x8.C; + @Shaped public static final int R = Neighbors9x8.R; + @Shaped public static final double SIZED = Neighbors9x8.SIZED;// ~18 + @Shaped private static final long[] NBR_LO = Neighbors9x8.NBR_LO; + @Shaped private static final long[] NBR_HI = Neighbors9x8.NBR_HI; + public static final int[][] MUTATE_RI = new int[SIZE][625]; + private static final boolean VERBOSE = false; + private final int[] activeCIdx = new int[SIZE]; + private final long[] activeSLo = new long[SIZE]; + private final long[] activeSHi = new long[SIZE]; + private final long[] adjLo = new long[SIZE]; + private final long[] adjHi = new long[SIZE]; + private final int[] rCount = new int[R]; + private final int[] cCount = new int[C]; private final Rng rng; private final int[] stack; private final Clues cache; - public static final int STACK_SIZE = 128; + public static final int STACK_SIZE = 128; public Masker(Rng rng, int[] stack, Clues cache) { this.rng = rng; this.stack = stack; @@ -75,7 +77,7 @@ public final class Masker { if (num == 0) return -1; - var start = rng.randint0_SIZE() % num; + var start = rng.randint0_SIZE(RANGE_0_SIZE) % num; var n = 0; for (var i = 0; i < num; i++) { var idx = activeCIdx[(start + i) % num]; @@ -470,7 +472,7 @@ public final class Masker { var g = Clues.createEmpty(); for (int placed = 0, guard = 0, ri; placed < clueSize && guard < 4000; guard++) { - ri = rng.randint0_SIZE(); + ri = rng.randint0_SIZE(RANGE_0_SIZE); if (isLo(ri)) { if (g.isClueLo(ri)) continue; var d_idx = rng.randomClueDir(); @@ -496,9 +498,9 @@ public final class Masker { } public Clues mutate(Clues c) { - var bytes = MUTATE_RI[rng.randint0_SIZE()]; + var bytes = MUTATE_RI[rng.randint0_SIZE(RANGE_0_SIZE)]; for (int k = 0, ri; k < 6; k++) { - ri = bytes[rng.randint0_624()]; + ri = bytes[rng.randint0_624(RANGE_0_624)]; if (c.notClue(ri)) { // ADD var d = rng.randomClueDir(); var key = Slot.packSlotKey(ri, d); @@ -543,7 +545,7 @@ public final class Masker { } } } // MOVE - var nri = bytes[rng.randint0_624()]; + var nri = bytes[rng.randint0_624(RANGE_0_624)]; if (c.notClue(nri)) { var d = c.getDir(ri); var nkey = Slot.packSlotKey(nri, d); diff --git a/src/main/java/puzzle/SwedishGenerator.java b/src/main/java/puzzle/SwedishGenerator.java index 1838fc0..456d3d3 100644 --- a/src/main/java/puzzle/SwedishGenerator.java +++ b/src/main/java/puzzle/SwedishGenerator.java @@ -3,11 +3,9 @@ package puzzle; import anno.ConstGen; import anno.GenerateNeighbor; import anno.GenerateNeighbors; -import anno.Shaped; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; import lombok.val; -import precomp.Neighbors9x8; import static java.lang.Long.bitCount; import static java.lang.Long.numberOfLeadingZeros; import static java.lang.Long.numberOfTrailingZeros; @@ -40,9 +38,6 @@ public record SwedishGenerator() { public static final int MAX_TRIES_PER_SLOT = 500;// MAX_TRIES_PER_SLOT; public static final long X = 0L; - @Shaped static final int SIZE = Neighbors9x8.SIZE; - @Shaped private static final long RANGE_0_SIZE = Neighbors9x8.RANGE_0_SIZE; - @Shaped private static final long RANGE_0_624 = Neighbors9x8.RANGE_0_624; interface Bit1029 { @@ -80,8 +75,8 @@ public record SwedishGenerator() { public byte randomClueDir() { return rand(BYTE); } public T rand(T[] p) { return p[(int) (((nextU32() & 0xFFFFFFFFL) % ((long) p.length)))]; } public byte rand(byte[] p) { return p[(int) (((nextU32() & 0xFFFFFFFFL) % ((long) p.length)))]; } - public int randint0_SIZE() { return (int) (((nextU32() & 0xFFFFFFFFL) % RANGE_0_SIZE)); } - public int randint0_624() { return (int) (((nextU32() & 0xFFFFFFFFL) % RANGE_0_624)); } + public int randint0_SIZE(long range0size) { return (int) (((nextU32() & 0xFFFFFFFFL) % range0size)); } + public int randint0_624(long range0624) { return (int) (((nextU32() & 0xFFFFFFFFL) % range0624)); } public double nextFloat() { return (nextU32() & 0xFFFFFFFFL) / 4294967295.0; } public int biasedIndexPow3(int N) { return (int) (((Math.min(nextU32(), Math.min(nextU32(), nextU32())) & 0xFFFFFFFFL) * (long) N) >>> 32); } } diff --git a/src/test/java/puzzle/MainTest.java b/src/test/java/puzzle/MainTest.java index 0d99dde..2ab7975 100644 --- a/src/test/java/puzzle/MainTest.java +++ b/src/test/java/puzzle/MainTest.java @@ -58,11 +58,11 @@ public class MainTest { assertEquals(1, slots.length); var s = slots[0]; assertEquals(8, Masker.Slot.length(s.lo(), s.hi())); - var cells = Puzzle.cellWalk((byte) s.key(), s.lo(), s.hi()).mapToObj(c -> Masker.IT[c]).toArray(rci[]::new); - assertEquals(0, cells[0].r()); - assertEquals(1, cells[0].c()); + var cells = Puzzle.cellWalk(s.key(), s.lo(), s.hi()).mapToObj(c -> Masker.IT[c]).toArray(rci[]::new); assertEquals(0, cells[1].r()); - assertEquals(2, cells[1].c()); + assertEquals(1, cells[1].c()); + assertEquals(0, cells[2].r()); + assertEquals(2, cells[2].c()); } @Test @@ -186,9 +186,10 @@ public class MainTest { Assertions.assertEquals("BEADEMT", Lemma.asWord(slotInfo[0].assign().w, Export.BYTES.get())); Assertions.assertEquals(74732156493031040L, grid.lo); Assertions.assertEquals(193L, grid.hi); - var g = new Puzzle(grid, mask.c()); - g.gridToString(); - var aa = new PuzzleResult(mask, g, slotInfo, filled).exportFormatFromFilled(new Rewards(1, 1, 1), Masker.IT, 3); + var g = new Puzzle(grid, mask.c()); + var result = new PuzzleResult(mask, g, slotInfo, filled); + var aa = result.exportFormatFromFilled(new Rewards(1, 1, 1), Masker.IT, 3); + result.gridGridToString(); System.out.println(String.join("\n", aa.grid())); } @@ -204,8 +205,8 @@ public class MainTest { System.out.println("[DEBUG_LOG] Seed found: " + seed); System.out.println("[DEBUG_LOG] ClueMap Size: " + Slotinfo.wordCount(0, res.slots())); System.out.println("[DEBUG_LOG] Grid:"); - System.out.println(res.grid().renderHuman()); - System.out.println(res.grid().gridToString()); + System.out.println(res.gridRenderHuman()); + System.out.println(res.gridGridToString()); break; } } diff --git a/src/test/java/puzzle/PerformanceTest.java b/src/test/java/puzzle/PerformanceTest.java index 39efaa0..0295c91 100644 --- a/src/test/java/puzzle/PerformanceTest.java +++ b/src/test/java/puzzle/PerformanceTest.java @@ -31,6 +31,13 @@ import static puzzle.dict900.DictData900.DICT900; simpleMax = 800, minLen = 2, maxLen = 8 +), @DictGen( + packageName = "puzzle.dict800_4", + className = "DictData800_4", + scv = "/home/mike/dev/puzzle-generator/nl_score_hints_v4.csv", + simpleMax = 800, + minLen = 2, + maxLen = 4 ) }) public class PerformanceTest { @@ -73,7 +80,7 @@ public class PerformanceTest { for (var i = 0; i < iterations; i++) { val slotInfo = Masker.slots(arr[c], DICT800); var grid = Masker.grid(slotInfo); - val result = fillMask(rng, slotInfo,grid.lo,grid.hi, grid.g); + val result = fillMask(rng, slotInfo, grid.lo, grid.hi, grid.g); if (result.ok()) successCount++; totalNodes += result.nodes(); totalBacktracks += result.backtracks(); @@ -143,7 +150,7 @@ public class PerformanceTest { for (var s : slots) s.assign().w = 0; var grid = Masker.grid(slots); - val result = fillMask(rng, slots, grid.lo,grid.hi,grid.g); + val result = fillMask(rng, slots, grid.lo, grid.hi, grid.g); if (result.ok()) { successCount++; } @@ -178,17 +185,19 @@ public class PerformanceTest { var slotChar = dir.slotChar; display[cr][cc] = clueChar; - Puzzle.cellWalk((byte) slot.key(), slot.lo(), slot.hi()).forEach(idx -> { - var r = Masker.IT[idx].r(); - var c = Masker.IT[idx].c(); - if (display[r][c] == ' ' || (display[r][c] >= 'A' && display[r][c] <= 'D')) { - if (display[r][c] != ' ' && display[r][c] != slotChar) { - display[r][c] = '+'; // Intersection - } else { - display[r][c] = slotChar; - } - } - }); + Puzzle.cellWalk(slot.key(), slot.lo(), slot.hi()) + .skip(1) + .forEach(idx -> { + var r = Masker.IT[idx].r(); + var c = Masker.IT[idx].c(); + if (display[r][c] == ' ' || (display[r][c] >= 'A' && display[r][c] <= 'D')) { + if (display[r][c] != ' ' && display[r][c] != slotChar) { + display[r][c] = '+'; // Intersection + } else { + display[r][c] = slotChar; + } + } + }); } for (var r = 0; r < R; r++) { diff --git a/src/test/java/puzzle/SwedishGeneratorTest.java b/src/test/java/puzzle/SwedishGeneratorTest.java index e9bd98c..4feb594 100644 --- a/src/test/java/puzzle/SwedishGeneratorTest.java +++ b/src/test/java/puzzle/SwedishGeneratorTest.java @@ -168,13 +168,13 @@ public class SwedishGeneratorTest { assertEquals(OFF_2_3, Slot.clueIndex(r2c3d0.slotKey)); assertEquals(CLUE_DOWN0, Slot.dir(r2c3d0.slotKey)); assertFalse(Slot.horiz(r2c3d0.slotKey)); - var cells = Puzzle.cellWalk((byte) r2c3d0.slotKey, r2c5.or(r3c5).or(r4c5).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()); + var cells = Puzzle.cellWalk( r2c3d0.slotKey, r2c5.or(r3c5).or(r4c5).lo(), 0L).mapToObj(i -> Masker.IT[i]).toArray(rci[]::new); + assertEquals(2, cells[1].r()); assertEquals(5, cells[1].c()); + assertEquals(3, cells[2].r()); assertEquals(5, cells[2].c()); + assertEquals(4, cells[3].r()); + assertEquals(5, cells[3].c()); assertTrue(Slot.horiz(CLUE_RIGHT1)); // right assertFalse(Slot.horiz(CLUE_DOWN0)); // down diff --git a/src/test/java/puzzle/TestDuplication.java b/src/test/java/puzzle/TestDuplication.java index f16bb2b..2308d9a 100644 --- a/src/test/java/puzzle/TestDuplication.java +++ b/src/test/java/puzzle/TestDuplication.java @@ -13,6 +13,7 @@ import puzzle.Export.Signa; import puzzle.Export.Vestigium; 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; @@ -29,6 +30,10 @@ public class TestDuplication { Test123X_Neighbors4x3.start(); Test123X_Neighbors9x8.start(); } + static void main() { + TestDuplication test = new TestDuplication(); + test.testFiller2(); + } @Test void testFiller2() { var mask = Signa.of( @@ -39,14 +44,15 @@ public class TestDuplication { Assertions.assertEquals(5, mask.clueCount()); val map = mask.stream().collect(Collectors.toMap(Vestigium::index, Vestigium::clue)); Assertions.assertEquals(5, map.size()); - var slots = Masker_Neighbors3x4.slots(mask.c(), DictData800.DICT800); + var slots = Masker_Neighbors3x4.slots(mask.c(), DictData800_4.DICT800); var grid = Masker_Neighbors3x4.grid(slots); var filled = SwedishGenerator.fillMask(new Rng(1), slots, grid.lo, grid.hi, grid.g); - 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; var grid1 = new Puzzle(grid, mask.c()); var result = new PuzzleResult(new Signa(mask.c()), grid1, slots, filled); if (filled.ok()) { + System.out.println(filled); val res = result.exportFormatFromFilled(new Rewards(0, 0, 0), Masker_Neighbors3x4.IT, 2); System.out.println(String.join("\n", res.grid())); }