I have a list of variable size, for example
[1, 2, 3, 4]
and I want to get every possible way to split this list into two:
Going over all the different sizes of combinations and "subtracting" them from the original list seems intuitive approach IMO:
from itertools import combinations
s = [1, 2, 3, 4]
for combs in (combinations(s, r) for r in range(len(s)+1)) :
for comb in combs:
diff = list(set(s[:]) - set(comb))
print diff, list(comb)
OUTPUT
[1, 2, 3, 4] []
[2, 3, 4] [1]
[1, 3, 4] [2]
[1, 2, 4] [3]
[1, 2, 3] [4]
[3, 4] [1, 2]
[2, 4] [1, 3]
[2, 3] [1, 4]
[1, 4] [2, 3]
[1, 3] [2, 4]
[1, 2] [3, 4]
[4] [1, 2, 3]
[3] [1, 2, 4]
[2] [1, 3, 4]
[1] [2, 3, 4]
[] [1, 2, 3, 4]
The same approach can be applied with Java (only that it's more verbose...):
private static List initial;
public static void main(String[] args) throws IOException {
initial = Arrays.asList(1, 2, 3);
combinations(initial);
}
static void combinations(List src) {
combinations(new LinkedList<>(), src);
}
private static void combinations(LinkedList prefix, List src) {
if (src.size() > 0) {
prefix = new LinkedList<>(prefix); //create a copy to not modify the orig
src = new LinkedList<>(src); //copy
Integer curr = src.remove(0);
print(prefix, curr); // <-- this is the only thing that shouldn't appear in a "normal" combinations method, and which makes it print the list-pairs
combinations(prefix, src); // recurse without curr
prefix.add(curr);
combinations(prefix, src); // recurse with curr
}
}
// print the prefix+curr, as one list, and initial-(prefix+curr) as a second list
private static void print(LinkedList prefix, Integer curr) {
prefix = new LinkedList<>(prefix); //copy
prefix.add(curr);
System.out.println(Arrays.toString(prefix.toArray()) +
" " + Arrays.toString(subtract(initial, prefix).toArray()));
}
private static List subtract(List initial, LinkedList prefix) {
initial = new LinkedList<>(initial); //copy
initial.removeAll(prefix);
return initial;
}
OUTPUT
[1] [2, 3]
[2] [1, 3]
[3] [1, 2]
[2, 3] [1]
[1, 2] [3]
[1, 3] [2]
[1, 2, 3] []