JPP: Added todo and tests for nether dial tones for lehmer codes

This commit is contained in:
Willem Cazander 2026-01-26 23:04:50 +01:00
parent 7b5e3e3522
commit bfc9e511f6
2 changed files with 188 additions and 8 deletions

View file

@ -39,9 +39,7 @@ import ᒢᐩᐩ.ᔆʸᔆᐪᓫᔿ.ᒃᣔᒃᓫᒻ.ᑊᐣᓑᖮᐪᔆ.DuytsDocAu
public class BabelTest {
// ᒢᐩᐩ.ᒡᒢᑊᒻᒻᓫᔿ.xxx
// ᒢᐩᐩ.ᣕᓫᐪᑋᓫᣗ.ᐪᐤᣕᓫ(8 times 2^6+2^6+2^6+2^9+2^6+2^6+2^6+2^6+2^6+2^6+2^9 = 12800 interface + mutex + etc)
// ᒢᐩᐩ.ᣕᓫᐪᑋᓫᣗ.ᒼᑋᐤᣗᑊᐣ (SKIP-JAVA4?: REDO 8 times 3 chords of 2^18 tree slug size + file groupings)
// = 8*3*(2^18) = 6_291_456 is above default jvm max class limit
// implement as group marker interface to readout relative distance to marker root
// ᒢᐩᐩ.ᣕᓫᐪᑋᓫᣗ.ᐪᐤᣕᓫ.ᒼᑋᐤᣗᑊᐣ // implement as group marker interface to readout relative distance to marker root
// ᒢᐩᐩ.ᣕᓫᐪᑋᓫᣗ.ᒄᑊᣔᒻ.ᒻᑊᣕᕐᓑᣔ (#interfaces; ~31K + file groupings)
// ᒢᐩᐩ.ᣕᓫᐪᑋᓫᣗ.ᒄᑊᣔᒻ.ᒃᣔᔆᓫᒄ (#interfaces; 2304 + 2_655_360 + file groupings)
// ᒢᐩᐩ.ᑊᑉᒻᣔᔆᔆ.ᒃᐤᣕᓫ.ᣖᑊᣗᣔᐪᓫ.ᒃᐤᣔᐪs
@ -58,7 +56,7 @@ public class BabelTest {
// - real enum terminator set is from FC18 (FCFlameNumberGram.java)
// - bone based terminators up to PIG size 2304 (after 99% of JPP code comes from nether generate on use)
// - virtual terminator from nether chord group selector slug path is 2^18 bit pie part values
// - extended virtual pie slice terminators of nether is thus 8 times 2^18
// - extended virtual pie slice terminators of nether is thus 2 times 2^18 (so max gun/etc leaf depth is 6 Q slugs) TODO: zerdinal => upgrade 2 long for 36 bit window size
// ^^ for java3, in java4 100% of runtime+libs is generated per method, so only code which is used.
// ᒢᐩᐩ.ᣕᓑᔿᒃᓫᣗ.ᙆᓫᣗᒄᑊᣕᣔᒻ.ᐪᓫᣗᔿᑊᣕᣔᐪᐤᣗ.ᕐᓑᣕᔆ
// ᒢᐩᐩ.ᣕᓑᔿᒃᓫᣗ.ᒻᓫᕐᐤ.ᒢᓫᑊᐣᑊ (+JediTempleBase256InfinityZero redo generics-tree from LegoᐧBrickᐧTapeᐧRecorderᐧχ3 ?)

View file

@ -27,6 +27,12 @@
package ᒢᐩᐩ.ᒡᒢᑊᒻᒻᓫᔿ.ᣳᣝᐤᣜᣳ.ᔿᣔᐪᣗᑊᕁ;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@ -44,7 +50,7 @@ public class NumberMatrixFactoryTest {
@Test
public void testFilmStudio() {
for (int filmSequence:NumberMatrixFactory.INSTANCE.opgenomenFilmNummers()) {
for (int filmSequence : NumberMatrixFactory.INSTANCE.opgenomenFilmNummers()) {
NumberMatrixSet film = NumberMatrixFactory.INSTANCE.geefFilmSet(filmSequence);
Assertions.assertEquals(filmSequence, film.geefDimensie());
}
@ -52,10 +58,186 @@ public class NumberMatrixFactoryTest {
@Test
public void testFilmSizes() {
for (int i=2;i<4;i++) {
for (int i = 2; i < 4; i++) {
NumberMatrixSet film = NumberMatrixFactory.INSTANCE.geefFilmSet(i);
Assertions.assertEquals(i, film.geefDimensie());
Assertions.assertEquals(film.waardes().sizeᴿᵈ(), film.waardes().getᴿᵈ(0).zerdinalSpaceBoundary());
}
}
// TODO: redo matrix with lehmer dial tones from jpp-nether-dial-lehmer
/**
* Calculates the Lehmer code for a given permutation. For each element at index i, count elements to the right (j > i) where permutation[j] <
* permutation[i].
*/
public int[] calculateLehmerCode(int[] permutation) {
int n = permutation.length;
int[] lehmer = new int[n];
for (int i = 0; i < n; i++) {
int count = 0;
for (int j = i + 1; j < n; j++) {
if (permutation[j] < permutation[i]) {
count++;
}
}
lehmer[i] = count;
}
return lehmer;
}
@Test
public void testSize3Sequence() {
// Expected Lehmer codes for size 3 (Total 3! = 6 permutations)
// [0,1,2] -> [0,0,0] (Identity)
// [2,1,0] -> [2,1,0] (Reverse)
Assertions.assertArrayEquals(new int[] { 0, 0, 0 }, calculateLehmerCode(new int[] { 0, 1, 2 }));
Assertions.assertArrayEquals(new int[] { 0, 1, 0 }, calculateLehmerCode(new int[] { 0, 2, 1 }));
Assertions.assertArrayEquals(new int[] { 1, 0, 0 }, calculateLehmerCode(new int[] { 1, 0, 2 }));
Assertions.assertArrayEquals(new int[] { 1, 1, 0 }, calculateLehmerCode(new int[] { 1, 2, 0 }));
Assertions.assertArrayEquals(new int[] { 2, 0, 0 }, calculateLehmerCode(new int[] { 2, 0, 1 }));
Assertions.assertArrayEquals(new int[] { 2, 1, 0 }, calculateLehmerCode(new int[] { 2, 1, 0 }));
}
@Test
public void testSize4Sequence() {
// Testing specific key cases for size 4 (Total 4! = 24 permutations)
// Example: [0, 1, 2, 3] (Identity)
Assertions.assertArrayEquals(new int[] { 0, 0, 0, 0 }, calculateLehmerCode(new int[] { 0, 1, 2, 3 }));
// Example: [3, 2, 1, 0] (Maximum inversions)
Assertions.assertArrayEquals(new int[] { 3, 2, 1, 0 }, calculateLehmerCode(new int[] { 3, 2, 1, 0 }));
// Example from literature: [1, 3, 0, 2]
// 1 > 0 (1 to the right is smaller) -> Lehmer[0] = 1
// 3 > 0, 3 > 2 (2 to the right are smaller) -> Lehmer[1] = 2
// 0 (none to the right are smaller) -> Lehmer[2] = 0
// 2 (none to the right are smaller) -> Lehmer[3] = 0
Assertions.assertArrayEquals(new int[] { 1, 2, 0, 0 }, calculateLehmerCode(new int[] { 1, 3, 0, 2 }));
}
@Test
public void testAllSize5Permutations() {
int n = 5;
int[] initial = { 0, 1, 2, 3, 4 };
Set<String> uniqueLehmerCodes = new HashSet<>();
List<int[]> allPermutations = new ArrayList<>();
// 1. Generate all 5! = 120 permutations
generatePermutations(initial, 0, allPermutations);
Assertions.assertEquals(120, allPermutations.size(), "Should find exactly 120 permutations for size 5");
// 2. Calculate and verify Lehmer code for each
for (int[] p : allPermutations) {
int[] code = calculateLehmerCode(p);
// Check that each digit is within bounds: code[i] < (n - i)
for (int i = 0; i < n; i++) {
assert (code[i] < (n - i));
}
uniqueLehmerCodes.add(Arrays.toString(code));
}
// 3. Verify that every permutation produced a unique Lehmer code
Assertions.assertEquals(120, uniqueLehmerCodes.size(), "Each permutation must have a unique Lehmer code");
// 4. Check that named math is equal to old math.
NumberMatrixSet film = NumberMatrixFactory.INSTANCE.geefFilmSet(5);
Assertions.assertEquals(120, film.waardes().sizeᴿᵈ());
// 4. Check that all permutations are equal
Set<String> uniquePermutationCodes = new HashSet<>();
for (int[] p : allPermutations) {
uniquePermutationCodes.add(Arrays.toString(p));
}
film.waardes().forEachᴿᵈ(v -> {
int[] code = new int[v.rȧñkNummerBlokGroote()];
for (int i = 0; i < code.length; i++) {
code[i] = v.rȧñkNummerBlokWaarde(code.length - i - 1);
}
uniquePermutationCodes.remove(Arrays.toString(code));
});
Assertions.assertEquals(0, uniquePermutationCodes.size());
}
private void generatePermutations(int[] arr, int index, List<int[]> res) {
if (index == arr.length) {
res.add(arr.clone());
return;
}
for (int i = index; i < arr.length; i++) {
swap(arr, index, i);
generatePermutations(arr, index + 1, res);
swap(arr, index, i); // Backtrack
}
}
private void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
/**
* The Inverse: Converts a Lehmer code back into the original permutation. Logic: The value at lehmer[i] is used as an index into a list of remaining
* available numbers.
*/
public int[] decodeLehmerCode(int[] lehmer) {
int n = lehmer.length;
int[] permutation = new int[n];
// Create a list of available numbers {0, 1, 2, ..., n-1}
List<Integer> numbers = new ArrayList<>();
for (int i = 0; i < n; i++) {
numbers.add(i);
}
// For each Lehmer digit, pick the element at that index and remove it
for (int i = 0; i < n; i++) {
int indexInAvailable = lehmer[i];
permutation[i] = numbers.remove(indexInAvailable);
}
return permutation;
}
@Test
public void testInverseSize3() {
// Lehmer [1, 1, 0]
// 1. Pick index 1 from {0, 1, 2} -> 1. Remaining {0, 2}
// 2. Pick index 1 from {0, 2} -> 2. Remaining {0}
// 3. Pick index 0 from {0} -> 0.
// Result: [1, 2, 0]
Assertions.assertArrayEquals(new int[] { 1, 2, 0 }, decodeLehmerCode(new int[] { 1, 1, 0 }));
// Lehmer [2, 0, 0] -> [2, 0, 1]
Assertions.assertArrayEquals(new int[] { 2, 0, 1 }, decodeLehmerCode(new int[] { 2, 0, 0 }));
}
@Test
public void testInverseSize4() {
// Lehmer [1, 2, 0, 0] -> [1, 3, 0, 2]
Assertions.assertArrayEquals(new int[] { 1, 3, 0, 2 }, decodeLehmerCode(new int[] { 1, 2, 0, 0 }));
// Maximum inversion: [3, 2, 1, 0] -> [3, 2, 1, 0]
Assertions.assertArrayEquals(new int[] { 3, 2, 1, 0 }, decodeLehmerCode(new int[] { 3, 2, 1, 0 }));
}
@Test
public void testRoundTripSize5() {
// Ensure that calculate(decode(x)) returns x for a size 5 permutation
int[] originalLehmer = { 4, 0, 2, 1, 0 };
// 1. Decode to permutation
int[] permutation = decodeLehmerCode(originalLehmer);
// 2. Re-calculate Lehmer from that permutation
int[] reconstructedLehmer = calculateLehmerCode(permutation);
Assertions.assertArrayEquals(originalLehmer, reconstructedLehmer, "The inverse operation should perfectly reconstruct the Lehmer code.");
}
}