public void StressPn_Ctor1B() { // Use higher maxWidth values for a longer running test. #if STRESS const int maxWidth = 8; #else const int maxWidth = 5; #endif long counter = 0; for (int w = 1; w <= maxWidth; ++w) { for (long rank = 0; rank < Combinatoric.Factorial(w); ++rank) { Permutation row1 = new Permutation(choices: w, picks: w, rank: rank); int[] source = new int[w]; row1.CopyTo(source); Permutation row2 = new Permutation(source); for (int i = 0; i < w; ++i) { Assert.AreEqual(row1[i], row2[i]); } // verify that rank(unrank(x)) = x Assert.AreEqual(rank, row1.Rank); Assert.AreEqual(rank, row2.Rank); ++counter; } } }
public void UnitPn_PlainRankSet() { var pn0 = new Permutation(0); var pn1 = new Permutation(1); var pn4 = new Permutation(4); var pn5 = new Permutation(5); pn0.PlainRank = -1; pn1.PlainRank = 4; pn4.PlainRank = pn4.RowCount + 1; pn5.PlainRank = -2; Assert.AreEqual(0, pn0.PlainRank); Assert.AreEqual(0, pn1.PlainRank); Assert.AreEqual(1, pn4.PlainRank); Assert.AreEqual(Combinatoric.Factorial(5) - 2, pn5.PlainRank); pn5.PlainRank = pn5.RowCount * -2 - 1; Assert.AreEqual(pn5.RowCount - 1, pn5.PlainRank); pn5.PlainRank = pn5.RowCount * -2; Assert.AreEqual(0, pn5.PlainRank); pn5.PlainRank = pn5.RowCount * -2 + 1; Assert.AreEqual(1, pn5.PlainRank); }
public void StressCn_Ctor2B() { // Use higher maxChoices values for a longer running test. #if STRESS const int maxChoices = 16; #else const int maxChoices = 5; #endif int counter = 0; for (int choices = 0; choices <= maxChoices; ++choices) { for (int picks = 0; picks <= choices; ++picks) { long maxRows = Combinatoric.BinomialCoefficient(choices, picks); for (int rank = 0; rank < maxRows; ++rank) { Combination row1 = new Combination(choices, picks, rank); int[] source = new int[picks]; row1.CopyTo(source); Combination row2 = new Combination(choices, source); // verify that rank(unrank(x)) = x Assert.AreEqual(rank, row1.Rank); Assert.AreEqual(rank, row2.Rank); ++counter; } } } }
public void StressPn_GetRowsOfPlainChanges() { // Higher maxWidth values may be used for stress, but will allocate more space. #if STRESS const int maxWidth = 8; #else const int maxWidth = 6; #endif for (int n = 1; n < maxWidth; ++n) { long rc = n == 0 ? 0 : Combinatoric.Factorial(n); var mat = new int[rc][]; int pcRank = 0; var pn0 = new Permutation(n); var beginData = new int[n]; pn0.CopyTo(beginData); foreach (var pn in pn0.GetRowsOfPlainChanges()) { mat[pcRank] = new int[n]; pn.CopyTo(mat[pcRank]); ++pcRank; Assert.AreEqual(pn.Rank, pn0.Rank); Assert.IsTrue(Enumerable.SequenceEqual(pn, pn0)); } Assert.AreEqual(0, pn0.Rank); Assert.IsTrue(Enumerable.SequenceEqual(beginData, pn0)); var isUsed = new bool[rc]; var lexPerm0 = new Permutation(mat[0]); isUsed[lexPerm0.Rank] = true; for (int rv = 1; rv < rc; ++rv) { var lexPerm = new Permutation(mat[rv]); Assert.IsFalse(isUsed[lexPerm.Rank], "row already used"); isUsed[lexPerm.Rank] = true; int e; for (e = 0; e < n; ++e) { if (mat[rv][e] != mat[rv - 1][e]) { Assert.AreNotEqual(e, n - 1, "last element only change"); Assert.AreEqual(mat[rv][e], mat[rv - 1][e + 1], "invalid swap"); Assert.AreEqual(mat[rv][e + 1], mat[rv - 1][e], "invalid swap"); e += 2; break; } } for (; e < n; ++e) { Assert.AreEqual(mat[rv][e], mat[rv - 1][e], "more than 1 swap"); } } } }
public void Unit_BinomialCoefficient2() { ResetCombinatoric(); long bc5 = Combinatoric.BinomialCoefficient(80, 3); Assert.AreEqual(82160, bc5); }
public void Unit_Factorial() { Assert.AreEqual(1, Combinatoric.Factorial(0)); long f = 1; for (int n = 1; n <= 20; ++n) { f = f * n; Assert.AreEqual(f, Combinatoric.Factorial(n)); } }
public void Unit_BinomialCoefficient3() { var bcTable = BuildPascalsTriangle(); for (int n = 0; n < bcTable.Count; ++n) { for (int k = 0; k < bcTable[n].Length; ++k) { long bc = Combinatoric.BinomialCoefficient(n, k); Assert.AreEqual(bcTable[n][k], bc, "n=" + n + ", k=" + k); } } }
public void UnitPn_Ctor3ALastRank() { for (int nn = 1; nn <= Permutation.MaxChoices; ++nn) { Permutation pn = new Permutation(nn, nn, -1); Assert.AreEqual(nn, pn.Choices); Assert.AreEqual(nn, pn.Picks); Assert.AreEqual(Combinatoric.Factorial(nn) - 1, pn.Rank); Assert.AreEqual(Combinatoric.Factorial(nn), pn.RowCount); for (int i = 0; i < pn.Choices; ++i) { Assert.AreEqual(nn - i - 1, pn[i]); } } }
public void UnitPn_Ctor2A1() { for (int ei = 1; ei <= Permutation.MaxChoices; ++ei) { Permutation pn = new Permutation(ei, ei); Assert.AreEqual(ei, pn.Choices); Assert.AreEqual(ei, pn.Picks); Assert.AreEqual(0, pn.Rank); Assert.AreEqual(Combinatoric.Factorial(ei), pn.RowCount); for (int i = 0; i < pn.Choices; ++i) { Assert.AreEqual(i, pn[i]); } } }
public void UnitCn_Properties() { int n = 8; int k = 3; long expectedCount = Combinatoric.Factorial(n) / (Combinatoric.Factorial(k) * Combinatoric.Factorial(n - k)); Combination cn = new Combination(n, k); Assert.AreEqual(n, cn.Choices); Assert.AreEqual(k, cn.Picks); Assert.AreEqual(expectedCount, cn.RowCount); cn.Rank = -1; Assert.AreEqual(cn.RowCount - 1, cn.Rank); }
public void Unit_BinomialCoefficient1() { ResetCombinatoric(); long bc1 = Combinatoric.BinomialCoefficient(1, -1); Assert.AreEqual(0, bc1); long bc2 = Combinatoric.BinomialCoefficient(1, 2); Assert.AreEqual(0, bc2); long bc3 = Combinatoric.BinomialCoefficient(65, 4); Assert.AreEqual(677040, bc3); long bc4 = Combinatoric.BinomialCoefficient(66, 33); Assert.AreEqual(7219428434016265740, bc4); }
public void UnitPn_PlainRankMany() { var expected = new int[][][] { new int[][] { new int[] { } }, new int[][] { new int[] { 0 } }, new int[][] { new int[] { 0, 1 }, new int[] { 1, 0 } }, new int[][] { new int[] { 0, 1, 2 }, new int[] { 0, 2, 1 }, new int[] { 2, 0, 1 }, new int[] { 2, 1, 0 }, new int[] { 1, 2, 0 }, new int[] { 1, 0, 2 } }, new int[][] { new int[] { 0, 1, 2, 3 }, new int[] { 0, 1, 3, 2 }, new int[] { 0, 3, 1, 2 }, new int[] { 3, 0, 1, 2 }, new int[] { 3, 0, 2, 1 }, new int[] { 0, 3, 2, 1 }, new int[] { 0, 2, 3, 1 }, new int[] { 0, 2, 1, 3 }, new int[] { 2, 0, 1, 3 }, new int[] { 2, 0, 3, 1 }, new int[] { 2, 3, 0, 1 }, new int[] { 3, 2, 0, 1 }, new int[] { 3, 2, 1, 0 }, new int[] { 2, 3, 1, 0 }, new int[] { 2, 1, 3, 0 }, new int[] { 2, 1, 0, 3 }, new int[] { 1, 2, 0, 3 }, new int[] { 1, 2, 3, 0 }, new int[] { 1, 3, 2, 0 }, new int[] { 3, 1, 2, 0 }, new int[] { 3, 1, 0, 2 }, new int[] { 1, 3, 0, 2 }, new int[] { 1, 0, 3, 2 }, new int[] { 1, 0, 2, 3 } } }; for (var n = 1; n < expected.Length; ++n) { var pn = new Permutation(n); Assert.AreEqual(expected[n].Length, pn.RowCount); for (var pr = 0; pr < Combinatoric.Factorial(n); ++pr) { pn.PlainRank = pr; for (var ei = 0; ei < n; ++ei) { Assert.AreEqual(expected[n][pr][ei], pn[ei]); } } } }
public void Unit_BinomialCoefficient4() { var bcTable = BuildPascalsTriangle(); int n = bcTable.Count; Assert.AreEqual(1, Combinatoric.BinomialCoefficient(n, 0)); for (int k = 1; k < n / 4; ++k) { long bc = Combinatoric.BinomialCoefficient(n, k); long expected = bcTable[n - 1][k - 1] + bcTable[n - 1][k]; long actual = Combinatoric.BinomialCoefficient(n, k); Assert.AreEqual(expected, actual, "k=" + k); } for (int k = (n * 3) / 4; k < n; ++k) { long bc = Combinatoric.BinomialCoefficient(n, k); long expected = bcTable[n - 1][k - 1] + bcTable[n - 1][k]; long actual = Combinatoric.BinomialCoefficient(n, k); Assert.AreEqual(expected, actual, "k=" + k); } }
public void Crash_BinomialCoefficient_Overflow() { long zz = Combinatoric.BinomialCoefficient(67, 34); }
public void Crash_Factorial_IndexOutOfRange() { long f = Combinatoric.Factorial(21); }