introduce bitloops
This commit is contained in:
@@ -58,7 +58,6 @@ public record Export() {
|
|||||||
|
|
||||||
record Gridded(@Delegate Grid grid) {
|
record Gridded(@Delegate Grid grid) {
|
||||||
|
|
||||||
static boolean isLetter(byte b) { return (b & SwedishGenerator.B64) != SwedishGenerator.B0; }
|
|
||||||
public static IntStream walk(byte base, long lo, long hi) {
|
public static IntStream walk(byte base, long lo, long hi) {
|
||||||
if (Slot.increasing(base)) {
|
if (Slot.increasing(base)) {
|
||||||
return IntStream.concat(
|
return IntStream.concat(
|
||||||
@@ -109,7 +108,7 @@ public record Export() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//public boolean isLetterSet(int idx) { return isLetter(g[idx]); }
|
//public boolean isLetterSet(int idx) { return isLetter(g[idx]); }
|
||||||
char NOT_CLUE_NOT_LETTER_TO(byte b, char fallback) { return isLetter(b) ? (char) (64 | b) : fallback; }
|
char NOT_CLUE_NOT_LETTER_TO(byte b, char fallback) { return b == SwedishGenerator.DASH ? fallback : (char) (64 | b); }
|
||||||
String gridToString(Clues clues) {
|
String gridToString(Clues clues) {
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
for (var r = 0; r < R; r++) {
|
for (var r = 0; r < R; r++) {
|
||||||
@@ -166,10 +165,10 @@ public record Export() {
|
|||||||
static final char[] DIRECTION = { Placed.VERTICAL, Placed.HORIZONTAL, Placed.VERTICAL, Placed.HORIZONTAL };
|
static final char[] DIRECTION = { Placed.VERTICAL, Placed.HORIZONTAL, Placed.VERTICAL, Placed.HORIZONTAL };
|
||||||
public static final char HORIZONTAL = 'h';
|
public static final char HORIZONTAL = 'h';
|
||||||
static final char VERTICAL = 'v';
|
static final char VERTICAL = 'v';
|
||||||
public int arrowCol() { return Grid.c(Slot.clueIndex(slotKey)); }
|
public int arrowCol() { return SwedishGenerator.IT[Slot.clueIndex(slotKey)].c(); }
|
||||||
public int arrowRow() { return Grid.r(Slot.clueIndex(slotKey)); }
|
public int arrowRow() { return SwedishGenerator.IT[Slot.clueIndex(slotKey)].r(); }
|
||||||
public int startRow() { return Grid.r(cells[0]); }
|
public int startRow() { return SwedishGenerator.IT[cells[0]].r(); }
|
||||||
public int startCol() { return Grid.c(cells[0]); }
|
public int startCol() { return SwedishGenerator.IT[cells[0]].c(); }
|
||||||
public boolean isReversed() { return !Slot.increasing(slotKey); }
|
public boolean isReversed() { return !Slot.increasing(slotKey); }
|
||||||
public char direction() { return DIRECTION[Slot.dir(slotKey)]; }
|
public char direction() { return DIRECTION[Slot.dir(slotKey)]; }
|
||||||
}
|
}
|
||||||
@@ -214,10 +213,11 @@ public record Export() {
|
|||||||
|
|
||||||
for (var rc : placed) {
|
for (var rc : placed) {
|
||||||
for (var c : rc.cells) {
|
for (var c : rc.cells) {
|
||||||
minR = Math.min(minR, Grid.r(c));
|
val it = SwedishGenerator.IT[c];
|
||||||
minC = Math.min(minC, Grid.c(c));
|
minR = Math.min(minR, it.r());
|
||||||
maxR = Math.max(maxR, Grid.r(c));
|
minC = Math.min(minC, it.c());
|
||||||
maxC = Math.max(maxC, Grid.c(c));
|
maxR = Math.max(maxR, it.r());
|
||||||
|
maxC = Math.max(maxC, it.c());
|
||||||
}
|
}
|
||||||
minR = Math.min(minR, rc.arrowRow());
|
minR = Math.min(minR, rc.arrowRow());
|
||||||
minC = Math.min(minC, rc.arrowCol());
|
minC = Math.min(minC, rc.arrowCol());
|
||||||
|
|||||||
@@ -99,9 +99,11 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
for (int dr1 = -2; dr1 <= 2; dr1++)
|
for (int dr1 = -2; dr1 <= 2; dr1++)
|
||||||
for (int dr2 = -2; dr2 <= 2; dr2++)
|
for (int dr2 = -2; dr2 <= 2; dr2++)
|
||||||
for (int dc1 = -2; dc1 <= 2; dc1++)
|
for (int dc1 = -2; dc1 <= 2; dc1++)
|
||||||
for (int dc2 = -2; dc2 <= 2; dc2++)
|
for (int dc2 = -2; dc2 <= 2; dc2++) {
|
||||||
MUTATE_RI[i][k++] = Grid.offset(clamp(Grid.r(i) + dr1 + dr2, 0, R - 1),
|
val ti = IT[i];
|
||||||
clamp(Grid.c(i) + dc1 + dc2, 0, C - 1));
|
MUTATE_RI[i][k++] = Grid.offset(clamp(ti.r() + dr1 + dr2, 0, R - 1),
|
||||||
|
clamp(ti.c() + dc1 + dc2, 0, C - 1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,14 +282,12 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
|
|
||||||
final byte[] g;
|
final byte[] g;
|
||||||
public long lo, hi;
|
public long lo, hi;
|
||||||
public static int r(int offset) { return offset & 7; }
|
|
||||||
public static int c(int offset) { return offset >>> 3; }
|
|
||||||
static int offset(int r, int c) { return r | (c << 3); }
|
static int offset(int r, int c) { return r | (c << 3); }
|
||||||
/// the pos will never target a clue
|
/// the pos will never target a clue
|
||||||
public byte letter32At(int pos) { return g[pos]; }
|
public byte letter32At(int pos) { return g[pos]; }
|
||||||
void setLetter(int idx, byte ch) { g[idx] = ch; }
|
void setLetter(int idx, byte ch) { g[idx] = ch; }
|
||||||
void clearletter(int idx) { g[idx] = DASH; }
|
|
||||||
|
|
||||||
|
private void clearletter(int idx) { g[idx] = DASH; }
|
||||||
void undoPlace(long maskLo, long maskHi) {
|
void undoPlace(long maskLo, long maskHi) {
|
||||||
for (long b = maskLo; b != 0; b &= b - 1) clearletter(Long.numberOfTrailingZeros(b));
|
for (long b = maskLo; b != 0; b &= b - 1) clearletter(Long.numberOfTrailingZeros(b));
|
||||||
for (long b = maskHi; b != 0; b &= b - 1) clearletter(64 | Long.numberOfTrailingZeros(b));
|
for (long b = maskHi; b != 0; b &= b - 1) clearletter(64 | Long.numberOfTrailingZeros(b));
|
||||||
@@ -305,12 +305,11 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
static long pack(int index, byte[] b) { return pack(b) | ((long) index << 40); }
|
static long pack(int index, byte[] b) { return pack(b) | ((long) index << 40); }
|
||||||
static long pack(byte[] b) {
|
static long pack(byte[] b) {
|
||||||
long w = 0;
|
long w = 0;
|
||||||
for (var i = 0; i < b.length; i++) w |= ((long) b[i] & 63) << (i * 5);
|
for (var i = 0; i < b.length; i++) w |= ((long) b[i] & 31) << (i * 5);
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
static public long from(int index, String word) { return pack(index, word.getBytes(US_ASCII)); }
|
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 byte byteAt(long word, int idx) { return (byte) ((word >>> (idx * 5)) & 0b11111); }
|
||||||
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 String[] clue(long w) { return CsvIndexService.clues(unpackIndex(w)); }
|
||||||
static int simpel(long w) { return CsvIndexService.simpel(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 int length(long word) { return ((63 - Long.numberOfLeadingZeros(word & LETTER_MASK)) / 5) + 1; }
|
||||||
@@ -338,7 +337,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
entry.words().add(lemma);
|
entry.words().add(lemma);
|
||||||
|
|
||||||
for (var i = 0; i < L; i++) {
|
for (var i = 0; i < L; i++) {
|
||||||
var letter = Lemma.intAt(lemma, i) - 1;
|
var letter = Lemma.byteAt(lemma, i) - 1;
|
||||||
if (letter < 0 || letter >= 26) throw new RuntimeException("Illegal letter: " + letter + " in word " + lemma);
|
if (letter < 0 || letter >= 26) throw new RuntimeException("Illegal letter: " + letter + " in word " + lemma);
|
||||||
entry.pos()[i][letter].add(idx);
|
entry.pos()[i][letter].add(idx);
|
||||||
}
|
}
|
||||||
@@ -724,12 +723,14 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static long patternForSlot(Grid grid, Slot s) {
|
static long patternForSlot(Grid grid, Slot s) {
|
||||||
if ((s.lo & ~grid.lo) == 0 && (s.hi & ~grid.hi) == 0) return 0;
|
/*if ((s.lo & ~grid.lo) == 0 && (s.hi & ~grid.hi) == 0) {
|
||||||
|
return 0;
|
||||||
|
}*/
|
||||||
long p = 0;
|
long p = 0;
|
||||||
if (s.increasing()) {
|
if (s.increasing()) {
|
||||||
for (long b = s.lo & ~grid.lo; b != 0; b &= b - 1) {
|
for (long b = s.lo & ~grid.lo; b != 0; b &= b - 1) {
|
||||||
int idx = Long.numberOfTrailingZeros(b);
|
int idx = Long.numberOfTrailingZeros(b);
|
||||||
int val = grid.g[idx] & 31;
|
int val = grid.g[idx];
|
||||||
if (val != 0) {
|
if (val != 0) {
|
||||||
int i = Long.bitCount(s.lo & ((1L << idx) - 1));
|
int i = Long.bitCount(s.lo & ((1L << idx) - 1));
|
||||||
p |= ((long) (i * 26 + val)) << (i << 3);
|
p |= ((long) (i * 26 + val)) << (i << 3);
|
||||||
@@ -738,7 +739,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
int offset = Long.bitCount(s.lo);
|
int offset = Long.bitCount(s.lo);
|
||||||
for (long b = s.hi & ~grid.hi; b != 0; b &= b - 1) {
|
for (long b = s.hi & ~grid.hi; b != 0; b &= b - 1) {
|
||||||
int idx = Long.numberOfTrailingZeros(b);
|
int idx = Long.numberOfTrailingZeros(b);
|
||||||
int val = grid.g[64 | idx] & 31;
|
int val = grid.g[64 | idx];
|
||||||
if (val != 0) {
|
if (val != 0) {
|
||||||
int i = offset + Long.bitCount(s.hi & ((1L << idx) - 1));
|
int i = offset + Long.bitCount(s.hi & ((1L << idx) - 1));
|
||||||
p |= ((long) (i * 26 + val)) << (i << 3);
|
p |= ((long) (i * 26 + val)) << (i << 3);
|
||||||
@@ -748,7 +749,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
int offset = Long.bitCount(s.hi);
|
int offset = Long.bitCount(s.hi);
|
||||||
for (long b = s.hi & ~grid.hi; b != 0; b &= b - 1) {
|
for (long b = s.hi & ~grid.hi; b != 0; b &= b - 1) {
|
||||||
int idx = Long.numberOfTrailingZeros(b);
|
int idx = Long.numberOfTrailingZeros(b);
|
||||||
int val = grid.g[64 | idx] & 31;
|
int val = grid.g[64 | idx];
|
||||||
if (val != 0) {
|
if (val != 0) {
|
||||||
int i = Long.bitCount(s.hi & ~((1L << idx) | ((1L << idx) - 1)));
|
int i = Long.bitCount(s.hi & ~((1L << idx) | ((1L << idx) - 1)));
|
||||||
p |= ((long) (i * 26 + val)) << (i << 3);
|
p |= ((long) (i * 26 + val)) << (i << 3);
|
||||||
@@ -756,7 +757,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
}
|
}
|
||||||
for (long b = s.lo & ~grid.lo; b != 0; b &= b - 1) {
|
for (long b = s.lo & ~grid.lo; b != 0; b &= b - 1) {
|
||||||
int idx = Long.numberOfTrailingZeros(b);
|
int idx = Long.numberOfTrailingZeros(b);
|
||||||
int val = grid.g[idx] & 31;
|
int val = grid.g[idx];
|
||||||
if (val != 0) {
|
if (val != 0) {
|
||||||
int i = offset + Long.bitCount(s.lo & ~((1L << idx) | ((1L << idx) - 1)));
|
int i = offset + Long.bitCount(s.lo & ~((1L << idx) | ((1L << idx) - 1)));
|
||||||
p |= ((long) (i * 26 + val)) << (i << 3);
|
p |= ((long) (i * 26 + val)) << (i << 3);
|
||||||
|
|||||||
@@ -59,10 +59,10 @@ public class MainTest {
|
|||||||
var s = slots[0];
|
var s = slots[0];
|
||||||
assertEquals(8, s.length());
|
assertEquals(8, s.length());
|
||||||
var cells = s.walk().toArray();
|
var cells = s.walk().toArray();
|
||||||
assertEquals(0, Grid.r(cells[0]));
|
assertEquals(0, SwedishGenerator.IT[cells[0]].r());
|
||||||
assertEquals(1, Grid.c(cells[0]));
|
assertEquals(1, SwedishGenerator.IT[cells[0]].c());
|
||||||
assertEquals(0, Grid.r(cells[1]));
|
assertEquals(0, SwedishGenerator.IT[cells[1]].r());
|
||||||
assertEquals(2, Grid.c(cells[1]));
|
assertEquals(2, SwedishGenerator.IT[cells[1]].c());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -82,8 +82,8 @@ public class MainTest {
|
|||||||
clues.forEachSlot((key, lo, hi) -> {
|
clues.forEachSlot((key, lo, hi) -> {
|
||||||
count.incrementAndGet();
|
count.incrementAndGet();
|
||||||
assertEquals(8, Long.bitCount(lo) + Long.bitCount(hi));
|
assertEquals(8, Long.bitCount(lo) + Long.bitCount(hi));
|
||||||
assertEquals(0, Grid.r(Long.numberOfTrailingZeros(lo)));
|
assertEquals(0, SwedishGenerator.IT[Long.numberOfTrailingZeros(lo)].r());
|
||||||
assertEquals(1, Grid.c(Long.numberOfTrailingZeros(lo)));
|
assertEquals(1, SwedishGenerator.IT[Long.numberOfTrailingZeros(lo)].c());
|
||||||
});
|
});
|
||||||
assertEquals(1, count.get());
|
assertEquals(1, count.get());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,11 +53,11 @@ public class SwedishGeneratorTest {
|
|||||||
static final long ABC = Lemma.from(26, "ABC");
|
static final long ABC = Lemma.from(26, "ABC");
|
||||||
static final long ABD = Lemma.from(27, "ABD");
|
static final long ABD = Lemma.from(27, "ABD");
|
||||||
static final long AZ = Lemma.from(28, "AZ");
|
static final long AZ = Lemma.from(28, "AZ");
|
||||||
static final byte LETTER_A = (byte) 'A';
|
static final byte LETTER_A = ((byte) 'A') & 31;
|
||||||
static final byte LETTER_B = (byte) 'B';
|
static final byte LETTER_B = ((byte) 'B') & 31;
|
||||||
static final byte LETTER_C = (byte) 'C';
|
static final byte LETTER_C = ((byte) 'C') & 31;
|
||||||
static final byte LETTER_X = (byte) 'X';
|
static final byte LETTER_X = ((byte) 'X') & 31;
|
||||||
static final byte LETTER_Z = (byte) 'Z';
|
static final byte LETTER_Z = ((byte) 'Z') & 31;
|
||||||
static final byte CLUE_DOWN = 0;
|
static final byte CLUE_DOWN = 0;
|
||||||
static final byte CLUE_RIGHT = 1;
|
static final byte CLUE_RIGHT = 1;
|
||||||
static final byte CLUE_UP = 2;
|
static final byte CLUE_UP = 2;
|
||||||
@@ -151,8 +151,7 @@ public class SwedishGeneratorTest {
|
|||||||
void testLemmaAndDict() {
|
void testLemmaAndDict() {
|
||||||
Assertions.assertEquals(Lemma.pack("APPLE".getBytes(StandardCharsets.US_ASCII)), Lemma.unpackLetters(l1));
|
Assertions.assertEquals(Lemma.pack("APPLE".getBytes(StandardCharsets.US_ASCII)), Lemma.unpackLetters(l1));
|
||||||
assertEquals(5, Lemma.length(l1));
|
assertEquals(5, Lemma.length(l1));
|
||||||
assertEquals((byte) 'A', Lemma.byteAt(l1, 0));
|
assertEquals(LETTER_A, Lemma.byteAt(l1, 0));
|
||||||
assertEquals(1, Lemma.intAt(l1, 0));
|
|
||||||
|
|
||||||
var dict = new Dict(new long[]{ l1, l2, l2a, l4a, l6a, l7a, l8a });
|
var dict = new Dict(new long[]{ l1, l2, l2a, l4a, l6a, l7a, l8a });
|
||||||
|
|
||||||
@@ -192,12 +191,12 @@ public class SwedishGeneratorTest {
|
|||||||
assertEquals(CLUE_DOWN, Slot.dir(s.key()));
|
assertEquals(CLUE_DOWN, Slot.dir(s.key()));
|
||||||
assertFalse(s.horiz());
|
assertFalse(s.horiz());
|
||||||
var cells = s.walk().toArray();
|
var cells = s.walk().toArray();
|
||||||
assertEquals(2, Grid.r(cells[0]));
|
assertEquals(2, SwedishGenerator.IT[cells[0]].r());
|
||||||
assertEquals(3, Grid.r(cells[1]));
|
assertEquals(3, SwedishGenerator.IT[cells[1]].r());
|
||||||
assertEquals(4, Grid.r(cells[2]));
|
assertEquals(4, SwedishGenerator.IT[cells[2]].r());
|
||||||
assertEquals(5, Grid.c(cells[0]));
|
assertEquals(5, SwedishGenerator.IT[cells[0]].c());
|
||||||
assertEquals(5, Grid.c(cells[1]));
|
assertEquals(5, SwedishGenerator.IT[cells[1]].c());
|
||||||
assertEquals(5, Grid.c(cells[2]));
|
assertEquals(5, SwedishGenerator.IT[cells[2]].c());
|
||||||
|
|
||||||
assertTrue(Slot.horiz(CLUE_RIGHT)); // right
|
assertTrue(Slot.horiz(CLUE_RIGHT)); // right
|
||||||
assertFalse(Slot.horiz(CLUE_DOWN)); // down
|
assertFalse(Slot.horiz(CLUE_DOWN)); // down
|
||||||
|
|||||||
Reference in New Issue
Block a user