With n=5 and k=3 the following loop will do it
List l=new ArrayList();
l.add(\"A\");l.add(\"B\");l.add(\"C\");l.add(\"D\");l.add(\"E\
This technique is called Gosper's hack. It only works for n <= 32
because it uses the bits of an int
, but you can increase it to 64 if you use a long
.
int nextCombo(int x) {
// moves to the next combination with the same number of 1 bits
int u = x & (-x);
int v = u + x;
return v + (((v ^ x) / u) >> 2);
}
...
for (int x = (1 << k) - 1; (x >>> n) == 0; x = nextCombo(x)) {
System.out.println(Integer.toBinaryString(x));
}
For n = 5
and k = 3
, this prints
111
1011
1101
1110
10011
10101
10110
11001
11010
11100
exactly as you'd expect.
Apache commons has iterators for subsets of size k, and for permutations. Here is an iterator that iterates through 1-k tuples of an n-tuple, that combines the two:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.collections4.iterators.PermutationIterator;
import org.apache.commons.math3.util.Combinations;
public class AllTuplesUpToKIterator implements Iterator<List<Integer>> {
private Iterator<int[]> combinationIterator;
private PermutationIterator<Integer> permutationIterator;
int i;
int k;
int n;
public AllTuplesUpToKIterator(int n, int k) {
this.i = 1;
this.k = k;
this.n = n;
combinationIterator = new Combinations(n, 1).iterator();
permutationIterator = new PermutationIterator<Integer>(intArrayToIntegerList(combinationIterator.next()));
}
@Override
public boolean hasNext() {
if (permutationIterator.hasNext()) {
return true;
} else if (combinationIterator.hasNext()) {
return true;
} else if (i<k) {
return true;
} else {
return false;
}
}
@Override
public List<Integer> next() {
if (!permutationIterator.hasNext()) {
if (!combinationIterator.hasNext()) {
i++;
combinationIterator = new Combinations(n, i).iterator();
}
permutationIterator = new PermutationIterator<Integer>(intArrayToIntegerList(combinationIterator.next()));
}
return permutationIterator.next();
}
@Override
public void remove() {
// TODO Auto-generated method stub
}
public static List<Integer> intArrayToIntegerList(int[] arr) {
List<Integer> result = new ArrayList<Integer>();
for (int i=0; i< arr.length; i++) {
result.add(arr[i]);
}
return result;
}
public static void main(String[] args) {
int n = 4;
int k = 2;
for (AllTuplesUpToKIterator iter= new AllTuplesUpToKIterator(n, k); iter.hasNext();) {
System.out.println(iter.next());
}
}
}
this should be the most efficient way, even if k embedded loops looks ugly
//singleton
for (int i = 0; i < l.size(); i++) {
System.out.println(l.get(i));
}
//pairs
for (int i = 0; i < l.size(); i++) {
for (int j = i+1; j < l.size(); j++) {
System.out.println(l.get(i)+l.get(j));
}
}
//3-tuple
for (int i = 0; i < l.size(); i++) {
for (int j = i+1; j < l.size(); j++) {
for (int k = j+1; k < l.size(); k++) {
System.out.println(l.get(i)+l.get(j)+l.get(k));
}
}
}
// ...
//k-tuple