Gather data
This commit is contained in:
@@ -51,10 +51,10 @@ public record ExportFormat() {
|
|||||||
var g = puz.filled().grid();
|
var g = puz.filled().grid();
|
||||||
var placed = new ArrayList<Placed>();
|
var placed = new ArrayList<Placed>();
|
||||||
var clueMap = puz.filled().clueMap();
|
var clueMap = puz.filled().clueMap();
|
||||||
puz.swe().forEachSlot(g, (int key, long rs, long cs, int len) -> {
|
puz.swe().forEachSlot(g, (int key, long packedPos, int len) -> {
|
||||||
var word = clueMap.get(key);
|
var word = clueMap.get(key);
|
||||||
if (word != null) {
|
if (word != null) {
|
||||||
var p = extractPlacedFromSlot(Slot.from(key, rs, cs, len), word);
|
var p = extractPlacedFromSlot(Slot.from(key, packedPos, len), word);
|
||||||
if (p != null) placed.add(p);
|
if (p != null) placed.add(p);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -327,25 +327,21 @@ public record SwedishGenerator(int[] buff) {
|
|||||||
|
|
||||||
return new CandidateInfo(cur, curLen);
|
return new CandidateInfo(cur, curLen);
|
||||||
}
|
}
|
||||||
static record Slot(int key, long rs, long cs, int len) {
|
static record Slot(int key, long packedPos) {
|
||||||
//perhaps just put len into key and use hash-code and derrive index from key. or just put both ints into tail of the two longs.
|
|
||||||
static Slot from(int key, long rs, long cs, int len) {
|
static Slot from(int key, long packedPos, int len) {
|
||||||
/* if ((Long.highestOneBit(rs | cs) >> 2) != (len - 1)) throw new RuntimeException();
|
return new Slot(key, packedPos | ((long) len << 56));
|
||||||
if ((Long.highestOneBit(cs) >> 2) != (len - 1)) throw new RuntimeException();
|
|
||||||
if ((Long.highestOneBit(rs) >> 2) != (len - 1)) throw new RuntimeException();*/
|
|
||||||
return new Slot(key, rs, cs, len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//public int len() { return (int) (Long.highestOneBit(rs | cs) >> 2); }
|
public int len() { return (int) (packedPos >>> 56); }
|
||||||
public int clueR() { return (key >> 8) & 15; }
|
public int clueR() { return (key >> 8) & 15; }
|
||||||
public int clueC() { return (key >> 4) & 15; }
|
public int clueC() { return (key >> 4) & 15; }
|
||||||
public int dir() { return key & 15; }
|
public int dir() { return key & 15; }
|
||||||
public boolean horiz() { return horiz(key); }
|
public boolean horiz() { return horiz(key); }
|
||||||
public int r(int i) { return r(rs, i); }
|
public int r(int i) { return Grid.r(offset(packedPos, i)); }
|
||||||
public int c(int i) { return c(cs, i); }
|
public int c(int i) { return Grid.c(offset(packedPos, i)); }
|
||||||
public static boolean horiz(int key) { return ((key & 15) & 1) == 0; }
|
public static boolean horiz(int key) { return ((key & 15) & 1) == 0; }
|
||||||
public static int r(long rs, int i) { return (int) ((rs >> (i << 2)) & 15); }
|
public static int offset(long packedPos, int i) { return (int) ((packedPos >> (i * 7)) & 127); }
|
||||||
public static int c(long cs, int i) { return (int) ((cs >> (i << 2)) & 15); }
|
|
||||||
}
|
}
|
||||||
static void undoPlace(Grid grid, long[] undoBuffer, int offset, int n) {
|
static void undoPlace(Grid grid, long[] undoBuffer, int offset, int n) {
|
||||||
for (var i = 0; i < n; i++) {
|
for (var i = 0; i < n; i++) {
|
||||||
@@ -356,7 +352,7 @@ public record SwedishGenerator(int[] buff) {
|
|||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
interface SlotVisitor {
|
interface SlotVisitor {
|
||||||
|
|
||||||
void visit(int key, long rs, long cs, int len);
|
void visit(int key, long packedPos, int len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void forEachSlot(Grid grid, SlotVisitor visitor) {
|
void forEachSlot(Grid grid, SlotVisitor visitor) {
|
||||||
@@ -368,19 +364,17 @@ public record SwedishGenerator(int[] buff) {
|
|||||||
int rr = r + nbrs16.r, cc = c + nbrs16.c;
|
int rr = r + nbrs16.r, cc = c + nbrs16.c;
|
||||||
|
|
||||||
if (rr < 0 || rr >= R || cc < 0 || cc >= C || grid.isDigitAt(rr, cc)) continue;
|
if (rr < 0 || rr >= R || cc < 0 || cc >= C || grid.isDigitAt(rr, cc)) continue;
|
||||||
long packedRs = 0;
|
long packedPos = 0;
|
||||||
long packedCs = 0;
|
|
||||||
var n = 0;
|
var n = 0;
|
||||||
|
|
||||||
while (rr >= 0 && rr < R && cc >= 0 && cc < C && grid.isLettercell(rr, cc) && n < MAX_WORD_LENGTH) {
|
while (rr >= 0 && rr < R && cc >= 0 && cc < C && grid.isLettercell(rr, cc) && n < MAX_WORD_LENGTH) {
|
||||||
packedRs |= (long) rr << (n << 2);
|
packedPos |= (long) Grid.offset(rr, cc) << (n * 7);
|
||||||
packedCs |= (long) cc << (n << 2);
|
|
||||||
n++;
|
n++;
|
||||||
rr += nbrs16.dr;
|
rr += nbrs16.dr;
|
||||||
cc += nbrs16.dc;
|
cc += nbrs16.dc;
|
||||||
}
|
}
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
visitor.visit((r << 8) | (c << 4) | d, packedRs, packedCs, n);
|
visitor.visit((r << 8) | (c << 4) | d, packedPos, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -388,7 +382,7 @@ public record SwedishGenerator(int[] buff) {
|
|||||||
|
|
||||||
ArrayList<Slot> extractSlots(Grid grid) {
|
ArrayList<Slot> extractSlots(Grid grid) {
|
||||||
var slots = new ArrayList<Slot>(64);
|
var slots = new ArrayList<Slot>(64);
|
||||||
forEachSlot(grid, (key, rs, cs, len) -> slots.add(Slot.from(key, rs, cs, len)));
|
forEachSlot(grid, (key, packedPos, len) -> slots.add(Slot.from(key, packedPos, len)));
|
||||||
return slots;
|
return slots;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,14 +422,12 @@ public record SwedishGenerator(int[] buff) {
|
|||||||
int rr = r + nbrs16.r, cc = c + nbrs16.c;
|
int rr = r + nbrs16.r, cc = c + nbrs16.c;
|
||||||
if (rr < 0 || rr >= R || cc < 0 || cc >= C || grid.isDigitAt(rr, cc)) continue;
|
if (rr < 0 || rr >= R || cc < 0 || cc >= C || grid.isDigitAt(rr, cc)) continue;
|
||||||
|
|
||||||
long packedRs = 0;
|
long packedPos = 0;
|
||||||
long packedCs = 0;
|
|
||||||
var n = 0;
|
var n = 0;
|
||||||
|
|
||||||
while (rr >= 0 && rr < R && cc >= 0 && cc < C && n < MAX_WORD_LENGTH) {
|
while (rr >= 0 && rr < R && cc >= 0 && cc < C && n < MAX_WORD_LENGTH) {
|
||||||
if (grid.isDigitAt(rr, cc)) break;
|
if (grid.isDigitAt(rr, cc)) break;
|
||||||
packedRs |= (long) rr << (n << 2);
|
packedPos |= (long) Grid.offset(rr, cc) << (n * 7);
|
||||||
packedCs |= (long) cc << (n << 2);
|
|
||||||
n++;
|
n++;
|
||||||
rr += nbrs16.dr;
|
rr += nbrs16.dr;
|
||||||
cc += nbrs16.dc;
|
cc += nbrs16.dc;
|
||||||
@@ -450,7 +442,7 @@ public record SwedishGenerator(int[] buff) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var horiz = Slot.horiz(d) ? covH : covV;
|
var horiz = Slot.horiz(d) ? covH : covV;
|
||||||
for (var i = 0; i < n; i++) horiz[Grid.offset(Slot.r(packedRs, i), Slot.c(packedCs, i))] += 1;
|
for (var i = 0; i < n; i++) horiz[Slot.offset(packedPos, i)] += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -730,12 +722,11 @@ public record SwedishGenerator(int[] buff) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int patternForSlot(Grid grid, Slot s, char[] pat) {
|
static void patternForSlot(Grid grid, Slot s, char[] pat) {
|
||||||
for (var i = 0; i < s.len(); i++) {
|
for (var i = 0; i < s.len(); i++) {
|
||||||
var ch = grid.getCharAt(s.r(i), s.c(i));
|
var ch = grid.getCharAt(s.r(i), s.c(i));
|
||||||
pat[i] = isLetter(ch) ? ch : C_DASH;
|
pat[i] = isLetter(ch) ? ch : C_DASH;
|
||||||
}
|
}
|
||||||
return s.len();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int slotScore(int[] cellCount, Slot s, Grid grid) {
|
static int slotScore(int[] cellCount, Slot s, Grid grid) {
|
||||||
@@ -821,8 +812,8 @@ public record SwedishGenerator(int[] buff) {
|
|||||||
if (entry == null) {
|
if (entry == null) {
|
||||||
return new Pick(null, null, false);
|
return new Pick(null, null, false);
|
||||||
}
|
}
|
||||||
|
var patLen = s.len();
|
||||||
var patLen = patternForSlot(grid, s, ctx.pattern);
|
patternForSlot(grid, s, ctx.pattern);
|
||||||
var info = candidateInfoForPattern(ctx, entry, patLen);
|
var info = candidateInfoForPattern(ctx, entry, patLen);
|
||||||
|
|
||||||
if (info.count == 0) {
|
if (info.count == 0) {
|
||||||
@@ -865,9 +856,10 @@ public record SwedishGenerator(int[] buff) {
|
|||||||
|
|
||||||
var s = pick.slot;
|
var s = pick.slot;
|
||||||
var k = s.key();
|
var k = s.key();
|
||||||
var entry = dictIndex[s.len()];
|
int patLen = s.len();
|
||||||
var pat = new char[s.len()];
|
var entry = dictIndex[patLen];
|
||||||
int patLen = patternForSlot(grid, s, pat);
|
var pat = new char[patLen];
|
||||||
|
patternForSlot(grid, s, pat);
|
||||||
int undoOffset = depth * SIZE;
|
int undoOffset = depth * SIZE;
|
||||||
if (pick.info.indices != null && pick.info.indices.length > 0) {
|
if (pick.info.indices != null && pick.info.indices.length > 0) {
|
||||||
var idxs = pick.info.indices;
|
var idxs = pick.info.indices;
|
||||||
|
|||||||
@@ -47,11 +47,11 @@ public class MainTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testStaticSlotMethods() {
|
void testStaticSlotMethods() {
|
||||||
// Test static r and c extraction
|
// Test static offset extraction
|
||||||
// packedRs: 1 at index 0, 2 at index 1
|
// packedPos: offset(1, 1) at index 0, offset(2, 2) at index 1
|
||||||
var packedRs = (1L << 0) | (2L << 4);
|
var packedPos = ((long) SwedishGenerator.Grid.offset(1, 1)) | (((long) SwedishGenerator.Grid.offset(2, 2)) << 7);
|
||||||
assertEquals(1, Slot.r(packedRs, 0));
|
assertEquals(SwedishGenerator.Grid.offset(1, 1), Slot.offset(packedPos, 0));
|
||||||
assertEquals(2, Slot.r(packedRs, 1));
|
assertEquals(SwedishGenerator.Grid.offset(2, 2), Slot.offset(packedPos, 1));
|
||||||
|
|
||||||
// Test static horiz
|
// Test static horiz
|
||||||
// dir 2 (right) is horizontal
|
// dir 2 (right) is horizontal
|
||||||
@@ -67,21 +67,21 @@ public class MainTest {
|
|||||||
grid.setCharAt(0, 0, '2'); // right
|
grid.setCharAt(0, 0, '2'); // right
|
||||||
|
|
||||||
var count = new AtomicInteger(0);
|
var count = new AtomicInteger(0);
|
||||||
generator.forEachSlot(grid, (key, rs, cs, len) -> {
|
generator.forEachSlot(grid, (key, packedPos, len) -> {
|
||||||
count.incrementAndGet();
|
count.incrementAndGet();
|
||||||
assertEquals(8, len);
|
assertEquals(8, len);
|
||||||
assertEquals(0, Slot.r(rs, 0));
|
assertEquals(0, SwedishGenerator.Grid.r(Slot.offset(packedPos, 0)));
|
||||||
assertEquals(1, Slot.c(cs, 0));
|
assertEquals(1, SwedishGenerator.Grid.c(Slot.offset(packedPos, 0)));
|
||||||
});
|
});
|
||||||
assertEquals(1, count.get());
|
assertEquals(1, count.get());
|
||||||
}
|
}
|
||||||
@Test
|
@Test
|
||||||
public void testHoriz() {
|
public void testHoriz() {
|
||||||
assertTrue(new Slot(2, 0L, 0L, 1).horiz());
|
assertTrue(Slot.from(2, 0L, 1).horiz());
|
||||||
assertTrue(new Slot(4, 0L, 0L, 1).horiz());
|
assertTrue(Slot.from(4, 0L, 1).horiz());
|
||||||
assertFalse(new Slot(1, 0L, 3L, 1).horiz());
|
assertFalse(Slot.from(1, 0L, 1).horiz());
|
||||||
assertFalse(new Slot(3, 0L, 3L, 1).horiz());
|
assertFalse(Slot.from(3, 0L, 1).horiz());
|
||||||
assertFalse(new Slot(5, 0L, 3L, 1).horiz());
|
assertFalse(Slot.from(5, 0L, 1).horiz());
|
||||||
}
|
}
|
||||||
@Test
|
@Test
|
||||||
public void testGridBasics() {
|
public void testGridBasics() {
|
||||||
|
|||||||
@@ -12,6 +12,45 @@ import static org.junit.jupiter.api.Assertions.*;
|
|||||||
|
|
||||||
public class SwedishGeneratorTest {
|
public class SwedishGeneratorTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testPatternForSlotAllLetters() {
|
||||||
|
var grid = new Grid(new byte[]{ 65, 66, 67 }); // A B C
|
||||||
|
var slot = Slot.from(0 << 8 | 1 << 4 | 2, ((long) 0) | ((long) 1 << 7) | ((long) 2 << 14), 3);
|
||||||
|
var pattern = new char[3];
|
||||||
|
SwedishGenerator.patternForSlot(grid, slot, pattern);
|
||||||
|
|
||||||
|
assertArrayEquals(new char[]{ 'A', 'B', 'C' }, pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testPatternForSlotMixed() {
|
||||||
|
var grid = new Grid(new byte[]{ 65, (byte) ('0' + 1), 67 }); // A - C
|
||||||
|
var slot = Slot.from(0 << 8 | 1 << 4 | 2, ((long) 0) | ((long) 1 << 7) | ((long) 2 << 14), 3);
|
||||||
|
var pattern = new char[3];
|
||||||
|
SwedishGenerator.patternForSlot(grid, slot, pattern);
|
||||||
|
|
||||||
|
assertArrayEquals(new char[]{ 'A', SwedishGenerator.C_DASH, 'C' }, pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testPatternForSlotAllDashes() {
|
||||||
|
var grid = new Grid(new byte[]{ (byte) ('0' + 1), (byte) ('0' + 1), (byte) ('0' + 1) }); // - - -
|
||||||
|
var slot = Slot.from(0 << 8 | 1 << 4 | 2, ((long) 0) | ((long) 1 << 7) | ((long) 2 << 14), 3);
|
||||||
|
var pattern = new char[3];
|
||||||
|
SwedishGenerator.patternForSlot(grid, slot, pattern);
|
||||||
|
|
||||||
|
assertArrayEquals(new char[]{ SwedishGenerator.C_DASH, SwedishGenerator.C_DASH, SwedishGenerator.C_DASH }, pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testPatternForSlotSingleLetter() {
|
||||||
|
var grid = new Grid(new byte[]{ 65, (byte) ('0' + 1), (byte) ('0' + 1) }); // A - -
|
||||||
|
var slot = Slot.from(0 << 8 | 1 << 4 | 2, ((long) 0) | ((long) 1 << 7) | ((long) 2 << 14), 3);
|
||||||
|
var pattern = new char[3];
|
||||||
|
SwedishGenerator.patternForSlot(grid, slot, pattern);
|
||||||
|
|
||||||
|
assertArrayEquals(new char[]{ 'A', SwedishGenerator.C_DASH, SwedishGenerator.C_DASH }, pattern);
|
||||||
|
}
|
||||||
@Test
|
@Test
|
||||||
void testRng() {
|
void testRng() {
|
||||||
var rng = new Rng(123);
|
var rng = new Rng(123);
|
||||||
@@ -93,18 +132,15 @@ public class SwedishGeneratorTest {
|
|||||||
void testSlot() {
|
void testSlot() {
|
||||||
// key = (r << 8) | (c << 4) | d
|
// key = (r << 8) | (c << 4) | d
|
||||||
var key = (2 << 8) | (3 << 4) | 5;
|
var key = (2 << 8) | (3 << 4) | 5;
|
||||||
long rs = 0;
|
long packedPos = 0;
|
||||||
long cs = 0;
|
// pos 0: (2, 5)
|
||||||
// rs: [2, 3, 4] -> packed 4-bit: 2 | (3<<4) | (4<<8)
|
packedPos |= (long) Grid.offset(2, 5) << 0;
|
||||||
rs |= 2L;
|
// pos 1: (3, 5)
|
||||||
rs |= 3L << 4;
|
packedPos |= (long) Grid.offset(3, 5) << 7;
|
||||||
rs |= 4L << 8;
|
// pos 2: (4, 5)
|
||||||
// cs: [5, 5, 5]
|
packedPos |= (long) Grid.offset(4, 5) << 14;
|
||||||
cs |= 5L;
|
|
||||||
cs |= 5L << 4;
|
|
||||||
cs |= 5L << 8;
|
|
||||||
|
|
||||||
var s = new Slot(key, rs, cs, 3);
|
var s = Slot.from(key, packedPos, 3);
|
||||||
assertEquals(2, s.clueR());
|
assertEquals(2, s.clueR());
|
||||||
assertEquals(3, s.clueC());
|
assertEquals(3, s.clueC());
|
||||||
assertEquals(5, s.dir());
|
assertEquals(5, s.dir());
|
||||||
@@ -223,7 +259,8 @@ public class SwedishGeneratorTest {
|
|||||||
void testBacktrackingHelpers() {
|
void testBacktrackingHelpers() {
|
||||||
var grid = SwedishGenerator.makeEmptyGrid();
|
var grid = SwedishGenerator.makeEmptyGrid();
|
||||||
// Slot at 0,1 length 2
|
// Slot at 0,1 length 2
|
||||||
var s = new Slot((0 << 8) | (1 << 4) | 2, 0L, (1L | (2L << 4)), 2);
|
var packedPos = ((long) Grid.offset(0, 1)) | (((long) Grid.offset(0, 2)) << 7);
|
||||||
|
var s = Slot.from((0 << 8) | (1 << 4) | 2, packedPos, 2);
|
||||||
var w = new Lemma("AZ", 1, "A to Z");
|
var w = new Lemma("AZ", 1, "A to Z");
|
||||||
var undoBuffer = new long[10];
|
var undoBuffer = new long[10];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user