initial commit
This commit is contained in:
@@ -1,3 +1,3 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
mkdir -p target
|
mkdir -p ~/dev/.target
|
||||||
javac -d target src/SwedishGenerator.java
|
javac -d ~/dev/.target src/puzzle/*.java
|
||||||
|
|||||||
2
run.sh
2
run.sh
@@ -1,2 +1,2 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
java -cp target SwedishGenerator "$@"
|
java -cp ~/dev/.target puzzle.Main "$@"
|
||||||
|
|||||||
329
src/puzzle/ExportFormat.java
Normal file
329
src/puzzle/ExportFormat.java
Normal file
@@ -0,0 +1,329 @@
|
|||||||
|
package puzzle;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ExportFormat.java
|
||||||
|
*
|
||||||
|
* Direct port of export_format.js:
|
||||||
|
* - scans filled grid for clue digits '1'..'4'
|
||||||
|
* - extracts placed words in canonical direction (horizontal=right, vertical=down)
|
||||||
|
* - crops to bounding box (words + arrow cells) with 1-cell margin
|
||||||
|
* - outputs gridv2 + words[] (+ difficulty, rewards)
|
||||||
|
*/
|
||||||
|
public final class ExportFormat {
|
||||||
|
|
||||||
|
private ExportFormat() { }
|
||||||
|
|
||||||
|
// Directions for digits '1'..'4'
|
||||||
|
private static final int[][] DIRS = new int[5][2];
|
||||||
|
static {
|
||||||
|
DIRS[1] = new int[]{ -1, 0 }; // up
|
||||||
|
DIRS[2] = new int[]{ 0, 1 }; // right
|
||||||
|
DIRS[3] = new int[]{ 1, 0 }; // down
|
||||||
|
DIRS[4] = new int[]{ 0, -1 }; // left
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isDigit(char ch) { return ch >= '1' && ch <= '4'; }
|
||||||
|
private static boolean isLetter(char ch) { return ch >= 'A' && ch <= 'Z'; }
|
||||||
|
|
||||||
|
private static boolean inBounds(int H, int W, int r, int c) {
|
||||||
|
return r >= 0 && r < H && c >= 0 && c < W;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Public API ----------
|
||||||
|
|
||||||
|
public static ExportedPuzzle exportFormatFromFilled(SwedishGenerator.PuzzleResult puz) {
|
||||||
|
return exportFormatFromFilled(puz, 1, new Rewards(50, 2, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ExportedPuzzle exportFormatFromFilled(SwedishGenerator.PuzzleResult puz, int difficulty, Rewards rewards) {
|
||||||
|
Objects.requireNonNull(puz, "puz");
|
||||||
|
char[][] g = puz.filled.grid;
|
||||||
|
int H = g.length;
|
||||||
|
int W = g[0].length;
|
||||||
|
|
||||||
|
// 1) extract "placed" list from all clue digits in the filled grid
|
||||||
|
List<Placed> placed = new ArrayList<>();
|
||||||
|
Set<String> seen = new HashSet<>();
|
||||||
|
|
||||||
|
for (int r = 0; r < H; r++) {
|
||||||
|
for (int c = 0; c < W; c++) {
|
||||||
|
char ch = g[r][c];
|
||||||
|
if (!isDigit(ch)) continue;
|
||||||
|
|
||||||
|
Placed p = extractPlacedFromClue(g, r, c, ch, 8, 2);
|
||||||
|
if (p == null) continue;
|
||||||
|
|
||||||
|
String key = p.startRow + "," + p.startCol + ":" + p.direction + ":" + p.word;
|
||||||
|
if (seen.contains(key)) continue;
|
||||||
|
seen.add(key);
|
||||||
|
placed.add(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If nothing placed: return full grid mapped to letters/# only
|
||||||
|
if (placed.isEmpty()) {
|
||||||
|
List<String> gridv2 = new ArrayList<>(H);
|
||||||
|
for (int r = 0; r < H; r++) {
|
||||||
|
StringBuilder sb = new StringBuilder(W);
|
||||||
|
for (int c = 0; c < W; c++) {
|
||||||
|
char ch = g[r][c];
|
||||||
|
sb.append(isLetter(ch) ? ch : '#');
|
||||||
|
}
|
||||||
|
gridv2.add(sb.toString());
|
||||||
|
}
|
||||||
|
return new ExportedPuzzle(gridv2, List.of(), difficulty, rewards);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) bounding box around all word cells + arrow cells, with 1-cell margin
|
||||||
|
List<int[]> allCells = new ArrayList<>();
|
||||||
|
for (Placed p : placed) {
|
||||||
|
allCells.addAll(p.cells);
|
||||||
|
allCells.add(p.arrow);
|
||||||
|
}
|
||||||
|
|
||||||
|
int minR = Integer.MAX_VALUE, minC = Integer.MAX_VALUE;
|
||||||
|
int maxR = Integer.MIN_VALUE, maxC = Integer.MIN_VALUE;
|
||||||
|
|
||||||
|
for (int[] rc : allCells) {
|
||||||
|
int rr = rc[0], cc = rc[1];
|
||||||
|
minR = Math.min(minR, rr);
|
||||||
|
minC = Math.min(minC, cc);
|
||||||
|
maxR = Math.max(maxR, rr);
|
||||||
|
maxC = Math.max(maxC, cc);
|
||||||
|
}
|
||||||
|
|
||||||
|
minR -= 1;
|
||||||
|
minC -= 1;
|
||||||
|
maxR += 1;
|
||||||
|
maxC += 1;
|
||||||
|
|
||||||
|
// 3) map of only used letter cells (everything else becomes '#')
|
||||||
|
Map<Long, Character> letterAt = new HashMap<>();
|
||||||
|
for (Placed p : placed) {
|
||||||
|
for (int[] rc : p.cells) {
|
||||||
|
int rr = rc[0], cc = rc[1];
|
||||||
|
if (inBounds(H, W, rr, cc) && isLetter(g[rr][cc])) {
|
||||||
|
letterAt.put(pack(rr, cc), g[rr][cc]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4) render gridv2 over cropped bounds (out-of-bounds become '#')
|
||||||
|
List<String> gridv2 = new ArrayList<>(Math.max(0, maxR - minR + 1));
|
||||||
|
for (int r = minR; r <= maxR; r++) {
|
||||||
|
StringBuilder row = new StringBuilder(Math.max(0, maxC - minC + 1));
|
||||||
|
for (int c = minC; c <= maxC; c++) {
|
||||||
|
Character ch = letterAt.get(pack(r, c));
|
||||||
|
row.append(ch != null ? ch : '#');
|
||||||
|
}
|
||||||
|
gridv2.add(row.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5) words output with cropped coordinates
|
||||||
|
List<WordOut> wordsOut = new ArrayList<>(placed.size());
|
||||||
|
for (Placed p : placed) {
|
||||||
|
wordsOut.add(new WordOut(
|
||||||
|
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
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ExportedPuzzle(gridv2, wordsOut, difficulty, rewards);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract a word run for a clue cell at (r,c) with direction digit d.
|
||||||
|
* Canonical output:
|
||||||
|
* - direction: "horizontal" (right) or "vertical" (down)
|
||||||
|
* - startRow/startCol: first letter cell in canonical direction
|
||||||
|
* - arrowRow/arrowCol: immediately before the start (left or above)
|
||||||
|
* - word read from grid in canonical order
|
||||||
|
*/
|
||||||
|
private static Placed extractPlacedFromClue(char[][] g, int r, int c, char d, int maxLen, int minLen) {
|
||||||
|
int H = g.length, W = g[0].length;
|
||||||
|
int di = d - '0';
|
||||||
|
int dr = DIRS[di][0], dc = DIRS[di][1];
|
||||||
|
|
||||||
|
// collect letter cells in ORIGINAL direction away from the clue
|
||||||
|
List<int[]> cells = new ArrayList<>();
|
||||||
|
int rr = r + dr, cc = c + dc;
|
||||||
|
while (inBounds(H, W, rr, cc) && isLetter(g[rr][cc]) && cells.size() < maxLen) {
|
||||||
|
cells.add(new int[]{ rr, cc });
|
||||||
|
rr += dr;
|
||||||
|
cc += dc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cells.size() < minLen) return null;
|
||||||
|
|
||||||
|
// Canonicalize: always output right/down
|
||||||
|
int startRow, startCol, arrowRow, arrowCol;
|
||||||
|
String direction;
|
||||||
|
|
||||||
|
if (d == '2') { // right -> horizontal
|
||||||
|
direction = "horizontal";
|
||||||
|
startRow = cells.get(0)[0];
|
||||||
|
startCol = cells.get(0)[1];
|
||||||
|
arrowRow = r;
|
||||||
|
arrowCol = c;
|
||||||
|
} else if (d == '3') { // down -> vertical
|
||||||
|
direction = "vertical";
|
||||||
|
startRow = cells.get(0)[0];
|
||||||
|
startCol = cells.get(0)[1];
|
||||||
|
arrowRow = r;
|
||||||
|
arrowCol = c;
|
||||||
|
} else if (d == '4') { // left -> canonical right
|
||||||
|
direction = "horizontal";
|
||||||
|
int[] farLeft = cells.get(cells.size() - 1);
|
||||||
|
startRow = farLeft[0];
|
||||||
|
startCol = farLeft[1];
|
||||||
|
arrowRow = startRow;
|
||||||
|
arrowCol = startCol - 1;
|
||||||
|
} else if (d == '1') { // up -> canonical down
|
||||||
|
direction = "vertical";
|
||||||
|
int[] topMost = cells.get(cells.size() - 1);
|
||||||
|
startRow = topMost[0];
|
||||||
|
startCol = topMost[1];
|
||||||
|
arrowRow = startRow - 1;
|
||||||
|
arrowCol = startCol;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read word from grid in canonical order (right/down)
|
||||||
|
StringBuilder wordChars = new StringBuilder();
|
||||||
|
if ("horizontal".equals(direction)) {
|
||||||
|
for (int i = 0; i < cells.size(); i++) {
|
||||||
|
int cc2 = startCol + i;
|
||||||
|
char ch = (inBounds(H, W, startRow, cc2) ? g[startRow][cc2] : '#');
|
||||||
|
if (!isLetter(ch)) break;
|
||||||
|
wordChars.append(ch);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < cells.size(); i++) {
|
||||||
|
int rr2 = startRow + i;
|
||||||
|
char ch = (inBounds(H, W, rr2, startCol) ? g[rr2][startCol] : '#');
|
||||||
|
if (!isLetter(ch)) break;
|
||||||
|
wordChars.append(ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String word = wordChars.toString();
|
||||||
|
if (word.length() < minLen || word.length() > maxLen) return null;
|
||||||
|
|
||||||
|
// Build exact used cells (only for actual word length)
|
||||||
|
List<int[]> used = new ArrayList<>(word.length());
|
||||||
|
if ("horizontal".equals(direction)) {
|
||||||
|
for (int i = 0; i < word.length(); i++) used.add(new int[]{ startRow, startCol + i });
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < word.length(); i++) used.add(new int[]{ startRow + i, startCol });
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Placed(
|
||||||
|
word,
|
||||||
|
word, // clue placeholder (same as JS)
|
||||||
|
startRow,
|
||||||
|
startCol,
|
||||||
|
direction,
|
||||||
|
word, // answer
|
||||||
|
arrowRow,
|
||||||
|
arrowCol,
|
||||||
|
used,
|
||||||
|
new int[]{ arrowRow, arrowCol }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// pack (r,c) into one long key (handles negatives too)
|
||||||
|
private static long pack(int r, int c) {
|
||||||
|
return (((long) r) << 32) ^ (c & 0xFFFFFFFFL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Data models ----------
|
||||||
|
|
||||||
|
private static final class Placed {
|
||||||
|
|
||||||
|
final String word;
|
||||||
|
final String clue;
|
||||||
|
final int startRow, startCol;
|
||||||
|
final String direction; // "horizontal" | "vertical"
|
||||||
|
final String answer;
|
||||||
|
final int arrowRow, arrowCol;
|
||||||
|
final List<int[]> cells; // word cells
|
||||||
|
final int[] arrow; // [arrowRow, arrowCol]
|
||||||
|
|
||||||
|
Placed(String word, String clue, int startRow, int startCol, String direction, String answer,
|
||||||
|
int arrowRow, int arrowCol, List<int[]> cells, int[] arrow) {
|
||||||
|
this.word = word;
|
||||||
|
this.clue = clue;
|
||||||
|
this.startRow = startRow;
|
||||||
|
this.startCol = startCol;
|
||||||
|
this.direction = direction;
|
||||||
|
this.answer = answer;
|
||||||
|
this.arrowRow = arrowRow;
|
||||||
|
this.arrowCol = arrowCol;
|
||||||
|
this.cells = cells;
|
||||||
|
this.arrow = arrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Rewards {
|
||||||
|
|
||||||
|
public final int coins;
|
||||||
|
public final int stars;
|
||||||
|
public final int hints;
|
||||||
|
|
||||||
|
public Rewards(int coins, int stars, int hints) {
|
||||||
|
this.coins = coins;
|
||||||
|
this.stars = stars;
|
||||||
|
this.hints = hints;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class WordOut {
|
||||||
|
|
||||||
|
public final String word;
|
||||||
|
public final String clue;
|
||||||
|
public final int startRow;
|
||||||
|
public final int startCol;
|
||||||
|
public final String direction; // "horizontal" | "vertical"
|
||||||
|
public final String answer;
|
||||||
|
public final int arrowRow;
|
||||||
|
public final int arrowCol;
|
||||||
|
|
||||||
|
public WordOut(String word, String clue, int startRow, int startCol, String direction,
|
||||||
|
String answer, int arrowRow, int arrowCol) {
|
||||||
|
this.word = word;
|
||||||
|
this.clue = clue;
|
||||||
|
this.startRow = startRow;
|
||||||
|
this.startCol = startCol;
|
||||||
|
this.direction = direction;
|
||||||
|
this.answer = answer;
|
||||||
|
this.arrowRow = arrowRow;
|
||||||
|
this.arrowCol = arrowCol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class ExportedPuzzle {
|
||||||
|
|
||||||
|
public final List<String> gridv2;
|
||||||
|
public final List<WordOut> words;
|
||||||
|
public final int difficulty;
|
||||||
|
public final Rewards rewards;
|
||||||
|
|
||||||
|
public ExportedPuzzle(List<String> gridv2, List<WordOut> words, int difficulty, Rewards rewards) {
|
||||||
|
this.gridv2 = gridv2;
|
||||||
|
this.words = words;
|
||||||
|
this.difficulty = difficulty;
|
||||||
|
this.rewards = rewards;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Tiny demo (optional) ----------
|
||||||
|
|
||||||
|
}
|
||||||
72
src/puzzle/Main.java
Normal file
72
src/puzzle/Main.java
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
package puzzle;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
// ---------------- CLI ----------------
|
||||||
|
|
||||||
|
public static class Opts {
|
||||||
|
public int seed = 1;
|
||||||
|
public int pop = 18;
|
||||||
|
public int gens = 100;
|
||||||
|
public int tries = 50;
|
||||||
|
public String wordsPath = "./word-list.txt";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usage() {
|
||||||
|
System.out.println("""
|
||||||
|
Usage:
|
||||||
|
java SwedishGenerator [--seed N] [--pop N] [--gens N] [--tries N] [--words word-list.txt]
|
||||||
|
|
||||||
|
Defaults:
|
||||||
|
--seed 1
|
||||||
|
--pop 18
|
||||||
|
--gens 100
|
||||||
|
--tries 50
|
||||||
|
--words ./word-list.txt
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
|
||||||
|
static Opts parseArgs(String[] argv) {
|
||||||
|
var out = new Opts();
|
||||||
|
for (int i = 0; i < argv.length; i++) {
|
||||||
|
String a = argv[i];
|
||||||
|
String v = (i + 1 < argv.length) ? argv[i + 1] : null;
|
||||||
|
if (a.equals("--help") || a.equals("-h")) {
|
||||||
|
usage();
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
if (a.equals("--seed")) { out.seed = Integer.parseInt(v); i++; }
|
||||||
|
else if (a.equals("--pop")) { out.pop = Integer.parseInt(v); i++; }
|
||||||
|
else if (a.equals("--gens")) { out.gens = Integer.parseInt(v); i++; }
|
||||||
|
else if (a.equals("--tries")) { out.tries = Integer.parseInt(v); i++; }
|
||||||
|
else if (a.equals("--words")) { out.wordsPath = v; i++; }
|
||||||
|
else throw new IllegalArgumentException("Unknown arg: " + a);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
var opts = parseArgs(args);
|
||||||
|
var res = SwedishGenerator.generatePuzzle(opts);
|
||||||
|
if (res == null) {
|
||||||
|
System.out.println("No solution found within tries.");
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("\n=== GENERATED MASK ===");
|
||||||
|
System.out.println(SwedishGenerator.gridToString(res.mask));
|
||||||
|
|
||||||
|
System.out.println("\n=== FILLED PUZZLE (RAW) ===");
|
||||||
|
System.out.println(SwedishGenerator.gridToString(res.filled.grid));
|
||||||
|
|
||||||
|
System.out.println("\n=== FILLED PUZZLE (HUMAN) ===");
|
||||||
|
System.out.println(SwedishGenerator.renderHuman(res.filled.grid));
|
||||||
|
var out = ExportFormat.exportFormatFromFilled(res, 1, new ExportFormat.Rewards(50, 2, 1));
|
||||||
|
System.out.println("gridv2:");
|
||||||
|
for (String row : out.gridv2) System.out.println(row);
|
||||||
|
System.out.println("words: " + out.words.size());
|
||||||
|
for (var w : out.words) {
|
||||||
|
System.out.printf("%s %s start=(%d,%d) arrow=(%d,%d)%n",
|
||||||
|
w.word, w.direction, w.startRow, w.startCol, w.arrowRow, w.arrowCol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
package puzzle;
|
||||||
|
|
||||||
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;
|
||||||
@@ -29,49 +31,7 @@ public class SwedishGenerator {
|
|||||||
static boolean isLetter(char ch) { return ch >= 'A' && ch <= 'Z'; }
|
static boolean isLetter(char ch) { return ch >= 'A' && ch <= 'Z'; }
|
||||||
static boolean isLetterCell(char ch) { return ch == '#' || isLetter(ch); }
|
static boolean isLetterCell(char ch) { return ch == '#' || isLetter(ch); }
|
||||||
|
|
||||||
// ---------------- CLI ----------------
|
|
||||||
|
|
||||||
static class Opts {
|
|
||||||
int seed = 1;
|
|
||||||
int pop = 18;
|
|
||||||
int gens = 100;
|
|
||||||
int tries = 50;
|
|
||||||
String wordsPath = "./word-list.txt";
|
|
||||||
}
|
|
||||||
|
|
||||||
static void usage() {
|
|
||||||
System.out.println("""
|
|
||||||
Usage:
|
|
||||||
java SwedishGenerator [--seed N] [--pop N] [--gens N] [--tries N] [--words word-list.txt]
|
|
||||||
|
|
||||||
Defaults:
|
|
||||||
--seed 1
|
|
||||||
--pop 18
|
|
||||||
--gens 100
|
|
||||||
--tries 50
|
|
||||||
--words ./word-list.txt
|
|
||||||
""");
|
|
||||||
}
|
|
||||||
|
|
||||||
static SwedishGenerator.Opts parseArgs(String[] argv) {
|
|
||||||
var out = new SwedishGenerator.Opts();
|
|
||||||
for (int i = 0; i < argv.length; i++) {
|
|
||||||
String a = argv[i];
|
|
||||||
String v = (i + 1 < argv.length) ? argv[i + 1] : null;
|
|
||||||
if (a.equals("--help") || a.equals("-h")) {
|
|
||||||
usage();
|
|
||||||
System.exit(0);
|
|
||||||
}
|
|
||||||
if (a.equals("--seed")) { out.seed = Integer.parseInt(v); i++; }
|
|
||||||
else if (a.equals("--pop")) { out.pop = Integer.parseInt(v); i++; }
|
|
||||||
else if (a.equals("--gens")) { out.gens = Integer.parseInt(v); i++; }
|
|
||||||
else if (a.equals("--tries")) { out.tries = Integer.parseInt(v); i++; }
|
|
||||||
else if (a.equals("--words")) { out.wordsPath = v; i++; }
|
|
||||||
else throw new IllegalArgumentException("Unknown arg: " + a);
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------- RNG (xorshift32) ----------------
|
// ---------------- RNG (xorshift32) ----------------
|
||||||
|
|
||||||
static final class Rng {
|
static final class Rng {
|
||||||
@@ -558,18 +518,18 @@ public class SwedishGenerator {
|
|||||||
|
|
||||||
// ---------------- Fill (CSP) ----------------
|
// ---------------- Fill (CSP) ----------------
|
||||||
|
|
||||||
static final class FillStats {
|
public static final class FillStats {
|
||||||
long nodes;
|
public long nodes;
|
||||||
long backtracks;
|
public long backtracks;
|
||||||
double seconds;
|
public double seconds;
|
||||||
int lastMRV;
|
public int lastMRV;
|
||||||
}
|
}
|
||||||
|
|
||||||
static final class FillResult {
|
public static final class FillResult {
|
||||||
boolean ok;
|
public boolean ok;
|
||||||
char[][] grid;
|
public char[][] grid;
|
||||||
HashMap<String, String> clueMap;
|
public HashMap<String, String> clueMap;
|
||||||
FillStats stats;
|
public FillStats stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
static final class Undo {
|
static final class Undo {
|
||||||
@@ -825,12 +785,12 @@ public class SwedishGenerator {
|
|||||||
|
|
||||||
// ---------------- Top-level generatePuzzle ----------------
|
// ---------------- Top-level generatePuzzle ----------------
|
||||||
|
|
||||||
static final class PuzzleResult {
|
public static final class PuzzleResult {
|
||||||
char[][] mask;
|
public char[][] mask;
|
||||||
FillResult filled;
|
public FillResult filled;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SwedishGenerator.PuzzleResult generatePuzzle(SwedishGenerator.Opts opts) {
|
public static PuzzleResult generatePuzzle(Main.Opts opts) {
|
||||||
var rng = new Rng(opts.seed);
|
var rng = new Rng(opts.seed);
|
||||||
|
|
||||||
var tLoad0 = System.nanoTime();
|
var tLoad0 = System.nanoTime();
|
||||||
@@ -863,8 +823,7 @@ public class SwedishGenerator {
|
|||||||
|
|
||||||
// ---------------- main ----------------
|
// ---------------- main ----------------
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void convert(Main.Opts opts) {
|
||||||
var opts = parseArgs(args);
|
|
||||||
|
|
||||||
var res = generatePuzzle(opts);
|
var res = generatePuzzle(opts);
|
||||||
if (res == null) {
|
if (res == null) {
|
||||||
Reference in New Issue
Block a user