Question

With n=5 and k=3 the following loop will do it

List<String> l=new ArrayList<String>();
l.add("A");l.add("B");l.add("C");l.add("D");l.add("E");
int broadcastSize = (int) Math.pow(2, l.size());
for (int i = 1; i < broadcastSize; i++) {
    StringBuffer buffer = new StringBuffer(50);
    int mask = i;
    int j = 0;   
    int size=0;
    System.out.println();
    while (mask > 0) {
        if ((mask & 1) == 1) {
            System.out.println(".. "+mask);
            buffer.append(l.get(j));
            if (++size>3){
                buffer = new StringBuffer(50);
                break;
            }
        }
        System.out.println(" "+mask);
        mask >>= 1;
        j++;
    }
    if (buffer.length()>0)
        System.out.println(buffer.toString());

}

but it's not efficient I would like to do it with Banker's sequence and thus explore first singletons, then pairs, then 3-tuple and stop.

I did not find a way do that, but at least this loop should be more efficient:

List<String> l=new ArrayList<String>();
l.add("A");l.add("B");l.add("C");l.add("D");l.add("E");
int broadcastSize = (int) Math.pow(2, l.size());
for (int i = 1; i < broadcastSize; i++) {
    StringBuffer buffer = new StringBuffer(50);
    int mask = i;
    int j = 0;   

    if (StringUtils.countMatches(Integer.toBinaryString(i), "1") < 4){
        while (mask > 0) {
            if ((mask & 1) == 1) {
                buffer.append(l.get(j));

            }
            mask >>= 1;
            j++;
        }
        if (buffer.length()>0)
            System.out.println(buffer.toString());
    }


}

there is also: but 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
Was it helpful?

Solution 2

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

OTHER TIPS

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());
        }

    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top