diff --git a/src/main/java/puzzle/SwedishGenerator.java b/src/main/java/puzzle/SwedishGenerator.java index 02ffd12..90ff8e6 100644 --- a/src/main/java/puzzle/SwedishGenerator.java +++ b/src/main/java/puzzle/SwedishGenerator.java @@ -1,5 +1,6 @@ package puzzle; +import javax.naming.Context; import javax.xml.crypto.Data; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -54,7 +55,7 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff) OFFSETS[6] = new nbrs_8(0, 1); STEPS[6] = new nbrs_8(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), @@ -64,15 +65,26 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff) new nbrs_8(1, 0), new nbrs_8(1, 1) }; - static final 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), new nbrs_8(0, 1) }; - static final char FIRST_ABC = 'A'; - static final char LAST_ABC = 'Z'; - static final char FIRST_ARROW = '1', LAST_ARROW = '6', HOR_ARROW_1 = '2', HOR_ARROW_2 = '4'; + static final char FIRST_ABC = 'A'; + static final char LAST_ABC = 'Z'; + + static record Context(int[] covH, + int[] covV, + int[] cellCount, + int[] stack, + BitSet seen) { + + public Context() { this(new int[256], new int[256], new int[256], new int[256], new BitSet(256)); } + } + + static final ThreadLocal CTX = ThreadLocal.withInitial(Context::new); + static boolean isLetter(char ch) { return ch >= FIRST_ABC && ch <= LAST_ABC; } static final class Rng { @@ -368,8 +380,11 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff) var slots = extractSlots(grid); if (slots.isEmpty()) return 1_000_000_000L; - var covH = new int[H][W]; - var covV = new int[H][W]; + var ctx = CTX.get(); + var covH = ctx.covH; + var covV = ctx.covV; + Arrays.fill(covH, 0, SIZE, 0); + Arrays.fill(covV, 0, SIZE, 0); for (var s : slots) { if (s.len < MIN_LEN) { @@ -384,24 +399,27 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff) } for (var i = 0; i < s.len; i++) { - int r = s.r(i), c = s.c(i); - if (s.horiz()) covH[r][c] += 1; - else covV[r][c] += 1; + int r = s.r(i), c = s.c(i); + int idx = grid.offset(r, c); + if (s.horiz()) covH[idx] += 1; + else covV[idx] += 1; } } for (var r = 0; r < H; r++) for (var c = 0; c < W; c++) { if (grid.isDigitAt(r, c)) continue; - int h = covH[r][c], v = covV[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; else penalty += 600; } // clue clustering (8-connected) - var seen = new BitSet(8); - var stack = new int[SIZE]; + var seen = ctx.seen; + seen.clear(); + var stack = ctx.stack; int sp, idx; for (var r = 0; r < H; r++) @@ -632,9 +650,9 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff) return pat; } - static int slotScore(int[][] cellCount, Slot s) { + static int slotScore(int[] cellCount, Slot s, Grid grid) { var cross = 0; - for (var i = 0; i < s.len; i++) cross += (cellCount[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; } @@ -674,8 +692,10 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff) var used = new BitSet(); var assigned = new HashMap(); - var cellCount = new int[H][W]; - for (var s : slots) for (var i = 0; i < s.len; i++) cellCount[s.r(i)][s.c(i)]++; + 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))]++; var t0 = System.currentTimeMillis(); final var lastLog = new java.util.concurrent.atomic.AtomicLong(t0); @@ -727,7 +747,7 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff) if (best == null || info.count < bestInfo.count - || (info.count == bestInfo.count && slotScore(cellCount, s) > slotScore(cellCount, best))) { + || (info.count == bestInfo.count && slotScore(cellCount, s, grid) > slotScore(cellCount, best, grid))) { best = s; bestInfo = info; if (info.count <= 1) break; @@ -740,7 +760,7 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff) return new Pick(best, bestInfo, false); } }; - IO.println("hit"); + System.out.println("hit"); class Solver { @@ -766,10 +786,6 @@ public record SwedishGenerator(int W, int H, int SIZE, int MAX_LEN, int[] buff) var pat = patternForSlot(grid, s); Predicate tryWord = (Lemma w) -> { - if (w == null) { - IO.println("tryword null Error"); - return false; - } if (used.get(w.index())) return false; for (var i = 0; i < pat.length; i++) {