introduce bitloops
This commit is contained in:
@@ -1,16 +1,10 @@
|
||||
package puzzle;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import lombok.experimental.Delegate;
|
||||
import lombok.val;
|
||||
import precomp.Neighbors9x8;
|
||||
import precomp.Neighbors9x8.rci;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import static java.lang.Long.*;
|
||||
import static java.lang.Long.numberOfTrailingZeros;
|
||||
import static java.nio.charset.StandardCharsets.US_ASCII;
|
||||
@@ -38,9 +32,7 @@ public record SwedishGenerator() {
|
||||
public static final int LOG_EVERY_MS = 200;
|
||||
public static final int BAR_LEN = 22;
|
||||
public static final int C = Config.PUZZLE_COLS;
|
||||
public static final double CROSS_R = (C - 1) / 2.0;
|
||||
public static final int R = Config.PUZZLE_ROWS;
|
||||
public static final double CROSS_C = (R - 1) / 2.0;
|
||||
public static final int SIZE = C * R;// ~18
|
||||
public static final int SIZE_MIN_1 = SIZE - 1;// ~18
|
||||
public static final double SIZED = (double) SIZE;// ~18
|
||||
@@ -55,7 +47,7 @@ public record SwedishGenerator() {
|
||||
public static final byte DASH = (byte) C_DASH;
|
||||
public static final long RANGE_0_SIZE = (long) SIZE_MIN_1 - 0L + 1L;
|
||||
public static final long RANGE_0_624 = 624L - 0L + 1L;
|
||||
public static int clamp(int x, int a, int b) { return Math.max(a, Math.min(b, x)); }
|
||||
public static boolean isLo(int n) { return (n & 64) == 0; }
|
||||
interface Bit1029 {
|
||||
|
||||
static long[] bit1029() { return new long[2048]; }
|
||||
@@ -64,10 +56,7 @@ public record SwedishGenerator() {
|
||||
static void set(long[] bits, int bitIndex) { bits[wordIndex(bitIndex)] |= 1L << bitIndex; }
|
||||
static void clear(long[] bits, int bitIndex) { bits[wordIndex(bitIndex)] &= ~(1L << bitIndex); }
|
||||
}
|
||||
static String padRight(String s, int n) {
|
||||
if (s.length() >= n) return s;
|
||||
return s + " ".repeat(n - s.length());
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
public static class Pick {
|
||||
|
||||
@@ -76,29 +65,36 @@ public record SwedishGenerator() {
|
||||
public int count;
|
||||
}
|
||||
|
||||
public static final long[] OFFSETS_D_IDX=Neighbors9x8.OFFSETS_D_IDX;
|
||||
public static final rci[] IT = Neighbors9x8.IT;
|
||||
//@formatter:off
|
||||
public static record Dict(DictEntry[] index, int length) { }
|
||||
@AllArgsConstructor @NoArgsConstructor static class Assign { long w; }
|
||||
public static final class FillStats { public double simplicity; }
|
||||
//@formatter:on
|
||||
@AllArgsConstructor
|
||||
public static class Grid {
|
||||
|
||||
public final byte[] g;
|
||||
public long lo, hi;
|
||||
}
|
||||
|
||||
public static record FillResult(boolean ok, long nodes, long backtracks, int lastMRV, long elapsed, FillStats stats) { }
|
||||
|
||||
public static record DictEntry(long[] words, long[][] posBitsets, int length, int numlong) { }
|
||||
|
||||
public static final long[] OFFSETS_D_IDX = Neighbors9x8.OFFSETS_D_IDX;
|
||||
public static final long[] NBR8_PACKED_LO = Neighbors9x8.NBR8_PACKED_LO;
|
||||
public static final long[] NBR8_PACKED_HI = Neighbors9x8.NBR8_PACKED_HI;
|
||||
public static final long[] PATH_LO= Neighbors9x8.PATH_LO;
|
||||
public static final long[] PATH_HI= Neighbors9x8.PATH_HI;
|
||||
|
||||
public static final Pick PICK_DONE = null;//new Pick(null, null, 0, true);
|
||||
public static final Pick PICK_NOT_DONE = new Pick(null, null, 0);
|
||||
public static final long[] PATH_LO = Neighbors9x8.PATH_LO;
|
||||
public static final long[] PATH_HI = Neighbors9x8.PATH_HI;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public static final class FillStats {
|
||||
|
||||
public double simplicity;
|
||||
}
|
||||
public static final Pick PICK_DONE = null;//new Pick(null, null, 0, true);
|
||||
|
||||
public static record FillResult(boolean ok, long nodes, long backtracks, int lastMRV, long elapsed, FillStats stats) {
|
||||
|
||||
}
|
||||
public static final Pick PICK_NOT_DONE = new Pick(null, null, 0);
|
||||
|
||||
public static final class Rng {
|
||||
|
||||
@Getter private int x;
|
||||
private int x;
|
||||
public Rng(int seed) {
|
||||
var s = seed;
|
||||
if (s == 0) s = 1;
|
||||
@@ -114,9 +110,9 @@ public record SwedishGenerator() {
|
||||
}
|
||||
public byte randint2bitByte() {
|
||||
int r = nextU32() & 7;
|
||||
if (r < 4) return (byte) r;
|
||||
if (r == 4) return (byte) 4;
|
||||
return (byte) (r % 4);
|
||||
//if (r < 4) return (byte) r;
|
||||
return (byte) (r & 3);
|
||||
}
|
||||
public <T> T rand(T[] p) { return p[(int) (((nextU32() & 0xFFFFFFFFL) % ((long) p.length /*- 0L*/ /*+ 1L*/)))]; }
|
||||
public <T> T rand(List<T> p) { return p.get((int) (((nextU32() & 0xFFFFFFFFL) % ((long) p.size() /*- 0L*/ /*+ 1L*/)))); }
|
||||
@@ -127,20 +123,6 @@ public record SwedishGenerator() {
|
||||
public int biasedIndexPow3(int N) { return (int) (((Math.min(nextU32(), Math.min(nextU32(), nextU32())) & 0xFFFFFFFFL) * (long) N) >>> 32); }
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
public static class Grid {
|
||||
|
||||
public final byte[] g;
|
||||
public long lo, hi;
|
||||
public static int offset(int r, int c) { return r | (c << 3); }
|
||||
|
||||
public Grid copy() {
|
||||
return new Grid(g.clone(), lo, hi);
|
||||
}
|
||||
}
|
||||
|
||||
public static record DictEntry(long[] words, long[][] posBitsets, int length, int numlong) { }
|
||||
|
||||
public static interface Lemma {
|
||||
|
||||
static final long LETTER_MASK = (1L << 40) - 1; // low 40 bits
|
||||
@@ -148,28 +130,20 @@ public record SwedishGenerator() {
|
||||
|
||||
static long from(byte[] word) { return packShiftIn(word) | ((long) (word.length - 1) << 40); }
|
||||
static long pack(long w, int shardIndex) { return w | (((long) shardIndex) << 43) | ((long) length0(w)) << 40; }
|
||||
/* static long pack(byte[] b) {
|
||||
long w = 0;
|
||||
for (var i = 0; i < b.length; i++) w |= ((long) b[i] & 31) << (i * 5);
|
||||
return w;
|
||||
}*/
|
||||
static long packShiftIn(byte[] b) {
|
||||
long w = 0;
|
||||
for (int i = b.length - 1; i >= 0; i--) w = (w << 5) | ((long) b[i] & 31);
|
||||
return w;
|
||||
}
|
||||
static public 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 >>> ((long) idx * 5L)) & 0b11111L); }
|
||||
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 ThreadLocal<byte[]> BYTES = ThreadLocal.withInitial(() -> new byte[MAX_WORD_LENGTH]);
|
||||
public static String asWord(long word) {
|
||||
var b = BYTES.get();
|
||||
public static String asWord(long word, byte[] bytes) {
|
||||
int bi = 0;
|
||||
|
||||
for (long w = word & LETTER_MASK; w != 0; w >>>= 5) {
|
||||
b[bi++] = (byte) ((w & 31) | 64); // neem laagste 5 bits
|
||||
bytes[bi++] = (byte) ((w & 31) | 64); // neem laagste 5 bits
|
||||
}
|
||||
return new String(b, 0, bi, US_ASCII);
|
||||
return new String(bytes, 0, bi, US_ASCII);
|
||||
}
|
||||
static int unpackIndex(long w) { return (int) (w >>> 40); }
|
||||
static int unpackShardIndex(long w) { return (int) (w >>> 43); }
|
||||
@@ -177,15 +151,6 @@ public record SwedishGenerator() {
|
||||
static int unpackLetters(long w) { return (int) (w & LETTER_MASK); }
|
||||
}
|
||||
|
||||
public static record Dict(DictEntry[] index, int length) { }
|
||||
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
static class Assign {
|
||||
|
||||
long w;
|
||||
}
|
||||
|
||||
public static record Slotinfo(int key, long lo, long hi, int score, Assign assign, DictEntry entry) {
|
||||
|
||||
public static int wordCount(int k, Slotinfo[] arr) {
|
||||
@@ -203,34 +168,29 @@ public record SwedishGenerator() {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isLo(int n) { return (n & 64) == 0; }
|
||||
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 0;
|
||||
if (((lo & glo) | (hi & ghi)) == X) return X;
|
||||
long p = 0;
|
||||
int n = 0;
|
||||
int n = 0, offset, idx;
|
||||
if (Slotinfo.increasing(key)) {
|
||||
for (long b = lo & glo; b != X; b &= b - 1) {
|
||||
int idx = numberOfTrailingZeros(b);
|
||||
int i = bitCount(lo & ((1L << idx) - 1));
|
||||
p |= ((long) (i * 26 + g[idx])) << (n++ << 3);
|
||||
idx = numberOfTrailingZeros(b);
|
||||
p |= ((long) (bitCount(lo & ((1L << idx) - 1)) * 26 + g[idx])) << (n++ << 3);
|
||||
}
|
||||
int offset = bitCount(lo);
|
||||
offset = bitCount(lo);
|
||||
for (long b = hi & ghi; b != X; b &= b - 1) {
|
||||
int idx = numberOfTrailingZeros(b);
|
||||
int i = offset + bitCount(hi & ((1L << idx) - 1));
|
||||
p |= ((long) (i * 26 + g[64 | idx])) << (n++ << 3);
|
||||
idx = numberOfTrailingZeros(b);
|
||||
p |= ((long) ((offset + bitCount(hi & ((1L << idx) - 1))) * 26 + g[64 | idx])) << (n++ << 3);
|
||||
}
|
||||
} else {
|
||||
int offset = bitCount(hi);
|
||||
offset = bitCount(hi);
|
||||
for (long b = hi & ghi; b != X; b &= b - 1) {
|
||||
int idx = numberOfTrailingZeros(b);
|
||||
int i = bitCount(hi & ~((1L << idx) | ((1L << idx) - 1)));
|
||||
p |= ((long) (i * 26 + g[64 | idx])) << (n++ << 3);
|
||||
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) {
|
||||
int idx = numberOfTrailingZeros(b);
|
||||
int i = offset + bitCount(lo & ~((1L << idx) | ((1L << idx) - 1)));
|
||||
p |= ((long) (i * 26 + g[idx])) << (n++ << 3);
|
||||
idx = numberOfTrailingZeros(b);
|
||||
p |= ((long) ((offset + bitCount(lo & ~((1L << idx) | ((1L << idx) - 1)))) * 26 + g[idx])) << (n++ << 3);
|
||||
}
|
||||
}
|
||||
return p;
|
||||
@@ -268,8 +228,7 @@ public record SwedishGenerator() {
|
||||
}
|
||||
|
||||
public static FillResult fillMask(final Rng rng, final Slotinfo[] slots,
|
||||
final Grid grid,
|
||||
final boolean NO_LOG) {
|
||||
final Grid grid) {
|
||||
val used = new long[2048];
|
||||
val bitset = new long[2500];
|
||||
val g = grid.g;
|
||||
@@ -283,27 +242,6 @@ public record SwedishGenerator() {
|
||||
int lastMRV;
|
||||
long lastLog = t0, glo = grid.lo, ghi = grid.hi;
|
||||
Pick current = CARRIER;
|
||||
void renderProgress() {
|
||||
var now = System.currentTimeMillis();
|
||||
if ((now - lastLog) < LOG_EVERY_MS) return;
|
||||
lastLog = (now);
|
||||
var done = 0;
|
||||
for (var lemma : slots) {
|
||||
if (lemma.assign.w != X) done++;
|
||||
}
|
||||
var pct = (TOTAL == 0) ? 100 : (int) Math.floor((done / (double) TOTAL) * 100);
|
||||
var filled = Math.min(BAR_LEN, (int) Math.floor((pct / 100.0) * BAR_LEN));
|
||||
var bar = "[" + "#".repeat(filled) + "-".repeat(BAR_LEN - filled) + "]";
|
||||
var elapsed = String.format(Locale.ROOT, "%.1fs", (now - t0) / 1000.0);
|
||||
|
||||
var msg = String.format(
|
||||
Locale.ROOT,
|
||||
"%s %d/%d slots | nodes=%d | backtracks=%d | mrv=%d | %s",
|
||||
bar, done, TOTAL, nodes, backtracks, lastMRV, elapsed
|
||||
);
|
||||
System.out.print("\r" + padRight(msg, 120));
|
||||
System.out.flush();
|
||||
}
|
||||
boolean placeWordDec(final long lo, final long hi, final long w) {
|
||||
int idx;
|
||||
int bcHi = bitCount(hi);
|
||||
@@ -358,7 +296,6 @@ public record SwedishGenerator() {
|
||||
if (count <= 1) break;
|
||||
}
|
||||
}
|
||||
// Re-calculate for the best slot to get actual indices
|
||||
if (best == null) {
|
||||
current = PICK_DONE;
|
||||
return;
|
||||
@@ -383,7 +320,6 @@ public record SwedishGenerator() {
|
||||
}
|
||||
val info = pick.indices;
|
||||
lastMRV = pick.count;
|
||||
if (!NO_LOG) renderProgress();
|
||||
|
||||
val s = pick.slot;
|
||||
val inc = Slotinfo.increasing(s.key);
|
||||
@@ -397,11 +333,8 @@ public record SwedishGenerator() {
|
||||
var tries = Math.min(MAX_TRIES_PER_SLOT, L);
|
||||
|
||||
for (var t = 0; t < tries; t++) {
|
||||
//var r = rng.nextFloat();
|
||||
//var idxInArray = (int) (r * r * r * (L - 1));
|
||||
int idxInArray = rng.biasedIndexPow3(L - 1);
|
||||
var w = entry.words[idxs[idxInArray/*(int) (r * r * r * (L - 1))*/]];
|
||||
var lemIdx = Lemma.unpackIndex(w);
|
||||
var w = entry.words[idxs[rng.biasedIndexPow3(L - 1)]];
|
||||
var lemIdx = Lemma.unpackIndex(w);
|
||||
if (Bit1029.get(used, lemIdx)) continue;
|
||||
low = glo;
|
||||
top = ghi;
|
||||
@@ -427,8 +360,7 @@ public record SwedishGenerator() {
|
||||
|
||||
var tries = Math.min(MAX_TRIES_PER_SLOT, N);
|
||||
for (var t = 0; t < tries; t++) {
|
||||
// double r = rng.nextFloat();
|
||||
var w = entry.words[rng.biasedIndexPow3(N - 1)/*(int) (r * r * r * (N - 1))*/];
|
||||
var w = entry.words[rng.biasedIndexPow3(N - 1)];
|
||||
var lemIdx = Lemma.unpackIndex(w);
|
||||
if (Bit1029.get(used, lemIdx)) continue;
|
||||
low = glo;
|
||||
@@ -454,11 +386,8 @@ public record SwedishGenerator() {
|
||||
}
|
||||
}
|
||||
|
||||
// initial render (same feel)
|
||||
var solver = new Solver();
|
||||
if (!NO_LOG) solver.renderProgress();
|
||||
var ok = solver.backtrack(0);
|
||||
// final progress line
|
||||
var ok = solver.backtrack(0);
|
||||
grid.lo = solver.glo;
|
||||
grid.hi = solver.ghi;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user