// On entry: elements & choices assumed valid, picks = elements.Length. private static long CalcRank(int[] elements, int choices) { long result = 0; var isUsed = new bool[choices]; // // Perform ranking: // for (var ei1 = 0; ei1 < elements.Length; ++ei1) { isUsed[elements[ei1]] = true; var digit = 0; for (var ei2 = 0; ei2 < elements[ei1]; ++ei2) { if (!isUsed[ei2]) { ++digit; } } result += digit * Combinatoric.Factorial(choices - ei1 - 1); } if (elements.Length < choices) { result = result / Combinatoric.Factorial(choices - elements.Length); } return(result); }
// On entry: elements allocated for choices. // On exit: result will be in elements. private static void CalcPlainUnrank(int[] elements, long plainRank) { elements[0] = 0; for (var ei = 1; ei < elements.Length; ++ei) { var yd = (int)(Combinatoric.Factorial(elements.Length) / Combinatoric.Factorial(ei + 1)); var yi = (int)((plainRank / yd) % ((ei + 1) * 2)); var ip = yi <= ei ? ei - yi : yi - ei - 1; for (var si = ei; si > ip; --si) { elements[si] = elements[si - 1]; } elements[ip] = ei; } }
// On entry: choices, picks assumed valid. private static long CalcCount(int choices, int picks) { if (picks == 0) { return(0); } var result = Combinatoric.Factorial(choices); if (picks < choices) { result = result / Combinatoric.Factorial(choices - picks); } return(result); }