introduce bitloops
This commit is contained in:
90
src/test/java/puzzle/ConnectivityTest.java
Normal file
90
src/test/java/puzzle/ConnectivityTest.java
Normal file
@@ -0,0 +1,90 @@
|
||||
package puzzle;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import puzzle.Masker.Clues;
|
||||
import puzzle.SwedishGenerator.Rng;
|
||||
import static puzzle.SwedishGenerator.STACK_SIZE;
|
||||
|
||||
public class ConnectivityTest {
|
||||
|
||||
@Test
|
||||
void testConnectivityPenalty() {
|
||||
Rng rng = new Rng(42);
|
||||
Masker masker = new Masker(rng, new int[STACK_SIZE], Clues.createEmpty());
|
||||
|
||||
// 1. Maak een masker met één component van clues (bijv. 3 clues naast elkaar)
|
||||
Clues singleComp = Clues.createEmpty();
|
||||
// Gebruik offsets die dicht bij elkaar liggen
|
||||
int off1 = SwedishGenerator.Grid.offset(1, 1);
|
||||
int off2 = SwedishGenerator.Grid.offset(1, 2);
|
||||
int off3 = SwedishGenerator.Grid.offset(2, 1);
|
||||
|
||||
singleComp.setClueLo(1L << off1, (byte)1); // Right
|
||||
singleComp.setClueLo(1L << off2, (byte)1); // Right
|
||||
singleComp.setClueLo(1L << off3, (byte)0); // Down
|
||||
|
||||
long fitnessSingle = masker.maskFitness(singleComp, 3);
|
||||
|
||||
// 2. Maak een masker met twee eilandjes van clues
|
||||
Clues twoIslands = Clues.createEmpty();
|
||||
int offA1 = SwedishGenerator.Grid.offset(1, 1);
|
||||
int offB1 = SwedishGenerator.Grid.offset(6, 6); // Ver weg
|
||||
|
||||
// We moeten zorgen dat ze elk minstens 1 slot vormen om door isValid(2) te komen
|
||||
twoIslands.setClueLo(1L << offA1, (byte)1);
|
||||
twoIslands.setClueLo(1L << offB1, (byte)1);
|
||||
|
||||
long fitnessIslands = masker.maskFitness(twoIslands, 2);
|
||||
|
||||
System.out.println("[DEBUG_LOG] Fitness single component: " + fitnessSingle);
|
||||
System.out.println("[DEBUG_LOG] Fitness two islands: " + fitnessIslands);
|
||||
|
||||
// De eilandjes moeten een hogere penalty hebben (als clueCount gelijk is)
|
||||
Clues twoIslands3 = Clues.createEmpty();
|
||||
twoIslands3.setClueLo(1L << offA1, (byte)1);
|
||||
twoIslands3.setClueLo(1L << offB1, (byte)1);
|
||||
int offB2 = SwedishGenerator.Grid.offset(6, 7);
|
||||
twoIslands3.setClueLo(1L << offB2, (byte)1);
|
||||
|
||||
long fitnessIslands3 = masker.maskFitness(twoIslands3, 3);
|
||||
System.out.println("[DEBUG_LOG] Fitness three clues in two islands: " + fitnessIslands3);
|
||||
|
||||
assertTrue(fitnessIslands3 > fitnessSingle, "Islands should have higher penalty than single component");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIntersectionConnectivity() {
|
||||
Rng rng = new Rng(42);
|
||||
Masker masker = new Masker(rng, new int[STACK_SIZE], Clues.createEmpty());
|
||||
|
||||
// Test of slots die elkaar kruisen als verbonden worden beschouwd,
|
||||
// zelfs als de clues niet 8-naburig zijn.
|
||||
Clues crossing = Clues.createEmpty();
|
||||
// Clue 1: (0,0) naar rechts. Slot op (0,1), (0,2), (0,3)
|
||||
// Clue 2: (1,2) omhoog. Slot op (0,2)
|
||||
// Ze kruisen op (0,2)
|
||||
crossing.setClueLo(1L << SwedishGenerator.Grid.offset(0,0), (byte)1); // Right
|
||||
crossing.setClueLo(1L << SwedishGenerator.Grid.offset(1,2), (byte)2); // Up
|
||||
|
||||
// Deze twee clues zijn niet 8-naburig (0,0 en 1,2)
|
||||
// Maar hun slots kruisen op (0,2)
|
||||
|
||||
long fitness = masker.maskFitness(crossing, 2);
|
||||
System.out.println("[DEBUG_LOG] Fitness crossing: " + fitness);
|
||||
|
||||
// Als ze als verbonden worden gezien, is er 1 component.
|
||||
// Penalty voor connectiviteit zou 0 moeten zijn (bovenop andere penalties).
|
||||
// Als we een derde clue ver weg toevoegen, moet de penalty significant stijgen.
|
||||
|
||||
Clues crossingPlusIsland = Clues.createEmpty();
|
||||
crossingPlusIsland.setClueLo(1L << SwedishGenerator.Grid.offset(0,0), (byte)1);
|
||||
crossingPlusIsland.setClueLo(1L << SwedishGenerator.Grid.offset(1,2), (byte)2);
|
||||
crossingPlusIsland.setClueLo(1L << SwedishGenerator.Grid.offset(7,7), (byte)1);
|
||||
|
||||
long fitnessIsland = masker.maskFitness(crossingPlusIsland, 3);
|
||||
System.out.println("[DEBUG_LOG] Fitness crossing plus island: " + fitnessIsland);
|
||||
|
||||
assertTrue(fitnessIsland > fitness + 10000, "Island should add significant penalty");
|
||||
}
|
||||
}
|
||||
@@ -196,9 +196,7 @@ public class MainTest {
|
||||
Assertions.assertEquals(20, mask.clueCount());
|
||||
val map = mask.stream().collect(Collectors.toMap(ClueAt::index, ClueAt::clue));
|
||||
Assertions.assertEquals(20, map.size());
|
||||
var slots = Masker.extractSlots(mask.c(), dict.index());
|
||||
val slotInfo = Masker.scoreSlots(slots);
|
||||
var grid = mask.toGrid();
|
||||
var slots = Masker.slots(mask.c(), dict.index());
|
||||
// var filled = fillMask(rng, slotInfo, grid, false);
|
||||
// val res = new PuzzleResult(new Clued(mask), new Gridded(grid), slotInfo, filled).exportFormatFromFilled(0, new Rewards(0, 0, 0));
|
||||
}
|
||||
@@ -214,15 +212,14 @@ public class MainTest {
|
||||
" 1 \n" +
|
||||
" 1 2\n" +
|
||||
"21 22 3");
|
||||
var slots = Masker.extractSlots(mask.c(), dict.index());
|
||||
val slotInfo = Masker.scoreSlots(slots);
|
||||
var grid = mask.toGrid();
|
||||
var slotInfo = Masker.slots(mask.c(), dict.index());
|
||||
var grid = Slotinfo.grid(slotInfo);
|
||||
var filled = fillMask(rng, slotInfo, grid, false);
|
||||
Assertions.assertTrue(filled.ok(), "Puzzle generation failed (not ok)");
|
||||
Assertions.assertEquals(13, Slotinfo.wordCount(0, slotInfo), "Number of assigned words changed");
|
||||
Assertions.assertEquals("WAANZIN", Lemma.asWord(slotInfo[0].assign().w));
|
||||
Assertions.assertEquals(-2155876353L, grid.lo);
|
||||
Assertions.assertEquals(255L, grid.hi);
|
||||
Assertions.assertEquals(-1L, grid.lo);
|
||||
Assertions.assertEquals(-1L, grid.hi);
|
||||
var g = new Gridded(grid);
|
||||
g.gridToString(mask.c());
|
||||
var aa = new PuzzleResult(mask, g, slotInfo, filled).exportFormatFromFilled(1, new Rewards(1, 1, 1));
|
||||
|
||||
Reference in New Issue
Block a user