If the order of the summands matters, so that [1,3]
and [3,1]
are not the same, then it is the integer composition. You can use the recursive method to build this sequence efficiently, but even so, it is too slow for large numbers. The number of permutations is 2(n-1)
, so I stopped at 27
.
Output of table n=[1-27]
, number of combinations, time milliseconds:
n: 1, composition: 1, time: 1
n: 2, composition: 2, time: 0
n: 3, composition: 4, time: 0
n: 4, composition: 8, time: 0
n: 5, composition: 16, time: 0
n: 6, composition: 32, time: 1
n: 7, composition: 64, time: 1
n: 8, composition: 128, time: 2
n: 9, composition: 256, time: 4
n: 10, composition: 512, time: 7
n: 11, composition: 1024, time: 14
n: 12, composition: 2048, time: 24
n: 13, composition: 4096, time: 24
n: 14, composition: 8192, time: 1
n: 15, composition: 16384, time: 3
n: 16, composition: 32768, time: 6
n: 17, composition: 65536, time: 11
n: 18, composition: 131072, time: 22
n: 19, composition: 262144, time: 46
n: 20, composition: 524288, time: 87
n: 21, composition: 1048576, time: 174
n: 22, composition: 2097152, time: 368
n: 23, composition: 4194304, time: 768
n: 24, composition: 8388608, time: 1635
n: 25, composition: 16777216, time: 3040
n: 26, composition: 33554432, time: 9015
n: 27, composition: 67108864, time: 45804
Java 7 code:
public static void main(String[] args) {
List<List<Integer>> list = composition(4, true);
for (List<Integer> comb : list)
System.out.println(comb);
for (int i = 1; i <= 27; i++) {
long time = System.currentTimeMillis();
List<List<Integer>> list1 = composition(i, false);
time = System.currentTimeMillis() - time;
System.out.println("n: " + String.format("%2d", i)
+ ", composition: " + String.format("%8d", list1.size())
+ ", time: " + String.format("%5d", time));
}
}
public static List<List<Integer>> composition(int n, boolean verbose) {
List<List<Integer>> list = new ArrayList<>();
composition(n, verbose ? "" : null, list, new ArrayList<Integer>());
return list;
}
public static void composition(
int i, String indent, List<List<Integer>> master, List<Integer> holder) {
if (indent != null && i == 0)
System.out.println(indent + "i=" + i + " comb=" + holder);
if (i == 0) master.add(holder);
for (int j = i; j >= 1; j--) {
ArrayList<Integer> temp = new ArrayList<>(holder);
temp.add(j);
if (indent != null)
System.out.println(indent + "i=" + i + ",j=" + j + " temp=" + temp);
composition(i - j, indent != null ? indent + " " : null, master, temp);
}
}
Output of recursive tree n=4
:
i=4,j=4 temp=[4]
i=0 comb=[4]
i=4,j=3 temp=[3]
i=1,j=1 temp=[3, 1]
i=0 comb=[3, 1]
i=4,j=2 temp=[2]
i=2,j=2 temp=[2, 2]
i=0 comb=[2, 2]
i=2,j=1 temp=[2, 1]
i=1,j=1 temp=[2, 1, 1]
i=0 comb=[2, 1, 1]
i=4,j=1 temp=[1]
i=3,j=3 temp=[1, 3]
i=0 comb=[1, 3]
i=3,j=2 temp=[1, 2]
i=1,j=1 temp=[1, 2, 1]
i=0 comb=[1, 2, 1]
i=3,j=1 temp=[1, 1]
i=2,j=2 temp=[1, 1, 2]
i=0 comb=[1, 1, 2]
i=2,j=1 temp=[1, 1, 1]
i=1,j=1 temp=[1, 1, 1, 1]
i=0 comb=[1, 1, 1, 1]
Output of the list n=4
:
[4]
[3, 1]
[2, 2]
[2, 1, 1]
[1, 3]
[1, 2, 1]
[1, 1, 2]
[1, 1, 1, 1]
n
are you hoping to go? I don't see any obvious optimization opportunities but I'm not that familiar with the problem domain. I guess if you use the DP approach to get unique partitions, then permute each result, that might yield some improvement (if that's what you're suggesting), but that seems like a lot of work that pretty much winds up mimicking doing it recursively in terms of total work (I'm not sure). BTW, if you run my solution below, it goes up ton = 23
on my machine then blows up the heap, so it also depends on how you plan to store/use the results. – Chair