98 lines
2.1 KiB
Java
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));
|
|
}
|
|
}
|