introduce bitloops
This commit is contained in:
@@ -108,7 +108,10 @@ 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 b == SwedishGenerator.DASH ? fallback : (char) (64 | b); }
|
char NOT_CLUE_NOT_LETTER_TO(byte b, char fallback) {
|
||||||
|
if (b == SwedishGenerator.DASH) throw new RuntimeException();
|
||||||
|
return (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++) {
|
||||||
@@ -117,8 +120,10 @@ public record Export() {
|
|||||||
var offset = Grid.offset(r, c);
|
var offset = Grid.offset(r, c);
|
||||||
if (clues.isClue(offset))
|
if (clues.isClue(offset))
|
||||||
sb.append((char) (48 | clues.digitAt(offset)));
|
sb.append((char) (48 | clues.digitAt(offset)));
|
||||||
else
|
else if (grid.lisLetterAtLo(offset))
|
||||||
sb.append((char) (64 | grid.letter32At(offset)));
|
sb.append((char) (64 | grid.letter32At(offset)));
|
||||||
|
else
|
||||||
|
sb.append(' ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
@@ -140,8 +145,10 @@ public record Export() {
|
|||||||
var offset = Grid.offset(r, c);
|
var offset = Grid.offset(r, c);
|
||||||
if (clues.isClue(offset)) {
|
if (clues.isClue(offset)) {
|
||||||
sb.append(clueChar.replace(new Cell(grid, clues, offset, clues.digitAt(offset))));
|
sb.append(clueChar.replace(new Cell(grid, clues, offset, clues.digitAt(offset))));
|
||||||
} else {
|
} else if (grid.lisLetterAt(offset)) {
|
||||||
sb.append(NOT_CLUE_NOT_LETTER_TO(grid.letter32At(offset), emptyFallback));
|
sb.append(NOT_CLUE_NOT_LETTER_TO(grid.letter32At(offset), emptyFallback));
|
||||||
|
} else {
|
||||||
|
sb.append(emptyFallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out[r] = sb.toString();
|
out[r] = sb.toString();
|
||||||
@@ -229,7 +236,8 @@ public record Export() {
|
|||||||
var letterAt = new HashMap<Integer, Character>();
|
var letterAt = new HashMap<Integer, Character>();
|
||||||
for (var p : placed) {
|
for (var p : placed) {
|
||||||
for (var c : p.cells) {
|
for (var c : p.cells) {
|
||||||
if (inBounds(c) && mask.notClue(c)) {
|
if (!inBounds(c)) throw new RuntimeException();
|
||||||
|
if (mask.notClue(c) && g.lisLetterAt(c)) {
|
||||||
letterAt.put(c, (char) (64 | g.letter32At(c)));
|
letterAt.put(c, (char) (64 | g.letter32At(c)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -285,6 +285,14 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
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]; }
|
||||||
|
public boolean lisLetterAt(int pos) {
|
||||||
|
if ((pos & 64) == 0)
|
||||||
|
return lisLetterAtLo(pos);
|
||||||
|
return lisLetterAtHi(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean lisLetterAtLo(int pos) { return (lo & (1L << pos)) != 0; }
|
||||||
|
public boolean lisLetterAtHi(int pos) { return (hi & (1L << (pos & 63))) != 0; }
|
||||||
void setLetterLo(int idx, byte ch) {
|
void setLetterLo(int idx, byte ch) {
|
||||||
lo |= (1L << idx);
|
lo |= (1L << idx);
|
||||||
|
|
||||||
@@ -313,8 +321,11 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
|||||||
hi &= ~(1L << (idx & 63));
|
hi &= ~(1L << (idx & 63));
|
||||||
}
|
}
|
||||||
void undoPlace(long maskLo, long maskHi) {
|
void undoPlace(long maskLo, long maskHi) {
|
||||||
for (long b = maskLo; b != 0; b &= b - 1) clearletterLo(Long.numberOfTrailingZeros(b));
|
lo &= ~maskLo;
|
||||||
for (long b = maskHi; b != 0; b &= b - 1) clearletterHi(64 | Long.numberOfTrailingZeros(b));
|
hi &= ~maskHi;
|
||||||
|
|
||||||
|
/*for (long b = maskLo; b != 0; b &= b - 1) clearletterLo(Long.numberOfTrailingZeros(b));
|
||||||
|
for (long b = maskHi; b != 0; b &= b - 1) clearletterHi(64 | Long.numberOfTrailingZeros(b));*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
|||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static puzzle.SwedishGenerator.*;
|
import static puzzle.SwedishGenerator.*;
|
||||||
import static puzzle.SwedishGenerator.DASH;
|
|
||||||
|
|
||||||
public class MainTest {
|
public class MainTest {
|
||||||
|
|
||||||
@@ -107,13 +106,13 @@ public class MainTest {
|
|||||||
Assertions.assertEquals(LETTER_A, grid.letter32At(OFF_0_0));
|
Assertions.assertEquals(LETTER_A, grid.letter32At(OFF_0_0));
|
||||||
Assertions.assertEquals(CLUE_UP, clues.digitAt(OFF_1_2));
|
Assertions.assertEquals(CLUE_UP, clues.digitAt(OFF_1_2));
|
||||||
Assertions.assertEquals(LETTER_Z, grid.letter32At(OFF_2_3));
|
Assertions.assertEquals(LETTER_Z, grid.letter32At(OFF_2_3));
|
||||||
Assertions.assertEquals(DASH, grid.letter32At(OFF_1_1));
|
Assertions.assertFalse(grid.lisLetterAtLo(OFF_1_1));
|
||||||
|
|
||||||
// Verify letter mask
|
// Verify letter mask
|
||||||
Assertions.assertTrue((grid.lo & (1L << OFF_0_0)) != 0);
|
Assertions.assertTrue((grid.lo & (1L << OFF_0_0)) != 0);
|
||||||
Assertions.assertTrue((grid.lo & (1L << OFF_2_3)) != 0);
|
Assertions.assertTrue((grid.lo & (1L << OFF_2_3)) != 0);
|
||||||
Assertions.assertTrue((grid.lo & (1L << OFF_1_2)) != 0); // Clue also in lo
|
Assertions.assertTrue((grid.lo & (1L << OFF_1_2)) != 0); // Clue also in lo
|
||||||
Assertions.assertTrue((grid.lo & (1L << OFF_1_1)) == 0); // Empty letter cell
|
assertEquals(0, (grid.lo & (1L << OFF_1_1))); // Empty letter cell
|
||||||
|
|
||||||
// Test isLetterAt
|
// Test isLetterAt
|
||||||
Assertions.assertTrue(clues.notClue(OFF_0_0));
|
Assertions.assertTrue(clues.notClue(OFF_0_0));
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ public class SwedishGeneratorTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testPatternForSlotAllDashes() {
|
void testPatternForSlotAllDashes() {
|
||||||
var grid = createEmpty();
|
var grid = createEmpty();
|
||||||
var slot = Slot.from(1 << Slot.BIT_FOR_DIR | (CLUE_RIGHT), 7L, 0L);
|
var slot = Slot.from(1 << Slot.BIT_FOR_DIR | (CLUE_RIGHT), 7L, 0L);
|
||||||
var pattern = patternForSlot(grid, slot);
|
var pattern = patternForSlot(grid, slot);
|
||||||
|
|
||||||
@@ -360,8 +360,8 @@ public class SwedishGeneratorTest {
|
|||||||
grid.setLetter(OFF_0_2, LETTER_X); // Conflict at the end
|
grid.setLetter(OFF_0_2, LETTER_X); // Conflict at the end
|
||||||
assertFalse(placeWord(grid, s, w1, undoBuffer, 3));
|
assertFalse(placeWord(grid, s, w1, undoBuffer, 3));
|
||||||
// Verify grid is still empty (except for 'X')
|
// Verify grid is still empty (except for 'X')
|
||||||
assertEquals(DASH, grid.letter32At(OFF_0_0));
|
assertFalse(grid.lisLetterAtLo(OFF_0_0));
|
||||||
assertEquals(DASH, grid.letter32At(OFF_0_1));
|
assertFalse(grid.lisLetterAtLo(OFF_0_1));
|
||||||
assertEquals(LETTER_X, grid.letter32At(OFF_0_2));
|
assertEquals(LETTER_X, grid.letter32At(OFF_0_2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,8 +382,8 @@ public class SwedishGeneratorTest {
|
|||||||
assertEquals(lo, undoBuffer[0]);
|
assertEquals(lo, undoBuffer[0]);
|
||||||
|
|
||||||
grid.undoPlace(undoBuffer[0], undoBuffer[1]);
|
grid.undoPlace(undoBuffer[0], undoBuffer[1]);
|
||||||
assertEquals(DASH, grid.letter32At(OFF_0_1));
|
assertFalse(grid.lisLetterAtLo(OFF_0_1));
|
||||||
assertEquals(DASH, grid.letter32At(OFF_0_2));
|
assertFalse(grid.lisLetterAtLo(OFF_0_2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user