Gather data

This commit is contained in:
mike
2026-01-08 03:59:28 +01:00
parent 5691b4c07b
commit 397bf14015

View File

@@ -1,11 +1,17 @@
package puzzle; package puzzle;
import lombok.*; import lombok.Data;
import lombok.Getter;
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.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Locale;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Supplier; import java.util.function.Supplier;
@@ -23,6 +29,8 @@ public record SwedishGenerator(int[] buff) {
record nbrs_8(int x, int y) { } record nbrs_8(int x, int y) { }
record nbrs_16(int x, int y, int dx, int dy) { }
static final int W = Config.PUZZLE_COLS; static final int W = Config.PUZZLE_COLS;
static final double CROSS_Y = (W - 1) / 2.0; static final double CROSS_Y = (W - 1) / 2.0;
static final int H = Config.PUZZLE_ROWS; static final int H = Config.PUZZLE_ROWS;
@@ -42,29 +50,22 @@ public record SwedishGenerator(int[] buff) {
public SwedishGenerator() { this(new int[8124]); } public SwedishGenerator() { this(new int[8124]); }
// Directions for '1'..'6' // Directions for '1'..'6'
static final nbrs_8[] OFFSETS = new nbrs_8[7]; static final nbrs_16[] OFFSETS = new nbrs_16[]{
static final nbrs_8[] STEPS = new nbrs_8[7]; null,
static { // 1: up
// 1: up new nbrs_16(-1, 0, -1, 0),
OFFSETS[1] = new nbrs_8(-1, 0); // 2: right
STEPS[1] = new nbrs_8(-1, 0); new nbrs_16(0, 1, 0, 1),
// 2: right // 3: down
OFFSETS[2] = new nbrs_8(0, 1); new nbrs_16(1, 0, 1, 0),
STEPS[2] = new nbrs_8(0, 1); // 4: left
// 3: down new nbrs_16(0, -1, 0, -1),
OFFSETS[3] = new nbrs_8(1, 0); // 5: vertical down, clue is on the right of the first letter
STEPS[3] = new nbrs_8(1, 0); new nbrs_16(0, -1, 1, 0),
// 4: left // 6: vertical down, clue is on the left of the first letter
OFFSETS[4] = new nbrs_8(0, -1); new nbrs_16(0, 1, 1, 0)
STEPS[4] = new nbrs_8(0, -1); };
// 5: vertical down, clue is on the right of the first letter final static nbrs_8[] nbrs8 = new nbrs_8[]{
OFFSETS[5] = new nbrs_8(0, -1);
STEPS[5] = new nbrs_8(1, 0);
// 6: vertical down, clue is on the left of the first letter
OFFSETS[6] = new nbrs_8(0, 1);
STEPS[6] = new nbrs_8(1, 0);
}
final static nbrs_8[] nbrs8 = new nbrs_8[]{
new nbrs_8(-1, -1), new nbrs_8(-1, -1),
new nbrs_8(-1, 0), new nbrs_8(-1, 0),
new nbrs_8(-1, 1), new nbrs_8(-1, 1),
@@ -74,7 +75,7 @@ public record SwedishGenerator(int[] buff) {
new nbrs_8(1, 0), new nbrs_8(1, 0),
new nbrs_8(1, 1) new nbrs_8(1, 1)
}; };
static final nbrs_8[] nbrs4 = new nbrs_8[]{ static final SwedishGenerator.nbrs_8[] nbrs4 = new nbrs_8[]{
new nbrs_8(-1, 0), new nbrs_8(-1, 0),
new nbrs_8(1, 0), new nbrs_8(1, 0),
new nbrs_8(0, -1), new nbrs_8(0, -1),
@@ -90,7 +91,7 @@ public record SwedishGenerator(int[] buff) {
IntList[] intListBuffer, IntList[] intListBuffer,
long[] undoBuffer) { long[] undoBuffer) {
public Context() { this(new int[256], new int[256], new int[256], new int[256], new BitSet(256), new char[32], new IntList[32], new long[2048]); } public Context() { this(new int[SIZE], new int[SIZE], new int[SIZE], new int[SIZE], new BitSet(128), new char[MAX_WORD_LENGTH], new IntList[MAX_WORD_LENGTH], new long[2048]); }
void setPatter(char[] chars) { System.arraycopy(chars, 0, this.pattern, 0, chars.length); } void setPatter(char[] chars) { System.arraycopy(chars, 0, this.pattern, 0, chars.length); }
} }
@@ -195,11 +196,11 @@ public record SwedishGenerator(int[] buff) {
int[] lenCounts) { int[] lenCounts) {
public Dict(Lemma[] wordz) { public Dict(Lemma[] wordz) {
Lemma[] lemmas = wordz.clone(); var lemmas = wordz.clone();
Arrays.sort(lemmas, Comparator.comparingInt(wd -> wd.simpel)); Arrays.sort(lemmas, Comparator.comparingInt(wd -> wd.simpel));
var lenCounts = new int[MAX_WORD_LENGTH+1]; var lenCounts = new int[MAX_WORD_LENGTH + 1];
var index = new DictEntry[MAX_WORD_LENGTH+1]; var index = new DictEntry[MAX_WORD_LENGTH + 1];
Arrays.setAll(index, i -> new DictEntry(i)); Arrays.setAll(index, i -> new DictEntry(i));
int maxLength = -1; int maxLength = -1;
for (var lemma : lemmas) { for (var lemma : lemmas) {
@@ -229,8 +230,8 @@ public record SwedishGenerator(int[] buff) {
raw = "WOORD,level_1_to_10,hint\nEU,2,hint\nUUR,2,hint\nAUTO,2,hint\nBOOM,2,hint\nHUIS,2,hint\nKAT,2,hint\nZEE,2,hint\nRODE,2,hint\nDRAAD,2,hint\nKENNIS,2,hint\nNETWERK,2,hint\nPAKTE,2,hint\n"; raw = "WOORD,level_1_to_10,hint\nEU,2,hint\nUUR,2,hint\nAUTO,2,hint\nBOOM,2,hint\nHUIS,2,hint\nKAT,2,hint\nZEE,2,hint\nRODE,2,hint\nDRAAD,2,hint\nKENNIS,2,hint\nNETWERK,2,hint\nPAKTE,2,hint\n";
} }
var map = new HashMap<String, Lemma>(); var map = new HashMap<String, Lemma>();
boolean first = true; var first = true;
for (var line : raw.split("\\R")) { for (var line : raw.split("\\R")) {
if (line.isBlank()) { if (line.isBlank()) {
System.err.println("Empty line: " + line); System.err.println("Empty line: " + line);
@@ -283,10 +284,10 @@ public record SwedishGenerator(int[] buff) {
return Arrays.copyOf(buff, k); return Arrays.copyOf(buff, k);
} }
CandidateInfo candidateInfoForPattern(Context ctx, DictEntry entry, int len) { SwedishGenerator.CandidateInfo candidateInfoForPattern(Context ctx, DictEntry entry, int len) {
char[] pattern = ctx.pattern; var pattern = ctx.pattern;
var listBuffer = ctx.intListBuffer; var listBuffer = ctx.intListBuffer;
int listCount = 0; var listCount = 0;
for (var i = 0; i < len; i++) { for (var i = 0; i < len; i++) {
var ch = pattern[i]; var ch = pattern[i];
if (isLetter(ch)) { if (isLetter(ch)) {
@@ -351,14 +352,11 @@ public record SwedishGenerator(int[] buff) {
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.digitAt(r, c); var d = grid.digitAt(r, c);
int or = OFFSETS[d].x, oc = OFFSETS[d].y; var nbrs16 = OFFSETS[d];
int dr = STEPS[d].x, dc = STEPS[d].y; int rr = r + nbrs16.x, cc = c + nbrs16.y;
int rr = r + or, cc = c + oc;
if (rr < 0 || rr >= H || cc < 0 || cc >= W) continue;
if (grid.isDigitAt(rr, cc)) continue;
if (rr < 0 || rr >= H || cc < 0 || cc >= W || grid.isDigitAt(rr, cc)) continue;
long packedRs = 0; long packedRs = 0;
long packedCs = 0; long packedCs = 0;
var n = 0; var n = 0;
@@ -367,8 +365,8 @@ public record SwedishGenerator(int[] buff) {
packedRs |= (long) rr << (n << 2); packedRs |= (long) rr << (n << 2);
packedCs |= (long) cc << (n << 2); packedCs |= (long) cc << (n << 2);
n++; n++;
rr += dr; rr += nbrs16.dx;
cc += dc; cc += nbrs16.dy;
} }
if (n > 0) { if (n > 0) {
visitor.visit((r << 8) | (c << 4) | d, packedRs, packedCs, n); visitor.visit((r << 8) | (c << 4) | d, packedRs, packedCs, n);
@@ -384,15 +382,13 @@ public record SwedishGenerator(int[] buff) {
} }
boolean hasRoomForClue(Grid grid, int r, int c, char d) { boolean hasRoomForClue(Grid grid, int r, int c, char d) {
var di = d - '0'; var nbrs16 = OFFSETS[d - '0'];
int or = OFFSETS[di].x, oc = OFFSETS[di].y; int rr = r + nbrs16.x, cc = c + nbrs16.y;
int dr = STEPS[di].x, dc = STEPS[di].y; var run = 0;
int rr = r + or, cc = c + oc;
var run = 0;
while (rr >= 0 && rr < H && cc >= 0 && cc < W && (grid.isLettercell(rr, cc)) && run < MAX_WORD_LENGTH) { while (rr >= 0 && rr < H && cc >= 0 && cc < W && (grid.isLettercell(rr, cc)) && run < MAX_WORD_LENGTH) {
run++; run++;
rr += dr; rr += nbrs16.dx;
cc += dc; cc += nbrs16.dy;
if (run >= MIN_LEN) return true; if (run >= MIN_LEN) return true;
} }
return false; return false;
@@ -417,13 +413,10 @@ public record SwedishGenerator(int[] buff) {
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.digitAt(r, c); var d = grid.digitAt(r, c);
int or = OFFSETS[d].x, oc = OFFSETS[d].y; var nbrs16 = OFFSETS[d];
int dr = STEPS[d].x, dc = STEPS[d].y; int rr = r + nbrs16.x, cc = c + nbrs16.y;
if (rr < 0 || rr >= H || cc < 0 || cc >= W || grid.isDigitAt(rr, cc)) continue;
int rr = r + or, cc = c + oc;
if (rr < 0 || rr >= H || cc < 0 || cc >= W) continue;
if (grid.isDigitAt(rr, cc)) continue;
long packedRs = 0; long packedRs = 0;
long packedCs = 0; long packedCs = 0;
@@ -434,8 +427,8 @@ public record SwedishGenerator(int[] buff) {
packedRs |= (long) rr << (n << 2); packedRs |= (long) rr << (n << 2);
packedCs |= (long) cc << (n << 2); packedCs |= (long) cc << (n << 2);
n++; n++;
rr += dr; rr += nbrs16.dx;
cc += dc; cc += nbrs16.dy;
} }
if (n == 0) continue; if (n == 0) continue;
hasSlots = true; hasSlots = true;
@@ -446,14 +439,8 @@ public record SwedishGenerator(int[] buff) {
if (lenCounts[n] <= 0) penalty += 12000; if (lenCounts[n] <= 0) penalty += 12000;
} }
boolean horiz = Slot.horiz(d); var horiz = Slot.horiz(d) ? covH : covV;
for (var i = 0; i < n; i++) { for (var i = 0; i < n; i++) horiz[grid.offset(Slot.r(packedRs, i), Slot.c(packedCs, i))] += 1;
int sr = Slot.r(packedRs, i);
int sc = Slot.c(packedCs, i);
int idx = grid.offset(sr, sc);
if (horiz) covH[idx] += 1;
else covV[idx] += 1;
}
} }
} }
@@ -719,8 +706,8 @@ public record SwedishGenerator(int[] buff) {
public FillResult fillMask(Rng rng, Grid mask, DictEntry[] dictIndex, public FillResult fillMask(Rng rng, Grid mask, DictEntry[] dictIndex,
int logEveryMs, int timeLimitMs, boolean verbose) { int logEveryMs, int timeLimitMs, boolean verbose) {
boolean multiThreaded = Thread.currentThread().getName().contains("pool"); boolean multiThreaded = Thread.currentThread().getName().contains("pool");
var grid = mask.deepCopyGrid(); var grid = mask.deepCopyGrid();
var slots = extractSlots(grid); var slots = extractSlots(grid);
var used = new BitSet(); var used = new BitSet();
var assigned = new HashMap<Integer, Lemma>(); var assigned = new HashMap<Integer, Lemma>();