This answer will print all combinations, without use of recursion, but will fail if the total number of combinations exceeds Long.MAX_VALUE
. Since printing that many lines would never end anyway, that's not really a problem.
To print combinations in order, think of an incrementing number, where each digit of the number is an index into the corresponding sub-list.
Examples (using list of list from question):
000: blue 1 dog
001: blue 1 cat
002: blue 1 fish
003: blue 1 bird
010: blue 2 dog
...
121: red 3 cat
122: red 3 fish
123: red 3 bird
Each "digit" will roll over when it reaches end of corresponding sublist, e.g. last sublist only has 4 elements, so digit rolls over from 3 to 0.
Note: A "digit" can count higher than 9. Think hex for one way to represent that.
Now, the number of digits is dynamic too, i.e. the size of the outer list. One way to do this with simple loops, is to calculate the total number of combinations (2 * 3 * 4 = 24), then calculate the digits using division and remainder.
Example:
Combination #10 (first combination is #0):
10 % 4 = 2 (last digit)
10 / 4 % 3 = 2 % 3 = 2 (middle digit)
10 / 4 / 3 % 2 = 0 % 2 = 0 (first digit)
Digits: 022 = blue 3 fish
To help with this, we first build an array of divisors, e.g. div[] = { 12, 4, 1 }
, and find the total number of combinations (24
).
long[] div = new long[array.length];
long total = 1;
for (int i = array.length - 1; i >= 0; i--) {
div[i] = total;
if ((total *= array[i].length) <= 0)
throw new IllegalStateException("Overflow or empty sublist");
}
Now we can loop through the combinations and print the result:
for (long combo = 0; combo < total; combo++) {
for (int i = 0; i < array.length; i++) {
int digit = (int) (combo / div[i] % array[i].length);
if (i != 0)
System.out.print(' ');
System.out.print(array[i][digit]);
}
System.out.println();
}
With input from question:
String[][] array = {{"blue", "red"}, {"1", "2", "3"}, {"dog","cat", "fish", "bird"}};
We get the following output:
blue 1 dog
blue 1 cat
blue 1 fish
blue 1 bird
blue 2 dog
blue 2 cat
blue 2 fish
blue 2 bird
blue 3 dog
blue 3 cat
blue 3 fish
blue 3 bird
red 1 dog
red 1 cat
red 1 fish
red 1 bird
red 2 dog
red 2 cat
red 2 fish
red 2 bird
red 3 dog
red 3 cat
red 3 fish
red 3 bird
It can handle any combination of sub-arrays, e.g. with 4 sub-arrays of sizes 2, 3, 2, and 2:
String[][] array = {{"small", "large"}, {"black", "tan", "silver"}, {"lazy", "happy"}, {"dog", "cat"}};
small black lazy dog
small black lazy cat
small black happy dog
small black happy cat
small tan lazy dog
small tan lazy cat
small tan happy dog
small tan happy cat
small silver lazy dog
small silver lazy cat
small silver happy dog
small silver happy cat
large black lazy dog
large black lazy cat
large black happy dog
large black happy cat
large tan lazy dog
large tan lazy cat
large tan happy dog
large tan happy cat
large silver lazy dog
large silver lazy cat
large silver happy dog
large silver happy cat