introduce bitloops

This commit is contained in:
mike
2026-01-14 07:25:46 +01:00
parent 5d34893ef1
commit c529ce90c7
7 changed files with 144 additions and 144 deletions

View File

@@ -6,7 +6,6 @@ import lombok.experimental.Delegate;
import lombok.val;
import puzzle.Export.Gridded.Replacar.Cell;
import puzzle.SwedishGenerator.Clues;
import puzzle.SwedishGenerator.Dict;
import puzzle.SwedishGenerator.FillResult;
import puzzle.SwedishGenerator.Grid;
import java.util.ArrayList;
@@ -47,7 +46,7 @@ public record Export() {
for (var c = 0; c < C; c++) {
val idx = Grid.offset(r, c);
if (mask.isClue(idx))
sb.append((char) mask.digitAt(idx));
sb.append((char) (mask.digitAt(idx) | 48));
else {
sb.append(' ');
}
@@ -182,7 +181,7 @@ public record Export() {
public record ExportedPuzzle(String[] grid, WordOut[] words, int difficulty, Rewards rewards) { }
public record PuzzleResult(SwedishGenerator swe, Dict dict, Clued mask, FillResult filled) {
public record PuzzleResult(Clued mask, FillResult filled) {
boolean inBounds(int idx) { return idx >= 0 && idx < SwedishGenerator.SIZE; }
Placed extractPlacedFromSlot(Slot s, long lemma) { return new Placed(lemma, s.key(), s.walk().toArray()); }

View File

@@ -1,7 +1,8 @@
package puzzle;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.val;
import lombok.NoArgsConstructor;
import puzzle.SwedishGenerator.Rng;
import java.io.IOException;
@@ -38,17 +39,18 @@ public class Main {
static final AtomicLong TOTAL_SIMPLICITY = new AtomicLong(0); // Scaled by 100 for precision
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Opts {
public int seed = (int) (System.nanoTime() ^ System.currentTimeMillis());
public int pop = 18;
public int seed = (int) (System.nanoTime() ^ System.currentTimeMillis());
public int pop = 18;
public int gens = 1200;
public String wordsPath = "nl_score_hints_v3.csv";
public double minSimplicity = 0; // 0 means no limit
public int threads = Math.max(1, Runtime.getRuntime().availableProcessors());
public int tries = threads;
public boolean reindex = false;
public int fillTimeout = 20_000;
public boolean verbose = false;
}
@@ -356,9 +358,9 @@ public class Main {
}
static PuzzleResult _attempt(Rng rng, Dict dict, Opts opts) {
TOTAL_ATTEMPTS.incrementAndGet();
val stack = new int[STACK_SIZE];
var swe = new SwedishGenerator(rng, stack, Clues.createEmpty());
var swe = new SwedishGenerator(rng, new int[STACK_SIZE], Clues.createEmpty());
var mask = swe.generateMask(opts.pop, opts.gens, Math.max(opts.pop, (int) Math.floor(opts.pop * 1.5)));
var filled = fillMask(rng, extractSlots(mask), mask.toGrid(), dict.index());
TOTAL_NODES.addAndGet(filled.stats().nodes);
@@ -380,7 +382,7 @@ public class Main {
);
if (filled.ok() && (opts.minSimplicity <= 0 || filled.stats().simplicity >= opts.minSimplicity)) {
return new PuzzleResult(swe, dict, new Clued(mask), filled);
return new PuzzleResult(new Clued(mask), filled);
}
if (opts.verbose && filled.ok()) {

View File

@@ -148,14 +148,6 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
}
}
static final record Context(long[] bitset) {
public Context() { this(new long[2500]); }
private static final ThreadLocal<Context> CTX = ThreadLocal.withInitial(Context::new);
public static Context get() { return CTX.get(); }
}
static final class Rng {
@Getter private int x;
@@ -315,8 +307,6 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
static record DictEntry(long[] words, long[][] posBitsets, int length, int numlong) { }
static int LEMMA_COUNTER = 0;
public static interface Lemma {
static final long LETTER_MASK = (1L << 40) - 1; // low 40 bits
@@ -329,12 +319,12 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
for (var i = 0; i < b.length; i++) w |= ((long) b[i] & 63) << (i * 5);
return w;
}
static public long from(String word) { return pack(LEMMA_COUNTER++, word.getBytes(US_ASCII)); }
static byte byteAt(long word, int idx) { return (byte) ((word >>> (idx * 5)) & 0b11111 | B64); }// word[]; }
static int intAt(long word, int idx) { return (int) (((word >>> (idx * 5))) & 0b11111); }// word[]; }
static String[] clue(long w) { return CsvIndexService.clues(unpackIndex(w)); }
static int simpel(long w) { return CsvIndexService.simpel(unpackIndex(w)); }
static int length(long word) { return ((63 - Long.numberOfLeadingZeros(word & LETTER_MASK)) / 5) + 1; }
static public long from(int index, String word) { return pack(index, word.getBytes(US_ASCII)); }
static byte byteAt(long word, int idx) { return (byte) ((word >>> (idx * 5)) & 0b11111 | B64); }// word[]; }
static int intAt(long word, int idx) { return (int) (((word >>> (idx * 5))) & 0b11111); }// word[]; }
static String[] clue(long w) { return CsvIndexService.clues(unpackIndex(w)); }
static int simpel(long w) { return CsvIndexService.simpel(unpackIndex(w)); }
static int length(long word) { return ((63 - Long.numberOfLeadingZeros(word & LETTER_MASK)) / 5) + 1; }
public static String asWord(long word) {
var b = new byte[Lemma.length(word)];
for (var i = 0; i < b.length; i++) b[i] = (byte) ((word >>> (i * 5)) & 0b11111 | B64);
@@ -851,14 +841,13 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
return true;
}
static int[] candidateInfoForPattern(long[] res, long pattern, DictEntry entry, int lenb) {
int numLongs = entry.numlong;
static int[] candidateInfoForPattern(long[] res, long pattern, long[][] posBitsets, int numLongs) {
boolean first = true;
for (long p = pattern; p != 0; ) {
int combined = (int) (p & 0xFF);
if (combined != 0) {
long[] bs = entry.posBitsets[combined - 1];
long[] bs = posBitsets[combined - 1];
if (first) {
System.arraycopy(bs, 0, res, 0, numLongs);
first = false;
@@ -888,8 +877,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
return indices;
}
static int candidateCountForPattern(final long[] res, final long pattern, final DictEntry entry, final int lenb) {
val numLongs = entry.numlong;
static int candidateCountForPattern(final long[] res, final long pattern, final DictEntry entry, final int numLongs) {
val posBitsets = entry.posBitsets;
boolean first = true;
@@ -975,7 +963,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
if (assigned[s.key] != X) continue;
var pattern = patternForSlot(grid, s);
var index = dictIndex[s.length()];
count = pattern == X ? index.length : candidateCountForPattern(bitset, pattern, index, s.length());
count = pattern == X ? index.length : candidateCountForPattern(bitset, pattern, index, index.numlong);
if (count == 0) {
current = PICK_NOT_DONE;
@@ -1004,7 +992,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
current.indices = null;
return;
}
current.indices = candidateInfoForPattern(bitset, pattern, index, best.length());
current.indices = candidateInfoForPattern(bitset, pattern, index.posBitsets, index.numlong);
}
boolean backtrack(int depth) {
if (Thread.currentThread().isInterrupted()) return false;