You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

98 lines
2.1 KiB
Java

import java.util.*;
// https://en.wikipedia.org/wiki/Combination
public class Combinations {
public static boolean nextCombination(int[] p, int n) {
int m = p.length;
for (int i = m - 1; i >= 0; i--) {
if (p[i] < n - m + i) {
++p[i];
while (++i < m) {
p[i] = p[i - 1] + 1;
}
return true;
}
}
return false;
}
public static int[] combinationByNumber(int n, int m, long number) {
int[] c = new int[m];
int cnt = n;
for (int i = 0; i < m; i++) {
int j = 1;
while (true) {
long am = binomial(cnt - j, m - 1 - i);
if (number < am)
break;
number -= am;
++j;
}
c[i] = (i > 0) ? (c[i - 1] + j) : (j - 1);
cnt -= j;
}
return c;
}
public static long numberByCombination(int[] c, int n) {
int m = c.length;
long res = 0;
int prev = -1;
for (int i = 0; i < m; i++) {
for (int j = prev + 1; j < c[i]; j++) {
res += binomial(n - 1 - j, m - 1 - i);
}
prev = c[i];
}
return res;
}
static long binomial(long n, long m) {
m = Math.min(m, n - m);
long res = 1;
for (long i = 0; i < m; i++) {
res = res * (n - i) / (i + 1);
}
return res;
}
public static boolean nextCombinationWithRepeats(int[] p, int n) {
int m = p.length;
for (int i = m - 1; i >= 0; i--) {
if (p[i] < n - 1) {
++p[i];
while (++i < m) {
p[i] = p[i - 1];
}
return true;
}
}
return false;
}
// Usage example
public static void main(String[] args) {
int[] p = {0, 1};
System.out.println(!nextCombination(p, 2));
System.out.println(Arrays.equals(new int[]{0, 1}, p));
p = new int[]{0, 0};
System.out.println(nextCombinationWithRepeats(p, 2));
System.out.println(Arrays.equals(new int[]{0, 1}, p));
System.out.println(nextCombinationWithRepeats(p, 2));
System.out.println(Arrays.equals(new int[]{1, 1}, p));
System.out.println(!nextCombinationWithRepeats(p, 2));
System.out.println(78 == numberByCombination(new int[]{1, 2, 3, 6, 8}, 9));
System.out.println(Arrays.toString(combinationByNumber(9, 5, 78)));
p = new int[]{0, 0, 0};
do {
System.out.println(Arrays.toString(p));
} while (nextCombinationWithRepeats(p, 3));
}
}