Gather data
This commit is contained in:
@@ -119,7 +119,7 @@ public final class ExportFormat {
|
|||||||
private static Placed extractPlacedFromSlot(Dict dict, Slot s, Lemma lemma) {
|
private static Placed extractPlacedFromSlot(Dict dict, Slot s, Lemma lemma) {
|
||||||
int r = s.clueR();
|
int r = s.clueR();
|
||||||
int c = s.clueC();
|
int c = s.clueC();
|
||||||
char d = s.dir();
|
int d = s.dir();
|
||||||
|
|
||||||
List<int[]> cells = new ArrayList<>();
|
List<int[]> cells = new ArrayList<>();
|
||||||
for (int i = 0; i < s.len(); i++) {
|
for (int i = 0; i < s.len(); i++) {
|
||||||
@@ -131,26 +131,26 @@ public final class ExportFormat {
|
|||||||
String direction;
|
String direction;
|
||||||
boolean isReversed = false;
|
boolean isReversed = false;
|
||||||
|
|
||||||
if (d == '2') { // right -> horizontal
|
if (d ==2) { // right -> horizontal
|
||||||
direction = HORIZONTAL;
|
direction = HORIZONTAL;
|
||||||
startRow = cells.get(0)[0];
|
startRow = cells.get(0)[0];
|
||||||
startCol = cells.get(0)[1];
|
startCol = cells.get(0)[1];
|
||||||
arrowRow = r;
|
arrowRow = r;
|
||||||
arrowCol = c;
|
arrowCol = c;
|
||||||
} else if (d == '3' || d == '5') { // down or down-bent -> vertical
|
} else if (d == 3 || d == 5) { // down or down-bent -> vertical
|
||||||
direction = VERTICAL;
|
direction = VERTICAL;
|
||||||
startRow = cells.get(0)[0];
|
startRow = cells.get(0)[0];
|
||||||
startCol = cells.get(0)[1];
|
startCol = cells.get(0)[1];
|
||||||
arrowRow = r;
|
arrowRow = r;
|
||||||
arrowCol = c;
|
arrowCol = c;
|
||||||
} else if (d == '4') { // left -> horizontal (REVERSED)
|
} else if (d == 4) { // left -> horizontal (REVERSED)
|
||||||
direction = HORIZONTAL;
|
direction = HORIZONTAL;
|
||||||
isReversed = true;
|
isReversed = true;
|
||||||
startRow = cells.get(0)[0];
|
startRow = cells.get(0)[0];
|
||||||
startCol = cells.get(0)[1];
|
startCol = cells.get(0)[1];
|
||||||
arrowRow = r;
|
arrowRow = r;
|
||||||
arrowCol = c;
|
arrowCol = c;
|
||||||
} else if (d == '1') { // up -> vertical (REVERSED)
|
} else if (d == 1) { // up -> vertical (REVERSED)
|
||||||
direction = VERTICAL;
|
direction = VERTICAL;
|
||||||
isReversed = true;
|
isReversed = true;
|
||||||
startRow = cells.get(0)[0];
|
startRow = cells.get(0)[0];
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
package puzzle;
|
package puzzle;
|
||||||
|
|
||||||
|
import javax.xml.crypto.Data;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SwedishGenerator.java
|
* SwedishGenerator.java
|
||||||
@@ -15,22 +17,14 @@ import java.util.function.Predicate;
|
|||||||
* java SwedishGenerator [--seed N] [--pop N] [--gens N] [--tries N] [--words word-list.txt]
|
* java SwedishGenerator [--seed N] [--pop N] [--gens N] [--tries N] [--words word-list.txt]
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("ALL")
|
@SuppressWarnings("ALL")
|
||||||
public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN) {
|
public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff) {
|
||||||
|
|
||||||
public static final char C_DASH = '\0';
|
public static final char C_DASH = '\0';
|
||||||
static final byte _1 = 49, _9 = 57, A = 65, Z = 90, DASH = (byte) C_DASH;
|
static final byte _1 = 49, _9 = 57, A = 65, Z = 90, DASH = (byte) C_DASH;
|
||||||
|
|
||||||
record nbrs_8(int x, int y) { }
|
record nbrs_8(int x, int y) { }
|
||||||
|
|
||||||
class Data {
|
public SwedishGenerator(int W, int H) { this(W, H, W * H, Math.min(W, H), new int[10000]); }
|
||||||
|
|
||||||
static byte[] EXAMPLE = new byte[0];
|
|
||||||
}
|
|
||||||
public SwedishGenerator {
|
|
||||||
Data.EXAMPLE = new byte[SIZE];
|
|
||||||
Arrays.fill(Data.EXAMPLE, DASH);
|
|
||||||
}
|
|
||||||
public SwedishGenerator(int W, int H) { this(W, H, W * H, Math.min(W, H)); }
|
|
||||||
public SwedishGenerator() { this(9, 8); }
|
public SwedishGenerator() { this(9, 8); }
|
||||||
|
|
||||||
static final int CLUE_SIZE = 4,
|
static final int CLUE_SIZE = 4,
|
||||||
@@ -79,7 +73,6 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN) {
|
|||||||
static final char FIRST_ABC = 'A';
|
static final char FIRST_ABC = 'A';
|
||||||
static final char LAST_ABC = 'Z';
|
static final char LAST_ABC = 'Z';
|
||||||
static final char FIRST_ARROW = '1', LAST_ARROW = '6', HOR_ARROW_1 = '2', HOR_ARROW_2 = '4';
|
static final char FIRST_ARROW = '1', LAST_ARROW = '6', HOR_ARROW_1 = '2', HOR_ARROW_2 = '4';
|
||||||
static boolean isDigit(char ch) { return ch >= FIRST_ARROW && ch <= LAST_ARROW; }
|
|
||||||
static boolean isLetter(char ch) { return ch >= FIRST_ABC && ch <= LAST_ABC; }
|
static boolean isLetter(char ch) { return ch >= FIRST_ABC && ch <= LAST_ABC; }
|
||||||
|
|
||||||
static final class Rng {
|
static final class Rng {
|
||||||
@@ -112,15 +105,16 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN) {
|
|||||||
record Grid(byte[] g, int H, int W) {
|
record Grid(byte[] g, int H, int W) {
|
||||||
|
|
||||||
Grid deepCopyGrid() { return new Grid(g.clone(), H, W); }
|
Grid deepCopyGrid() { return new Grid(g.clone(), H, W); }
|
||||||
private int getOffset(int r, int c) { return r * W + c; }
|
private int offset(int r, int c) { return r * W + c; }
|
||||||
boolean isLettercell(int r, int c) { return !isDigitAt(r, c); }
|
boolean isLettercell(int r, int c) { return !isDigitAt(r, c); }
|
||||||
char getCharAt(int r, int c) { return (char) (g[getOffset(r, c)] & 0xFF); }
|
char getCharAt(int r, int c) { return (char) (g[offset(r, c)] & 0xFF); }
|
||||||
byte byteAt(int r, int c) { return g[getOffset(r, c)]; }
|
int digitAt(int r, int c) { return g[offset(r, c)] - 48; }
|
||||||
void setCharAt(int r, int c, char ch) { g[getOffset(r, c)] = (byte) ch; }
|
byte byteAt(int r, int c) { return g[offset(r, c)]; }
|
||||||
boolean isLetterAt(int r, int c) { return ((g[getOffset(r, c)] & 64) != 0); }
|
void setCharAt(int r, int c, char ch) { g[offset(r, c)] = (byte) ch; }
|
||||||
boolean isDigitAt(int r, int c) { return (g[getOffset(r, c)] & 48) == 48; }
|
boolean isLetterAt(int r, int c) { return ((g[offset(r, c)] & 64) != 0); }
|
||||||
|
boolean isDigitAt(int r, int c) { return (g[offset(r, c)] & 48) == 48; }
|
||||||
}
|
}
|
||||||
Grid makeEmptyGrid() { return new Grid(Data.EXAMPLE.clone(), H, W); }
|
Grid makeEmptyGrid() { return new Grid(new byte[SIZE], H, W); }
|
||||||
|
|
||||||
String gridToString(Grid g) {
|
String gridToString(Grid g) {
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
@@ -252,23 +246,23 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN) {
|
|||||||
|
|
||||||
return new Dict(map.values().toArray(Lemma[]::new));
|
return new Dict(map.values().toArray(Lemma[]::new));
|
||||||
}
|
}
|
||||||
|
int[] intersectSorted(int[] a, int aLen, int[] b, int bLen) {
|
||||||
static int[] intersectSorted(int[] a, int aLen, int[] b, int bLen) {
|
//var out = new int[Math.min(aLen, bLen)];
|
||||||
var out = new int[Math.min(aLen, bLen)];
|
int i = 0, j = 0, k = 0, x = 0, y = 0;
|
||||||
int i = 0, j = 0, k = 0;
|
|
||||||
while (i < aLen && j < bLen) {
|
while (i < aLen && j < bLen) {
|
||||||
int x = a[i], y = b[j];
|
x = a[i];
|
||||||
|
y = b[j];
|
||||||
if (x == y) {
|
if (x == y) {
|
||||||
out[k++] = x;
|
buff[k++] = x;
|
||||||
i++;
|
i++;
|
||||||
j++;
|
j++;
|
||||||
} else if (x < y) i++;
|
} else if (x < y) i++;
|
||||||
else j++;
|
else j++;
|
||||||
}
|
}
|
||||||
return Arrays.copyOf(out, k);
|
return Arrays.copyOf(buff, k);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CandidateInfo candidateInfoForPattern(DictEntry entry, char[] pattern /* 0 means null */) {
|
CandidateInfo candidateInfoForPattern(DictEntry entry, char[] pattern ) {
|
||||||
var lists = new ArrayList<IntList>();
|
var lists = new ArrayList<IntList>();
|
||||||
for (var i = 0; i < pattern.length; i++) {
|
for (var i = 0; i < pattern.length; i++) {
|
||||||
var ch = pattern[i];
|
var ch = pattern[i];
|
||||||
@@ -296,10 +290,10 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN) {
|
|||||||
|
|
||||||
return new CandidateInfo(cur, curLen);
|
return new CandidateInfo(cur, curLen);
|
||||||
}
|
}
|
||||||
static record Slot(String key, int clueR, int clueC, char dir, int[] rs, int[] cs, int len, boolean horiz) {
|
static record Slot(String key, int clueR, int clueC, int dir, int[] rs, int[] cs, int len, boolean horiz) {
|
||||||
|
|
||||||
public Slot(int clueR, int clueC, char dir, int[] rs, int[] cs) {
|
public Slot(int clueR, int clueC, int d, int[] rs, int[] cs) {
|
||||||
this(clueR + "," + clueC + ":" + dir, clueR, clueC, dir, rs, cs, rs.length, dir == HOR_ARROW_1 || dir == HOR_ARROW_2);
|
this(clueR + "," + clueC + ":" + d, clueR, clueC, d, rs, cs, rs.length, d == 2 || d == 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,10 +302,9 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN) {
|
|||||||
for (var r = 0; r < H; r++) {
|
for (var r = 0; r < H; r++) {
|
||||||
for (var c = 0; c < W; c++) {
|
for (var c = 0; c < W; c++) {
|
||||||
if (!grid.isDigitAt(r, c)) continue;
|
if (!grid.isDigitAt(r, c)) continue;
|
||||||
var d = grid.getCharAt(r, c);
|
var d = grid.digitAt(r, c);
|
||||||
var dir = d - '0';
|
int or = OFFSETS[d].x, oc = OFFSETS[d].y;
|
||||||
int or = OFFSETS[dir].x, oc = OFFSETS[dir].y;
|
int dr = STEPS[d].x, dc = STEPS[d].y;
|
||||||
int dr = STEPS[dir].x, dc = STEPS[dir].y;
|
|
||||||
|
|
||||||
int rr = r + or, cc = c + oc;
|
int rr = r + or, cc = c + oc;
|
||||||
if (rr < 0 || rr >= H || cc < 0 || cc >= W) continue;
|
if (rr < 0 || rr >= H || cc < 0 || cc >= W) continue;
|
||||||
@@ -502,8 +495,7 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN) {
|
|||||||
|
|
||||||
for (var r = 0; r < H; r++)
|
for (var r = 0; r < H; r++)
|
||||||
for (var c = 0; c < W; c++) {
|
for (var c = 0; c < W; c++) {
|
||||||
var ch = out.getCharAt(r, c);
|
if (out.isDigitAt(r, c) && !hasRoomForClue(out, r, c, out.getCharAt(r, c))) out.setCharAt(r, c, C_DASH);
|
||||||
if (isDigit(ch) && !hasRoomForClue(out, r, c, ch)) out.setCharAt(r, c, C_DASH);
|
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,35 +29,36 @@ public class MainTest {
|
|||||||
grid.setCharAt(r, c, C_DASH);
|
grid.setCharAt(r, c, C_DASH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test set/get
|
// Test set/get
|
||||||
grid.setCharAt(0, 0, 'A');
|
grid.setCharAt(0, 0, 'A');
|
||||||
grid.setCharAt(1, 2, '5');
|
grid.setCharAt(1, 2, '5');
|
||||||
grid.setCharAt(2, 3, 'Z');
|
grid.setCharAt(2, 3, 'Z');
|
||||||
|
|
||||||
Assertions.assertEquals('A', grid.getCharAt(0, 0));
|
Assertions.assertEquals('A', grid.getCharAt(0, 0));
|
||||||
Assertions.assertEquals('5', grid.getCharAt(1, 2));
|
Assertions.assertEquals('5', grid.getCharAt(1, 2));
|
||||||
Assertions.assertEquals('Z', grid.getCharAt(2, 3));
|
Assertions.assertEquals('Z', grid.getCharAt(2, 3));
|
||||||
Assertions.assertEquals(C_DASH, grid.getCharAt(1, 1));
|
Assertions.assertEquals(C_DASH, grid.getCharAt(1, 1));
|
||||||
|
|
||||||
// Test isLetterAt
|
// Test isLetterAt
|
||||||
Assertions.assertTrue(grid.isLetterAt(0, 0));
|
Assertions.assertTrue(grid.isLetterAt(0, 0));
|
||||||
Assertions.assertFalse(grid.isLetterAt(1, 2));
|
Assertions.assertFalse(grid.isLetterAt(1, 2));
|
||||||
Assertions.assertTrue(grid.isLetterAt(2, 3));
|
Assertions.assertTrue(grid.isLetterAt(2, 3));
|
||||||
Assertions.assertFalse(grid.isLetterAt(1, 1));
|
Assertions.assertFalse(grid.isLetterAt(1, 1));
|
||||||
|
|
||||||
// Test isDigitAt
|
// Test isDigitAt
|
||||||
Assertions.assertFalse(grid.isDigitAt(0, 0));
|
Assertions.assertFalse(grid.isDigitAt(0, 0));
|
||||||
Assertions.assertTrue(grid.isDigitAt(1, 2));
|
Assertions.assertTrue(grid.isDigitAt(1, 2));
|
||||||
|
Assertions.assertEquals(5, grid.digitAt(1, 2));
|
||||||
Assertions.assertFalse(grid.isDigitAt(2, 3));
|
Assertions.assertFalse(grid.isDigitAt(2, 3));
|
||||||
Assertions.assertFalse(grid.isDigitAt(1, 1));
|
Assertions.assertFalse(grid.isDigitAt(1, 1));
|
||||||
|
|
||||||
// Test isLettercell
|
// Test isLettercell
|
||||||
Assertions.assertTrue(grid.isLettercell(0, 0)); // 'A' is letter
|
Assertions.assertTrue(grid.isLettercell(0, 0)); // 'A' is letter
|
||||||
Assertions.assertFalse(grid.isLettercell(1, 2)); // '5' is digit
|
Assertions.assertFalse(grid.isLettercell(1, 2)); // '5' is digit
|
||||||
Assertions.assertTrue(grid.isLettercell(1, 1)); // '#' is lettercell
|
Assertions.assertTrue(grid.isLettercell(1, 1)); // '#' is lettercell
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGridDeepCopy() {
|
public void testGridDeepCopy() {
|
||||||
var grid = new Grid(new byte[2 * 2], 2, 2);
|
var grid = new Grid(new byte[2 * 2], 2, 2);
|
||||||
@@ -65,7 +66,7 @@ public class MainTest {
|
|||||||
grid.setCharAt(0, 1, 'B');
|
grid.setCharAt(0, 1, 'B');
|
||||||
grid.setCharAt(1, 0, 'C');
|
grid.setCharAt(1, 0, 'C');
|
||||||
grid.setCharAt(1, 1, 'D');
|
grid.setCharAt(1, 1, 'D');
|
||||||
|
|
||||||
var copy = grid.deepCopyGrid();
|
var copy = grid.deepCopyGrid();
|
||||||
Assertions.assertEquals('A', copy.getCharAt(0, 0));
|
Assertions.assertEquals('A', copy.getCharAt(0, 0));
|
||||||
|
|
||||||
@@ -73,8 +74,7 @@ public class MainTest {
|
|||||||
Assertions.assertEquals('X', copy.getCharAt(0, 0));
|
Assertions.assertEquals('X', copy.getCharAt(0, 0));
|
||||||
Assertions.assertEquals('A', grid.getCharAt(0, 0)); // Original should be unchanged
|
Assertions.assertEquals('A', grid.getCharAt(0, 0)); // Original should be unchanged
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMini() {
|
public void testMini() {
|
||||||
var grid = new Grid(new byte[3 * 3], 3, 3);
|
var grid = new Grid(new byte[3 * 3], 3, 3);
|
||||||
|
|||||||
47
src/test/java/puzzle/SwedishGeneratorTest.java
Normal file
47
src/test/java/puzzle/SwedishGeneratorTest.java
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package puzzle;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import puzzle.SwedishGenerator.Grid;
|
||||||
|
import puzzle.SwedishGenerator.Slot;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
class SwedishGeneratorTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testExtractSlots() {
|
||||||
|
SwedishGenerator generator = new SwedishGenerator(3, 3);
|
||||||
|
Grid grid = generator.makeEmptyGrid();
|
||||||
|
|
||||||
|
// Set up digits on the grid to create slots.
|
||||||
|
for (int r = 0; r < 3; r++) {
|
||||||
|
for (int c = 0; c < 3; c++) {
|
||||||
|
if ((r + c) % 2 == 0) {
|
||||||
|
grid.setCharAt(r, c, '1');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up letter cells around digits to form valid slots.
|
||||||
|
int[][] directions = { { -1, -1 }, { -1, 0 }, { -1, 1 }, { 0, -1 }, { 0, 1 }, { 1, -1 }, { 1, 0 } };
|
||||||
|
|
||||||
|
for (int r = 0; r < 3; r++) {
|
||||||
|
for (int c = 0; c < 3; c++) {
|
||||||
|
if (grid.isDigitAt(r, c)) {
|
||||||
|
int dr = directions[grid.digitAt(r, c)][0];
|
||||||
|
int dc = directions[grid.digitAt(r, c)][1];
|
||||||
|
|
||||||
|
int rr = r + dr;
|
||||||
|
int cc = c + dc;
|
||||||
|
|
||||||
|
if (rr >= 0 && rr < generator.H() && cc >= 0 && cc < generator.W())
|
||||||
|
grid.setCharAt(rr, cc, 'A');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the extractSlots method.
|
||||||
|
ArrayList<Slot> slots = generator.extractSlots(grid);
|
||||||
|
assertEquals(3, slots.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user