224 lines
8.9 KiB
Java
224 lines
8.9 KiB
Java
package puzzle;
|
|
|
|
import lombok.val;
|
|
import org.junit.jupiter.api.Assertions;
|
|
import org.junit.jupiter.api.Test;
|
|
import puzzle.Export.ClueAt;
|
|
import puzzle.Export.Clued;
|
|
import puzzle.Export.Gridded;
|
|
import puzzle.Export.LetterVisit.LetterAt;
|
|
import puzzle.Export.PuzzleResult;
|
|
import puzzle.Export.Rewards;
|
|
import puzzle.Main.Opts;
|
|
import puzzle.SwedishGenerator.Rng;
|
|
import puzzle.SwedishGenerator.Slot;
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
import java.util.stream.Collectors;
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
import static puzzle.ExportFormatTest.Clue.*;
|
|
import static puzzle.SwedishGenerator.*;
|
|
import static puzzle.SwedishGeneratorTest.*;
|
|
import static puzzle.SwedishGeneratorTest.Idx.IDX_0_0;
|
|
import static puzzle.SwedishGeneratorTest.Idx.IDX_0_1;
|
|
import static puzzle.SwedishGeneratorTest.Idx.IDX_1_0;
|
|
import static puzzle.SwedishGeneratorTest.Idx.IDX_1_1;
|
|
import static puzzle.SwedishGeneratorTest.Idx.IDX_2_1;
|
|
import static puzzle.SwedishGeneratorTest.OFF_0_0;
|
|
import static puzzle.SwedishGeneratorTest.OFF_0_1;
|
|
import static puzzle.SwedishGeneratorTest.OFF_0_2;
|
|
|
|
public class MainTest {
|
|
|
|
static final Opts opts = new Main.Opts() {{
|
|
this.seed = 12348;
|
|
this.clueSize = 4;
|
|
this.pop = 4; // Tiny population
|
|
this.offspring = 18;
|
|
this.gens = 20; // Very few generations
|
|
this.minSimplicity = 0;
|
|
this.threads = 1;
|
|
this.tries = 1;
|
|
this.verbose = false;
|
|
}};
|
|
static final Dict dict = Dict.loadDict(opts.wordsPath);
|
|
@Test
|
|
void testExtractSlots() {
|
|
|
|
var clues = Clues.createEmpty();
|
|
val key = Slot.packSlotKey(OFF_0_0, CLUE_RIGHT);
|
|
clues.setClueLo(IDX_0_0.lo, CLUE_RIGHT);
|
|
var grid = new Gridded(clues.toGrid());
|
|
val g = grid.grid().g;
|
|
placeWord(grid.grid(), g, key, (1L << OFF_0_1) | (1L << OFF_0_2), 0, AB);
|
|
|
|
var slots = extractSlots(clues, dict.index());
|
|
assertEquals(1, slots.length);
|
|
var s = slots[0];
|
|
assertEquals(8, Slot.length(s.lo(), s.hi()));
|
|
var cells = s.walk().toArray();
|
|
assertEquals(0, SwedishGenerator.IT[cells[0]].r());
|
|
assertEquals(1, SwedishGenerator.IT[cells[0]].c());
|
|
assertEquals(0, SwedishGenerator.IT[cells[1]].r());
|
|
assertEquals(2, SwedishGenerator.IT[cells[1]].c());
|
|
}
|
|
|
|
@Test
|
|
void testStaticSlotMethods() {
|
|
// Test static horiz
|
|
// dir 1 (right) is horizontal
|
|
assertTrue(Slot.horiz(1));
|
|
// dir 0 (down) is vertical
|
|
assertFalse(Slot.horiz(0));
|
|
}
|
|
|
|
@Test
|
|
void testForEachSlot() {
|
|
var clues = Clues.createEmpty();
|
|
clues.setClueLo(IDX_0_0.lo, CLUE_RIGHT);
|
|
var count = new AtomicInteger(0);
|
|
clues.forEachSlot((key, lo, hi) -> {
|
|
count.incrementAndGet();
|
|
assertEquals(8, Long.bitCount(lo) + Long.bitCount(hi));
|
|
assertEquals(0, SwedishGenerator.IT[Long.numberOfTrailingZeros(lo)].r());
|
|
assertEquals(1, SwedishGenerator.IT[Long.numberOfTrailingZeros(lo)].c());
|
|
});
|
|
assertEquals(1, count.get());
|
|
}
|
|
@Test
|
|
public void testHoriz() {
|
|
assertTrue(Slot.horiz(1)); // Right
|
|
assertTrue(Slot.horiz(3)); // Left
|
|
assertFalse(Slot.horiz(0)); // Down
|
|
assertFalse(Slot.horiz(2)); // Up
|
|
}
|
|
@Test
|
|
public void testGridBasics() {
|
|
var clues = new Clued(Clues.createEmpty());
|
|
val key = Slot.packSlotKey(OFF_2_1, CLUE_UP);
|
|
clues.setClueLo(IDX_2_1.lo, CLUE_UP);
|
|
var grid = new Gridded(clues.toGrid());
|
|
|
|
// Test set/get
|
|
placeWord(grid.grid(), grid.grid().g, key, (1L << OFF_1_1) | (1L << OFF_0_1), 0, AZ);
|
|
val map = grid.stream(clues.c()).collect(Collectors.toMap(LetterAt::index, LetterAt::letter));
|
|
Assertions.assertEquals(LETTER_A, map.get(OFF_1_1));
|
|
Assertions.assertEquals(LETTER_Z, map.get(OFF_0_1));
|
|
var clueMap = clues.stream().collect(Collectors.toMap(ClueAt::index, ClueAt::clue));
|
|
Assertions.assertEquals(1, clueMap.size());
|
|
Assertions.assertEquals(CLUE_UP, clueMap.get(OFF_2_1));
|
|
|
|
// Test isLetterAt
|
|
Assertions.assertTrue(clues.notClue(OFF_0_0));
|
|
Assertions.assertTrue(clues.notClue(OFF_1_2));
|
|
Assertions.assertTrue(clues.notClue(OFF_2_3));
|
|
Assertions.assertFalse(clues.isClueLo(OFF_1_1));
|
|
|
|
// Test isDigitAt
|
|
Assertions.assertFalse(clues.isClueLo(OFF_0_0));
|
|
Assertions.assertTrue(clues.isClueLo(OFF_2_1));
|
|
clueMap = clues.stream().collect(Collectors.toMap(ClueAt::index, ClueAt::clue));
|
|
Assertions.assertEquals(CLUE_UP, clueMap.get(OFF_2_1));
|
|
Assertions.assertFalse(clues.isClueLo(OFF_2_3));
|
|
Assertions.assertFalse(clues.isClueLo(OFF_1_1));
|
|
|
|
// Test isLettercell
|
|
Assertions.assertTrue(clues.notClue(OFF_0_0)); // 'A' is letter
|
|
Assertions.assertTrue(clues.isClueLo(OFF_2_1)); // digit
|
|
Assertions.assertTrue(clues.notClue(OFF_1_1)); // '#' is lettercell
|
|
}
|
|
@Test
|
|
public void testCluesDeepCopy() {
|
|
var clues = new Clued(Clues.createEmpty());
|
|
clues.setClueLo(IDX_0_0.lo, RIGHT.dir);
|
|
clues.setClueLo(IDX_0_1.lo, UP.dir);
|
|
clues.setClueLo(IDX_1_0.lo, LEFT.dir);
|
|
clues.setClueLo(IDX_1_1.lo, DOWN.dir);
|
|
|
|
var copy = clues.deepCopyGrid();
|
|
var clueMap = clues.stream().collect(Collectors.toMap(ClueAt::index, ClueAt::clue));
|
|
Assertions.assertEquals(CLUE_RIGHT, clueMap.get(OFF_0_0));
|
|
|
|
copy.setClueLo(IDX_0_0.lo, DOWN.dir);
|
|
var copied = copy.stream().collect(Collectors.toMap(ClueAt::index, ClueAt::clue));
|
|
Assertions.assertEquals(DOWN.dir, copied.get(OFF_0_0));
|
|
Assertions.assertEquals(RIGHT.dir, clueMap.get(OFF_0_0));
|
|
}
|
|
@Test
|
|
public void testMini() {
|
|
val idx = IDX_1_1;
|
|
var clues = Clues.createEmpty();
|
|
clues.setClueLo(idx.lo, CLUE_LEFT);
|
|
Assertions.assertTrue(clues.isClueLo(idx.index));
|
|
}
|
|
@Test
|
|
void testMaskerCreation() {
|
|
var swe = new SwedishGenerator(new Rng(12348), new int[STACK_SIZE], Clues.createEmpty());
|
|
var mask = swe.generateMask(opts.clueSize, opts.pop, opts.gens, opts.offspring);
|
|
val clued = new Clued(mask);
|
|
val test = clued.gridToString();
|
|
val RESULT = "1 \n" +
|
|
" \n" +
|
|
" 3\n" +
|
|
" \n" +
|
|
" \n" +
|
|
"1 \n" +
|
|
" \n" +
|
|
" 3";
|
|
|
|
Assertions.assertEquals(4, clued.clueCount(), "Found seed changed");
|
|
Assertions.assertEquals(RESULT, test, "Found seed changed");
|
|
}
|
|
@Test
|
|
void testFiller() {
|
|
val rng = new Rng(-343913721);
|
|
val mask = new Clues(
|
|
74732156493031040L,
|
|
193L,
|
|
281475397248512L,
|
|
128L,
|
|
422762372923520L,
|
|
192L);
|
|
var slots = extractSlots(mask, dict.index());
|
|
val slotInfo = scoreSlots(new int[slots.length], slots);
|
|
var filled = fillMask(rng, slotInfo, mask.toGrid(), false);
|
|
Assertions.assertTrue(filled.ok(), "Puzzle generation failed (not ok)");
|
|
Assertions.assertEquals(18, filled.wordCount(0), "Number of assigned words changed");
|
|
Assertions.assertEquals("SLEDE", Lemma.asWord(filled.clueMap()[282]));
|
|
Assertions.assertEquals(-1L, filled.grid().grid().lo);
|
|
Assertions.assertEquals(255L, filled.grid().grid().hi);
|
|
filled.grid().gridToString(mask);
|
|
var aa = new PuzzleResult(new Clued(mask), filled).exportFormatFromFilled(1, new Rewards(1, 1, 1));
|
|
|
|
}
|
|
@Test
|
|
public void testAttempt() {
|
|
PuzzleResult res = null;
|
|
int foundSeed = -1;
|
|
for (int i = 0; i < 50; i++) {
|
|
int seed = opts.seed + i;
|
|
res = Main.attempt(new Rng(seed), dict, opts);
|
|
if (res != null && res.filled().ok()) {
|
|
foundSeed = seed;
|
|
System.out.println("[DEBUG_LOG] Seed found: " + seed);
|
|
System.out.println("[DEBUG_LOG] Simplicity: " + res.filled().stats().simplicity);
|
|
System.out.println("[DEBUG_LOG] ClueMap Size: " + res.filled().wordCount(0));
|
|
System.out.println("[DEBUG_LOG] Grid:");
|
|
System.out.println(res.filled().grid().renderHuman(res.clues().c()));
|
|
System.out.println(res.filled().grid().gridToString(res.clues().c()));
|
|
System.out.println(res.filled().grid().renderHuman(res.clues().c()));
|
|
break;
|
|
}
|
|
}
|
|
|
|
Assertions.assertNotNull(res, "Puzzle generation failed (null result)");
|
|
Assertions.assertTrue(res.filled().ok(), "Puzzle generation failed (not ok)");
|
|
Assertions.assertEquals(12348, foundSeed, "Found seed changed");
|
|
}
|
|
boolean isLetter(byte b) { return (b & 64) != 0; }
|
|
@Test public void testIsLetterA() { assertTrue(isLetter((byte) 'A')); }
|
|
@Test public void testIsLetterZ() { assertTrue(isLetter((byte) 'Z')); }
|
|
|
|
}
|