I would just use a simple integer counter and print it in base 3 :
for (int i=0; i < Math.pow(3, 20); i++) {
System.out.println(Integer.toString(i, 20));
}
This is actually sufficient to represent your 20 variable object and generate all its states, however we have a lot of conversions to do to meet your requirements :
- the number would naturally use the
0
, 1
and 2
symbols, we have to shift them to 1
, 2
and 3
- the number wouldn't naturally be padded. We use the
%1$20s
format descriptor, which means "positional argument 1, as a 20 char string (padded left by default)". That pads with spaces however, so we must also replace spaces with 1
.
Which gives us this final code :
for (int i=0; i < Math.pow(3, 20); i++) {
System.out.println(String.format("%1$20s", Integer.toString(i, 20)).replace("2", "3").replace("1", "2").replace("0", "1").replace(" ", "1"));
}
Edit : why must I write ugly code when I can use streams and lambdas?
IntStream.range(0, (int)Math.pow(3, 20)) // yields 0 to 3^20-1
.mapToObj(number -> Integer.toString(number, 3)) // base 3 conversion
.map(string -> String.format("%1$20s", string)) // 20 char padding
.map(paddedString -> paddedString.replace("2", "3")) // number shifting. must be made in this specific order not to fail
.map(paddedString -> paddedString.replace("1", "2"))
.map(paddedString -> paddedString.replace("0", "1"))
.map(paddedString -> paddedString.replace(" ", "1"))
.forEach(System.out::println);