redo
This commit is contained in:
@@ -195,16 +195,16 @@ public record Export() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
record Placed(long lemma, int slotKey, int[] cells) {
|
record Placed(rci[] rcis, long lemma, int slotKey, int[] cells) {
|
||||||
|
|
||||||
public static final char HORIZONTAL = 'h';
|
public static final char HORIZONTAL = 'h';
|
||||||
static final char VERTICAL = 'v';
|
static final char VERTICAL = 'v';
|
||||||
static final char[] DIRECTION = { Placed.VERTICAL, Placed.HORIZONTAL, Placed.VERTICAL, Placed.HORIZONTAL, Placed.VERTICAL, Placed.VERTICAL };
|
static final char[] DIRECTION = { Placed.VERTICAL, Placed.HORIZONTAL, Placed.VERTICAL, Placed.HORIZONTAL, Placed.VERTICAL, Placed.VERTICAL };
|
||||||
|
|
||||||
public int arrowCol() { return Masker.IT[Slot.clueIndex(slotKey)].c(); }
|
public int arrowCol() { return rcis[Slot.clueIndex(slotKey)].c(); }
|
||||||
public int arrowRow() { return Masker.IT[Slot.clueIndex(slotKey)].r(); }
|
public int arrowRow() { return rcis[Slot.clueIndex(slotKey)].r(); }
|
||||||
public int startRow() { return Masker.IT[cells[0]].r(); }
|
public int startRow() { return rcis[cells[0]].r(); }
|
||||||
public int startCol() { return Masker.IT[cells[0]].c(); }
|
public int startCol() { return rcis[cells[0]].c(); }
|
||||||
public boolean isReversed() { return !Slotinfo.increasing(slotKey); }
|
public boolean isReversed() { return !Slotinfo.increasing(slotKey); }
|
||||||
public char direction() { return DIRECTION[Slot.dir(slotKey)]; }
|
public char direction() { return DIRECTION[Slot.dir(slotKey)]; }
|
||||||
}
|
}
|
||||||
@@ -247,13 +247,13 @@ public record Export() {
|
|||||||
|
|
||||||
public record PuzzleResult(Signa clues, Puzzle grid, Slotinfo[] slots, FillResult filled) {
|
public record PuzzleResult(Signa clues, Puzzle grid, Slotinfo[] slots, FillResult filled) {
|
||||||
|
|
||||||
public ExportedPuzzle exportFormatFromFilled(Rewards rewards) {
|
public ExportedPuzzle exportFormatFromFilled(Rewards rewards, rci[] rcis, int bits) {
|
||||||
// If nothing placed: return full grid mapped to letters/# only
|
// If nothing placed: return full grid mapped to letters/# only
|
||||||
if (slots.length == 0) {
|
if (slots.length == 0) {
|
||||||
return new ExportedPuzzle(grid.exportGrid(_ -> '#', '#'), new WordOut[0], 1, rewards);
|
return new ExportedPuzzle(grid.exportGrid(_ -> '#', '#'), new WordOut[0], 1, rewards);
|
||||||
}
|
}
|
||||||
|
|
||||||
var placed = Arrays.stream(slots).map(slot -> new Placed(slot.assign().w, slot.key(), Puzzle.cellWalk((byte) slot.key(), slot.lo(), slot.hi()).toArray())).toArray(
|
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);
|
Placed[]::new);
|
||||||
|
|
||||||
// 2) bounding box around all word cells + arrow cells, with 1-cell margin
|
// 2) bounding box around all word cells + arrow cells, with 1-cell margin
|
||||||
@@ -262,7 +262,7 @@ public record Export() {
|
|||||||
|
|
||||||
for (var rc : placed) {
|
for (var rc : placed) {
|
||||||
for (var c : rc.cells) {
|
for (var c : rc.cells) {
|
||||||
val it = Masker.IT[c];
|
val it = rcis[c];
|
||||||
minR = Math.min(minR, it.r());
|
minR = Math.min(minR, it.r());
|
||||||
minC = Math.min(minC, it.c());
|
minC = Math.min(minC, it.c());
|
||||||
maxR = Math.max(maxR, it.r());
|
maxR = Math.max(maxR, it.r());
|
||||||
@@ -280,7 +280,7 @@ public record Export() {
|
|||||||
var gridv2 = new String[Math.max(0, maxR - minR + 1)];
|
var gridv2 = new String[Math.max(0, maxR - minR + 1)];
|
||||||
for (int r = minR, i = 0; r <= maxR; r++, i++) {
|
for (int r = minR, i = 0; r <= maxR; r++, i++) {
|
||||||
var row = new StringBuilder(Math.max(0, maxC - minC + 1));
|
var row = new StringBuilder(Math.max(0, maxC - minC + 1));
|
||||||
for (var c = minC; c <= maxC; c++) row.append(map.getOrDefault(Masker.offset(r, c), '#'));
|
for (var c = minC; c <= maxC; c++) row.append(map.getOrDefault(r | (c << bits), '#'));
|
||||||
gridv2[i] = row.toString();
|
gridv2[i] = row.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import lombok.AllArgsConstructor;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
import precomp.Neighbors9x8;
|
|
||||||
import puzzle.SwedishGenerator.Rng;
|
import puzzle.SwedishGenerator.Rng;
|
||||||
|
|
||||||
import static puzzle.Export.*;
|
import static puzzle.Export.*;
|
||||||
@@ -25,7 +24,8 @@ import static puzzle.SwedishGenerator.*;
|
|||||||
@ConstGen(C = 9, R = 8, packageName = "precomp", className = "Const9x8")
|
@ConstGen(C = 9, R = 8, packageName = "precomp", className = "Const9x8")
|
||||||
@GenerateNeighbors({
|
@GenerateNeighbors({
|
||||||
@GenerateNeighbor(C = 9, R = 8, packageName = "precomp", className = "Neighbors9x8", MIN_LEN = 2),
|
@GenerateNeighbor(C = 9, R = 8, packageName = "precomp", className = "Neighbors9x8", MIN_LEN = 2),
|
||||||
@GenerateNeighbor(C = 4, R = 3, packageName = "precomp", className = "Neighbors4x3", MIN_LEN = 2)
|
@GenerateNeighbor(C = 4, R = 3, packageName = "precomp", className = "Neighbors4x3", MIN_LEN = 2),
|
||||||
|
@GenerateNeighbor(C = 3, R = 4, packageName = "precomp", className = "Neighbors3x4", MIN_LEN = 2)
|
||||||
})
|
})
|
||||||
public class Main {
|
public class Main {
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ public class Main {
|
|||||||
section("Grid (human)");
|
section("Grid (human)");
|
||||||
System.out.print(indentLines(res.grid().renderHuman()));
|
System.out.print(indentLines(res.grid().renderHuman()));
|
||||||
|
|
||||||
var exported = res.exportFormatFromFilled(new Rewards(50, 2, 1));
|
var exported = res.exportFormatFromFilled(new Rewards(50, 2, 1), Masker.IT, 3);
|
||||||
|
|
||||||
section("Clues");
|
section("Clues");
|
||||||
info("status : generating...");
|
info("status : generating...");
|
||||||
@@ -378,7 +378,7 @@ public class Main {
|
|||||||
if (mask == null) return null;
|
if (mask == null) return null;
|
||||||
|
|
||||||
val slotInfo = Masker_Neighbors9x8.slots(mask, dict.index(), dict.reversed());
|
val slotInfo = Masker_Neighbors9x8.slots(mask, dict.index(), dict.reversed());
|
||||||
var grid = Masker_Neighbors9x8.grid(slotInfo, Neighbors9x8.SIZE);// mask.toGrid();
|
var grid = Masker_Neighbors9x8.grid(slotInfo);// mask.toGrid();
|
||||||
var filled = fillMask(rng, slotInfo, grid.lo, grid.hi, grid.g);
|
var filled = fillMask(rng, slotInfo, grid.lo, grid.hi, grid.g);
|
||||||
|
|
||||||
if (!multiThreaded) {
|
if (!multiThreaded) {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import static puzzle.SwedishGenerator.*;
|
|||||||
@GenerateShapedCopies(
|
@GenerateShapedCopies(
|
||||||
packageName = "puzzle",
|
packageName = "puzzle",
|
||||||
className = "Masker",
|
className = "Masker",
|
||||||
shapes = { "precomp.Neighbors9x8", "precomp.Neighbors4x3" }
|
shapes = { "precomp.Neighbors9x8", "precomp.Neighbors4x3" , "precomp.Neighbors3x4" }
|
||||||
)
|
)
|
||||||
public final class Masker {
|
public final class Masker {
|
||||||
|
|
||||||
@@ -52,13 +52,13 @@ public final class Masker {
|
|||||||
|
|
||||||
return (bitCount(matchLo & MASK_LO) + bitCount(matchHi & MASK_HI)) / SIZED;
|
return (bitCount(matchLo & MASK_LO) + bitCount(matchHi & MASK_HI)) / SIZED;
|
||||||
}
|
}
|
||||||
public static Grid grid(Slotinfo[] slots, int size) {
|
public static Grid grid(Slotinfo[] slots) {
|
||||||
long lo = X, hi = X;
|
long lo = X, hi = X;
|
||||||
for (var slot : slots) {
|
for (var slot : slots) {
|
||||||
lo |= slot.lo();
|
lo |= slot.lo();
|
||||||
hi |= slot.hi();
|
hi |= slot.hi();
|
||||||
}
|
}
|
||||||
return new Grid(new byte[size], ~lo & MASK_LO, ~hi & MASK_HI);
|
return new Grid(new byte[SIZE], ~lo & MASK_LO, ~hi & MASK_HI);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isValid(Clues c) {
|
public boolean isValid(Clues c) {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import anno.DictGen;
|
|||||||
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 precomp.Neighbors9x8;
|
|
||||||
import puzzle.Export.Vestigium;
|
import puzzle.Export.Vestigium;
|
||||||
import puzzle.Export.Signa;
|
import puzzle.Export.Signa;
|
||||||
import puzzle.Export.Puzzle;
|
import puzzle.Export.Puzzle;
|
||||||
@@ -180,7 +179,7 @@ public class MainTest {
|
|||||||
r7c0d2, r7c1d1, r7c4d2, r7c5d2, r7c8d3
|
r7c0d2, r7c1d1, r7c4d2, r7c5d2, r7c8d3
|
||||||
);
|
);
|
||||||
var slotInfo = mask.slots(DictData950.DICT950);
|
var slotInfo = mask.slots(DictData950.DICT950);
|
||||||
var grid = Masker.grid(slotInfo, Neighbors9x8.SIZE);
|
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");
|
||||||
@@ -189,7 +188,7 @@ public class MainTest {
|
|||||||
Assertions.assertEquals(193L, grid.hi);
|
Assertions.assertEquals(193L, grid.hi);
|
||||||
var g = new Puzzle(grid, mask.c());
|
var g = new Puzzle(grid, mask.c());
|
||||||
g.gridToString();
|
g.gridToString();
|
||||||
var aa = new PuzzleResult(mask, g, slotInfo, filled).exportFormatFromFilled(new Rewards(1, 1, 1));
|
var aa = new PuzzleResult(mask, g, slotInfo, filled).exportFormatFromFilled(new Rewards(1, 1, 1), Masker.IT, 3);
|
||||||
System.out.println(String.join("\n", aa.grid()));
|
System.out.println(String.join("\n", aa.grid()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,22 +112,22 @@ public class MarkerTest {
|
|||||||
var g = Clues.createEmpty();
|
var g = Clues.createEmpty();
|
||||||
|
|
||||||
// Room for Right clue at (0,0) (length 8)
|
// Room for Right clue at (0,0) (length 8)
|
||||||
assertTrue(Masker.hasRoomForClue(g,r0c0d1.slotKey));
|
assertTrue(Masker.hasRoomForClue(g, r0c0d1.slotKey));
|
||||||
|
|
||||||
// No room for Right clue at (0,8) (length 0 < MIN_LEN)
|
// No room for Right clue at (0,8) (length 0 < MIN_LEN)
|
||||||
assertFalse(Masker.hasRoomForClue(g,r0c8d1.slotKey));
|
assertFalse(Masker.hasRoomForClue(g, r0c8d1.slotKey));
|
||||||
|
|
||||||
// Blocked room
|
// Blocked room
|
||||||
// Let's place a clue that leaves only 1 cell for another clue.
|
// Let's place a clue that leaves only 1 cell for another clue.
|
||||||
g.setClue(r0c2d1);
|
g.setClue(r0c2d1);
|
||||||
// Now Right at (0,0) only has (0,1) available -> length 1 < MIN_LEN (which is 2)
|
// Now Right at (0,0) only has (0,1) available -> length 1 < MIN_LEN (which is 2)
|
||||||
assertFalse(Masker.hasRoomForClue(g,r0c0d1.slotKey));
|
assertFalse(Masker.hasRoomForClue(g, r0c0d1.slotKey));
|
||||||
|
|
||||||
// But enough room
|
// But enough room
|
||||||
g.clearClueLo(0L);
|
g.clearClueLo(0L);
|
||||||
g.setClue(r0c3d1);
|
g.setClue(r0c3d1);
|
||||||
// Now Right at (0,0) has (0,1), (0,2) -> length 2 == MIN_LEN
|
// Now Right at (0,0) has (0,1), (0,2) -> length 2 == MIN_LEN
|
||||||
assertTrue(Masker.hasRoomForClue(g,r0c0d1.slotKey));
|
assertTrue(Masker.hasRoomForClue(g, r0c0d1.slotKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -307,7 +307,7 @@ public class MarkerTest {
|
|||||||
}, fillResult);
|
}, fillResult);
|
||||||
|
|
||||||
var rewards = new Rewards(10, 5, 1);
|
var rewards = new Rewards(10, 5, 1);
|
||||||
var exported = puzzleResult.exportFormatFromFilled(rewards);
|
var exported = puzzleResult.exportFormatFromFilled(rewards, Masker.IT, 3);
|
||||||
|
|
||||||
assertNotNull(exported);
|
assertNotNull(exported);
|
||||||
assertEquals(709, exported.difficulty());
|
assertEquals(709, exported.difficulty());
|
||||||
@@ -346,7 +346,7 @@ public class MarkerTest {
|
|||||||
var fillResult = new FillResult(true, 0, 0, 0, 0);
|
var fillResult = new FillResult(true, 0, 0, 0, 0);
|
||||||
var puzzleResult = new PuzzleResult(new Signa(clues), new Puzzle(grid, clues), new Slotinfo[0], fillResult);
|
var puzzleResult = new PuzzleResult(new Signa(clues), new Puzzle(grid, clues), new Slotinfo[0], fillResult);
|
||||||
|
|
||||||
var exported = puzzleResult.exportFormatFromFilled(new Rewards(0, 0, 0));
|
var exported = puzzleResult.exportFormatFromFilled(new Rewards(0, 0, 0), Masker.IT, 3);
|
||||||
|
|
||||||
assertNotNull(exported);
|
assertNotNull(exported);
|
||||||
assertEquals(0, exported.words().length);
|
assertEquals(0, exported.words().length);
|
||||||
|
|||||||
@@ -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 precomp.Neighbors9x8;
|
|
||||||
import puzzle.Export.Clue;
|
import puzzle.Export.Clue;
|
||||||
import puzzle.Export.Signa;
|
import puzzle.Export.Signa;
|
||||||
import puzzle.Export.Puzzle;
|
import puzzle.Export.Puzzle;
|
||||||
@@ -73,7 +72,7 @@ public class PerformanceTest {
|
|||||||
|
|
||||||
for (var i = 0; i < iterations; i++) {
|
for (var i = 0; i < iterations; i++) {
|
||||||
val slotInfo = Masker.slots(arr[c], DICT800);
|
val slotInfo = Masker.slots(arr[c], DICT800);
|
||||||
var grid = Masker.grid(slotInfo, Neighbors9x8.SIZE);
|
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++;
|
if (result.ok()) successCount++;
|
||||||
totalNodes += result.nodes();
|
totalNodes += result.nodes();
|
||||||
@@ -143,7 +142,7 @@ public class PerformanceTest {
|
|||||||
// Reset assignments for each iteration
|
// Reset assignments for each iteration
|
||||||
for (var s : slots) s.assign().w = 0;
|
for (var s : slots) s.assign().w = 0;
|
||||||
|
|
||||||
var grid = Masker.grid(slots, Neighbors9x8.SIZE);
|
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()) {
|
if (result.ok()) {
|
||||||
successCount++;
|
successCount++;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import puzzle.Export.Signa;
|
|||||||
import puzzle.Export.Vestigium;
|
import puzzle.Export.Vestigium;
|
||||||
import puzzle.SwedishGenerator.Rng;
|
import puzzle.SwedishGenerator.Rng;
|
||||||
import puzzle.dict800.DictData800;
|
import puzzle.dict800.DictData800;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import static precomp.Const9x8.Cell.r0c0d1;
|
import static precomp.Const9x8.Cell.r0c0d1;
|
||||||
import static precomp.Const9x8.Cell.r1c0d1;
|
import static precomp.Const9x8.Cell.r1c0d1;
|
||||||
@@ -35,9 +36,16 @@ public class TestDuplication {
|
|||||||
Assertions.assertEquals(4, mask.clueCount());
|
Assertions.assertEquals(4, mask.clueCount());
|
||||||
val map = mask.stream().collect(Collectors.toMap(Vestigium::index, Vestigium::clue));
|
val map = mask.stream().collect(Collectors.toMap(Vestigium::index, Vestigium::clue));
|
||||||
Assertions.assertEquals(4, map.size());
|
Assertions.assertEquals(4, map.size());
|
||||||
var slots = Masker_Neighbors4x3.slots(mask.c(), DictData800.DICT800);
|
var slots = Masker_Neighbors3x4.slots(mask.c(), DictData800.DICT800);
|
||||||
var grid = Masker_Neighbors4x3.grid(slots, Masker_Neighbors4x3.SIZE);
|
var grid = Masker_Neighbors3x4.grid(slots);
|
||||||
var filled = SwedishGenerator.fillMask(new Rng(1), slots, grid.lo, grid.hi, grid.g);
|
var filled = SwedishGenerator.fillMask(new Rng(1), slots, grid.lo, grid.hi, grid.g);
|
||||||
val res = new PuzzleResult(new Signa(mask.c()), new Puzzle(grid, mask.c()), slots, filled).exportFormatFromFilled(new Rewards(0, 0, 0));
|
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()) {
|
||||||
|
val res = result.exportFormatFromFilled(new Rewards(0, 0, 0), Masker_Neighbors3x4.IT, 2);
|
||||||
|
System.out.println(String.join("\n", res.grid()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user