introduce bitloops

This commit is contained in:
mike
2026-01-16 23:42:50 +01:00
parent 5c7d1120db
commit aceaa0fc18
5 changed files with 78 additions and 50 deletions

View File

@@ -21,6 +21,7 @@ import static puzzle.SwedishGenerator.R;
import static puzzle.SwedishGenerator.Lemma;
import static puzzle.SwedishGenerator.Slot;
import static puzzle.SwedishGenerator.C;
import static puzzle.SwedishGenerator.X;
/**
* ExportFormat.java
@@ -43,8 +44,11 @@ public record Export() {
static final String INIT = IntStream.range(0, R).mapToObj(l_ -> " ").collect(Collectors.joining("\n"));
public record Clued(@Delegate Clues mask) {
public record ClueAt(int index, int clue) { }
public record Clued(@Delegate Clues c) {
public Clued deepCopyGrid() { return new Clued(new Clues(c.lo, c.hi, c.vlo, c.vhi, c.rlo, c.rhi)); }
String gridToString() {
var sb = new StringBuilder(INIT);
forEachSlot((s, l, a) -> {
@@ -56,6 +60,19 @@ public record Export() {
});
return sb.toString();
}
public Stream<ClueAt> stream() {
val stream = Stream.<ClueAt>builder();
for (var l = c.lo & ~c.rlo & c.vlo ; l != X; l &= l - 1) stream.accept(new ClueAt(Long.numberOfTrailingZeros(l), 1));
for (var l = c.lo & ~c.rlo & ~c.vlo ; l != X; l &= l - 1) stream.accept(new ClueAt(Long.numberOfTrailingZeros(l), 0));
for (var l = c.lo & c.rlo & ~c.vlo ; l != X; l &= l - 1) stream.accept(new ClueAt(Long.numberOfTrailingZeros(l), 2));
for (var l = c.lo & c.rlo & c.vlo ; l != X; l &= l - 1) stream.accept(new ClueAt(Long.numberOfTrailingZeros(l), 3));
for (var h = c.hi & ~c.rhi & c.vhi ; h != X; h &= h - 1) stream.accept(new ClueAt(64 | Long.numberOfTrailingZeros(h), 1));
for (var h = c.hi & ~c.rhi & ~c.vhi ; h != X; h &= h - 1) stream.accept(new ClueAt(64 | Long.numberOfTrailingZeros(h), 0));
for (var h = c.hi & c.rhi & ~c.vhi ; h != X; h &= h - 1) stream.accept(new ClueAt((64 | Long.numberOfTrailingZeros(h)), 2));
for (var h = c.hi & c.rhi & c.vhi ; h != X; h &= h - 1) stream.accept(new ClueAt((64 | Long.numberOfTrailingZeros(h)), 3));
return stream.build();
}
}
@FunctionalInterface
@@ -74,13 +91,13 @@ public record Export() {
public Stream<LetterAt> stream(Clues clues) {
val stream = Stream.<LetterAt>builder();
for (var l = grid.lo & ~clues.lo; l != SwedishGenerator.X; l &= l - 1) stream.accept(LetterAt.from(Long.numberOfTrailingZeros(l), grid.g));
for (var h = grid.hi & ~clues.hi; h != SwedishGenerator.X; h &= h - 1) stream.accept(LetterAt.from(64 | Long.numberOfTrailingZeros(h), grid.g));
for (var l = grid.lo & ~clues.lo; l != X; l &= l - 1) stream.accept(LetterAt.from(Long.numberOfTrailingZeros(l), grid.g));
for (var h = grid.hi & ~clues.hi; h != X; h &= h - 1) stream.accept(LetterAt.from(64 | Long.numberOfTrailingZeros(h), grid.g));
return stream.build();
}
public void forEachLetter(Clues clues, LetterVisit visitor) {
for (var l = grid.lo & ~clues.lo; l != SwedishGenerator.X; l &= l - 1) visitor.visit(Long.numberOfTrailingZeros(l), grid.g);
for (var h = grid.hi & ~clues.hi; h != SwedishGenerator.X; h &= h - 1) visitor.visit(64 | Long.numberOfTrailingZeros(h), grid.g);
for (var l = grid.lo & ~clues.lo; l != X; l &= l - 1) visitor.visit(Long.numberOfTrailingZeros(l), grid.g);
for (var h = grid.hi & ~clues.hi; h != X; h &= h - 1) visitor.visit(64 | Long.numberOfTrailingZeros(h), grid.g);
}
public static IntStream walk(byte base, long lo, long hi) {
if (Slot.increasing(base)) {
@@ -227,7 +244,7 @@ public record Export() {
// If nothing placed: return full grid mapped to letters/# only
if (placed.isEmpty()) {
return new ExportedPuzzle(g.exportGrid(clues.mask, _ -> '#', '#'), new WordOut[0], difficulty, rewards);
return new ExportedPuzzle(g.exportGrid(clues.c, _ -> '#', '#'), new WordOut[0], difficulty, rewards);
}
// 2) bounding box around all word cells + arrow cells, with 1-cell margin
@@ -251,7 +268,7 @@ public record Export() {
// 3) map of only used letter cells (everything else becomes '#')
var letterAt = new HashMap<Integer, Character>();
g.forEachLetter(clues.mask(), (idx, letter) -> {
g.forEachLetter(clues.c(), (idx, letter) -> {
if (letter == 0) return;
letterAt.put(idx, (char) (64 | letter));
});