From efe70fb1214b1a877f3630b754342a964990a4bc Mon Sep 17 00:00:00 2001 From: mike Date: Wed, 7 Jan 2026 23:28:14 +0100 Subject: [PATCH] Gather data --- pom.xml | 19 +++++ src/main/java/puzzle/ExportFormat.java | 98 ++++++++++++---------- src/main/java/puzzle/Main.java | 35 ++++---- src/main/java/puzzle/SwedishGenerator.java | 17 ++-- 4 files changed, 100 insertions(+), 69 deletions(-) diff --git a/pom.xml b/pom.xml index 189a633..b8862b2 100644 --- a/pom.xml +++ b/pom.xml @@ -47,10 +47,29 @@ RELEASE test + + org.projectlombok + lombok + 1.18.42 + provided + + + org.apache.maven.plugins + maven-compiler-plugin + + + + org.projectlombok + lombok + 1.18.42 + + + + org.apache.maven.plugins maven-shade-plugin diff --git a/src/main/java/puzzle/ExportFormat.java b/src/main/java/puzzle/ExportFormat.java index 7178234..0443366 100644 --- a/src/main/java/puzzle/ExportFormat.java +++ b/src/main/java/puzzle/ExportFormat.java @@ -1,5 +1,8 @@ package puzzle; +import lombok.AllArgsConstructor; +import lombok.Value; +import lombok.experimental.Accessors; import java.util.*; import static puzzle.SwedishGenerator.*; @@ -50,7 +53,7 @@ public final class ExportFormat { } gridv2.add(sb.toString()); } - return new ExportedPuzzle(gridv2, List.of(), difficulty, rewards); + return new ExportedPuzzle(gridv2, new WordOut[0], difficulty, rewards); } // 2) bounding box around all word cells + arrow cells, with 1-cell margin @@ -72,7 +75,7 @@ public final class ExportFormat { } // 3) map of only used letter cells (everything else becomes '#') - Map letterAt = new HashMap<>(); + var letterAt = new HashMap(); for (var p : placed) { for (var rc : p.cells) { int rr = rc[0], cc = rc[1]; @@ -83,7 +86,7 @@ public final class ExportFormat { } // 4) render gridv2 over cropped bounds (out-of-bounds become '#') - List gridv2 = new ArrayList<>(Math.max(0, maxR - minR + 1)); + var gridv2 = new ArrayList(Math.max(0, maxR - minR + 1)); for (var r = minR; r <= maxR; r++) { var row = new StringBuilder(Math.max(0, maxC - minC + 1)); for (var c = minC; c <= maxC; c++) { @@ -93,23 +96,17 @@ public final class ExportFormat { } // 5) words output with cropped coordinates - var wordsOut = new ArrayList(placed.size()); - for (var p : placed) { - wordsOut.add(new WordOut( - p.lemma, - p.word, - p.clue, // placeholder = word (same as JS) - p.startRow - minR, - p.startCol - minC, - p.direction, - p.word, // answer - p.arrowRow - minR, - p.arrowCol - minC, - p.isReversed, - p.lemma.simpel() - )); - } - + int MIN_R = minR, MIN_C = minC; + var wordsOut = placed.stream().map(p -> new WordOut( + p.lemma, + p.startRow - MIN_R, + p.startCol - MIN_C, + p.direction, + p.arrowRow - MIN_R, + p.arrowCol - MIN_C, + p.isReversed, + p.lemma.simpel() + )).toArray(WordOut[]::new); return new ExportedPuzzle(gridv2, wordsOut, difficulty, rewards); } @@ -117,8 +114,8 @@ public final class ExportFormat { * Convert a generator Slot + assigned word into a Placed object for export. */ private static Placed extractPlacedFromSlot(Slot s, Lemma lemma) { - int r = s.clueR(); - int c = s.clueC(); + int r = s.clueR(); + int c = s.clueC(); int d = s.dir(); List cells = new ArrayList<>(); @@ -131,7 +128,7 @@ public final class ExportFormat { String direction; boolean isReversed = false; - if (d ==2) { // right -> horizontal + if (d == 2) { // right -> horizontal direction = HORIZONTAL; startRow = cells.get(0)[0]; startCol = cells.get(0)[1]; @@ -163,12 +160,9 @@ public final class ExportFormat { return new Placed( lemma, - lemma.word(), - lemma.clue().toArray(String[]::new), startRow, startCol, direction, - lemma.word(), // answer arrowRow, arrowCol, cells, @@ -177,21 +171,41 @@ public final class ExportFormat { ); } - // pack (r,c) into one long key (handles negatives too) private static long pack(int r, int c) { return (((long) r) << 32) ^ (c & 0xFFFFFFFFL); } - /** - * @param direction "h" | "v" - * @param cells word cells - * @param arrow [arrowRow, arrowCol] */ - private record Placed(Lemma lemma, String word, String[] clue, int startRow, int startCol, String direction, String answer, int arrowRow, int arrowCol, List cells, - int[] arrow, - boolean isReversed) { } - - public record Rewards(int coins, int stars, int hints) { } - - /// @param direction "h" | "v" - public record WordOut(Lemma lemma, String word, String[] clue, int startRow, int startCol, String direction, String answer, int arrowRow, int arrowCol, boolean isReversed, - int complex) { } - - public record ExportedPuzzle(List gridv2, List words, int difficulty, Rewards rewards) { } + @Value @Accessors(fluent = true) @AllArgsConstructor + private static class Placed { + Lemma lemma; + int startRow, startCol; + String direction; + int arrowRow, arrowCol; + List cells; + int[] arrow; + boolean isReversed; + } + + @Value @Accessors(fluent = true) @AllArgsConstructor + public static class Rewards { + int coins, stars, hints; + } + + @Value @Accessors(fluent = true) @AllArgsConstructor + public static class WordOut { + Lemma lemma; + int startRow, startCol; + String direction; + int arrowRow, arrowCol; + boolean isReversed; + int complex; + + public String word() { return lemma().word(); } + public ArrayList clue() { return lemma.clue(); } + } + + @Value @Accessors(fluent = true) @AllArgsConstructor + public static class ExportedPuzzle { + List gridv2; + WordOut[] words; + int difficulty; + Rewards rewards; + } } diff --git a/src/main/java/puzzle/Main.java b/src/main/java/puzzle/Main.java index 62a7eee..7313afb 100644 --- a/src/main/java/puzzle/Main.java +++ b/src/main/java/puzzle/Main.java @@ -1,5 +1,6 @@ package puzzle; +import lombok.Data; import puzzle.SwedishGenerator.PuzzleResult; import puzzle.SwedishGenerator.Rng; @@ -13,6 +14,7 @@ import java.util.*; import java.util.concurrent.*; import java.util.stream.Collectors; +import static puzzle.ExportFormat.*; import static puzzle.SwedishGenerator.*; import static puzzle.SwedishGenerator.loadWords; @@ -28,8 +30,8 @@ public class Main { static final Path OUTPUT_PATH = PUZZLE_DIR.resolve(FILE_NAME); static final String DATE_STRING = now.toLocalDate().toString(); + @Data public static class Opts { - public int seed = (int) (System.nanoTime() ^ System.currentTimeMillis()); public int pop = 18; public int gens = 500; @@ -82,11 +84,11 @@ public class Main { section("Grid (human)"); System.out.print(indentLines(res.swe().renderHuman(res.filled().grid()), " ")); - var exported = ExportFormat.exportFormatFromFilled(res, 1, new ExportFormat.Rewards(50, 2, 1)); + var exported = exportFormatFromFilled(res, 1, new Rewards(50, 2, 1)); section("Clues"); info("status : generating..."); - info("generatedFor : " + exported.words().size()); + info("generatedFor : " + exported.words().length); info("status : done"); section("Words"); @@ -144,21 +146,20 @@ public class Main { private static String fmtPoint(int r, int c) { return String.format(Locale.ROOT, "(%d,%d)", r, c); } - private static void printWordsTable(List words) { + private static void printWordsTable(WordOut[] words) { System.out.println(" # WORD CX DIR START ARROW CLUE"); - var i = 1; - for (var w : words) { + for (int j = 0; j < words.length; j++) { + var w = words[j]; System.out.printf( Locale.ROOT, " %-2d %-12s %-4s %-3s %-9s %-9s %s%n", - i++, + j, safe(w.word(), 12), safe("" + w.complex(), 4), safe(w.direction(), 3), fmtPoint(w.startRow(), w.startCol()), fmtPoint(w.arrowRow(), w.arrowCol()), - w.clue() == null ? "" : Arrays.toString(w.clue()) - ); + Arrays.toString(w.lemma().clue().toArray(String[]::new))); } } @@ -168,7 +169,7 @@ public class Main { return s.substring(0, Math.max(0, max - 1)) + "…"; } - static String indentLines(String s, String indent) { + static String indentLines(String s, String indent) { if (s == null || s.isEmpty()) return ""; var lines = s.split("\\R", -1); var sb = new StringBuilder(); @@ -330,7 +331,7 @@ public class Main { // ---------------- Export (unchanged logic) ---------------- - private static String toJson(ExportFormat.ExportedPuzzle puzzle, String date, String theme) { + private static String toJson(ExportedPuzzle puzzle, String date, String theme) { var sb = new StringBuilder(); sb.append("{\n"); sb.append(" \"date\": \"").append(escapeJson(date)).append("\",\n"); @@ -349,21 +350,21 @@ public class Main { } sb.append(" ],\n"); sb.append(" \"words\": [\n"); - for (var i = 0; i < puzzle.words().size(); i++) { - var w = puzzle.words().get(i); - Arrays.sort(w.clue(), Comparator.comparingInt(String::length)); + for (var i = 0; i < puzzle.words().length; i++) { + var w = puzzle.words()[i]; + var clues = w. clue().toArray(String[]::new); + Arrays.sort(clues, Comparator.comparingInt(String::length)); sb.append(" {\n"); sb.append(" \"word\": \"").append(escapeJson(w.word())).append("\",\n"); - sb.append(" \"clue\": [").append(Arrays.stream(w.clue()).map(ss -> "\"" + escapeJson(ss) + "\"").collect(Collectors.joining(","))).append("],\n"); + sb.append(" \"clue\": [").append(Arrays.stream(clues).map(ss -> "\"" + escapeJson(ss) + "\"").collect(Collectors.joining(","))).append("],\n"); sb.append(" \"startRow\": ").append(w.startRow()).append(",\n"); sb.append(" \"startCol\": ").append(w.startCol()).append(",\n"); sb.append(" \"direction\": \"").append(escapeJson(w.direction())).append("\",\n"); - sb.append(" \"answer\": \"").append(escapeJson(w.answer())).append("\",\n"); sb.append(" \"arrowRow\": ").append(w.arrowRow()).append(",\n"); sb.append(" \"arrowCol\": ").append(w.arrowCol()).append(",\n"); sb.append(" \"isReversed\": ").append(w.isReversed()).append("\n"); sb.append(" }"); - if (i < puzzle.words().size() - 1) sb.append(","); + if (i < puzzle.words().length - 1) sb.append(","); sb.append("\n"); } sb.append(" ]\n"); diff --git a/src/main/java/puzzle/SwedishGenerator.java b/src/main/java/puzzle/SwedishGenerator.java index 134c209..8bd0b54 100644 --- a/src/main/java/puzzle/SwedishGenerator.java +++ b/src/main/java/puzzle/SwedishGenerator.java @@ -1,7 +1,8 @@ package puzzle; +import lombok.experimental.Accessors; +import lombok.*; import javax.naming.Context; -import javax.xml.crypto.Data; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -25,7 +26,7 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff) public static final char C_DASH = '\0'; static final byte _1 = 49, _9 = 57, A = 65, Z = 90, DASH = (byte) C_DASH; - record nbrs_8(int x, int y) { } + static record nbrs_8(int x, int y) { } public SwedishGenerator(int W, int H) { this(W, H, W * H, Math.min(W, H), new int[10000]); } public SwedishGenerator() { this(9, 8); } @@ -94,7 +95,7 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff) static final class Rng { - private int x; + @Getter private int x; Rng(int seed) { var s = seed; if (s == 0) s = 1; @@ -117,7 +118,7 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff) } static int clamp(int x, int a, int b) { return Math.max(a, Math.min(b, x)); } - static final record CandidateInfo(int[] indices, int count) { } + static record CandidateInfo(int[] indices, int count) { } record Grid(byte[] g, int W) { @@ -506,7 +507,6 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff) } // dead-end-ish letter cell (3+ walls) - for (var r = 0; r < H; r++) for (var c = 0; c < W; c++) { if (grid.isDigitAt(r, c)) continue; @@ -663,13 +663,10 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff) pop.sort(Comparator.comparingLong(g -> maskFitness(g, lenCounts))); return pop.get(0); } - record UndoPlace(int ur, int uc, char up) { } - // ---------------- Fill (CSP) ---------------- - record Undo(UndoPlace[] ur, int n) { } + @Data public static final class FillStats { - public long nodes; public long backtracks; public double seconds; @@ -680,7 +677,7 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff) CandidateInfo info, boolean done) { } - public static final record FillResult(boolean ok, + public static record FillResult(boolean ok, Grid grid, HashMap clueMap, FillStats stats,