This commit is contained in:
mike
2026-01-23 01:55:12 +01:00
parent 2295a7d97c
commit dc45ad45c9
13 changed files with 210 additions and 731 deletions

View File

@@ -12,6 +12,8 @@ import puzzle.SwedishGenerator.Dict;
import puzzle.SwedishGenerator.FillResult;
import puzzle.SwedishGenerator.Grid;
import puzzle.SwedishGenerator.Slotinfo;
import static precomp.Const9x8.CLUE_DOWN0;
import static precomp.Const9x8.CLUE_RIGHT1;
import static precomp.Const9x8.INIT_GRID_OUTPUT;
import static precomp.Const9x8.INIT_GRID_OUTPUT_ARR;
import static puzzle.Export.Clue.DOWN0;
@@ -34,8 +36,6 @@ import static puzzle.SwedishGenerator.X;
public record Export() {
public static final ThreadLocal<byte[]> BYTES = ThreadLocal.withInitial(() -> new byte[8]);
static final byte CLUE_DOWN = 0;
static final byte CLUE_RIGHT = 1;
static final byte CLUE_UP = 2;
static final byte CLUE_LEFT = 3;
static final byte CLUE_LEFT_TOP = 4;
@@ -48,8 +48,8 @@ public record Export() {
static int INDEX(int r, int cols, int c) { return r * cols + c; }
@AllArgsConstructor
enum Clue {
DOWN0(CLUE_DOWN, 'B', 'b'),
RIGHT1(CLUE_RIGHT, 'A', 'a'),
DOWN0(CLUE_DOWN0, 'B', 'b'),
RIGHT1(CLUE_RIGHT1, 'A', 'a'),
UP2(CLUE_UP, 'C', 'c'),
LEFT3(CLUE_LEFT, 'D', 'd'),
LEFT_TOP4(CLUE_LEFT_TOP, 'E', 'e'),
@@ -89,8 +89,8 @@ public record Export() {
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 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_RIGHT1));
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_DOWN0));
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));
@@ -99,7 +99,7 @@ public record Export() {
return stream.build();
}
public Slotinfo[] slots(Dict D) {
return Masker.slots(c, D.index());
return Masker.slots(c, D.index(), D.reversed());
}
}
@@ -214,20 +214,32 @@ 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) {
record ShaLemma(String word, @Delegate ShardLem rec) { }
private static ShaLemma 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;
var word1 = Lemma.asWord(w, bytes);
System.out.println(" word=" + word1 + "\n" + " simpel=" + rec.simpel() + "\n" + " clues=" + Arrays.toString(rec.clues()));
return new ShaLemma(word1, rec);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static long reverse(long w) {
int L = Lemma.unpackSize(w) + 1;
long letters = w & Lemma.LETTER_MASK;
long rev = 0;
for (int i = 0; i < L; i++) {
long letter = (letters >>> (5 * i)) & 31;
rev |= (letter << (5 * (L - 1 - i)));
}
return (w & ~Lemma.LETTER_MASK) | rev;
}
public WordOut(long l, int startRow, int startCol, char d, int arrowRow, int arrowCol, boolean isReversed, byte[] bytes) {
val meta = lookup(l, bytes);
this(Lemma.asWord(l, bytes), new int[]{ arrowRow, arrowCol, startRow, startCol }, startRow, startCol, d, arrowRow, arrowCol, isReversed,
val meta = lookup(isReversed ? reverse(l) : l, bytes);
this(meta.word, new int[]{ arrowRow, arrowCol, startRow, startCol }, startRow, startCol, d, arrowRow, arrowCol, isReversed,
meta.simpel(), meta.clues());
}
}

View File

@@ -59,7 +59,6 @@ public class Main {
void main(String[] args) {
_main(args);
}
@SneakyThrows
public void _main(String[] args) {
var opts = parseArgs(args);
@@ -254,9 +253,9 @@ public class Main {
// Package-private method for testing
PuzzleResult generatePuzzle(Opts opts) {
var tLoad0 = System.nanoTime();
var tLoad0 = System.nanoTime();
Dict dict = puzzle.dict800.DictData800.DICT800;//loadDict(opts.wordsPath);
var tLoad1 = System.nanoTime();
var tLoad1 = System.nanoTime();
section("Load");
info(String.format(Locale.ROOT, "words : %,d", dict.length()));
@@ -370,9 +369,9 @@ public class Main {
//val mask = generateClues();
if (mask == null) return null;
val slotInfo = Masker.slots(mask, dict.index());
val slotInfo = Masker.slots(mask, dict.index(), dict.reversed());
var grid = Slotinfo.grid(slotInfo);// mask.toGrid();
var filled = fillMask(rng, slotInfo, grid);
var filled = fillMask(rng, slotInfo, grid.lo, grid.hi, grid.g);
if (!multiThreaded) {
System.out.print("\r" + " ".repeat(120 - "".length()) + "\r");
@@ -405,6 +404,8 @@ public class Main {
//System.out.println(Arrays.stream(new Clued(mask).gridToString().split("\n")).map(s -> "\"" + s + "\\n\" +").collect(Collectors.joining("\n")));
}
if (filled.ok()) {
grid.lo = ~mask.lo;
grid.hi = 0xFFL & ~mask.hi;
return new PuzzleResult(new Signa(mask), new Puzzle(grid, mask), slotInfo, filled);
}

View File

@@ -0,0 +1,12 @@
package puzzle;
public interface Mask {
record Masker(long lo, long hi)
implements Mask { }
default Mask or(Mask o) { return new Masker(o.lo() | lo(), o.hi() | hi()); }
default Mask and(Mask o) { return new Masker(o.lo() & lo(), o.hi() & hi()); }
long hi();
long lo();
}

View File

@@ -1,8 +1,6 @@
package puzzle;
import module java.base;
import anno.GenerateNeighbor;
import anno.GenerateNeighbors;
import anno.Shaped;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -24,6 +22,7 @@ public final class Masker {
@Shaped public static final int MIN_LEN = Neighbors9x8.MIN_LEN;//Config.MIN_LEN;
@Shaped public static final int C = Neighbors9x8.C;
@Shaped public static final int R = Neighbors9x8.R;
@Shaped public static final int SIZE = Neighbors9x8.SIZE;
@Shaped public static final double SIZED = Neighbors9x8.SIZED;// ~18
@Shaped private static final long[] NBR_LO = Neighbors9x8.NBR_LO;
@Shaped private static final long[] NBR_HI = Neighbors9x8.NBR_HI;
@@ -43,6 +42,7 @@ public final class Masker {
this.stack = stack;
this.cache = cache;
}
public static boolean isLo(int n) { return (n & 64) == 0; }
public boolean isValid(Clues c) {
return findOffendingClue(c) == -1;
@@ -172,17 +172,18 @@ public final class Masker {
if (Long.bitCount(rayLo) + Long.bitCount(rayHi) >= MIN_LEN)
visitor.visit(key, rayLo, rayHi);
}
public static Slot[] extractSlots(Clues c, DictEntry[] index) {
public static Slot[] extractSlots(Clues c, DictEntry[] index, DictEntry[] rev) {
var slots = new ArrayList<Slot>(c.clueCount());
c.forEachSlot((key, lo, hi) -> slots.add(Slot.from(key, lo, hi, index[Slot.length(lo, hi)])));
c.forEachSlot((key, lo, hi) -> slots.add(Slot.from(key, lo, hi, Slotinfo.increasing(key) ? index[Slot.length(lo, hi)] : rev[Slot.length(lo, hi)])));
return slots.toArray(Slot[]::new);
}
public static Slotinfo[] slots(Clues mask, DictEntry[] index) {
var slots = Masker.extractSlots(mask, index);
public static Slotinfo[] slots(Clues mask, Dict d) { return slots(mask, d.index(), d.reversed()); }
public static Slotinfo[] slots(Clues mask, DictEntry[] index, DictEntry[] rev) {
var slots = Masker.extractSlots(mask, index, rev);
return Masker.scoreSlots(slots);
}
public static Slotinfo[] scoreSlots(Slot[] slots) {
val count = new byte[SwedishGenerator.SIZE];
val count = new byte[SIZE];
var slotInfo = new Slotinfo[slots.length];
for (var s : slots) {
for (var b = s.lo; b != X; b &= b - 1) count[numberOfTrailingZeros(b)]++;
@@ -714,7 +715,7 @@ public final class Masker {
return (bitCount(matchLo & MASK_LO) + bitCount(matchHi & MASK_HI)) / SIZED;
}
public Grid toGrid() { return new Grid(new byte[SwedishGenerator.SIZE], lo, hi); }
public Grid toGrid() { return new Grid(new byte[SIZE], lo, hi); }
public void forEachSlot(SlotVisitor visitor) {
for (var l = lo & ~xlo & ~rlo & vlo; l != X; l &= l - 1) processSlot(this, visitor, Slot.packSlotKey(numberOfTrailingZeros(l), 1));

View File

@@ -3,6 +3,8 @@ package puzzle;
import anno.ConstGen;
import anno.GenerateNeighbor;
import anno.GenerateNeighbors;
import anno.GenerateShapedCopies;
import anno.Shaped;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.val;
@@ -33,21 +35,21 @@ import static java.nio.charset.StandardCharsets.US_ASCII;
@GenerateNeighbor(C = 9, R = 8, packageName = "precomp", className = "Neighbors9x8", MIN_LEN = 2),
@GenerateNeighbor(C = 4, R = 3, packageName = "precomp", className = "Neighbors4x3", MIN_LEN = 2)
})
/*@GenerateShapedCopies(
className = "SwedishGeneratorX",
shapes = { "precomp.Neighbors9x8", "precomp.Neighbors4x3" }
)*/
public record SwedishGenerator() {
public static final long X = 0L;
public static final int SIZE = Neighbors9x8.SIZE;
public static final int MAX_TRIES_PER_SLOT = 500;// MAX_TRIES_PER_SLOT;
public static final long RANGE_0_SIZE = Neighbors9x8.RANGE_0_SIZE;
public static final long RANGE_0_624 = Neighbors9x8.RANGE_0_624;
public static final int MAX_TRIES_PER_SLOT = 500;// MAX_TRIES_PER_SLOT;
public static final long X = 0L;
@Shaped private static final int SIZE = Neighbors9x8.SIZE;
@Shaped private static final long RANGE_0_SIZE = Neighbors9x8.RANGE_0_SIZE;
@Shaped private static final long RANGE_0_624 = Neighbors9x8.RANGE_0_624;
public static boolean isLo(int n) { return (n & 64) == 0; }
interface Bit1029 {
static long[] bit1029() { return new long[2048]; }
private static int wordIndex(int bitIndex) { return bitIndex >> 6; }
static boolean get(long[] bits, int bitIndex) { return (bits[wordIndex(bitIndex)] & 1L << bitIndex) != X; }
static void set(long[] bits, int bitIndex) { bits[wordIndex(bitIndex)] |= 1L << bitIndex; }
@@ -55,12 +57,11 @@ public record SwedishGenerator() {
}
//@formatter:off
public record Dict(DictEntry[] index, int length) { }
public record Dict(DictEntry[] index,DictEntry[] reversed, int length) { public Dict(DictEntry[] index,int length){this(index,index,length);} }
public record DictEntry(long[] words, long[][] posBitsets, int length, int numlong) { }
@AllArgsConstructor @NoArgsConstructor static final class Assign { long w; }
public static final class FillStats { public double simplicity; }
@AllArgsConstructor public static final class Grid { public final byte[] g; public long lo, hi; }
public record FillResult(boolean ok, long nodes, long backtracks, int lastMRV, long elapsed, FillStats stats) { }
public record FillResult(boolean ok, long nodes, long backtracks, int lastMRV, long elapsed ) { }
//@formatter:on
public static final class Rng {
@@ -98,15 +99,15 @@ public record SwedishGenerator() {
static long pack(long w, int shardIndex) { return w | (((long) shardIndex) << 43) | ((long) length0(w)) << 40; }
static long packShiftIn(byte[] b) {
long w = 0;
for (int i = b.length - 1; i >= 0; i--) w = (w << 5) | ((long) b[i] & 31);
for (var i = b.length - 1; i >= 0; i--) w = (w << 5) | ((long) b[i] & 31);
return w;
}
static long from(String word) { return packShiftIn(word.getBytes(US_ASCII)) | ((long) (word.length() - 1) << 40); }
static byte byteAt(long word, int idx) { return (byte) ((word >>> (idx * 5)) & 0b11111L); }
static int length0(long word) { return ((63 - numberOfLeadingZeros(word & LETTER_MASK)) / 5); }
static String asWord(long word, byte[] bytes) {
int bi = 0;
for (long w = word & LETTER_MASK; w != 0; w >>>= 5) bytes[bi++] = (byte) ((w & 31) | 64);
var bi = 0;
for (var w = word & LETTER_MASK; w != 0; w >>>= 5) bytes[bi++] = (byte) ((w & 31) | 64);
return new String(bytes, 0, bi, US_ASCII);
}
static int unpackIndex(long w) { return (int) (w >>> 40); }
@@ -132,70 +133,45 @@ public record SwedishGenerator() {
}
}
public static long patternForSlot(final long glo, final long ghi, final byte[] g, final int key, final long lo, final long hi) {
if (((lo & glo) | (hi & ghi)) == X) return X;
public static long patternForSlot(final long glo, final long ghi, final byte[] g, final long lo, final long hi) {
if (((lo & glo) == X) && (hi & ghi) == X) return X;
long p = 0;
int n = 0, offset, idx;
if (Slotinfo.increasing(key)) {
for (long b = lo & glo; b != X; b &= b - 1) {
idx = numberOfTrailingZeros(b);
p |= ((long) (bitCount(lo & ((1L << idx) - 1)) * 26 + g[idx])) << (n++ << 3);
}
offset = bitCount(lo);
for (long b = hi & ghi; b != X; b &= b - 1) {
idx = numberOfTrailingZeros(b);
p |= ((long) ((offset + bitCount(hi & ((1L << idx) - 1))) * 26 + g[64 | idx])) << (n++ << 3);
}
} else {
offset = bitCount(hi);
for (long b = hi & ghi; b != X; b &= b - 1) {
idx = numberOfTrailingZeros(b);
p |= ((long) (bitCount(hi & ~((1L << idx) | ((1L << idx) - 1))) * 26 + g[64 | idx])) << (n++ << 3);
}
for (long b = lo & glo; b != X; b &= b - 1) {
idx = numberOfTrailingZeros(b);
p |= ((long) ((offset + bitCount(lo & ~((1L << idx) | ((1L << idx) - 1)))) * 26 + g[idx])) << (n++ << 3);
}
for (var b = lo & glo; b != X; b &= b - 1) {
idx = numberOfTrailingZeros(b);
p |= ((long) (bitCount(lo & ((1L << idx) - 1)) * 26 + g[idx])) << (n++ << 3);
}
offset = bitCount(lo);
for (var b = hi & ghi; b != X; b &= b - 1) {
idx = numberOfTrailingZeros(b);
p |= ((long) ((offset + bitCount(hi & ((1L << idx) - 1))) * 26 + g[64 | idx])) << (n++ << 3);
}
return p;
}
/// pattern cannot be X
public static int[] candidateInfoForPattern(long[] res, long pattern, long[][] posBitsets, int numLongs) {
System.arraycopy(posBitsets[(int) (pattern & 0xFF) - 1], 0, res, 0, numLongs);
for (long p = pattern >>> 8; p != X; p >>>= 8) {
long[] bs = posBitsets[(int) (p & 0xFF) - 1];
for (int k = 0; k < numLongs; k++) res[k] &= bs[k];
}
int count = 0;
for (int k = 0; k < numLongs; k++) count += bitCount(res[k]);
int[] indices = new int[count];
for (int k = 0, ki = 0; k < numLongs; k++) {
for (long w = res[k]; w != X; w &= w - 1) indices[ki++] = (k << 6) | numberOfTrailingZeros(w);
}
var indices = new int[candidateCountForPattern(res, pattern, posBitsets, numLongs)];
for (int k = 0, ki = 0; k < numLongs; k++) for (var w = res[k]; w != X; w &= w - 1) indices[ki++] = (k << 6) | numberOfTrailingZeros(w);
return indices;
}
/// pattern cannot be X
public static int candidateCountForPattern(final long[] res, final long pattern, final long[][] posBitsets, final int numLongs) {
System.arraycopy(posBitsets[(int) (pattern & 0xFF) - 1], 0, res, 0, numLongs);
for (long p = pattern >>> 8; p != X; p >>>= 8) {
long[] bs = posBitsets[(int) (p & 0xFF) - 1];
for (int k = 0; k < numLongs; k++) res[k] &= bs[k];
public static int candidateCountForPattern(final long[] res, final long pattern, final long[][] pos, final int num) {
System.arraycopy(pos[(int) (pattern & 0xFF) - 1], 0, res, 0, num);
for (var p = pattern >>> 8; p != X; p >>>= 8) {
var bs = pos[(int) (p & 0xFF) - 1];
for (var k = 0; k < num; k++) res[k] &= bs[k];
}
int count = 0;
for (int k = 0; k < numLongs; k++) count += bitCount(res[k]);
var count = 0;
for (var k = 0; k < num; k++) count += bitCount(res[k]);
return count;
}
public static FillResult fillMask(final Rng rng, final Slotinfo[] slots,
final Grid grid) {
final long lo, final long hi, final byte[] g) {
val used = new long[2048];
val bitset = new long[2500];
val g = grid.g;
val TOTAL = slots.length;
val t0 = System.currentTimeMillis();
class Solver {
@@ -203,82 +179,64 @@ public record SwedishGenerator() {
static final int PICK_NOT_DONE = -1;
static final int PICK_DONE = 0;
long nodes;
long backtracks;
long glo = grid.lo, ghi = grid.hi;
Slotinfo currentSlot;
int[] currentIndices;
boolean placeWordDec(final long lo, final long hi, final long w) {
long tracks;
long glo = lo, ghi = hi;
Slotinfo slot;
int[] indices;
boolean place(final long lo, final long hi, final long w) {
int idx;
int bcHi = bitCount(hi);
for (long b = hi & ghi; b != X; b &= b - 1)
if (g[64 | (idx = numberOfTrailingZeros(b))] != Lemma.byteAt(w, bitCount(hi & ~((1L << idx) | ((1L << idx) - 1))))) return false;
for (long b = lo & glo; b != X; b &= b - 1)
if (g[idx = numberOfTrailingZeros(b)] != Lemma.byteAt(w, bcHi + bitCount(lo & ~((1L << idx) | ((1L << idx) - 1))))) return false;
for (var b = lo & glo; b != X; b &= b - 1) if (g[idx = numberOfTrailingZeros(b)] != Lemma.byteAt(w, bitCount(lo & ((1L << idx) - 1)))) return true;
var bcLo = bitCount(lo);
for (var b = hi & ghi; b != X; b &= b - 1) if (g[64 | (idx = numberOfTrailingZeros(b))] != Lemma.byteAt(w, bcLo + bitCount(hi & ((1L << idx) - 1)))) return true;
long maskLo = lo & ~glo, maskHi = hi & ~ghi;
if ((maskLo | maskHi) != X) {
for (long b = maskHi; b != X; b &= b - 1) g[64 | (idx = numberOfTrailingZeros(b))] = Lemma.byteAt(w, bitCount(hi & ~((1L << idx) | ((1L << idx) - 1))));
for (long b = maskLo; b != X; b &= b - 1) g[idx = numberOfTrailingZeros(b)] = Lemma.byteAt(w, bcHi + bitCount(lo & ~((1L << idx) | ((1L << idx) - 1))));
for (var b = maskLo; b != X; b &= b - 1) g[idx = numberOfTrailingZeros(b)] = Lemma.byteAt(w, bitCount(lo & ((1L << idx) - 1)));
for (var b = maskHi; b != X; b &= b - 1) g[64 | (idx = numberOfTrailingZeros(b))] = Lemma.byteAt(w, bcLo + bitCount(hi & ((1L << idx) - 1)));
glo |= maskLo;
ghi |= maskHi;
}
return true;
}
boolean placeWordInc(final long lo, final long hi, final long w) {
int idx;
for (long b = lo & glo; b != X; b &= b - 1) if (g[idx = numberOfTrailingZeros(b)] != Lemma.byteAt(w, bitCount(lo & ((1L << idx) - 1)))) return false;
int bcLo = bitCount(lo);
for (long b = hi & ghi; b != X; b &= b - 1) if (g[64 | (idx = numberOfTrailingZeros(b))] != Lemma.byteAt(w, bcLo + bitCount(hi & ((1L << idx) - 1)))) return false;
long maskLo = lo & ~glo, maskHi = hi & ~ghi;
if ((maskLo | maskHi) != X) {
for (long b = maskLo; b != X; b &= b - 1) g[idx = idx = numberOfTrailingZeros(b)] = Lemma.byteAt(w, bitCount(lo & ((1L << idx) - 1)));
for (long b = maskHi; b != X; b &= b - 1) g[64 | (idx = numberOfTrailingZeros(b))] = Lemma.byteAt(w, bcLo + bitCount(hi & ((1L << idx) - 1)));
glo |= maskLo;
ghi |= maskHi;
}
return true;
return false;
}
int chooseMRV() {
Slotinfo best = null;
int count2 = -1, bestScore = -1;
Slotinfo best = null;
int max = -1, bestScore = -1;
for (int i = 0, n = TOTAL; i < n; i++) {
var s = slots[i];
if (s.assign.w != X) continue;
var pattern = patternForSlot(glo, ghi, g, s.key, s.lo, s.hi);
var pattern = patternForSlot(glo, ghi, g, s.lo, s.hi);
var index = s.entry;
int count = pattern == X ? index.length : candidateCountForPattern(bitset, pattern, index.posBitsets, index.numlong);
var count = pattern == X ? index.length : candidateCountForPattern(bitset, pattern, index.posBitsets, index.numlong);
if (count == 0) return PICK_NOT_DONE;
if (best == null
|| count < count2
|| (count == count2 && s.score > bestScore)) {
|| count < max
|| (count == max && s.score > bestScore)) {
best = s;
bestScore = s.score;
count2 = count;
max = count;
if (count <= 1) break;
}
}
if (best == null) return PICK_DONE;
var pattern = patternForSlot(glo, ghi, g, best.key, best.lo, best.hi);
currentSlot = best;
var pattern = patternForSlot(glo, ghi, g, best.lo, best.hi);
slot = best;
var index = best.entry;
currentIndices = pattern == X ? null : candidateInfoForPattern(bitset, pattern, index.posBitsets, index.numlong);
indices = pattern == X ? null : candidateInfoForPattern(bitset, pattern, index.posBitsets, index.numlong);
return 1;
}
boolean backtrack(int depth) {
if (Thread.currentThread().isInterrupted() || (System.currentTimeMillis() - t0) > 20_000) return false;
nodes++;
int status = chooseMRV();
var status = chooseMRV();
if (status == PICK_DONE) return true;
if (status == PICK_NOT_DONE) {
backtracks++;
tracks++;
return false;
}
val info = currentIndices;
val s = currentSlot;
val inc = Slotinfo.increasing(s.key);
val info = indices;
val s = slot;
val slo = s.lo;
val shi = s.hi;
val assign = s.assign;
@@ -294,11 +252,7 @@ public record SwedishGenerator() {
if (Bit1029.get(used, lemIdx)) continue;
low = glo;
top = ghi;
if (inc) {
if (!placeWordInc(slo, shi, w)) continue;
} else {
if (!placeWordDec(slo, shi, w)) continue;
}
if (place(slo, shi, w)) continue;
Bit1029.set(used, lemIdx);
assign.w = w;
@@ -308,45 +262,36 @@ public record SwedishGenerator() {
glo = low;
ghi = top;
}
backtracks++;
tracks++;
return false;
}
var N = words.length;
for (var t = 0; t < s.minL; t++) {
var w = words[rng.biasedIndexPow3(N - 1)];
var lemIdx = Lemma.unpackIndex(w);
if (Bit1029.get(used, lemIdx)) continue;
var w = words[rng.biasedIndexPow3(N - 1)];
var lem = Lemma.unpackIndex(w);
if (Bit1029.get(used, lem)) continue;
low = glo;
top = ghi;
if (inc) {
if (!placeWordInc(slo, shi, w)) continue;
} else {
if (!placeWordDec(slo, shi, w)) continue;
}
if (place(slo, shi, w)) continue;
Bit1029.set(used, lemIdx);
Bit1029.set(used, lem);
assign.w = w;
if (backtrack(depth + 1)) return true;
assign.w = X;
Bit1029.clear(used, lemIdx);
Bit1029.clear(used, lem);
glo = low;
ghi = top;
}
backtracks++;
tracks++;
return false;
}
}
var solver = new Solver();
var ok = solver.backtrack(0);
grid.lo = solver.glo;
grid.hi = solver.ghi;
return new FillResult(ok, solver.nodes, solver.backtracks, solver.currentSlot == null ? 0 : solver.currentSlot.entry.length, System.currentTimeMillis() - t0,
new FillStats());
return new FillResult(ok, solver.nodes, solver.tracks, solver.slot == null ? 0 : solver.slot.entry.length, System.currentTimeMillis() - t0);
}
}