introduce bitloops

This commit is contained in:
mike
2026-01-22 18:47:04 +01:00
parent a659bd5162
commit 2295a7d97c
71 changed files with 254 additions and 205151 deletions

View File

@@ -5,8 +5,9 @@ import lombok.AllArgsConstructor;
import lombok.experimental.Delegate;
import lombok.val;
import precomp.Const9x8.Cell;
import puzzle.Export.Gridded.Replacar.Rell;
import puzzle.Export.Puzzle.Replacar.Rell;
import puzzle.Masker.Clues;
import puzzle.Meta.ShardLem;
import puzzle.SwedishGenerator.Dict;
import puzzle.SwedishGenerator.FillResult;
import puzzle.SwedishGenerator.Grid;
@@ -19,7 +20,6 @@ import static puzzle.Masker.Clues.createEmpty;
import static puzzle.Masker.Slot;
import static puzzle.Masker.C;
import static puzzle.SwedishGenerator.Lemma;
import static puzzle.SwedishGenerator.SIZE;
import static puzzle.SwedishGenerator.X;
/**
@@ -61,21 +61,16 @@ public record Export() {
public static Clue from(int dir) { return CLUES[dir]; }
}
record Strings() {
static String padRight(String s, int n) { return s.length() >= n ? s : s + " ".repeat(n - s.length()); }
}
public record Vestigium(int index, int clue) { }
public record ClueAt(int index, int clue) { }
public record Clued(@Delegate Clues c) {
public record Signa(@Delegate Clues c) {
public static Clued of(Cell... cells) {
public static Signa of(Cell... cells) {
var c = createEmpty();
for (var cell : cells) c.setClue(cell);
return new Clued(c);
return new Signa(c);
}
public Clued deepCopyGrid() { return new Clued(new Clues(c.lo, c.hi, c.vlo, c.vhi, c.rlo, c.rhi, c.xlo, c.xhi)); }
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);
forEachSlot((s, _, _) -> {
@@ -85,21 +80,21 @@ public record Export() {
});
return sb.toString();
}
public Stream<ClueAt> stream() {
val stream = Stream.<ClueAt>builder();
for (var l = c.lo & ~c.xlo & ~c.rlo & c.vlo; l != X; l &= l - 1) stream.accept(new ClueAt(Long.numberOfTrailingZeros(l), RIGHT1.dir));
for (var l = c.lo & ~c.xlo & ~c.rlo & ~c.vlo; l != X; l &= l - 1) stream.accept(new ClueAt(Long.numberOfTrailingZeros(l), DOWN0.dir));
for (var l = c.lo & ~c.xlo & c.rlo & ~c.vlo; l != X; l &= l - 1) stream.accept(new ClueAt(Long.numberOfTrailingZeros(l), CLUE_UP));
for (var l = c.lo & ~c.xlo & c.rlo & c.vlo; l != X; l &= l - 1) stream.accept(new ClueAt(Long.numberOfTrailingZeros(l), CLUE_LEFT));
for (var l = c.lo & c.xlo & ~c.rlo & ~c.vlo; l != X; l &= l - 1) stream.accept(new ClueAt(Long.numberOfTrailingZeros(l), CLUE_LEFT_TOP));
for (var l = c.lo & c.xlo & ~c.rlo & c.vlo; l != X; l &= l - 1) stream.accept(new ClueAt(Long.numberOfTrailingZeros(l), CLUE_RIGHT_TOP));
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_UP));
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));
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_TOP));
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_TOP));
for (var h = c.hi & ~c.xhi & ~c.rhi & c.vhi; h != X; h &= h - 1) stream.accept(new ClueAt(HI(Long.numberOfTrailingZeros(h)), CLUE_RIGHT));
for (var h = c.hi & ~c.xhi & ~c.rhi & ~c.vhi; h != X; h &= h - 1) stream.accept(new ClueAt(HI(Long.numberOfTrailingZeros(h)), CLUE_DOWN));
for (var h = c.hi & ~c.xhi & c.rhi & ~c.vhi; h != X; h &= h - 1) stream.accept(new ClueAt(HI(Long.numberOfTrailingZeros(h)), CLUE_UP));
for (var h = c.hi & ~c.xhi & c.rhi & c.vhi; h != X; h &= h - 1) stream.accept(new ClueAt(HI(Long.numberOfTrailingZeros(h)), CLUE_LEFT));
for (var h = c.hi & c.xhi & ~c.rhi & ~c.vhi; h != X; h &= h - 1) stream.accept(new ClueAt(HI(Long.numberOfTrailingZeros(h)), CLUE_LEFT_TOP));
for (var h = c.hi & c.xhi & ~c.rhi & c.vhi; h != X; h &= h - 1) stream.accept(new ClueAt(HI(Long.numberOfTrailingZeros(h)), CLUE_RIGHT_TOP));
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));
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_DOWN));
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_UP));
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));
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_TOP));
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_TOP));
return stream.build();
}
@@ -108,15 +103,15 @@ public record Export() {
}
}
record Gridded(@Delegate Grid grid, Clues cl)
implements Stream<LetterAt> {
record Puzzle(@Delegate Grid grid, Clues cl)
implements Stream<Lettrix> {
public Gridded(Clues clues) { this(clues.toGrid(), clues); }
public Gridded(Clued clues) { this(clues.c); }
public @Delegate Stream<LetterAt> stream() {
val stream = Stream.<LetterAt>builder();
for (var l = grid.lo & ~cl.lo; l != X; l &= l - 1) stream.accept(LetterAt.from(Long.numberOfTrailingZeros(l), grid.g));
for (var h = grid.hi & ~cl.hi & 0xFF; h != X; h &= h - 1) stream.accept(LetterAt.from(64 | Long.numberOfTrailingZeros(h), grid.g));
public Puzzle(Clues clues) { this(clues.toGrid(), clues); }
public Puzzle(Signa clues) { this(clues.c); }
public @Delegate Stream<Lettrix> stream() {
val stream = Stream.<Lettrix>builder();
for (var l = grid.lo & ~cl.lo; l != X; l &= l - 1) stream.accept(Lettrix.from(Long.numberOfTrailingZeros(l), grid.g));
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() {
@@ -141,7 +136,7 @@ public record Export() {
sb[r * (C + 1) + c] = (byte) clueChar.replace(new Rell(grid, cl, idx, (byte) (dir | 48)));
});
stream().forEach((l) -> sb[l.index(C + 1)] = (byte) l.human());
return new String(sb).replaceAll(" ", "" + emptyFallback).split("\n");
return new String(sb).replaceAll(" ", String.valueOf(emptyFallback)).split("\n");
}
public static IntStream cellWalk(byte base, long lo, long hi) {
if (Slotinfo.increasing(base)) {
@@ -219,8 +214,19 @@ public record Export() {
public record WordOut(String word, int[] cell, int startRow, int startCol, char direction, int arrowRow, int arrowCol, boolean isReversed, int complex, String[] clue) {
private static ShardLem lookup(long w, byte[] bytes) {
try {
val rec = Meta.lookupSilent(w);
System.out.println("\nQuery: w=" + w + " -> i=" + rec.mmap());
System.out.println(" word=" + Lemma.asWord(w, bytes) + "\n" + " simpel=" + rec.simpel() + "\n" + " clues=" + Arrays.toString(rec.clues()));
return rec;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public WordOut(long l, int startRow, int startCol, char d, int arrowRow, int arrowCol, boolean isReversed, byte[] bytes) {
val meta = Meta.lookup(l);
val meta = lookup(l, bytes);
this(Lemma.asWord(l, bytes), new int[]{ arrowRow, arrowCol, startRow, startCol }, startRow, startCol, d, arrowRow, arrowCol, isReversed,
meta.simpel(), meta.clues());
}
@@ -228,7 +234,7 @@ public record Export() {
public record ExportedPuzzle(String[] grid, WordOut[] words, int difficulty, Rewards rewards) { }
public record PuzzleResult(Clued clues, Gridded grid, Slotinfo[] slots, FillResult filled) {
public record PuzzleResult(Signa clues, Puzzle grid, Slotinfo[] slots, FillResult filled) {
public ExportedPuzzle exportFormatFromFilled(Rewards rewards) {
// If nothing placed: return full grid mapped to letters/# only
@@ -236,7 +242,7 @@ public record Export() {
return new ExportedPuzzle(grid.exportGrid(_ -> '#', '#'), new WordOut[0], 1, rewards);
}
var placed = Arrays.stream(slots).map(slot -> new Placed(slot.assign().w, slot.key(), Gridded.cellWalk((byte) slot.key(), slot.lo(), slot.hi()).toArray())).toArray(
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(
Placed[]::new);
// 2) bounding box around all word cells + arrow cells, with 1-cell margin
@@ -258,7 +264,7 @@ public record Export() {
}
// 3) map of only used letter cells (everything else becomes '#')
var map = grid.stream().collect(Collectors.toMap(LetterAt::index, LetterAt::human));
var map = grid.stream().collect(Collectors.toMap(Lettrix::index, Lettrix::human));
// 4) render gridv2 over cropped bounds (out-of-bounds become '#')
var gridv2 = new String[Math.max(0, maxR - minR + 1)];
for (int r = minR, i = 0; r <= maxR; r++, i++) {
@@ -279,20 +285,17 @@ public record Export() {
p.arrowCol() - MIN_C,
p.isReversed(), bytes
)).toArray(WordOut[]::new);
var total = 0.0001d;
for (var word : wordsOut) {
total += word.complex();
}
var total = 0.0001d + Arrays.stream(wordsOut).mapToDouble(WordOut::complex).sum();
return new ExportedPuzzle(gridv2, wordsOut, (int) (total / wordsOut.length), rewards);
}
}
record LetterAt(int index, byte letter) {
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 LetterAt from(int index, byte[] bytes) { return new LetterAt(index, bytes[index]); }
public int index(int cols) { return (row() * cols) + col(); }
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(); }
}
}