update them

This commit is contained in:
mike
2025-12-22 01:03:18 +01:00
parent 83d1a907c1
commit f9f0f31d12
56 changed files with 37953 additions and 37322 deletions

View File

@@ -14,6 +14,7 @@ import java.util.stream.IntStream;
* javac SwedishGenerator.java
* java SwedishGenerator [--seed N] [--pop N] [--gens N] [--tries N] [--words word-list.txt]
*/
@SuppressWarnings("ALL")
public class SwedishGenerator {
static final int W = 9, H = 8;
@@ -136,7 +137,7 @@ public class SwedishGenerator {
final int score;
public WordDifficulty(String word, int score) {
this.word = word;
this.word = word;
this.score = score;
// We want LONGER and SIMPLER words to be tried earlier (lower difficulty value).
// word.length() is 2 to 8.
@@ -144,7 +145,8 @@ public class SwedishGenerator {
// Base difficulty starts high and decreases with length and score.
// Length impact: up to 8 * 10 = 80
// Score impact: up to 10 * 15 = 150
this.difficulty = 250 - (word.length() * 10) - (score * 15);
var difficulty1 = 0 + ((8 - word.length()) * 30) + ((10-score) * 15);
this.difficulty = difficulty1;
}
}
@@ -154,17 +156,26 @@ public class SwedishGenerator {
var lines = Files.readAllLines(Path.of("word_scores.csv"), StandardCharsets.UTF_8);
var first = true;
for (var line : lines) {
if (first) { first = false; continue; }
var parts = line.split(",", 3);
if (first) {
first = false;
continue;
}
var parts = line.split("," );
if (parts.length >= 3) {
try {
var word = parts[0].trim().toUpperCase(Locale.ROOT);
var score = Integer.parseInt(parts[1].trim());
var word = parts[0].trim().toUpperCase(Locale.ROOT);
var score = Integer.parseInt(parts[1].trim());
var status = parts[2].trim();
if ("OK".equalsIgnoreCase(status)) {
scores.put(word, score);
} else {
System.err.println("Skipping:" +Arrays.toString( parts));
}
} catch (NumberFormatException ignored) {}
} catch (NumberFormatException ignored) {
System.err.println("Illegal number format: " + line);
}
} else {
System.err.println("Illegal word: " + line);
}
}
} catch (IOException e) {
@@ -184,7 +195,7 @@ public class SwedishGenerator {
this.lenCounts = lenCounts;
}
}
static Dict loadWords(String wordsPath) {
static Dict loadWords(String wordsPath, Map<String, Integer> llmScores) {
String raw;
try {
raw = Files.readString(Path.of(wordsPath), StandardCharsets.UTF_8);
@@ -192,8 +203,7 @@ public class SwedishGenerator {
raw = "EU\nUUR\nAUTO\nBOOM\nHUIS\nKAT\nZEE\nRODE\nDRAAD\nKENNIS\nNETWERK\nPAKTE\n";
}
var llmScores = loadScores();
var words = new ArrayList<WordDifficulty>();
var words = new ArrayList<WordDifficulty>();
for (var line : raw.split("\\R")) {
var s = line.trim().toUpperCase(Locale.ROOT);
if (s.matches("^[A-Z]{2,8}$")) {
@@ -289,11 +299,10 @@ public class SwedishGenerator {
return ci;
}
static int indexToDifficulty(DictEntry entry, int index, Map<String, Integer> llmScores) {
var word = entry.words.get(index);
var word = entry.words.get(index);
var score = llmScores.getOrDefault(word, 5);
return new WordDifficulty(word, score).difficulty;
}
// ---------------- Slots ----------------
@@ -617,6 +626,7 @@ public class SwedishGenerator {
public char[][] grid;
public HashMap<String, String> clueMap;
public FillStats stats;
public double simplicity;
}
record Undo(int[] rs, int[] cs, char[] prev, int n) {
@@ -667,6 +677,7 @@ public class SwedishGenerator {
}
static FillResult fillMask(Rng rng, char[][] mask, HashMap<Integer, DictEntry> dictIndex,
Map<String, Integer> llmScores,
int logEveryMs, int timeLimitMs) {
var grid = deepCopyGrid(mask);
@@ -819,10 +830,10 @@ public class SwedishGenerator {
// (lower difficulty) but still have some randomness.
for (var t = 0; t < tries; t++) {
// Bias strongly towards lower indices (simpler words) using r^3
double r = rng.nextFloat();
int idxInArray = (int) (r * r * r * L);
var idx = idxs[idxInArray];
var w = entry.words.get(idx);
double r = rng.nextFloat();
int idxInArray = (int) (r * r * r * L);
var idx = idxs[idxInArray];
var w = entry.words.get(idx);
if (tryWord.apply(w)) return true;
}
stats.backtracks++;
@@ -837,9 +848,9 @@ public class SwedishGenerator {
var tries = Math.min(MAX_TRIES_PER_SLOT, N);
for (var t = 0; t < tries; t++) {
double r = rng.nextFloat();
int idxInArray = (int) (r * r * r * N);
var w = entry.words.get(idxInArray);
double r = rng.nextFloat();
int idxInArray = (int) (r * r * r * N);
var w = entry.words.get(idxInArray);
if (tryWord.apply(w)) return true;
}
@@ -862,6 +873,14 @@ public class SwedishGenerator {
stats.seconds = (System.currentTimeMillis() - t0) / 1000.0;
res.stats = stats;
if (ok) {
double totalSimplicity = 0;
for (var w : assigned.values()) {
totalSimplicity += llmScores.getOrDefault(w, 5);
}
res.simplicity = assigned.isEmpty() ? 0 : totalSimplicity / assigned.size();
}
// print a final progress line
System.out.println(
String.format(Locale.ROOT,
@@ -882,11 +901,12 @@ public class SwedishGenerator {
public record PuzzleResult(char[][] mask, FillResult filled) { }
public static PuzzleResult generatePuzzle(Main.Opts opts) {
var rng = new Rng(opts.seed);
var tLoad0 = System.nanoTime();
var dict = loadWords(opts.wordsPath);
var tLoad1 = System.nanoTime();
System.out.printf(Locale.ROOT, "LOAD_WORDS: %.3fs%n", (tLoad1 - tLoad0) / 1e9);
var rng = new Rng(opts.seed);
var llmScores = loadScores();
var tLoad0 = System.nanoTime();
var dict = loadWords(opts.wordsPath, llmScores);
var tLoad1 = System.nanoTime();
System.out.printf(Locale.ROOT, "LOAD_WORDS: %.3fs%n %s words", (tLoad1 - tLoad0) / 1e9,dict.words.size());
for (var attempt = 1; attempt <= opts.tries; attempt++) {
System.out.println("\nAttempt " + attempt + "/" + opts.tries);
@@ -897,14 +917,19 @@ public class SwedishGenerator {
System.out.printf(Locale.ROOT, "MASK: %.3fs%n", (tMask1 - tMask0) / 1e9);
var tFill0 = System.nanoTime();
var filled = fillMask(rng, mask, dict.index, 200, 60000);
var filled = fillMask(rng, mask, dict.index, llmScores, 200, 60000);
var tFill1 = System.nanoTime();
System.out.printf(Locale.ROOT, "FILL: %.3fms%n", (tFill1 - tFill0) / 1e6);
System.out.printf(Locale.ROOT, "FILL: %.3fms | Simplicity: %.2f%n", (tFill1 - tFill0) / 1e6, filled.simplicity);
if (filled.ok) {
if (filled.ok && (opts.minSimplicity <= 0 || filled.simplicity >= opts.minSimplicity)) {
return new PuzzleResult(mask, filled);
}
if (filled.ok) {
System.out.printf(Locale.ROOT, "Puzzle simplicity %.2f is below min %.2f, retrying...%n",
filled.simplicity, opts.minSimplicity);
}
}
return null;
}
}