introduce bitloops
This commit is contained in:
@@ -245,30 +245,36 @@ public record SwedishGenerator(Rng rng) {
|
||||
|
||||
static record DictEntry(Lemma[] words, long[][] posBitsets) { }
|
||||
|
||||
public static record Lemma(int index, long word) {
|
||||
public static record Lemma(long word) {
|
||||
|
||||
static int LEMMA_COUNTER = 0;
|
||||
static long pack(String word) {
|
||||
return pack(word.getBytes(US_ASCII));
|
||||
static final long LETTER_MASK = (1L << 40) - 1; // low 40 bits
|
||||
static final long INDEX_MASK = (1L << 24) - 1; // 24 bits
|
||||
static int LEMMA_COUNTER = 0;
|
||||
static long pack(String word) { return pack(word.getBytes(US_ASCII)); }
|
||||
static long pack(int index, byte[] b) {
|
||||
return pack(b) | ((long) index << 40);
|
||||
}
|
||||
static long pack(byte[] b) {
|
||||
long w = 0;
|
||||
for (var i = 0; i < b.length; i++) w |= ((long) b[i] & ~64) << (i * 5);
|
||||
return w;
|
||||
}
|
||||
public Lemma(int index, String word) {
|
||||
this(index, pack(word.getBytes(US_ASCII)));
|
||||
}
|
||||
public Lemma(int index, String word) { this(pack(index, word.getBytes(US_ASCII))); }
|
||||
public Lemma(String word) { this(LEMMA_COUNTER++, word); }
|
||||
byte byteAt(int idx) { return (byte) ((word >>> (idx * 5)) & 0b11111 | B64); }// word[]; }
|
||||
int intAt(int idx) { return (int) (((word >>> (idx * 5))) & 0b11111); }// word[]; }
|
||||
@Override public int hashCode() { return index; }
|
||||
@Override public boolean equals(Object o) { return (o == this) || (o instanceof Lemma l && l.index == index); }
|
||||
String[] clue() { return CsvIndexService.clues(index); }
|
||||
int simpel() { return CsvIndexService.simpel(index); }
|
||||
@Override public int hashCode() { return unpackIndex(word); }
|
||||
@Override public boolean equals(Object o) { return (o == this) || (o instanceof Lemma l && l.word == word); }
|
||||
String[] clue() { return CsvIndexService.clues(unpackIndex(word)); }
|
||||
int simpel() { return CsvIndexService.simpel(unpackIndex(word)); }
|
||||
int length() {
|
||||
if (word == 0) return 0;
|
||||
int highestBit = 63 - Long.numberOfLeadingZeros(word & 0xffffffffffffffffL);
|
||||
int highestBit = 63 - Long.numberOfLeadingZeros(word & LETTER_MASK);
|
||||
return (highestBit / 5) + 1;
|
||||
}
|
||||
static int usedCharsInPattern(long p) {
|
||||
if (p == 0) return 0;
|
||||
int highestBit = 63 - Long.numberOfLeadingZeros(p & LETTER_MASK); // 0-based
|
||||
return (highestBit / 5) + 1;
|
||||
}
|
||||
public String asWord() {
|
||||
@@ -276,6 +282,12 @@ public record SwedishGenerator(Rng rng) {
|
||||
for (var i = 0; i < length(); i++) b[i] = (byte) ((word >>> (i * 5)) & 0b11111 | B64);
|
||||
return new String(b, US_ASCII);
|
||||
}
|
||||
static int unpackIndex(long w) {
|
||||
return (int) (w >>> 40);
|
||||
}
|
||||
static int unpackLetters(long w) {
|
||||
return (int) (w & LETTER_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
public static record Dict(
|
||||
@@ -648,11 +660,7 @@ public record SwedishGenerator(Rng rng) {
|
||||
//return pop.get(0).grid;
|
||||
return best.grid;
|
||||
}
|
||||
static int usedCharsInPattern(long p) {
|
||||
if (p == 0) return 0;
|
||||
int highestBit = 63 - Long.numberOfLeadingZeros(p); // 0-based
|
||||
return (highestBit / 5) + 1;
|
||||
}
|
||||
|
||||
static long patternForSlot(Grid grid, Slot s) {
|
||||
long p = 0;
|
||||
for (int i = 0, len = s.len(); i < len; i++) {
|
||||
@@ -702,7 +710,7 @@ public record SwedishGenerator(Rng rng) {
|
||||
long[] res = ctx.bitset;
|
||||
boolean first = true;
|
||||
|
||||
for (int i = 0, len = usedCharsInPattern(pattern); i < len; i++) {
|
||||
for (int i = 0, len = Lemma.usedCharsInPattern(pattern); i < len; i++) {
|
||||
int val = (int) ((pattern >>> (i * 5)) & 31);
|
||||
if (val != 0) {
|
||||
long[] bs = entry.posBitsets[i * 26 + (val - 1)];
|
||||
@@ -742,7 +750,7 @@ public record SwedishGenerator(Rng rng) {
|
||||
long[] res = ctx.bitset;
|
||||
boolean first = true;
|
||||
|
||||
for (int i = 0, len = usedCharsInPattern(pattern); i < len; i++) {
|
||||
for (int i = 0, len = Lemma.usedCharsInPattern(pattern); i < len; i++) {
|
||||
int val = (int) ((pattern >>> (i * 5)) & 31);
|
||||
if (val != 0) {
|
||||
long[] bs = entry.posBitsets[i * 26 + (val - 1)];
|
||||
@@ -872,18 +880,18 @@ public record SwedishGenerator(Rng rng) {
|
||||
int idxInArray = (int) (r * r * r * L);
|
||||
var idx = idxs[idxInArray];
|
||||
var w = entry.words[idx];
|
||||
|
||||
if (used.get(w.index)) continue;
|
||||
var lemIdx = Lemma.unpackIndex(w.word);
|
||||
if (used.get(lemIdx)) continue;
|
||||
|
||||
if (!placeWord(grid, s, w, ctx.undo, depth)) continue;
|
||||
|
||||
used.set(w.index);
|
||||
used.set(lemIdx);
|
||||
assigned[k] = w;
|
||||
|
||||
if (backtrack(depth + 1)) return true;
|
||||
|
||||
assigned[k] = null;
|
||||
used.clear(w.index);
|
||||
used.clear(lemIdx);
|
||||
s.undoPlace(grid, ctx.undo[depth]);
|
||||
}
|
||||
stats.backtracks++;
|
||||
@@ -901,18 +909,18 @@ public record SwedishGenerator(Rng rng) {
|
||||
double r = rng.nextFloat();
|
||||
int idxInArray = (int) (r * r * r * N);
|
||||
var w = entry.words[idxInArray];
|
||||
|
||||
if (used.get(w.index)) continue;
|
||||
var lemIdx = Lemma.unpackIndex(w.word);
|
||||
if (used.get(lemIdx)) continue;
|
||||
|
||||
if (!placeWord(grid, s, w, ctx.undo, depth)) continue;
|
||||
|
||||
used.set(w.index);
|
||||
used.set(lemIdx);
|
||||
assigned[k] = w;
|
||||
|
||||
if (backtrack(depth + 1)) return true;
|
||||
|
||||
assigned[k] = null;
|
||||
used.clear(w.index);
|
||||
used.clear(lemIdx);
|
||||
s.undoPlace(grid, ctx.undo[depth]);
|
||||
}
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ public class SwedishGeneratorTest {
|
||||
var l8a = new Lemma("INERENAE");
|
||||
|
||||
var l1 = new Lemma("APPLE");
|
||||
Assertions.assertEquals(Lemma.pack("APPLE".getBytes(StandardCharsets.US_ASCII)), l1.word());
|
||||
Assertions.assertEquals(Lemma.pack("APPLE".getBytes(StandardCharsets.US_ASCII)), Lemma.unpackLetters(l1.word()));
|
||||
assertEquals(5, l1.length());
|
||||
assertEquals((byte) 'A', l1.byteAt(0));
|
||||
assertEquals(1, l1.intAt(0));
|
||||
@@ -120,7 +120,7 @@ public class SwedishGeneratorTest {
|
||||
|
||||
var entry3 = dict.index()[3];
|
||||
assertEquals(1, entry3.words().length);
|
||||
assertEquals(Lemma.pack("AXE".getBytes(StandardCharsets.US_ASCII)), entry3.words()[0].word());
|
||||
assertEquals(Lemma.pack("AXE".getBytes(StandardCharsets.US_ASCII)), Lemma.unpackLetters(entry3.words()[0].word()));
|
||||
|
||||
// Check pos indexing
|
||||
// AXE: A at 0, X at 1, E at 2
|
||||
|
||||
Reference in New Issue
Block a user