// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.plugins.JunctionChecker.junctionchecking;
public class Combination {
private long n = 0;
private long k = 0;
long[] data = null;
public Combination(long n, long k) {
if (n < 0 || k < 0)
try {
throw new Exception("Negative parameter in constructor");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.n = n;
this.k = k;
this.data = new long[(int) k];
for (long i = 0; i < k; ++i) {
this.data[(int) i] = i;
}
}
public static long Choose(long n, long k) {
if (n < 0 || k < 0)
try {
throw new Exception("Invalid negative parameter in Choose()");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (n < k) return 0;
if (n == k) return 1;
long delta, iMax;
if (k < n-k) { // ex: Choose(100,3)
delta = n-k;
iMax = k;
} else { // ex: Choose(100,97)
delta = k;
iMax = n-k;
}
long ans = delta + 1;
for (long i = 2; i <= iMax; ++i) {
ans = (ans * (delta + i)) / i;
}
return ans;
}
public long Choose() {
if (n < k) return 0;
if (n == k) return 1;
long delta, iMax;
if (k < n-k) { // ex: Choose(100,3)
delta = n-k;
iMax = k;
} else { // ex: Choose(100,97)
delta = k;
iMax = n-k;
}
long ans = delta + 1;
for (long i = 2; i <= iMax; ++i) {
ans = (ans * (delta + i)) / i;
}
return ans;
}
public Combination Successor() {
if (this.data.length == 0 ||
this.data[0] == this.n - this.k)
return null;
Combination ans = new Combination(this.n, this.k);
long i;
for (i = 0; i < this.k; ++i) {
ans.data[(int) i] = this.data[(int) i];
}
for (i = this.k - 1; i > 0 && ans.data[(int) i] == this.n - this.k + i; --i) {
// Count
}
++ans.data[(int) i];
for (long j = i; j < this.k - 1; ++j) {
ans.data[(int) j+1] = ans.data[(int) j] + 1;
}
return ans;
}
public String ToString() {
StringBuilder sb = new StringBuilder();
sb.append("{");
for (long i = 0; i < this.k; ++i) {
sb.append(this.data[(int) i]);
if (i < this.k-1) sb.append(", ");
}
sb.append("}");
return sb.toString();
}
}