Gather data
This commit is contained in:
@@ -2,13 +2,15 @@ package puzzle;
|
||||
|
||||
import puzzle.Main.PuzzleResult;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import static puzzle.SwedishGenerator.H;
|
||||
import static puzzle.SwedishGenerator.R;
|
||||
import static puzzle.SwedishGenerator.Lemma;
|
||||
import static puzzle.SwedishGenerator.SIZE;
|
||||
import static puzzle.SwedishGenerator.Slot;
|
||||
import static puzzle.SwedishGenerator.W;
|
||||
import static puzzle.SwedishGenerator.C;
|
||||
|
||||
/**
|
||||
* ExportFormat.java
|
||||
@@ -19,19 +21,34 @@ import static puzzle.SwedishGenerator.W;
|
||||
* - crops to bounding box (words + arrow cells) with 1-cell margin
|
||||
* - outputs gridv2 + words[] (+ difficulty, rewards)
|
||||
*/
|
||||
public final class ExportFormat {
|
||||
public record ExportFormat() {
|
||||
|
||||
record Bit(long[] bits) {
|
||||
|
||||
public Bit() { this(new long[(SIZE >> 6) + 1]); }
|
||||
static int wordIndex(int bitIndex) { return bitIndex >> 6; }
|
||||
public boolean get(int bitIndex) { return (this.bits[wordIndex(bitIndex)] & 1L << bitIndex) != 0L; }
|
||||
public void set(int bitIndex) { bits[wordIndex(bitIndex)] |= 1L << bitIndex; }
|
||||
public void clear(int bitIndex) { this.bits[wordIndex(bitIndex)] &= ~(1L << bitIndex); }
|
||||
public void clear() { Arrays.fill(bits, 0L); }
|
||||
}
|
||||
|
||||
record Bit1029(long[] bits) {
|
||||
|
||||
public Bit1029() { this(new long[1029]); }
|
||||
static int wordIndex(int bitIndex) { return bitIndex >> 6; }
|
||||
public boolean get(int bitIndex) { return (this.bits[wordIndex(bitIndex)] & 1L << bitIndex) != 0L; }
|
||||
public void set(int bitIndex) { bits[wordIndex(bitIndex)] |= 1L << bitIndex; }
|
||||
public void clear(int bitIndex) { this.bits[wordIndex(bitIndex)] &= ~(1L << bitIndex); }
|
||||
public void clear() { Arrays.fill(bits, 0L); }
|
||||
}
|
||||
|
||||
private ExportFormat() { }
|
||||
static final String HORIZONTAL = "h", VERTICAL = "v";
|
||||
private static boolean inBounds(int H, int W, int r, int c) { return r >= 0 && r < H && c >= 0 && c < W; }
|
||||
|
||||
// ---------- Public API ----------
|
||||
private static boolean inBounds(int r, int c) { return r >= 0 && r < SwedishGenerator.R && c >= 0 && c < SwedishGenerator.C; }
|
||||
|
||||
public static ExportedPuzzle exportFormatFromFilled(PuzzleResult puz, int difficulty, Rewards rewards) {
|
||||
Objects.requireNonNull(puz, "puz");
|
||||
var g = puz.filled().grid();
|
||||
|
||||
// 1) extract "placed" list from all clue digits in the filled grid
|
||||
var g = puz.filled().grid();
|
||||
var placed = new ArrayList<Placed>();
|
||||
var clueMap = puz.filled().clueMap();
|
||||
puz.swe().forEachSlot(g, (int key, long rs, long cs, int len) -> {
|
||||
@@ -44,10 +61,10 @@ public final class ExportFormat {
|
||||
|
||||
// If nothing placed: return full grid mapped to letters/# only
|
||||
if (placed.isEmpty()) {
|
||||
var gridv2 = new ArrayList<String>(H);
|
||||
for (var r = 0; r < H; r++) {
|
||||
var sb = new StringBuilder(W);
|
||||
for (var c = 0; c < W; c++) {
|
||||
var gridv2 = new ArrayList<String>(R);
|
||||
for (var r = 0; r < R; r++) {
|
||||
var sb = new StringBuilder(C);
|
||||
for (var c = 0; c < C; c++) {
|
||||
sb.append(g.isLetterAt(r, c) ? g.getCharAt(r, c) : '#');
|
||||
}
|
||||
gridv2.add(sb.toString());
|
||||
@@ -78,7 +95,7 @@ public final class ExportFormat {
|
||||
for (var p : placed) {
|
||||
for (var rc : p.cells) {
|
||||
int rr = rc[0], cc = rc[1];
|
||||
if (inBounds(H, W, rr, cc) && g.isLetterAt(rr, cc)) {
|
||||
if (inBounds(rr, cc) && g.isLetterAt(rr, cc)) {
|
||||
letterAt.put(pack(rr, cc), g.getCharAt(rr, cc));
|
||||
}
|
||||
}
|
||||
@@ -181,4 +198,5 @@ public final class ExportFormat {
|
||||
}
|
||||
|
||||
public record ExportedPuzzle(List<String> gridv2, WordOut[] words, int difficulty, Rewards rewards) { }
|
||||
|
||||
}
|
||||
|
||||
@@ -2,13 +2,14 @@ package puzzle;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import puzzle.ExportFormat.Bit;
|
||||
import puzzle.ExportFormat.Bit1029;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.BitSet;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
@@ -27,16 +28,17 @@ public record SwedishGenerator(int[] buff) {
|
||||
|
||||
record CandidateInfo(int[] indices, int count) { }
|
||||
|
||||
record nbrs_8(int x, int y) { }
|
||||
record nbrs_8(int r, int c) { }
|
||||
|
||||
record nbrs_16(int x, int y, int dx, int dy) { }
|
||||
record nbrs_16(int r, int c, int dr, int dc) { }
|
||||
|
||||
static final int W = Config.PUZZLE_COLS;
|
||||
static final double CROSS_Y = (W - 1) / 2.0;
|
||||
static final int H = Config.PUZZLE_ROWS;
|
||||
static final double CROSS_X = (H - 1) / 2.0;
|
||||
static final int SIZE = W * H;
|
||||
static final int MAX_WORD_LENGTH = Math.min(W, H);
|
||||
static final int C = Config.PUZZLE_COLS;
|
||||
static final double CROSS_Y = (C - 1) / 2.0;
|
||||
static final int R = Config.PUZZLE_ROWS;
|
||||
static final double CROSS_X = (R - 1) / 2.0;
|
||||
static final int SIZE = C * R;// ~18
|
||||
static final int TARGET_CLUES = SIZE >> 2;
|
||||
static final int MAX_WORD_LENGTH = Math.min(C, R);
|
||||
static final int MIN_LEN = Config.MIN_LEN;
|
||||
static final int CLUE_SIZE = Config.CLUE_SIZE;
|
||||
static final int SIMPLICITY_DEFAULT_SCORE = 2;
|
||||
@@ -52,18 +54,12 @@ public record SwedishGenerator(int[] buff) {
|
||||
// Directions for '1'..'6'
|
||||
static final nbrs_16[] OFFSETS = new nbrs_16[]{
|
||||
null,
|
||||
// 1: up
|
||||
new nbrs_16(-1, 0, -1, 0),
|
||||
// 2: right
|
||||
new nbrs_16(0, 1, 0, 1),
|
||||
// 3: down
|
||||
new nbrs_16(1, 0, 1, 0),
|
||||
// 4: left
|
||||
new nbrs_16(0, -1, 0, -1),
|
||||
// 5: vertical down, clue is on the right of the first letter
|
||||
new nbrs_16(0, -1, 1, 0),
|
||||
// 6: vertical down, clue is on the left of the first letter
|
||||
new nbrs_16(0, 1, 1, 0)
|
||||
new nbrs_16(-1, 0, -1, 0), // 1: up
|
||||
new nbrs_16(0, 1, 0, 1), // 2: right
|
||||
new nbrs_16(1, 0, 1, 0),// 3: down
|
||||
new nbrs_16(0, -1, 0, -1),// 4: left
|
||||
new nbrs_16(0, -1, 1, 0),// 5: vertical down, clue is on the right of the first letter
|
||||
new nbrs_16(0, 1, 1, 0)// 6: vertical down, clue is on the left of the first letter
|
||||
};
|
||||
final static nbrs_8[] nbrs8 = new nbrs_8[]{
|
||||
new nbrs_8(-1, -1),
|
||||
@@ -86,13 +82,13 @@ public record SwedishGenerator(int[] buff) {
|
||||
int[] covV,
|
||||
int[] cellCount,
|
||||
int[] stack,
|
||||
BitSet seen,
|
||||
Bit seen,
|
||||
char[] pattern,
|
||||
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],
|
||||
this(new int[SIZE], new int[SIZE], new int[SIZE], new int[SIZE], new Bit(), 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); }
|
||||
@@ -114,7 +110,7 @@ public record SwedishGenerator(int[] buff) {
|
||||
x = y;
|
||||
return y;
|
||||
}
|
||||
int randint(int min, int max) { // inclusive
|
||||
int randint(int min, int max) {
|
||||
var u = (nextU32() & 0xFFFFFFFFL);
|
||||
var range = (long) max - (long) min + 1L;
|
||||
return (int) (min + (u % range));
|
||||
@@ -124,8 +120,10 @@ public record SwedishGenerator(int[] buff) {
|
||||
|
||||
record Grid(byte[] g) {
|
||||
|
||||
public static int r(int offset) { return offset & 7; }
|
||||
public static int c(int offset) { return offset >> 3; }
|
||||
Grid deepCopyGrid() { return new Grid(g.clone()); }
|
||||
private int offset(int r, int c) { return r | (c << 3); }
|
||||
static int offset(int r, int c) { return r | (c << 3); }
|
||||
boolean isLettercell(int r, int c) { return (g[offset(r, c)] & 48) != 48; }
|
||||
char getCharAt(int r, int c) { return (char) (g[offset(r, c)]); }
|
||||
int digitAt(int r, int c) { return g[offset(r, c)] - 48; }
|
||||
@@ -133,6 +131,7 @@ public record SwedishGenerator(int[] buff) {
|
||||
void setCharAt(int r, int c, char ch) { g[offset(r, c)] = (byte) ch; }
|
||||
boolean isLetterAt(int r, int c) { return ((g[offset(r, c)] & 64) != 0); }
|
||||
boolean isDigitAt(int r, int c) { return (g[offset(r, c)] & 48) == 48; }
|
||||
boolean isDigitAt(int index) { return (g[index] & 48) == 48; }
|
||||
public double similarity(Grid b) {
|
||||
var same = 0;
|
||||
for (int i = 0; i < SIZE; i++) if (g[i] == b.g[i]) same++;
|
||||
@@ -143,18 +142,18 @@ public record SwedishGenerator(int[] buff) {
|
||||
|
||||
String gridToString(Grid g) {
|
||||
var sb = new StringBuilder();
|
||||
for (var r = 0; r < H; r++) {
|
||||
for (var r = 0; r < R; r++) {
|
||||
if (r > 0) sb.append('\n');
|
||||
for (var c = 0; c < W; c++) sb.append(g.getCharAt(r, c));
|
||||
for (var c = 0; c < C; c++) sb.append(g.getCharAt(r, c));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String renderHuman(Grid g) {
|
||||
var sb = new StringBuilder();
|
||||
for (var r = 0; r < H; r++) {
|
||||
for (var r = 0; r < R; r++) {
|
||||
if (r > 0) sb.append('\n');
|
||||
for (var c = 0; c < W; c++) {
|
||||
for (var c = 0; c < C; c++) {
|
||||
sb.append(g.isDigitAt(r, c) ? ' ' : g.getCharAt(r, c));
|
||||
}
|
||||
}
|
||||
@@ -352,24 +351,24 @@ public record SwedishGenerator(int[] buff) {
|
||||
}
|
||||
|
||||
void forEachSlot(Grid grid, SlotVisitor visitor) {
|
||||
for (var r = 0; r < H; r++) {
|
||||
for (var c = 0; c < W; c++) {
|
||||
for (var r = 0; r < R; r++) {
|
||||
for (var c = 0; c < C; c++) {
|
||||
if (!grid.isDigitAt(r, c)) continue;
|
||||
var d = grid.digitAt(r, c);
|
||||
var nbrs16 = OFFSETS[d];
|
||||
int rr = r + nbrs16.x, cc = c + nbrs16.y;
|
||||
int rr = r + nbrs16.r, cc = c + nbrs16.c;
|
||||
|
||||
if (rr < 0 || rr >= H || cc < 0 || cc >= W || grid.isDigitAt(rr, cc)) continue;
|
||||
if (rr < 0 || rr >= R || cc < 0 || cc >= C || grid.isDigitAt(rr, cc)) continue;
|
||||
long packedRs = 0;
|
||||
long packedCs = 0;
|
||||
var n = 0;
|
||||
|
||||
while (rr >= 0 && rr < H && cc >= 0 && cc < W && grid.isLettercell(rr, cc) && n < MAX_WORD_LENGTH) {
|
||||
while (rr >= 0 && rr < R && cc >= 0 && cc < C && grid.isLettercell(rr, cc) && n < MAX_WORD_LENGTH) {
|
||||
packedRs |= (long) rr << (n << 2);
|
||||
packedCs |= (long) cc << (n << 2);
|
||||
n++;
|
||||
rr += nbrs16.dx;
|
||||
cc += nbrs16.dy;
|
||||
rr += nbrs16.dr;
|
||||
cc += nbrs16.dc;
|
||||
}
|
||||
if (n > 0) {
|
||||
visitor.visit((r << 8) | (c << 4) | d, packedRs, packedCs, n);
|
||||
@@ -386,12 +385,12 @@ public record SwedishGenerator(int[] buff) {
|
||||
|
||||
boolean hasRoomForClue(Grid grid, int r, int c, char d) {
|
||||
var nbrs16 = OFFSETS[d - '0'];
|
||||
int rr = r + nbrs16.x, cc = c + nbrs16.y;
|
||||
int rr = r + nbrs16.r, cc = c + nbrs16.c;
|
||||
var run = 0;
|
||||
while (rr >= 0 && rr < H && cc >= 0 && cc < W && (grid.isLettercell(rr, cc)) && run < MAX_WORD_LENGTH) {
|
||||
while (rr >= 0 && rr < R && cc >= 0 && cc < C && (grid.isLettercell(rr, cc)) && run < MAX_WORD_LENGTH) {
|
||||
run++;
|
||||
rr += nbrs16.dx;
|
||||
cc += nbrs16.dy;
|
||||
rr += nbrs16.dr;
|
||||
cc += nbrs16.dc;
|
||||
if (run >= MIN_LEN) return true;
|
||||
}
|
||||
return false;
|
||||
@@ -401,10 +400,9 @@ public record SwedishGenerator(int[] buff) {
|
||||
long penalty = 0;
|
||||
|
||||
var clueCount = 0;
|
||||
for (var r = 0; r < H; r++) for (var c = 0; c < W; c++) if (grid.isDigitAt(r, c)) clueCount++;
|
||||
for (var r = 0; r < R; r++) for (var c = 0; c < C; c++) if (grid.isDigitAt(r, c)) clueCount++;
|
||||
|
||||
var targetClues = (int) Math.round(SIZE * 0.25); // ~18
|
||||
penalty += 8L * Math.abs(clueCount - targetClues);
|
||||
penalty += 8L * Math.abs(clueCount - TARGET_CLUES);
|
||||
|
||||
var ctx = CTX.get();
|
||||
var covH = ctx.covH;
|
||||
@@ -413,25 +411,25 @@ public record SwedishGenerator(int[] buff) {
|
||||
Arrays.fill(covV, 0, SIZE, 0);
|
||||
|
||||
boolean hasSlots = false;
|
||||
for (var r = 0; r < H; r++) {
|
||||
for (var c = 0; c < W; c++) {
|
||||
for (var r = 0; r < R; r++) {
|
||||
for (var c = 0; c < C; c++) {
|
||||
if (!grid.isDigitAt(r, c)) continue;
|
||||
var d = grid.digitAt(r, c);
|
||||
var nbrs16 = OFFSETS[d];
|
||||
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 + nbrs16.r, cc = c + nbrs16.c;
|
||||
if (rr < 0 || rr >= R || cc < 0 || cc >= C || grid.isDigitAt(rr, cc)) continue;
|
||||
|
||||
long packedRs = 0;
|
||||
long packedCs = 0;
|
||||
var n = 0;
|
||||
|
||||
while (rr >= 0 && rr < H && cc >= 0 && cc < W && n < MAX_WORD_LENGTH) {
|
||||
while (rr >= 0 && rr < R && cc >= 0 && cc < C && n < MAX_WORD_LENGTH) {
|
||||
if (grid.isDigitAt(rr, cc)) break;
|
||||
packedRs |= (long) rr << (n << 2);
|
||||
packedCs |= (long) cc << (n << 2);
|
||||
n++;
|
||||
rr += nbrs16.dx;
|
||||
cc += nbrs16.dy;
|
||||
rr += nbrs16.dr;
|
||||
cc += nbrs16.dc;
|
||||
}
|
||||
if (n == 0) continue;
|
||||
hasSlots = true;
|
||||
@@ -443,16 +441,16 @@ public record SwedishGenerator(int[] buff) {
|
||||
}
|
||||
|
||||
var horiz = Slot.horiz(d) ? covH : covV;
|
||||
for (var i = 0; i < n; i++) horiz[grid.offset(Slot.r(packedRs, i), Slot.c(packedCs, i))] += 1;
|
||||
for (var i = 0; i < n; i++) horiz[Grid.offset(Slot.r(packedRs, i), Slot.c(packedCs, i))] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasSlots) return 1_000_000_000L;
|
||||
|
||||
for (var r = 0; r < H; r++)
|
||||
for (var c = 0; c < W; c++) {
|
||||
for (var r = 0; r < R; r++)
|
||||
for (var c = 0; c < C; c++) {
|
||||
if (grid.isDigitAt(r, c)) continue;
|
||||
int idx = grid.offset(r, c);
|
||||
int idx = Grid.offset(r, c);
|
||||
int h = covH[idx], v = covV[idx];
|
||||
if (h == 0 && v == 0) penalty += 1500;
|
||||
else if (h > 0 && v > 0) { /* ok */ } else if (h + v == 1) penalty += 200;
|
||||
@@ -465,8 +463,8 @@ public record SwedishGenerator(int[] buff) {
|
||||
var stack = ctx.stack;
|
||||
int sp, idx;
|
||||
|
||||
for (var r = 0; r < H; r++)
|
||||
for (var c = 0; c < W; c++) {
|
||||
for (var r = 0; r < R; r++)
|
||||
for (var c = 0; c < C; c++) {
|
||||
idx = grid.offset(r, c);
|
||||
if (!grid.isDigitAt(r, c) || seen.get(idx)) continue;
|
||||
sp = 0;
|
||||
@@ -476,12 +474,12 @@ public record SwedishGenerator(int[] buff) {
|
||||
|
||||
while (sp > 0) {
|
||||
var p = stack[--sp];
|
||||
int x = p / W, y = p % W;
|
||||
int x = p / C, y = p % C;
|
||||
size++;
|
||||
|
||||
for (var d : nbrs8) {
|
||||
int nx = x + d.x, ny = y + d.y;
|
||||
if (nx < 0 || nx >= H || ny < 0 || ny >= W) continue;
|
||||
int nx = x + d.r, ny = y + d.c;
|
||||
if (nx < 0 || nx >= R || ny < 0 || ny >= C) continue;
|
||||
int nidx = grid.offset(nx, ny);
|
||||
if (seen.get(nidx)) continue;
|
||||
if (!grid.isDigitAt(nx, ny)) continue;
|
||||
@@ -494,13 +492,13 @@ public record SwedishGenerator(int[] buff) {
|
||||
}
|
||||
|
||||
// dead-end-ish letter cell (3+ walls)
|
||||
for (var r = 0; r < H; r++)
|
||||
for (var c = 0; c < W; c++) {
|
||||
for (var r = 0; r < R; r++)
|
||||
for (var c = 0; c < C; c++) {
|
||||
if (grid.isDigitAt(r, c)) continue;
|
||||
var walls = 0;
|
||||
for (var d : nbrs4) {
|
||||
int rr = r + d.x, cc = c + d.y;
|
||||
if (rr < 0 || rr >= H || cc < 0 || cc >= W) {
|
||||
int rr = r + d.r, cc = c + d.c;
|
||||
if (rr < 0 || rr >= R || cc < 0 || cc >= C) {
|
||||
walls++;
|
||||
continue;
|
||||
}
|
||||
@@ -520,8 +518,8 @@ public record SwedishGenerator(int[] buff) {
|
||||
int placed = 0, guard = 0;
|
||||
|
||||
while (placed < targetClues && guard++ < 4000) {
|
||||
var r = rng.randint(0, H - 1);
|
||||
var c = rng.randint(0, W - 1);
|
||||
var r = rng.randint(0, R - 1);
|
||||
var c = rng.randint(0, C - 1);
|
||||
if (g.isDigitAt(r, c)) continue;
|
||||
|
||||
var d = (char) ('0' + rng.randint(1, c == 0 ? CLUE_SIZE : 4));
|
||||
@@ -537,13 +535,13 @@ public record SwedishGenerator(int[] buff) {
|
||||
|
||||
Grid mutate(Rng rng, Grid grid) {
|
||||
var g = grid.deepCopyGrid();
|
||||
var cx = rng.randint(0, H - 1);
|
||||
var cy = rng.randint(0, W - 1);
|
||||
var cx = rng.randint(0, R - 1);
|
||||
var cy = rng.randint(0, C - 1);
|
||||
|
||||
var steps = 4;
|
||||
for (var k = 0; k < steps; k++) {
|
||||
var rr = clamp(cx + (rng.randint(-2, 2) + rng.randint(-2, 2)), 0, H - 1);
|
||||
var cc = clamp(cy + (rng.randint(-2, 2) + rng.randint(-2, 2)), 0, W - 1);
|
||||
var rr = clamp(cx + (rng.randint(-2, 2) + rng.randint(-2, 2)), 0, R - 1);
|
||||
var cc = clamp(cy + (rng.randint(-2, 2) + rng.randint(-2, 2)), 0, C - 1);
|
||||
|
||||
if (g.isDigitAt(rr, cc)) {
|
||||
g.setCharAt(rr, cc, C_DASH);
|
||||
@@ -562,13 +560,13 @@ public record SwedishGenerator(int[] buff) {
|
||||
var nx = Math.cos(theta);
|
||||
var ny = Math.sin(theta);
|
||||
|
||||
for (var r = 0; r < H; r++)
|
||||
for (var c = 0; c < W; c++) {
|
||||
for (var r = 0; r < R; r++)
|
||||
for (var c = 0; c < C; c++) {
|
||||
out.setCharAt(r, c, ((r - CROSS_X) * nx + (c - CROSS_Y) * ny >= 0) ? a.getCharAt(r, c) : b.getCharAt(r, c));
|
||||
}
|
||||
|
||||
for (var r = 0; r < H; r++)
|
||||
for (var c = 0; c < W; c++) {
|
||||
for (var r = 0; r < R; r++)
|
||||
for (var c = 0; c < C; c++) {
|
||||
if (out.isDigitAt(r, c) && !hasRoomForClue(out, r, c, out.getCharAt(r, c))) out.setCharAt(r, c, C_DASH);
|
||||
}
|
||||
return out;
|
||||
@@ -648,6 +646,7 @@ public record SwedishGenerator(int[] buff) {
|
||||
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<Grid>();
|
||||
@@ -734,7 +733,7 @@ public record SwedishGenerator(int[] buff) {
|
||||
|
||||
static int slotScore(int[] cellCount, Slot s, Grid grid) {
|
||||
var cross = 0;
|
||||
for (var i = 0; i < s.len(); i++) cross += (cellCount[grid.offset(s.r(i), s.c(i))] - 1);
|
||||
for (var i = 0; i < s.len(); i++) cross += (cellCount[Grid.offset(s.r(i), s.c(i))] - 1);
|
||||
return cross * 10 + s.len();
|
||||
}
|
||||
|
||||
@@ -767,13 +766,13 @@ public record SwedishGenerator(int[] buff) {
|
||||
var grid = mask.deepCopyGrid();
|
||||
var slots = extractSlots(grid);
|
||||
|
||||
var used = new BitSet(SIZE << 1);
|
||||
var used = new Bit1029();
|
||||
var assigned = new HashMap<Integer, Lemma>();
|
||||
|
||||
var ctx = CTX.get();
|
||||
var cellCount = ctx.cellCount;
|
||||
Arrays.fill(cellCount, 0, SIZE, 0);
|
||||
for (var s : slots) for (var i = 0; i < s.len(); i++) cellCount[grid.offset(s.r(i), s.c(i))]++;
|
||||
for (var s : slots) for (var i = 0; i < s.len(); i++) cellCount[Grid.offset(s.r(i), s.c(i))]++;
|
||||
|
||||
var t0 = System.currentTimeMillis();
|
||||
final var lastLog = new AtomicLong(t0);
|
||||
@@ -894,7 +893,7 @@ public record SwedishGenerator(int[] buff) {
|
||||
if (backtrack(depth + 1)) return true;
|
||||
|
||||
assigned.remove(k);
|
||||
used.set(w.index, false);
|
||||
used.clear(w.index);
|
||||
undoPlace(grid, ctx.undoBuffer, undoOffset, nPlaced);
|
||||
}
|
||||
stats.backtracks++;
|
||||
@@ -933,7 +932,7 @@ public record SwedishGenerator(int[] buff) {
|
||||
if (backtrack(depth + 1)) return true;
|
||||
|
||||
assigned.remove(k);
|
||||
used.set(w.index, false);
|
||||
used.clear(w.index);
|
||||
undoPlace(grid, ctx.undoBuffer, undoOffset, nPlaced);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user