using System; using System.Numerics; using System.Collections.Generic; public class Test { // Helper functions for calculating values of (n choose k). // These are not optimally coded! // ---------------------------------------------------------------------- protected static BigInteger factorial(int n) { BigInteger f = 1; while (n > 1) f *= n--; return f; } protected static int binomial(int n, int k) { if (k > n) return 0; return (int)(factorial(n) / (factorial(k) * factorial(n-k))); } // In the combinatorial number system, a combination {c_1, c_2, ..., c_k} // corresponds to the integer value obtained by adding (c_1 choose 1) + // (c_2 choose 2) + ... + (c_k choose k) // NOTE: combination values are assumed to start from zero, so // a combination like {1, 2, 3, 4, 5} will give a non-zero result // ---------------------------------------------------------------------- public static int combination_2_index(int[] combo) { int ix = 0, i = 1; Array.Sort(combo); foreach (int c in combo) { if (c > 0) ix += binomial(c, i); i++; } return ix; } // The reverse of this process is a bit fiddly. See Wikipedia for an // explanation: https://e...content-available-to-author-only...a.org/wiki/Combinatorial_number_system // ---------------------------------------------------------------------- public static int[] index_2_combination(int ix, int k) { List combo_list = new List(); while (k >= 1) { int n = k - 1; if (ix == 0) { combo_list.Add(n); k--; continue; } int b = 0; while (true) { // (Using a linear search here, but a binary search with // precomputed binomial values would be faster) int b0 = b; b = binomial(n, k); if (b > ix || ix == 0) { ix -= b0; combo_list.Add(n-1); break; } n++; } k--; } int[] combo = combo_list.ToArray(); Array.Sort(combo); return combo; } public static void Main() { int[][] test_combos = new int[][] { new int[] {0,1,2,3,4,5}, new int[] {0,1,2,3,4,6}, new int[] {38,40,41,42,43,44}, new int[] {39,40,41,42,43,44} }; int ix; for (int i=0; i [{1}]", ix, string.Join(", ", combo)); } } }