diff --git a/src/main/java/puzzle/SwedishGenerator.java b/src/main/java/puzzle/SwedishGenerator.java index d65e82e..70f187b 100644 --- a/src/main/java/puzzle/SwedishGenerator.java +++ b/src/main/java/puzzle/SwedishGenerator.java @@ -38,7 +38,7 @@ public record SwedishGenerator(Rng rng) { public CandidateInfo(int n) { this(null, n); } } - + // static final CandidateInfo[] CANDIDATES = IntStream.range(0, 10192 << 2).mapToObj(CandidateInfo::new).toArray(CandidateInfo[]::new); //@formatter:off @@ -121,22 +121,20 @@ public record SwedishGenerator(Rng rng) { } } - static record Context(int[] covH, - int[] covV, - int[] cellCount, - int[] stack, - Bit seen, - byte[] pattern, - IntList[] intListBuffer, - int[] undo, - int[] inter1, - int[] inter2) { + static final class Context { - public Context() { - this(new int[SIZE], new int[SIZE], new int[SIZE], new int[SIZE], new Bit(), new byte[MAX_WORD_LENGTH], new IntList[MAX_WORD_LENGTH], - new int[2048], new int[160000], new int[160000]); - } - void setPatter(byte[] chars) { System.arraycopy(chars, 0, this.pattern, 0, chars.length); } + final int[] covH = new int[SIZE]; + final int[] covV = new int[SIZE]; + final int[] cellCount = new int[SIZE]; + final int[] stack = new int[SIZE]; + final Bit seen = new Bit(); + long pattern; + final IntList[] intListBuffer = new IntList[MAX_WORD_LENGTH]; + final int[] undo = new int[2048]; + final int[] inter1 = new int[160000]; + final int[] inter2 = new int[160000]; + + void setPattern(long p) { this.pattern = p; } } static final class Rng { @@ -364,7 +362,7 @@ public record SwedishGenerator(Rng rng) { public int dir() { return key & 7; } public boolean horiz() { return horiz(key); } public int pos(int i) { return offset(packedPos, i); } - public static boolean horiz(int key) { return (key & 1) == 0/*((key & 15) & 1) == 0*/; } + public static boolean horiz(int key) { return (key & 1) == 0; } public static int offset(long packedPos, int i) { return (int) ((packedPos >> (i * 7)) & 127); } public static int packSlotDir(int idx, int d) { return (idx << BIT_FOR_DIR) | d; } } @@ -415,7 +413,7 @@ public record SwedishGenerator(Rng rng) { Arrays.fill(covH, 0, SIZE, 0); Arrays.fill(covV, 0, SIZE, 0); long lo_cl = grid.lo, hi_cl = grid.hi; - long penalty = (((long) Math.abs(grid.clueCount() - TARGET_CLUES)) << 3); + long penalty = (((long) Math.abs(grid.clueCount() - TARGET_CLUES)) * 16000L); boolean hasSlots = false; for (int i = 0; i < 65; i += 64) { @@ -434,6 +432,8 @@ public record SwedishGenerator(Rng rng) { if (k > 0) { hasSlots = true; if (k < MIN_LEN7) penalty += 8000; + } else { + penalty += 25000; } } } @@ -615,12 +615,15 @@ public record SwedishGenerator(Rng rng) { //return pop.get(0).grid; return best.grid; } - static void patternForSlot(Grid grid, Slot s, byte[] pat) { - byte ch; + static long patternForSlot(Grid grid, Slot s) { + long p = 0; for (int i = 0, len = s.len(); i < len; i++) { - ch = grid.byteAt(s.pos(i)); - pat[i] = isLetter(ch) ? ch : DASH; + byte ch = grid.byteAt(s.pos(i)); + if (isLetter(ch)) { + p |= ((long) (ch & 31)) << (i * 5); + } } + return p; } static int slotScore(int[] count, Slot s) { @@ -656,11 +659,10 @@ public record SwedishGenerator(Rng rng) { var listBuffer = ctx.intListBuffer; var listCount = 0; IntList tmp; - byte ch; for (var i = 0; i < len; i++) { - ch = pattern[i]; - if (isLetter(ch)) { - listBuffer[listCount++] = entry.pos[i][ch - 'A']; + int val = (int) ((pattern >>> (i * 5)) & 31); + if (val != 0) { + listBuffer[listCount++] = entry.pos[i][val - 1]; } } @@ -754,7 +756,7 @@ public record SwedishGenerator(Rng rng) { if (assigned[s.key()] != null) continue; var entry = dictIndex[s.len()]; if (entry == null) return PICK_NOT_DONE; - patternForSlot(grid, s, ctx.pattern); + ctx.pattern = patternForSlot(grid, s); var info = candidateInfoForPattern(ctx, entry, s.len()); if (info.count == 0) return PICK_NOT_DONE; diff --git a/src/test/java/puzzle/MainTest.java b/src/test/java/puzzle/MainTest.java index bef492a..fc067d6 100644 --- a/src/test/java/puzzle/MainTest.java +++ b/src/test/java/puzzle/MainTest.java @@ -166,10 +166,10 @@ public class MainTest { // Regression baseline for seed search starting at 12347, pop 4, gens 20 Assertions.assertEquals(12348, foundSeed, "Found seed changed"); - Assertions.assertEquals(22, res.filled().clueMap().size(), "Number of assigned words changed"); - Assertions.assertEquals(Lemma.pack(new byte[]{ 'I', 'E', 'M', 'A', 'N', 'D', 'S' }), res.filled().clueMap().get(259).word()); - Assertions.assertEquals(648985643903632391L, res.filled().grid().grid().lo); - Assertions.assertEquals(140L, res.filled().grid().grid().hi); + Assertions.assertEquals(18, res.filled().clueMap().size(), "Number of assigned words changed"); + Assertions.assertEquals(Lemma.pack(new byte[]{ 'L', 'E', 'L', 'I', 'J', 'K', 'S' }), res.filled().clueMap().get(451).word()); + Assertions.assertEquals(73207692597665799L, res.filled().grid().grid().lo); + Assertions.assertEquals(193L, res.filled().grid().grid().hi); } @Test public void testIsLetterA() { diff --git a/src/test/java/puzzle/SwedishGeneratorTest.java b/src/test/java/puzzle/SwedishGeneratorTest.java index a39f95c..c0c0400 100644 --- a/src/test/java/puzzle/SwedishGeneratorTest.java +++ b/src/test/java/puzzle/SwedishGeneratorTest.java @@ -15,40 +15,36 @@ public class SwedishGeneratorTest { void testPatternForSlotAllLetters() { var grid = new Grid(new byte[]{ 65, 66, 67 }); // A B C var slot = Slot.from(18, ((long) 0) | ((long) 1 << 7) | ((long) 2 << 14), 3); - var pattern = new byte[3]; - patternForSlot(grid, slot, pattern); + long pattern = patternForSlot(grid, slot); - assertArrayEquals(new byte[]{ 'A', 'B', 'C' }, pattern); + assertEquals(1 | (2 << 5) | (3 << 10), pattern); } @Test void testPatternForSlotMixed() { var grid = new Grid(new byte[]{ 65, DASH, 67 }); // A - C var slot = Slot.from(1 << 4 | 2, ((long) 0) | ((long) 1 << 7) | ((long) 2 << 14), 3); - var pattern = new byte[3]; - patternForSlot(grid, slot, pattern); + long pattern = patternForSlot(grid, slot); - assertArrayEquals(new byte[]{ 'A', DASH, 'C' }, pattern); + assertEquals(1 | (0 << 5) | (3 << 10), pattern); } @Test void testPatternForSlotAllDashes() { var grid = new Grid(new byte[]{ DASH, DASH, DASH }); // - - - var slot = Slot.from(1 << 4 | 2, ((long) 0) | ((long) 1 << 7) | ((long) 2 << 14), 3); - var pattern = new byte[3]; - patternForSlot(grid, slot, pattern); + long pattern = patternForSlot(grid, slot); - assertArrayEquals(new byte[]{ DASH, DASH, DASH }, pattern); + assertEquals(0, pattern); } @Test void testPatternForSlotSingleLetter() { var grid = new Grid(new byte[]{ 65, DASH, DASH }); // A - - var slot = Slot.from(1 << 4 | 2, ((long) 0) | ((long) 1 << 7) | ((long) 2 << 14), 3); - var pattern = new byte[3]; - patternForSlot(grid, slot, pattern); + long pattern = patternForSlot(grid, slot); - assertArrayEquals(new byte[]{ 'A', DASH, DASH }, pattern); + assertEquals(1, pattern); } @Test void testRng() { @@ -198,7 +194,7 @@ public class SwedishGeneratorTest { // Pattern "APP--" for length 5 var context = new Context(); - context.setPatter(new byte[]{ 'A', 'P', 'P', DASH, DASH }); + context.setPattern(Lemma.pack(new byte[]{ 'A', 'P', 'P', DASH, DASH })); var info = candidateInfoForPattern(context, dict.index()[5], 5); assertEquals(2, info.count()); @@ -214,7 +210,7 @@ public class SwedishGeneratorTest { grid.setClue(0, (byte) '2'); // This should detect a slot starting at 0,1 with length 2 (0,1 and 0,2) - var slots = gen.extractSlots(grid); + var slots = extractSlots(grid); // Depending on MAX_WORD_LENGTH and grid size. // In 3x3, if we have '2' at 0,0, rr=0, cc=1. // while loop: