redo
This commit is contained in:
@@ -6,7 +6,7 @@ import anno.Shaped;
|
||||
import lombok.experimental.Delegate;
|
||||
import lombok.val;
|
||||
import precomp.Const9x8;
|
||||
import puzzle.Replacar.Rell;
|
||||
import puzzle.Riddle.ClueSign;
|
||||
import puzzle.Riddle.ExportedPuzzle;
|
||||
import puzzle.Riddle.Placed;
|
||||
import puzzle.Riddle.Rewards;
|
||||
@@ -23,6 +23,7 @@ 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.isLo;
|
||||
import static puzzle.SwedishGenerator.X;
|
||||
|
||||
@GenerateShapedCopies(
|
||||
@@ -32,13 +33,14 @@ import static puzzle.SwedishGenerator.X;
|
||||
)
|
||||
public record Export() {
|
||||
|
||||
public static final ThreadLocal<byte[]> BYTES = ThreadLocal.withInitial(() -> new byte[8]);
|
||||
@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 long MASK_HI = Const9x8.MASK_HI;
|
||||
@Shaped static final long MASK_LO = Const9x8.MASK_LO;
|
||||
public static final ThreadLocal<byte[]> BYTES = ThreadLocal.withInitial(() -> new byte[8]);
|
||||
@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; }
|
||||
static char LETTER(int in) { return (char) (in | 64); }
|
||||
@@ -46,19 +48,24 @@ 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; }
|
||||
record Lettrix(int index, byte letter) {
|
||||
|
||||
public int row() { return INDEX_ROW(index); }
|
||||
public int col() { return INDEX_COL(index); }
|
||||
public char human() { return LETTER(letter); }
|
||||
static Lettrix from(int index, byte[] bytes) { return new Lettrix(index, bytes[index]); }
|
||||
public int index(int cols) { return (row() * cols) + col(); }
|
||||
}
|
||||
|
||||
public record Signa(@Delegate Clues c) {
|
||||
|
||||
public static Signa of(Mask... cells) {
|
||||
var c = createEmpty();
|
||||
for (var cell : cells) {
|
||||
if ((cell.index() & 64) == 0) c.setClueLo(cell.lo(), cell.d());
|
||||
else c.setClueHi(cell.hi(), cell.d());
|
||||
}
|
||||
return new Signa(c);
|
||||
var signa = new Signa(createEmpty());
|
||||
Arrays.stream(cells).forEach(signa::setClue);
|
||||
return signa;
|
||||
}
|
||||
public Signa setClue(Mask cell) {
|
||||
if ((cell.index() & 64) == 0) setClueLo(cell.lo(), cell.d());
|
||||
if (isLo((cell.index()))) setClueLo(cell.lo(), cell.d());
|
||||
else setClueHi(cell.hi(), cell.d());
|
||||
return this;
|
||||
}
|
||||
@@ -100,75 +107,27 @@ public record Export() {
|
||||
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) {
|
||||
var sb = INIT_GRID_OUTPUT_ARR.clone();
|
||||
public String[] exportGrid(Slotinfo[] slots, ClueSign clueChar, byte[] template) {
|
||||
var sb = template.clone();
|
||||
for (var slot : slots) {
|
||||
val idx = Slot.clueIndex(slot.key());
|
||||
val r = INDEX_ROW(idx);
|
||||
val c = INDEX_COL(idx);
|
||||
val dir = Slot.dir(slot.key());
|
||||
sb[r * (C + 1) + c] = (byte) clueChar.replace(new Rell(grid, cl, idx, (byte) (dir | 48)));
|
||||
sb[r * (C + 1) + c] = (byte) clueChar.replace((byte) (dir | 48));
|
||||
}
|
||||
stream().forEach((l) -> sb[l.index(C + 1)] = (byte) l.human());
|
||||
return new String(sb).replaceAll(" ", String.valueOf(emptyFallback)).split("\n");
|
||||
return new String(sb) .split("\n");
|
||||
}
|
||||
public static IntStream cellWalk(int base, long lo, long hi) {
|
||||
if (Slotinfo.increasing(base)) {
|
||||
return IntStream.concat(IntStream.of(Slot.clueIndex(base)), IntStream.concat(
|
||||
IntStream.generate(new IntSupplier() {
|
||||
|
||||
long temp = lo;
|
||||
@Override
|
||||
public int getAsInt() {
|
||||
int res = Long.numberOfTrailingZeros(temp);
|
||||
temp &= temp - 1;
|
||||
return res;
|
||||
}
|
||||
}).limit(Long.bitCount(lo)),
|
||||
IntStream.generate(new IntSupplier() {
|
||||
|
||||
long temp = hi;
|
||||
@Override
|
||||
public int getAsInt() {
|
||||
int res = 64 | Long.numberOfTrailingZeros(temp);
|
||||
temp &= temp - 1;
|
||||
return res;
|
||||
}
|
||||
}).limit(Long.bitCount(hi))));
|
||||
} else {
|
||||
return IntStream.concat(IntStream.of(Slot.clueIndex(base)), IntStream.concat(
|
||||
IntStream.generate(new IntSupplier() {
|
||||
|
||||
long temp = hi;
|
||||
@Override
|
||||
public int getAsInt() {
|
||||
int msb = 63 - Long.numberOfLeadingZeros(temp);
|
||||
temp &= ~(1L << msb);
|
||||
return 64 | msb;
|
||||
}
|
||||
}).limit(Long.bitCount(hi)),
|
||||
IntStream.generate(new IntSupplier() {
|
||||
|
||||
long temp = lo;
|
||||
@Override
|
||||
public int getAsInt() {
|
||||
int msb = 63 - Long.numberOfLeadingZeros(temp);
|
||||
temp &= ~(1L << msb);
|
||||
return msb;
|
||||
}
|
||||
}).limit(Long.bitCount(lo))));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public record PuzzleResult(Signa clues, Puzzle grid, Slotinfo[] slots, FillResult filled) {
|
||||
public record PuzzleResult(Signa clues, Puzzle puzzle, Slotinfo[] slots, FillResult filled) {
|
||||
|
||||
public String cluesGridToString() {
|
||||
return clues.gridToString();
|
||||
}
|
||||
public String gridRenderHuman() {
|
||||
return String.join("\n", grid.exportGrid(slots, _ -> ' ', '#'));
|
||||
return String.join("\n", puzzle.exportGrid(slots, _ -> ' ', INIT_GRID_OUTPUT_DASH_ARR));
|
||||
}
|
||||
public String gridGridToString() {
|
||||
var sb = INIT_GRID_OUTPUT_ARR.clone();
|
||||
@@ -179,17 +138,16 @@ public record Export() {
|
||||
val dir = Slot.dir(slot.key());
|
||||
sb[r * (C + 1) + c] = (byte) (dir | 48);
|
||||
}
|
||||
grid.stream().forEach((l) -> sb[l.index(C + 1)] = (byte) l.human());
|
||||
puzzle.stream().forEach((l) -> sb[l.index(C + 1)] = (byte) l.human());
|
||||
return new String(sb);
|
||||
}
|
||||
public ExportedPuzzle exportFormatFromFilled(Rewards rewards, rci[] rcis) {
|
||||
// If nothing placed: return full grid mapped to letters/# only
|
||||
if (slots.length == 0) {
|
||||
return new ExportedPuzzle(grid.exportGrid(slots, _ -> '#', '#'), new WordOut[0], 1, rewards);
|
||||
return new ExportedPuzzle(puzzle.exportGrid(slots, _ -> '#', INIT_GRID_OUTPUT_DASH_ARR), new WordOut[0], 1, rewards);
|
||||
}
|
||||
|
||||
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)))
|
||||
.map(slot -> new Placed(slot.assign().w, slot.key(), Riddle.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
|
||||
@@ -213,7 +171,7 @@ public record Export() {
|
||||
Arrays.fill(template, (byte) '#');
|
||||
for (int i = width; i < template.length; i += width + 1) template[i] = (byte) '\n';
|
||||
|
||||
grid.forEach(l -> {
|
||||
puzzle.forEach(l -> {
|
||||
int rr = l.row() - MINR;
|
||||
int cc = l.col() - MINC;
|
||||
if (rr >= 0 && rr < height && cc >= 0 && cc < width) {
|
||||
@@ -239,12 +197,4 @@ public record Export() {
|
||||
|
||||
}
|
||||
|
||||
record Lettrix(int index, byte letter) {
|
||||
|
||||
public int row() { return INDEX_ROW(index); }
|
||||
public int col() { return INDEX_COL(index); }
|
||||
public char human() { return LETTER(letter); }
|
||||
static Lettrix from(int index, byte[] bytes) { return new Lettrix(index, bytes[index]); }
|
||||
public int index(int cols) { return (row() * cols) + col(); }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
package puzzle;
|
||||
|
||||
import puzzle.SwedishGenerator.Grid;
|
||||
@FunctionalInterface
|
||||
interface Replacar {
|
||||
|
||||
record Rell(Grid grid, Clues clues, int index, byte data) { }
|
||||
char replace(Rell c);
|
||||
}
|
||||
@@ -8,6 +8,8 @@ import puzzle.Meta.ShardLem;
|
||||
import puzzle.SwedishGenerator.Lemma;
|
||||
import puzzle.SwedishGenerator.Slotinfo;
|
||||
import java.util.Arrays;
|
||||
import java.util.function.IntSupplier;
|
||||
import java.util.stream.IntStream;
|
||||
import static precomp.Const9x8.CLUE_DOWN0;
|
||||
import static precomp.Const9x8.CLUE_LEFT3;
|
||||
import static precomp.Const9x8.CLUE_LEFT_TOP4;
|
||||
@@ -17,6 +19,53 @@ import static precomp.Const9x8.CLUE_RIGHT_TOP5;
|
||||
import static precomp.Const9x8.CLUE_UP2;
|
||||
public class Riddle {
|
||||
|
||||
public static IntStream cellWalk(int base, long lo, long hi) {
|
||||
if (Slotinfo.increasing(base)) {
|
||||
return IntStream.concat(IntStream.of(Slot.clueIndex(base)), IntStream.concat(
|
||||
IntStream.generate(new IntSupplier() {
|
||||
|
||||
long temp = lo;
|
||||
@Override
|
||||
public int getAsInt() {
|
||||
int res = Long.numberOfTrailingZeros(temp);
|
||||
temp &= temp - 1;
|
||||
return res;
|
||||
}
|
||||
}).limit(Long.bitCount(lo)),
|
||||
IntStream.generate(new IntSupplier() {
|
||||
|
||||
long temp = hi;
|
||||
@Override
|
||||
public int getAsInt() {
|
||||
int res = 64 | Long.numberOfTrailingZeros(temp);
|
||||
temp &= temp - 1;
|
||||
return res;
|
||||
}
|
||||
}).limit(Long.bitCount(hi))));
|
||||
} else {
|
||||
return IntStream.concat(IntStream.of(Slot.clueIndex(base)), IntStream.concat(
|
||||
IntStream.generate(new IntSupplier() {
|
||||
|
||||
long temp = hi;
|
||||
@Override
|
||||
public int getAsInt() {
|
||||
int msb = 63 - Long.numberOfLeadingZeros(temp);
|
||||
temp &= ~(1L << msb);
|
||||
return 64 | msb;
|
||||
}
|
||||
}).limit(Long.bitCount(hi)),
|
||||
IntStream.generate(new IntSupplier() {
|
||||
|
||||
long temp = lo;
|
||||
@Override
|
||||
public int getAsInt() {
|
||||
int msb = 63 - Long.numberOfLeadingZeros(temp);
|
||||
temp &= ~(1L << msb);
|
||||
return msb;
|
||||
}
|
||||
}).limit(Long.bitCount(lo))));
|
||||
}
|
||||
}
|
||||
@AllArgsConstructor
|
||||
enum Clue {
|
||||
DOWN0(CLUE_DOWN0, 'B', 'b'),
|
||||
@@ -83,4 +132,11 @@ public class Riddle {
|
||||
meta.simpel(), meta.clues());
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
static
|
||||
interface ClueSign {
|
||||
|
||||
char replace(byte data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ public class MainTest {
|
||||
assertEquals(1, slots.length);
|
||||
var s = slots[0];
|
||||
assertEquals(8, Masker.Slot.length(s.lo(), s.hi()));
|
||||
var cells = Puzzle.cellWalk(s.key(), s.lo(), s.hi()).mapToObj(c -> Masker.IT[c]).toArray(rci[]::new);
|
||||
var cells = Riddle.cellWalk(s.key(), s.lo(), s.hi()).mapToObj(c -> Masker.IT[c]).toArray(rci[]::new);
|
||||
assertEquals(0, cells[1].r());
|
||||
assertEquals(1, cells[1].c());
|
||||
assertEquals(0, cells[2].r());
|
||||
|
||||
@@ -5,7 +5,6 @@ import anno.DictGen;
|
||||
import anno.Dictionaries;
|
||||
import lombok.val;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import puzzle.Export.Puzzle;
|
||||
import puzzle.Export.Signa;
|
||||
import puzzle.SwedishGenerator.Rng;
|
||||
import puzzle.SwedishGenerator.Slotinfo;
|
||||
@@ -202,7 +201,7 @@ public class PerformanceTest {
|
||||
var slotChar = dir.slotChar;
|
||||
display[cr][cc] = clueChar;
|
||||
|
||||
Puzzle.cellWalk(slot.key(), slot.lo(), slot.hi())
|
||||
Riddle.cellWalk(slot.key(), slot.lo(), slot.hi())
|
||||
.skip(1)
|
||||
.forEach(idx -> {
|
||||
var r = Masker.IT[idx].r();
|
||||
|
||||
@@ -207,7 +207,7 @@ 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( r2c3d0.slotKey, r2c5.or(r3c5).or(r4c5).lo(), 0L).mapToObj(i -> Masker.IT[i]).toArray(rci[]::new);
|
||||
var cells = Riddle.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());
|
||||
|
||||
Reference in New Issue
Block a user