Gather data

This commit is contained in:
mike
2026-01-06 02:57:17 +01:00
parent f031e97a58
commit effb1145d4
4 changed files with 89 additions and 51 deletions

View File

@@ -15,13 +15,14 @@ import java.util.function.Predicate;
* java SwedishGenerator [--seed N] [--pop N] [--gens N] [--tries N] [--words word-list.txt]
*/
@SuppressWarnings("ALL")
public class SwedishGenerator {
public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN) {
static final int W = 9, H = 8,
SIZE = W * H,
CLUE_SIZE = 4,
public SwedishGenerator(int W,int H) { this(W, H, W * H, Math.min(W, H)); }
public SwedishGenerator() { this(9, 8); }
static final int CLUE_SIZE = 4,
SIMPLICITY_DEFAULT_SCORE = 2;
static final int MIN_LEN = 2, MAX_LEN = 8;
static final int MIN_LEN = 2;
// Directions for '1'..'6'
static final int[][] OFFSETS = new int[7][2];
static final int[][] STEPS = new int[7][2];
@@ -81,19 +82,19 @@ public class SwedishGenerator {
static int clamp(int x, int a, int b) { return Math.max(a, Math.min(b, x)); }
// ---------------- Grid helpers ----------------
static char[][] makeEmptyGrid() {
char[][] makeEmptyGrid() {
var g = new char[H][W];
for (var r = 0; r < H; r++) Arrays.fill(g[r], '#');
return g;
}
static char[][] deepCopyGrid(char[][] g) {
char[][] deepCopyGrid(char[][] g) {
var out = new char[H][W];
for (var r = 0; r < H; r++) out[r] = Arrays.copyOf(g[r], W);
return out;
}
static String gridToString(char[][] g) {
String gridToString(char[][] g) {
var sb = new StringBuilder();
for (var r = 0; r < H; r++) {
if (r > 0) sb.append('\n');
@@ -102,7 +103,7 @@ public class SwedishGenerator {
return sb.toString();
}
static String renderHuman(char[][] g) {
public String renderHuman(char[][] g) {
var sb = new StringBuilder();
for (var r = 0; r < H; r++) {
if (r > 0) sb.append('\n');
@@ -295,7 +296,7 @@ public class SwedishGenerator {
public Slot(int clueR, int clueC, char dir, int[] rs, int[] cs) { this(clueR + "," + clueC + ":" + dir, clueR, clueC, dir, rs, cs, rs.length); }
}
static ArrayList<Slot> extractSlots(char[][] grid) {
ArrayList<Slot> extractSlots(char[][] grid) {
var slots = new ArrayList<Slot>();
for (var r = 0; r < H; r++) {
for (var c = 0; c < W; c++) {
@@ -332,7 +333,7 @@ public class SwedishGenerator {
}
return slots;
}
static boolean hasRoomForClue(char[][] grid, int r, int c, char d) {
boolean hasRoomForClue(char[][] grid, int r, int c, char d) {
var di = d - '0';
int or = OFFSETS[di][0], oc = OFFSETS[di][1];
int dr = STEPS[di][0], dc = STEPS[di][1];
@@ -353,7 +354,7 @@ public class SwedishGenerator {
{ 1, -1 }, { 1, 0 }, { 1, 1 }
};
static final int[][] nbrs4 = new int[][]{ { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };
static long maskFitness(char[][] grid, int[] lenCounts) {
long maskFitness(char[][] grid, int[] lenCounts) {
long penalty = 0;
var clueCount = 0;
@@ -447,7 +448,7 @@ public class SwedishGenerator {
// ---------------- Mask generation ----------------
static char[][] randomMask(Rng rng) {
char[][] randomMask(Rng rng) {
var g = makeEmptyGrid();
var targetClues = (int) Math.round(SIZE * 0.25);
int placed = 0, guard = 0;
@@ -468,7 +469,7 @@ public class SwedishGenerator {
return g;
}
static char[][] mutate(Rng rng, char[][] grid) {
char[][] mutate(Rng rng, char[][] grid) {
var g = deepCopyGrid(grid);
var cx = rng.randint(0, H - 1);
var cy = rng.randint(0, W - 1);
@@ -490,7 +491,7 @@ public class SwedishGenerator {
return g;
}
static char[][] crossover(Rng rng, char[][] a, char[][] b) {
char[][] crossover(Rng rng, char[][] a, char[][] b) {
var out = makeEmptyGrid();
var cx = (H - 1) / 2.0;
var cy = (W - 1) / 2.0;
@@ -513,7 +514,7 @@ public class SwedishGenerator {
return out;
}
static char[][] hillclimb(Rng rng, char[][] start, int[] lenCounts, int limit) {
char[][] hillclimb(Rng rng, char[][] start, int[] lenCounts, int limit) {
var best = deepCopyGrid(start);
var bestF = maskFitness(best, lenCounts);
var fails = 0;
@@ -532,13 +533,13 @@ public class SwedishGenerator {
return best;
}
static double similarity(char[][] a, char[][] b) {
double similarity(char[][] a, char[][] b) {
var same = 0;
for (var r = 0; r < H; r++) for (var c = 0; c < W; c++) if (a[r][c] == b[r][c]) same++;
return same / (double) (W * H);
}
static char[][] generateMask(Rng rng, int[] lenCounts, int popSize, int gens, boolean verbose) {
public char[][] generateMask(Rng rng, int[] lenCounts, int popSize, int gens, boolean verbose) {
if (verbose) System.out.println("generateMask init pop: " + popSize);
var pop = new ArrayList<char[][]>();
@@ -660,7 +661,7 @@ public class SwedishGenerator {
record Pick(Slot slot,
CandidateInfo info,
boolean done) { }
static FillResult fillMask(Rng rng, char[][] mask, DictEntry[] dictIndex,
public FillResult fillMask(Rng rng, char[][] mask, DictEntry[] dictIndex,
int logEveryMs, int timeLimitMs, boolean verbose) {
var grid = deepCopyGrid(mask);
@@ -854,6 +855,6 @@ public class SwedishGenerator {
}
// ---------------- Top-level generatePuzzle ----------------
public record PuzzleResult(Dict dict, char[][] mask, FillResult filled) { }
public record PuzzleResult(SwedishGenerator swe, Dict dict, char[][] mask, FillResult filled) { }
}