introduce bitloops

This commit is contained in:
mike
2026-01-18 03:32:34 +01:00
parent 6daab5ef4e
commit b026ebfbd2
6 changed files with 194 additions and 74 deletions

View 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");
}
}