diff --git a/src/main/java/puzzle/SwedishGenerator.java b/src/main/java/puzzle/SwedishGenerator.java index 5531710..fb85996 100644 --- a/src/main/java/puzzle/SwedishGenerator.java +++ b/src/main/java/puzzle/SwedishGenerator.java @@ -121,10 +121,9 @@ 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()); } + public static int c(int offset) { return offset >>> 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; } + Grid deepCopyGrid() { return new Grid(g.clone()); } char getCharAt(int r, int c) { return (char) (g[offset(r, c)]); } int digitAt(int r, int c) { return g[offset(r, c)] - 48; } byte byteAt(int r, int c) { return g[offset(r, c)]; } @@ -132,6 +131,9 @@ public record SwedishGenerator(int[] buff) { 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; } + static boolean isDigit(byte b) { return (b & 48) == 48; } + boolean isLettercell(int r, int c) { return (g[offset(r, c)] & 48) != 48; } + boolean isLetterAt(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++; @@ -327,6 +329,10 @@ public record SwedishGenerator(int[] buff) { } static record Slot(int key, long rs, long cs, int len) { + static Slot from(int key, long rs, long cs, int len) { + return new Slot(key, rs, cs, len); + } + //public int len() { return (int) (Long.highestOneBit(rs | cs) >> 2); } public int clueR() { return (key >> 8) & 15; } public int clueC() { return (key >> 4) & 15; } @@ -400,7 +406,7 @@ public record SwedishGenerator(int[] buff) { long penalty = 0; var clueCount = 0; - for (var r = 0; r < R; r++) for (var c = 0; c < C; c++) if (grid.isDigitAt(r, c)) clueCount++; + for (var v : grid.g) if (Grid.isDigit(v)) clueCount++; penalty += 8L * Math.abs(clueCount - TARGET_CLUES); @@ -446,12 +452,13 @@ public record SwedishGenerator(int[] buff) { } if (!hasSlots) return 1_000_000_000L; - + int idx, h, v; 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 h = covH[idx], v = covV[idx]; + idx = Grid.offset(r, c); + if (grid.isDigitAt(idx)) continue; + 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; @@ -460,49 +467,46 @@ public record SwedishGenerator(int[] buff) { // clue clustering (8-connected) var seen = ctx.seen; seen.clear(); - var stack = ctx.stack; - int sp, idx; - + var stack = ctx.stack; + int sp, nr, nc; + long size; 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; + idx = Grid.offset(r, c); + if (seen.get(idx) || grid.isLetterAt(idx)) continue; sp = 0; stack[sp++] = idx; seen.set(idx); - var size = 0; + size = 0; while (sp > 0) { - var p = stack[--sp]; - int x = p / C, y = p % C; + var p = stack[--sp]; + int rr = Grid.c(p), cc = Grid.r(p); size++; for (var d : nbrs8) { - 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; - seen.set(nidx); - stack[sp++] = nidx; + nr = rr + d.r; + nc = cc + d.c; + if (nr < 0 || nr >= R || nc < 0 || nc >= C) continue; + idx = Grid.offset(nr, nc); + if (seen.get(idx) || grid.isLetterAt(idx)) continue; + seen.set(idx); + stack[sp++] = idx; } } - if (size >= 2) penalty += (long) (size - 1) * 120L; + if (size >= 2) penalty += (size - 1L) * 120L; } - + int walls, wr, wc; // dead-end-ish letter cell (3+ walls) for (var r = 0; r < R; r++) for (var c = 0; c < C; c++) { if (grid.isDigitAt(r, c)) continue; - var walls = 0; + walls = 0; for (var d : nbrs4) { - int rr = r + d.r, cc = c + d.c; - if (rr < 0 || rr >= R || cc < 0 || cc >= C) { - walls++; - continue; - } - if (grid.isDigitAt(rr, cc)) walls++; + wr = r + d.r; + wc = c + d.c; + if (wr < 0 || wr >= R || wc < 0 || wc >= C || grid.isDigitAt(wr, wc)) walls++; } if (walls >= 3) penalty += 400; }