introduce bitloops

This commit is contained in:
mike
2026-01-21 05:13:39 +01:00
parent 92a736aa0a
commit f203f2106e
11 changed files with 97 additions and 108 deletions

View File

@@ -8,16 +8,17 @@ import precomp.Const9x8.Cell;
import puzzle.Export.Gridded.Replacar.Rell;
import puzzle.Export.LetterVisit.LetterAt;
import puzzle.Masker.Clues;
import puzzle.SwedishGenerator.Dict;
import puzzle.SwedishGenerator.FillResult;
import puzzle.SwedishGenerator.Grid;
import puzzle.SwedishGenerator.Slotinfo;
import static precomp.Const9x8.INIT_GRID_OUTPUT;
import static puzzle.Export.Clue.DOWN0;
import static puzzle.Export.Clue.RIGHT1;
import static puzzle.Masker.Clues.createEmpty;
import static puzzle.SwedishGenerator.R;
import static puzzle.SwedishGenerator.Lemma;
import static puzzle.Masker.Slot;
import static puzzle.SwedishGenerator.C;
import static puzzle.SwedishGenerator.Lemma;
import static puzzle.SwedishGenerator.X;
/**
@@ -64,8 +65,6 @@ public record Export() {
static String padRight(String s, int n) { return s.length() >= n ? s : s + " ".repeat(n - s.length()); }
}
static final String INIT = IntStream.range(0, Config.PUZZLE_ROWS).mapToObj(l_ -> " ").collect(Collectors.joining("\n"));
public record ClueAt(int index, int clue) { }
public record Clued(@Delegate Clues c) {
@@ -76,25 +75,8 @@ public record Export() {
return new Clued(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 static Clued parse(String s) {
var c = createEmpty();
var lines = s.split("\n");
for (int r = 0; r < Math.min(lines.length, R); r++) {
var line = lines[r];
for (int col = 0; col < Math.min(line.length(), C); col++) {
char ch = line.charAt(col);
if (ch >= '0' && ch <= '4') {
int idx = Masker.offset(r, col);
byte dir = (byte) (ch - '0');
if ((idx & 64) == 0) c.setClueLo(1L << idx, dir);
else c.setClueHi(1L << (idx & 63), dir);
}
}
}
return new Clued(c);
}
String gridToString() {
var sb = new StringBuilder(INIT);
var sb = new StringBuilder(INIT_GRID_OUTPUT);
forEachSlot((s, _, _) -> {
val idx = Slot.clueIndex(s);
val dir = Slot.dir(s);
@@ -121,11 +103,13 @@ public record Export() {
return stream.build();
}
public Slotinfo[] slots() {
return Masker.slots(c, DictData.DICT.index());
return slots(DictData.DICT);
}
public Slotinfo[] slots(Dict D) {
return Masker.slots(c, D.index());
}
}
@FunctionalInterface
interface LetterVisit {
record LetterAt(int index, byte letter) {
@@ -137,24 +121,22 @@ public record Export() {
public int index(int cols) { return (row() * cols) + col(); }
}
void visit(int index, byte letter);
default void visit(int index, byte[] letters) { visit(index, letters[index]); }
}
record Gridded(@Delegate Grid grid, Clues cl)
implements Stream<LetterAt> {
public Gridded(Clues clues) { this(clues.toGrid(), clues); }
public Gridded(Clued clues) { this(clues.toGrid(), clues.c); }
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));
return stream.build();
}
String gridToString(Clues clues) {
var sb = new StringBuilder(INIT);
clues.forEachSlot((s, _, _) -> {
String gridToString() {
var sb = new StringBuilder(INIT_GRID_OUTPUT);
cl.forEachSlot((s, _, _) -> {
val idx = Slot.clueIndex(s);
val r = idx & 7;
val c = idx >>> 3;
@@ -164,14 +146,14 @@ public record Export() {
stream().forEach((l) -> sb.setCharAt(l.index(C + 1), l.human()));
return sb.toString();
}
public String[] exportGrid(Clues clues, Replacar clueChar, char emptyFallback) {
var sb = new StringBuilder(INIT);
clues.forEachSlot((s, l, a) -> {
public String[] exportGrid(Replacar clueChar, char emptyFallback) {
var sb = new StringBuilder(INIT_GRID_OUTPUT);
cl.forEachSlot((s, l, a) -> {
val idx = Slot.clueIndex(s);
val r = idx & 7;
val c = idx >>> 3;
val dir = Slot.dir(s);
sb.setCharAt(r * (C + 1) + c, clueChar.replace(new Rell(grid, clues, idx, (byte) (dir | 48))));
sb.setCharAt(r * (C + 1) + c, clueChar.replace(new Rell(grid, cl, idx, (byte) (dir | 48))));
});
stream().forEach((l) -> sb.setCharAt(l.index(C + 1), l.human()));
return sb.toString().replaceAll(" ", "" + emptyFallback).split("\n");
@@ -224,7 +206,7 @@ public record Export() {
}
}
public String renderHuman(Clues clues) { return String.join("\n", exportGrid(clues, _ -> ' ', '#')); }
public String renderHuman() { return String.join("\n", exportGrid(_ -> ' ', '#')); }
@FunctionalInterface
interface Replacar {
@@ -266,7 +248,7 @@ public record Export() {
public ExportedPuzzle exportFormatFromFilled(Rewards rewards) {
// If nothing placed: return full grid mapped to letters/# only
if (slots.length == 0) {
return new ExportedPuzzle(grid.exportGrid(clues.c, _ -> '#', '#'), 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(), Gridded.cellWalk((byte) slot.key(), slot.lo(), slot.hi()).toArray())).toArray(