I am working on a project involving the unique partitioning of integers. I.e. I am looking to have all of the partitions of n = x1 + x2 + x3 + ... + xk, where xi = xj implies i = j.
For example, if I give my code input of 10, I want to have as output (in an ArrayList<ArrayList<BigInteger>>
) the following:
[[1, 2, 3, 4], [2, 3, 5], [1, 4, 5], [1, 3, 6], [4, 6], [1, 2, 7], [3, 7], [2, 8], [1, 9], [10]]
Note that I don't have [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], etc. because these have duplicate entries.
The problem is, once I try to get all of the unique partitions of numbers greater than 70 or so, it starts to take a noticeable amount of time. Further, this shouldn't be a particularly slow algorithm.
The class is below:
import java.math.*;
import java.util.*;
public class UniquePartition {
private BigInteger n;
private ArrayList<ArrayList<BigInteger>> allPartitions;
//Constructs the object with integer. Sets the target and then calculates partitions.
public UniquePartition(int num) {
n = new BigInteger(String.valueOf(num));
allPartitions = new ArrayList<ArrayList<BigInteger>>();
allPartitions = findPartitions();
}
//Constructs the object. Sets the target and then calculates partitions.
public UniquePartition(BigInteger num) {
n = num;
allPartitions = new ArrayList<ArrayList<BigInteger>>();
allPartitions = findPartitions();
}
//Returns partitions without calculating them.
public ArrayList<ArrayList<BigInteger>> getPartitions() {
return allPartitions;
}
//Returns the nth partition without calculating them.
public ArrayList<BigInteger> getPartitionN(int n) {
// ArrayList<ArrayList<BigInteger>> partitions = new ArrayList<ArrayList<BigInteger>>();
return allPartitions.get(n);
}
// Returns an ArrayList containing ArrayLists, each of which is a single partition. Should never be called, otherwise
// will redo calculation.
public ArrayList<ArrayList<BigInteger>> findPartitions() {
ArrayList<String> pS = new ArrayList<String>();
pS = findPartitions(pS,n,n,"");
for(int i=0;i<pS.size();i++) {
ArrayList<BigInteger> partition = new ArrayList<BigInteger>();
String line[] = (pS.get(i)).split(" ");
for (String entry: line) {
BigInteger num = new BigInteger(entry);
partition.add(num);
}
allPartitions.add(partition);
}
return allPartitions;
}
//Stores the partitions in an ArrayList<String>. Never used alone. getAllPartitions() is the driver for this method.
public ArrayList<String> findPartitions(ArrayList<String> p, BigInteger target, BigInteger maxValue, String suffix) {
if (target.equals(BigInteger.ZERO)) {
// System.out.println(suffix);
p.add(suffix);
}
else {
if (maxValue.compareTo(BigInteger.ONE) > 0)
findPartitions(p, target, maxValue.subtract(BigInteger.ONE), suffix);
if (maxValue.compareTo(target)<=0 && !containsInteger(maxValue,suffix))
findPartitions(p, target.subtract(maxValue), maxValue, maxValue + " " + suffix);
}
return p;
}
//Checks if String s contains the BigInteger n. If so, return true, otherwise return false.
public boolean containsInteger(BigInteger n, String s) {
boolean b = false;
String line[] = s.split(" ");
for(String entry: line) {
if(entry == "")
entry = "0";
BigInteger BI = new BigInteger(entry);
if(n.equals(BI))
b = true;
}
return b;
}
//Returns string with all partitions.
public String toString() {
String output = "";
for(int i = 0;i<allPartitions.size();i++) {
for(int j=0; j<(allPartitions.get(i)).size();j++) {
output = output + (allPartitions.get(i)).get(j).toString()+" ";
}
output = output + "\n";
}
return output;
}
//Returns string with kth partition.
public String toString(int k) {
String output = "";
for(int j=0; j<(allPartitions.get(k)).size();j++) {
output = output + (allPartitions.get(k)).get(j).toString()+" ";
}
return output;
}
}
My driver class is below:
import java.math.*;
import java.util.*;
public class test {
public static void main(String[] args) {
long nanos =0;
int target = TARGET;
System.gc();
nanos = System.nanoTime();
UniquePartition part = new UniquePartition(target);
nanos = System.nanoTime() - nanos;
System.out.println("Time taken to calculate: "+nanos/1000000.0+"ms");
}
}
So the question is, is there any way that I can improve the speed of this code? I'm looking to be able to search partitions of very large numbers in a reasonable period of time (as you can tell from the BigInteger constructor!). Is that unreasonable to expect? The algorithm itself doesn't seem to be slow... or is it? Any help would be appreciated!