|
|
|
@ -1,25 +1,74 @@ |
|
|
|
|
namespace WhiteRabbit |
|
|
|
|
{ |
|
|
|
|
using System; |
|
|
|
|
using System.Collections.Generic; |
|
|
|
|
using System.Linq; |
|
|
|
|
|
|
|
|
|
internal static class PrecomputedPermutationsGenerator |
|
|
|
|
{ |
|
|
|
|
private static long[][] Permutations { get; } = Enumerable.Range(0, 9).Select(GeneratePermutations).ToArray(); |
|
|
|
|
private static ulong[][][] Permutations { get; } = Enumerable.Range(0, 9).Select(GeneratePermutations).ToArray(); |
|
|
|
|
|
|
|
|
|
private static long[] PermutationsNumbers { get; } = GeneratePermutationsNumbers().Take(19).ToArray(); |
|
|
|
|
|
|
|
|
|
public static long[] HamiltonianPermutations(int n) => Permutations[n]; |
|
|
|
|
public static ulong[] HamiltonianPermutations(int n, uint filter) => Permutations[n][filter]; |
|
|
|
|
|
|
|
|
|
public static long GetPermutationsNumber(int n) => PermutationsNumbers[n]; |
|
|
|
|
|
|
|
|
|
private static long[] GeneratePermutations(int n) |
|
|
|
|
private static ulong[][] GeneratePermutations(int n) |
|
|
|
|
{ |
|
|
|
|
var result = PermutationsGenerator.HamiltonianPermutations(n) |
|
|
|
|
if (n == 0) |
|
|
|
|
{ |
|
|
|
|
return new ulong[0][]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var allPermutations = PermutationsGenerator.HamiltonianPermutations(n) |
|
|
|
|
.Select(FormatPermutation) |
|
|
|
|
.ToArray(); |
|
|
|
|
|
|
|
|
|
return PadToWholeChunks(result, Constants.PhrasesPerSet); |
|
|
|
|
var statesCount = (uint)1 << (n - 1); |
|
|
|
|
var result = new ulong[statesCount][]; |
|
|
|
|
for (uint i = 0; i < statesCount; i++) |
|
|
|
|
{ |
|
|
|
|
result[i] = PadToWholeChunks(FilterPermutations(allPermutations, i).ToArray(), Constants.PhrasesPerSet); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static IEnumerable<ulong> FilterPermutations(IEnumerable<ulong> permutations, uint state) |
|
|
|
|
{ |
|
|
|
|
for (int position = 0; position < 16; position++) |
|
|
|
|
{ |
|
|
|
|
if (((state >> position) & 1) != 0) |
|
|
|
|
{ |
|
|
|
|
var innerPosition = (uint)position; |
|
|
|
|
permutations = permutations.Where(permutation => IsOrderPreserved(permutation, innerPosition)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return permutations; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static bool IsOrderPreserved(ulong permutation, uint position) |
|
|
|
|
{ |
|
|
|
|
var currentPermutation = permutation; |
|
|
|
|
|
|
|
|
|
while (currentPermutation != 0) |
|
|
|
|
{ |
|
|
|
|
if ((currentPermutation & 15) == position) |
|
|
|
|
{ |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ((currentPermutation & 15) == (position + 1)) |
|
|
|
|
{ |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
currentPermutation = currentPermutation >> 4; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
throw new ApplicationException("Malformed permutation " + permutation + " for position " + position); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static T[] PadToWholeChunks<T>(T[] original, int chunkSize) |
|
|
|
@ -32,14 +81,14 @@ |
|
|
|
|
return original.Concat(Enumerable.Repeat(default(T), chunkSize - (original.Length % chunkSize))).ToArray(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static long FormatPermutation(PermutationsGenerator.Permutation permutation) |
|
|
|
|
private static ulong FormatPermutation(PermutationsGenerator.Permutation permutation) |
|
|
|
|
{ |
|
|
|
|
System.Diagnostics.Debug.Assert(permutation.PermutationData.Length <= 16); |
|
|
|
|
|
|
|
|
|
long result = 0; |
|
|
|
|
ulong result = 0; |
|
|
|
|
for (var i = 0; i < permutation.PermutationData.Length; i++) |
|
|
|
|
{ |
|
|
|
|
result |= (long)(permutation.PermutationData[i]) << (4 * i); |
|
|
|
|
result |= (ulong)(permutation.PermutationData[i]) << (4 * i); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
|