Yes, it is unreasonable to expect this approach to be "fast".
This answer will focus on... drumroll, please!
#Why your current approach is slow
Why your current approach is slow
The reason for why it is unreasonable to expect this approach to be fast can be shown simply by adding a private int calls;
field to your class and increasing it at the beginning of your findPartitions(ArrayList<String> p, BigInteger target, BigInteger maxValue, String suffix)
method. Then log this value for different values in your main method.
Value 5 Calls: 20
Value 10 Calls: 103
Value 15 Calls: 333
Value 20 Calls: 896
Value 25 Calls: 2141
Value 30 Calls: 4735
Value 35 Calls: 9877
Value 40 Calls: 19679
Value 45 Calls: 37729
Value 50 Calls: 70073
Value 55 Calls: 126586
Value 60 Calls: 223195
As you can see, the number of calls to the method increases dramatically, of exponential order.enter image description here
This is because you are using a recursive approach to the problem that often creates a new "branch".
So, how to speed this up?
Let's take a look at some of the output for the value 20
:
2 3 7 8
1 4 7 8
5 7 8
2 3 6 9
1 4 6 9
5 6 9
2 3 5 10
1 4 5 10
2 3 4 11
4 5 11
2 3 15
1 4 15
5 15
What do all these have in common? They all can make the value 5
in there some where. 11 + 4 (= 15) + 3 + 2 (= 5).
So, what do I want to say with this?
Once you have calculated the possible partitions for the value of 5, reuse them!
To accomplish this you can use a Map<Integer, List<Integer>>
structure. In your findPartitions
method, check if the map contains a value for target
(map.containsKey
) and if it does then reuse it. If it does not, then do something similar to what you are doing there already and use map.put
at the end to add the found values to the map.
I have to warn you though that even adding this reusing-feature, I still expect it to take quite a long time for larger numbers.
I strongly suggest that you switch back to using int
(or Integer
for storing them in collections). An int will take you to 2 147 483 647
, try partitioning that number first before switching to BigInteger
(Hint hint: It will still take a tremendous amount of time to partition 2 147 483 647
, if you don't believe me then try doing it by hand).
Yes, it is unreasonable to expect this approach to be "fast".
This answer will focus on... drumroll, please!
#Why your current approach is slow
The reason for why it is unreasonable to expect this approach to be fast can be shown simply by adding a private int calls;
field to your class and increasing it at the beginning of your findPartitions(ArrayList<String> p, BigInteger target, BigInteger maxValue, String suffix)
method. Then log this value for different values in your main method.
Value 5 Calls: 20
Value 10 Calls: 103
Value 15 Calls: 333
Value 20 Calls: 896
Value 25 Calls: 2141
Value 30 Calls: 4735
Value 35 Calls: 9877
Value 40 Calls: 19679
Value 45 Calls: 37729
Value 50 Calls: 70073
Value 55 Calls: 126586
Value 60 Calls: 223195
As you can see, the number of calls to the method increases dramatically, of exponential order.enter image description here
This is because you are using a recursive approach to the problem that often creates a new "branch".
So, how to speed this up?
Let's take a look at some of the output for the value 20
:
2 3 7 8
1 4 7 8
5 7 8
2 3 6 9
1 4 6 9
5 6 9
2 3 5 10
1 4 5 10
2 3 4 11
4 5 11
2 3 15
1 4 15
5 15
What do all these have in common? They all can make the value 5
in there some where. 11 + 4 (= 15) + 3 + 2 (= 5).
So, what do I want to say with this?
Once you have calculated the possible partitions for the value of 5, reuse them!
To accomplish this you can use a Map<Integer, List<Integer>>
structure. In your findPartitions
method, check if the map contains a value for target
(map.containsKey
) and if it does then reuse it. If it does not, then do something similar to what you are doing there already and use map.put
at the end to add the found values to the map.
I have to warn you though that even adding this reusing-feature, I still expect it to take quite a long time for larger numbers.
I strongly suggest that you switch back to using int
(or Integer
for storing them in collections). An int will take you to 2 147 483 647
, try partitioning that number first before switching to BigInteger
(Hint hint: It will still take a tremendous amount of time to partition 2 147 483 647
, if you don't believe me then try doing it by hand).
Yes, it is unreasonable to expect this approach to be "fast".
This answer will focus on... drumroll, please!
Why your current approach is slow
The reason for why it is unreasonable to expect this approach to be fast can be shown simply by adding a private int calls;
field to your class and increasing it at the beginning of your findPartitions(ArrayList<String> p, BigInteger target, BigInteger maxValue, String suffix)
method. Then log this value for different values in your main method.
Value 5 Calls: 20
Value 10 Calls: 103
Value 15 Calls: 333
Value 20 Calls: 896
Value 25 Calls: 2141
Value 30 Calls: 4735
Value 35 Calls: 9877
Value 40 Calls: 19679
Value 45 Calls: 37729
Value 50 Calls: 70073
Value 55 Calls: 126586
Value 60 Calls: 223195
As you can see, the number of calls to the method increases dramatically, of exponential order.enter image description here
This is because you are using a recursive approach to the problem that often creates a new "branch".
So, how to speed this up?
Let's take a look at some of the output for the value 20
:
2 3 7 8
1 4 7 8
5 7 8
2 3 6 9
1 4 6 9
5 6 9
2 3 5 10
1 4 5 10
2 3 4 11
4 5 11
2 3 15
1 4 15
5 15
What do all these have in common? They all can make the value 5
in there some where. 11 + 4 (= 15) + 3 + 2 (= 5).
So, what do I want to say with this?
Once you have calculated the possible partitions for the value of 5, reuse them!
To accomplish this you can use a Map<Integer, List<Integer>>
structure. In your findPartitions
method, check if the map contains a value for target
(map.containsKey
) and if it does then reuse it. If it does not, then do something similar to what you are doing there already and use map.put
at the end to add the found values to the map.
I have to warn you though that even adding this reusing-feature, I still expect it to take quite a long time for larger numbers.
I strongly suggest that you switch back to using int
(or Integer
for storing them in collections). An int will take you to 2 147 483 647
, try partitioning that number first before switching to BigInteger
(Hint hint: It will still take a tremendous amount of time to partition 2 147 483 647
, if you don't believe me then try doing it by hand).
Yes, it is unreasonable to expect this approach to be "fast".
This answer will focus on... drumroll, please!
#Why your current approach is slow
The reason for why it is unreasonable to expect this approach to be fast can be shown simply by adding a private int calls;
field to your class and increasing it at the beginning of your findPartitions(ArrayList<String> p, BigInteger target, BigInteger maxValue, String suffix)
method. Then log this value for different values in your main method.
Value 5 Calls: 20
Value 10 Calls: 103
Value 15 Calls: 333
Value 20 Calls: 896
Value 25 Calls: 2141
Value 30 Calls: 4735
Value 35 Calls: 9877
Value 40 Calls: 19679
Value 45 Calls: 37729
Value 50 Calls: 70073
Value 55 Calls: 126586
Value 60 Calls: 223195
As you can see, the number of calls to the method increases dramatically, of exponential order.enter image description here
This is because you are using a recursive approach to the problem that often creates a new "branch".
So, how to speed this up?
Let's take a look at some of the output for the value 20
:
2 3 7 8
1 4 7 8
5 7 8
2 3 6 9
1 4 6 9
5 6 9
2 3 5 10
1 4 5 10
2 3 4 11
4 5 11
2 3 15
1 4 15
5 15
What do all these have in common? They all can make the value 5
in there some where. 11 + 4 (= 15) + 3 + 2 (= 5).
So, what do I want to say with this?
Once you have calculated the possible partitions for the value of 5, reuse them!
To accomplish this you can use a Map<Integer, List<Integer>>
structure. In your findPartitions
method, check if the map contains a value for target
(map.containsKey
) and if it does then reuse it. If it does not, then do something similar to what you are doing there already and use map.put
at the end to add the found values to the map.
I have to warn you though that even adding this reusing-feature, I still expect it to take quite a long time for larger numbers.
I strongly suggest that you switch back to using int
(or Integer
for storing them in collections). An int will take you to 2 147 483 647
, try partitioning that number first before switching to BigInteger
(Hint hint: It will still take a tremendous amount of time to partition 2 147 483 647
, if you don't believe me then try doing it by hand).
Yes, it is unreasonable to expect this approach to be "fast".
This answer will focus on... drumroll, please!
#Why your current approach is slow
The reason for why it is unreasonable to expect this approach to be fast can be shown simply by adding a private int calls;
field to your class and increasing it at the beginning of your findPartitions(ArrayList<String> p, BigInteger target, BigInteger maxValue, String suffix)
method. Then log this value for different values in your main method.
Value 5 Calls: 20
Value 10 Calls: 103
Value 15 Calls: 333
Value 20 Calls: 896
Value 25 Calls: 2141
Value 30 Calls: 4735
Value 35 Calls: 9877
Value 40 Calls: 19679
Value 45 Calls: 37729
Value 50 Calls: 70073
Value 55 Calls: 126586
Value 60 Calls: 223195
As you can see, the number of calls to the method increases dramatically, of exponential order.enter image description here
This is because you are using a recursive approach to the problem that often creates a new "branch".
So, how to speed this up?
Let's take a look at some of the output for the value 20
:
2 3 7 8
1 4 7 8
5 7 8
2 3 6 9
1 4 6 9
5 6 9
2 3 5 10
1 4 5 10
2 3 4 11
4 5 11
2 3 15
1 4 15
5 15
What do all these have in common? They all can make the value 5
in there some where. 11 + 4 (= 15) + 3 + 2 (= 5).
So, what do I want to say with this?
Once you have calculated the possible partitions for the value of 5, reuse them!
To accomplish this you can use a Map<Integer, List<Integer>>
structure. In your findPartitions
method, check if the map contains a value for target
(map.containsKey
) and if it does then reuse it. If it does not, then do something similar to what you are doing there already and use map.put
at the end to add the found values to the map.
I strongly suggest that you switch back to using int
(or Integer
for storing them in collections). An int will take you to 2 147 483 647
, try partitioning that number first before switching to BigInteger
(Hint hint: It will still take a tremendous amount of time to partition 2 147 483 647
, if you don't believe me then try doing it by hand).
Yes, it is unreasonable to expect this approach to be "fast".
This answer will focus on... drumroll, please!
#Why your current approach is slow
The reason for why it is unreasonable to expect this approach to be fast can be shown simply by adding a private int calls;
field to your class and increasing it at the beginning of your findPartitions(ArrayList<String> p, BigInteger target, BigInteger maxValue, String suffix)
method. Then log this value for different values in your main method.
Value 5 Calls: 20
Value 10 Calls: 103
Value 15 Calls: 333
Value 20 Calls: 896
Value 25 Calls: 2141
Value 30 Calls: 4735
Value 35 Calls: 9877
Value 40 Calls: 19679
Value 45 Calls: 37729
Value 50 Calls: 70073
Value 55 Calls: 126586
Value 60 Calls: 223195
As you can see, the number of calls to the method increases dramatically, of exponential order.enter image description here
This is because you are using a recursive approach to the problem that often creates a new "branch".
So, how to speed this up?
Let's take a look at some of the output for the value 20
:
2 3 7 8
1 4 7 8
5 7 8
2 3 6 9
1 4 6 9
5 6 9
2 3 5 10
1 4 5 10
2 3 4 11
4 5 11
2 3 15
1 4 15
5 15
What do all these have in common? They all can make the value 5
in there some where. 11 + 4 (= 15) + 3 + 2 (= 5).
So, what do I want to say with this?
Once you have calculated the possible partitions for the value of 5, reuse them!
To accomplish this you can use a Map<Integer, List<Integer>>
structure. In your findPartitions
method, check if the map contains a value for target
(map.containsKey
) and if it does then reuse it. If it does not, then do something similar to what you are doing there already and use map.put
at the end to add the found values to the map.
I have to warn you though that even adding this reusing-feature, I still expect it to take quite a long time for larger numbers.
I strongly suggest that you switch back to using int
(or Integer
for storing them in collections). An int will take you to 2 147 483 647
, try partitioning that number first before switching to BigInteger
(Hint hint: It will still take a tremendous amount of time to partition 2 147 483 647
, if you don't believe me then try doing it by hand).
Yes, it is unreasonable to expect this approach to be "fast".
This answer will focus on... drumroll, please!
#Why your current approach is slow
The reason for why it is unreasonable to expect this approach to be fast can be shown simply by adding a private int calls;
field to your class and increasing it at the beginning of your findPartitions(ArrayList<String> p, BigInteger target, BigInteger maxValue, String suffix)
method. Then log this value for different values in your main method.
Value 5 Calls: 20
Value 10 Calls: 103
Value 15 Calls: 333
Value 20 Calls: 896
Value 25 Calls: 2141
Value 30 Calls: 4735
Value 35 Calls: 9877
Value 40 Calls: 19679
Value 45 Calls: 37729
Value 50 Calls: 70073
Value 55 Calls: 126586
Value 60 Calls: 223195
As you can see, the number of calls to the method increases dramatically, of exponential order.enter image description here
This is because you are using a recursive approach to the problem that often creates a new "branch".
So, how to speed this up?
Let's take a look at some of the output for the value 20
:
2 3 7 8
1 4 7 8
5 7 8
2 3 6 9
1 4 6 9
5 6 9
2 3 5 10
1 4 5 10
2 3 4 11
4 5 11
2 3 15
1 4 15
5 15
What do all these have in common? They all can make the value 5
in there some where. 11 + 4 (= 15) + 3 + 2 (= 5).
So, what do I want to say with this?
Once you have calculated the possible partitions for the value of 5, reuse them!
To accomplish this you can use a Map<Integer, List<Integer>>
structure. In your findPartitions
method, check if the map contains a value for target
(map.containsKey
) and if it does then reuse it. If it does not, then do something similar to what you are doing there already and use map.put
at the end to add the found values to the map.
I strongly suggest that you switch back to using int
(or Integer
for storing them in collections). An int will take you to 2 147 483 647
, try partitioning that number first before switching to BigInteger
(Hint hint: It will still take a tremendous amount of time to partition 2 147 483 647
, if you don't believe me then try doing it by hand).