From dbdd8ecfdbb0f6c28ff2ae8f5b850882d52005f4 Mon Sep 17 00:00:00 2001 From: mike Date: Thu, 8 Jan 2026 17:27:17 +0100 Subject: [PATCH] Gather data --- src/main/java/puzzle/ExportFormat.java | 34 +++++------ src/main/java/puzzle/SwedishGenerator.java | 70 ++++++++++++++++++++-- 2 files changed, 81 insertions(+), 23 deletions(-) diff --git a/src/main/java/puzzle/ExportFormat.java b/src/main/java/puzzle/ExportFormat.java index eb4ac4e..bd6c202 100644 --- a/src/main/java/puzzle/ExportFormat.java +++ b/src/main/java/puzzle/ExportFormat.java @@ -1,11 +1,14 @@ package puzzle; -import lombok.AllArgsConstructor; -import lombok.Value; -import lombok.experimental.Accessors; import puzzle.Main.PuzzleResult; -import java.util.*; -import static puzzle.SwedishGenerator.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Objects; +import static puzzle.SwedishGenerator.H; +import static puzzle.SwedishGenerator.Lemma; +import static puzzle.SwedishGenerator.Slot; +import static puzzle.SwedishGenerator.W; /** * ExportFormat.java @@ -29,18 +32,15 @@ public final class ExportFormat { var g = puz.filled().grid(); // 1) extract "placed" list from all clue digits in the filled grid - var placed = new ArrayList(); - var allSlots = puz.swe().extractSlots(g); - var clueMap = puz.filled().clueMap(); - - for (var s : allSlots) { - var word = clueMap.get(s.key()); - if (word == null) continue; - - var p = extractPlacedFromSlot(s, word); - if (p == null) continue; - placed.add(p); - } + var placed = new ArrayList(); + var clueMap = puz.filled().clueMap(); + puz.swe().forEachSlot(g, (int key, long rs, long cs, int len) -> { + var word = clueMap.get(key); + if (word != null) { + var p = extractPlacedFromSlot(new Slot(key, rs, cs, len), word); + if (p != null) placed.add(p); + } + }); // If nothing placed: return full grid mapped to letters/# only if (placed.isEmpty()) { diff --git a/src/main/java/puzzle/SwedishGenerator.java b/src/main/java/puzzle/SwedishGenerator.java index dc12967..c876077 100644 --- a/src/main/java/puzzle/SwedishGenerator.java +++ b/src/main/java/puzzle/SwedishGenerator.java @@ -50,7 +50,7 @@ public record SwedishGenerator(int[] buff) { public SwedishGenerator() { this(new int[8124]); } // Directions for '1'..'6' - static final nbrs_16[] OFFSETS = new nbrs_16[]{ + static final nbrs_16[] OFFSETS = new nbrs_16[]{ null, // 1: up new nbrs_16(-1, 0, -1, 0), @@ -65,7 +65,7 @@ public record SwedishGenerator(int[] buff) { // 6: vertical down, clue is on the left of the first letter new nbrs_16(0, 1, 1, 0) }; - final static nbrs_8[] nbrs8 = new nbrs_8[]{ + final static nbrs_8[] nbrs8 = new nbrs_8[]{ new nbrs_8(-1, -1), new nbrs_8(-1, 0), new nbrs_8(-1, 1), @@ -75,7 +75,7 @@ public record SwedishGenerator(int[] buff) { new nbrs_8(1, 0), new nbrs_8(1, 1) }; - static final SwedishGenerator.nbrs_8[] nbrs4 = new nbrs_8[]{ + static final nbrs_8[] nbrs4 = new nbrs_8[]{ new nbrs_8(-1, 0), new nbrs_8(1, 0), new nbrs_8(0, -1), @@ -91,7 +91,10 @@ public record SwedishGenerator(int[] buff) { IntList[] intListBuffer, long[] undoBuffer) { - 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]); } + 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); } } @@ -284,7 +287,7 @@ public record SwedishGenerator(int[] buff) { return Arrays.copyOf(buff, k); } - SwedishGenerator.CandidateInfo candidateInfoForPattern(Context ctx, DictEntry entry, int len) { + CandidateInfo candidateInfoForPattern(Context ctx, DictEntry entry, int len) { var pattern = ctx.pattern; var listBuffer = ctx.intListBuffer; var listCount = 0; @@ -591,6 +594,61 @@ public record SwedishGenerator(int[] buff) { } public Grid generateMask(Rng rng, int[] lenCounts, int popSize, int gens, boolean verbose) { + class GridAndFit { + + Grid grid; + Long fite; + GridAndFit(Grid grid) { this.grid = grid; } + long fit() { + if (fite == null) this.fite = maskFitness(grid, lenCounts); + return this.fite; + } + } + if (verbose) System.out.println("generateMask init pop: " + popSize); + var pop = new ArrayList(); + for (var i = 0; i < popSize; i++) { + pop.add(new GridAndFit(hillclimb(rng, randomMask(rng), lenCounts, 180))); + } + + for (var gen = 0; gen < gens; gen++) { + if (Thread.currentThread().isInterrupted()) break; + var children = new ArrayList(); + var pairs = Math.max(popSize, (int) Math.floor(popSize * 1.5)); + + for (var k = 0; k < pairs; k++) { + var p1 = pop.get(rng.randint(0, pop.size() - 1)); + var p2 = pop.get(rng.randint(0, pop.size() - 1)); + var child = crossover(rng, p1.grid, p2.grid); + children.add(new GridAndFit(hillclimb(rng, child, lenCounts, 70))); + } + + pop.addAll(children); + pop.sort(Comparator.comparingLong(GridAndFit::fit)); + + var next = new ArrayList(); + for (var cand : pop) { + if (next.size() >= popSize) break; + var ok = true; + for (var kept : next) { + if (cand.grid.similarity(kept.grid) > 0.92) { + ok = false; + break; + } + } + if (ok) next.add(cand); + } + pop = next; + + if (verbose && gen % 10 == 0) { + var bestF = pop.get(0).fit(); + System.out.println(" gen " + gen + "/" + gens + " bestFitness=" + bestF); + } + } + + pop.sort(Comparator.comparingLong(GridAndFit::fit)); + return pop.get(0).grid; + } + public Grid generateMask2(Rng rng, int[] lenCounts, int popSize, int gens, boolean verbose) { if (verbose) System.out.println("generateMask init pop: " + popSize); var pop = new ArrayList(); @@ -709,7 +767,7 @@ public record SwedishGenerator(int[] buff) { var grid = mask.deepCopyGrid(); var slots = extractSlots(grid); - var used = new BitSet(); + var used = new BitSet(SIZE << 1); var assigned = new HashMap(); var ctx = CTX.get();