How to display all number by increment? - validation

i was task to ask a user to enter a number in range from 1 to 15 and after 5 input, i suppose to display all the number that enter by the user.
saying the user enter 2, 3, 4, 5, and 6, this is what i suppose to display:
1 2
1 2 3
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6
package barChartPrinting;
import java.util.Scanner;
public class barChart {
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
int getNumber;
for (int counter = 0; counter < 5; counter++){
System.out.println("Enter a numbers in range of 1 to 15: ");
getNumber = keyboard.nextInt();
while (getNumber < 1 || getNumber > 15){
System.out.println("Invalid number!, please re-enter: ");
getNumber = keyboard.nextInt();
}
}
//end of statement here
}
}

Related

How would one solve the staircase problem recursively with a variable number of steps?

The problem of determining the n amount of ways to climb a staircase given you can take 1 or 2 steps is well known with the Fibonacci sequencing solution being very clear. However how exactly could one solve this recursively if you also assume that you can take a variable M amount of steps?
I tried to make a quick mockup of this algorithm in typescript with
function counter(n: number, h: number){
console.log(`counter(n=${n},h=${h})`);
let sum = 0
if(h<1) return 0;
sum = 1
if (n>h) {
n = h;
}
if (n==h) {
sum = Math.pow(2, h-1)
console.log(`return sum=${sum}, pow(2,${h-1}) `)
return sum
}
for (let c = 1; c <= h; c++) {
console.log(`c=${c}`)
sum += counter(n, h-c);
console.log(`sum=${sum}`)
}
console.log(`return sum=${sum}`)
return sum;
}
let result = counter (2, 4);
console.log(`result=${result}`)
but unfortunately this doesn't seem to work for most cases where the height is not equal to the number of steps one could take.
I think this could be solved with recursive DP.
vector<vector<int>> dp2; //[stair count][number of jumps]
int stair(int c, int p) {
int& ret = dp2[c][p];
if (ret != -1) return ret; //If you've already done same search, return saved result
if (c == n) { //If you hit the last stair, return 1
return ret = 1;
}
int s1 = 0, s2 = 0;
if (p < m) { //If you can do more jumps, make recursive call
s1 = stair(c + 1, p + 1);
if (c + 2 <= n) { //+2 stairs can jump over the last stair. That shouldn't happen.
s2 = stair(c + 2, p + 1);
}
}
return ret = s1 + s2; //Final result will be addition of +1 stair methods and +2 methods
}
int main()
{
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> n >> m; dp2 = vector<vector<int>>(n + 1, vector<int>(m + 1, -1));
for (int i = 1; i <= m; i++) {
dp2[n][i] = 1; //All last stair method count should be 1, because there is no more after.
}
cout << stair(0, 0) << "\n";
return 0;
}
Example IO 1
5 5
8
// 1 1 1 1 1
// 1 1 1 2
// 1 1 2 1
// 1 2 1 1
// 2 1 1 1
// 1 2 2
// 2 1 2
// 2 2 1
Example IO 2
5 4
7
// 1 1 1 2
// 1 1 2 1
// 1 2 1 1
// 2 1 1 1
// 1 2 2
// 2 1 2
// 2 2 1
Example IO 3
5 3
3
// 1 2 2
// 2 1 2
// 2 2 1

2d array table form print out

so if a user input 9 random numbers
my code prints like this in its sorted form
1 2 3 4 5 6 7 8 9
but I want it to print like a table form
like this
1 2 3
4 5 6
7 8 9
The output after running the code appears as follows:
Please enter number of rows: 3
Please enter number of columns: 3
Please enter 9 numbers to sort: 9 8 7 6 5 4 3 2 1
Sorted numbers:
1 2 3 4 5 6 7 8 9
<emtpy line>
import java.util.Scanner;
public class table
{
public static void main(String args[])
{
System.out.println("Sorted numbers: ");
for(int x = 0; x < matrix.length; x++)
for (int y = 0; y < matrix[x].length; y++)
{
System.out.print(matrix[x][y] + " ");
}
System.out.println(" ");
}
}
Your issue is here:
for(int x = 0; x < matrix.length; x++)
for (int y = 0; y < matrix[x].length; y++)
{
System.out.print(matrix[x][y] + " ");
}
System.out.println(" ");
You didn't enclose your print statement in the outer for loop. If you add brackets, everything in your for loop will execute.
for(int x = 0; x < matrix.length; x++)
{
for (int y = 0; y < matrix[x].length; y++)
{
System.out.print(matrix[x][y] + " ");
}
System.out.println(" ");
}
This way your inner for loop will execute printing all your numbers on a line followed by the println execution and then it repeats.
With this modification, I have arrived at this output:
Please enter number of rows: 3
Please enter number of columns: 3
Please enter 9 numbers to sort: 8 7 6 4 3 1 2 5 9
Sorted numbers:
1 2 3
4 5 6
7 8 9
<empty line>

Gold Mine Problem - Sequence of for loops

Gold mine problem. Following sequence for loop is giving correct result.
//see link for other code
static int getMaxGold(int gold[][], int m, int n) {
//see link for other code
for (int col = n-1; col >= 0; col--) {
for (int row = 0; row < m; row++) {
int right = (col == n-1) ? 0 : goldTable[row][col+1];
int right_up = (row == 0 || col == n-1) ? 0 : goldTable[row-1][col+1];
int right_down = (row == m-1 || col == n-1) ? 0 : goldTable[row+1][col+1];
goldTable[row][col] = gold[row][col] + Math.max(right, Math.max(right_up, right_down));
}
}
}
//see link for other code
While other way round does not give the expected result. For example
for (int col = 0; col < n; col ++) {
for (int row = 0; row < m; row++) {
//same code to calculate right, rightUp and rightDown
}
}
Any explanation for this behaviour?
You don't need to store a whole matrix.
When you build the table, you just need to keep the last layer you processed.
In your recursion, there is diagonally right, or right, so the layer is a column because to compute the value of some cell, you need to know three values (on its right)
You conclude (as spotted by Damien already) that you start from the rightmost column, then to compute the value of every cells of the n-1 column, you only need to know the nth column (which you luckily computed already)
In below example. m_ij refers to i-th line, j-th column. (e.g m_01 == 2, m_10 = 5)
1 2 3 4
5 6 7 8
9 1 2 3
4 5 6 3
The last column is {4,8,3,3}
To compute the max value for m_02 you need to choose between 4 and 8
3 - 4
\
8
m_02 = 3 + 8 = 11
To compute the max value of m_12 you need to choose between 4, 8 and 3
4
/
7 - 8
\
3
m_12 = 7 + 8 = 15
Skipping stuff
m_22 = 2 + 8 = 10
m_32 = 6 + 3 = 9
Now you know the max value for each square of the third column
1 2 11 .
5 6 15 .
9 1 10 .
4 5 9 .
You do the same for m_10, m_11, ...
idem
m_01 = 2 + max(11, 15) = 17
m_11 = 6 + 15
m_21 = 1 + 15
m_31 = 5 + 10
Left to process is thus
1 17
5 21
9 16
4 15
Then
1+21
5+21
9+21
4+16
And finally score = max(22, 26, 30, 20)
As you have noticed you only need to keep track of the last processed column. Not a whole table of computation. And the last processed column must start from the right and always be the rightmost one...
I don't think an implem is relevant to help you understand but in case
const s = `
1 2 3 4
5 6 7 8
9 1 2 3
4 5 6 3`
const m = s.trim().split('\n').map(x => x.trim().split(' ').map(y => parseInt(y)))
let layer = [0, 0, 0, 0]
for (let j = 3; j >= 0; --j) {
const nextLayer = []
for (let i = 0; i < 4; ++i) {
nextLayer[i] = m[i][j] + Math.max(
layer[i-1] || 0, // we default undefined value as 0 supposing s only holds positive coefficient
layer[i],
layer[i+1] || 0
)
}
layer = nextLayer
}
console.log(Math.max(...layer))

Most Frequent Digit In a Specific Range

First of all: before you downgrade THIS IS NOT MY HOMEWORK, this question belongs to codingbat or eulerproject or another website. I am NOT asking you to give me a fully completed and coded answer I am asking you to give me some ideas to HELP me.
Later on, I am having a time limit trouble with this problem. I actually solved it but my solution is too slow. It needs to be done within at 0 to 1 second. In the worst case scenario my code consumes more than 8 seconds. If you could help me with some ideas or if you could show me a more accurate solution pseudo code etc. I would really appreciate it.
First input means how many times we are going to process. Later on, user enters two numbers [X, Y], (0 < X < Y < 100000) We need to compute the most frequent digit in the range of these two numbers X and Y. (including X and Y) Besides, If multiple digits have the same maximum frequency than we suppose to print the smallest of them.
To illustrate:
User first enters number of test cases: 7
User enters X and Y(first test case): 0 21
Now I did open all digits in my solution you may have another idea you are free to use it but to give you a hint: We need to treat numbers like this: 0 1 2 3 ... (here we should open 10 as 1 and 0 same for all of them) 1 0 1 1 1 2 1 3 ... 1 9 2 0 2 1 than we show the most frequent digit between 0 and 21 (In this case: 1)
More examples: (Test cases if you want to check your solution)
X: 7 Y: 956 Result: 1
X: 967 Y: 8000 Result: 7
X: 420 Y: 1000 Result: 5 etc.
Here's my code so far:
package most_frequent_digit;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
public class Main
{
public static int secondP = 0;
public static void getPopularElement(int[] list)
{
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (Integer nextInt : list)
{
Integer count = map.get(nextInt);
if (count == null)
{
count = 1;
} else
{
count = count + 1;
}
map.put(nextInt, count);
}
Integer mostRepeatedNumber = null;
Integer mostRepeatedCount = null;
Set<Integer> keys = map.keySet();
for (Integer key : keys)
{
Integer count = map.get(key);
if (mostRepeatedNumber == null)
{
mostRepeatedNumber = key;
mostRepeatedCount = count;
} else if (count > mostRepeatedCount)
{
mostRepeatedNumber = key;
mostRepeatedCount = count;
} else if (count == mostRepeatedCount && key < mostRepeatedNumber)
{
mostRepeatedNumber = key;
mostRepeatedCount = count;
}
}
System.out.println(mostRepeatedNumber);
}
public static void main(String[] args)
{
#SuppressWarnings("resource")
Scanner read = new Scanner(System.in);
int len = read.nextInt();
for (int w = 0; w < len; w++)
{
int x = read.nextInt();
int y = read.nextInt();
String list = "";
for (int i = x; i <= y; i++)
{
list += i;
}
String newList = "";
newList += list.replaceAll("", " ").trim();
int[] listArr = new int[list.length()];
for (int j = 0; j < newList.length(); j += 2)
{
listArr[secondP] = Character.getNumericValue(newList.charAt(j));
secondP++;
}
getPopularElement(listArr);
secondP = 0;
}
}
}
As you can see it takes too long if user enters X: 0 Y: 1000000 like 8 - 9 seconds. But it supposed to return answer in 1 second. Thanks for checking...
Listing all digits and then count them is a very slow way to do this.
There are some simple cases:
X = 10n, X = 10n+1-1 (n > 0) :
The digits 1 to 9 are appearing 10n + n⋅(10n-10n-1) times, 0 appears n⋅(10n-10n-1) times.
E.g.
10, 99: the digits 1 to 9 are appearing 19 times, 0 appears 9 times.
100, 999: the digits 1 to 9 are appearing 280 times, 0 appears 180 times.
X = a⋅10ⁿ, Y = (a+1)⋅10ⁿ-1 (1 ≤ a ≤ 9):
All digits except for a appears n⋅10n-1, the digit a appears 10n + n⋅10n-1 times.
E.g.
10, 19: all digits except for 1 appear one time, 1 appears 11 times.
20, 299: all digits except for 2 appear 20 times, 2 appears 120 times.
With this cases you can split off the input into sub cases. E.g.
X = 0, Y = 21. Split it up into
X₁ = 0, Y₁ = 9 (special case, but very simple),
X₂ = 10, Y₂ = 19 (case 2),
X₃ = 20, Y₃ = 21 (case 3)
X = 0, Y = 3521. Split it up into
X₁ = 0, Y₁ = 9 (special case, but very simple),
X₂ = 10, Y₂ = 99 (case 1),
X₃ = 100, Y₃ = 999 (case 1),
X₄ = 1000, Y₄ = 1999 (case 2),
X₅ = 2000, Y₅ = 2999 (case 2),
X₆ = 3000, Y₆ = 3521 (case 3)
I left case 3 open. The case looks like X = a⋅10ⁿ, Y = a⋅10ⁿ + b (1 ≤ a ≤ 9, 0 ≤ b < 10ⁿ).
Here you know you get the digit a b-times plus the number of appearances in 0 to b. Since X and Y are n+1 digit numbers, b has n digits, with leading zeros.
The missing parts of case 3 have to be filled by the reader.

Finding all possible combinations of numbers to reach a given sum

How would you go about testing all possible combinations of additions from a given set N of numbers so they add up to a given final number?
A brief example:
Set of numbers to add: N = {1,5,22,15,0,...}
Desired result: 12345
This problem can be solved with a recursive combinations of all possible sums filtering out those that reach the target. Here is the algorithm in Python:
def subset_sum(numbers, target, partial=[]):
s = sum(partial)
# check if the partial sum is equals to target
if s == target:
print "sum(%s)=%s" % (partial, target)
if s >= target:
return # if we reach the number why bother to continue
for i in range(len(numbers)):
n = numbers[i]
remaining = numbers[i+1:]
subset_sum(remaining, target, partial + [n])
if __name__ == "__main__":
subset_sum([3,9,8,4,5,7,10],15)
#Outputs:
#sum([3, 8, 4])=15
#sum([3, 5, 7])=15
#sum([8, 7])=15
#sum([5, 10])=15
This type of algorithms are very well explained in the following Stanford's Abstract Programming lecture - this video is very recommendable to understand how recursion works to generate permutations of solutions.
Edit
The above as a generator function, making it a bit more useful. Requires Python 3.3+ because of yield from.
def subset_sum(numbers, target, partial=[], partial_sum=0):
if partial_sum == target:
yield partial
if partial_sum >= target:
return
for i, n in enumerate(numbers):
remaining = numbers[i + 1:]
yield from subset_sum(remaining, target, partial + [n], partial_sum + n)
Here is the Java version of the same algorithm:
package tmp;
import java.util.ArrayList;
import java.util.Arrays;
class SumSet {
static void sum_up_recursive(ArrayList<Integer> numbers, int target, ArrayList<Integer> partial) {
int s = 0;
for (int x: partial) s += x;
if (s == target)
System.out.println("sum("+Arrays.toString(partial.toArray())+")="+target);
if (s >= target)
return;
for(int i=0;i<numbers.size();i++) {
ArrayList<Integer> remaining = new ArrayList<Integer>();
int n = numbers.get(i);
for (int j=i+1; j<numbers.size();j++) remaining.add(numbers.get(j));
ArrayList<Integer> partial_rec = new ArrayList<Integer>(partial);
partial_rec.add(n);
sum_up_recursive(remaining,target,partial_rec);
}
}
static void sum_up(ArrayList<Integer> numbers, int target) {
sum_up_recursive(numbers,target,new ArrayList<Integer>());
}
public static void main(String args[]) {
Integer[] numbers = {3,9,8,4,5,7,10};
int target = 15;
sum_up(new ArrayList<Integer>(Arrays.asList(numbers)),target);
}
}
It is exactly the same heuristic. My Java is a bit rusty but I think is easy to understand.
C# conversion of Java solution: (by #JeremyThompson)
public static void Main(string[] args)
{
List<int> numbers = new List<int>() { 3, 9, 8, 4, 5, 7, 10 };
int target = 15;
sum_up(numbers, target);
}
private static void sum_up(List<int> numbers, int target)
{
sum_up_recursive(numbers, target, new List<int>());
}
private static void sum_up_recursive(List<int> numbers, int target, List<int> partial)
{
int s = 0;
foreach (int x in partial) s += x;
if (s == target)
Console.WriteLine("sum(" + string.Join(",", partial.ToArray()) + ")=" + target);
if (s >= target)
return;
for (int i = 0; i < numbers.Count; i++)
{
List<int> remaining = new List<int>();
int n = numbers[i];
for (int j = i + 1; j < numbers.Count; j++) remaining.Add(numbers[j]);
List<int> partial_rec = new List<int>(partial);
partial_rec.Add(n);
sum_up_recursive(remaining, target, partial_rec);
}
}
Ruby solution: (by #emaillenin)
def subset_sum(numbers, target, partial=[])
s = partial.inject 0, :+
# check if the partial sum is equals to target
puts "sum(#{partial})=#{target}" if s == target
return if s >= target # if we reach the number why bother to continue
(0..(numbers.length - 1)).each do |i|
n = numbers[i]
remaining = numbers.drop(i+1)
subset_sum(remaining, target, partial + [n])
end
end
subset_sum([3,9,8,4,5,7,10],15)
Edit: complexity discussion
As others mention this is an NP-hard problem. It can be solved in exponential time O(2^n), for instance for n=10 there will be 1024 possible solutions. If the targets you are trying to reach are in a low range then this algorithm works. So for instance:
subset_sum([1,2,3,4,5,6,7,8,9,10],100000) generates 1024 branches because the target never gets to filter out possible solutions.
On the other hand subset_sum([1,2,3,4,5,6,7,8,9,10],10) generates only 175 branches, because the target to reach 10 gets to filter out many combinations.
If N and Target are big numbers one should move into an approximate version of the solution.
The solution of this problem has been given a million times on the Internet. The problem is called The coin changing problem. One can find solutions at http://rosettacode.org/wiki/Count_the_coins and mathematical model of it at http://jaqm.ro/issues/volume-5,issue-2/pdfs/patterson_harmel.pdf (or Google coin change problem).
By the way, the Scala solution by Tsagadai, is interesting. This example produces either 1 or 0. As a side effect, it lists on the console all possible solutions. It displays the solution, but fails making it usable in any way.
To be as useful as possible, the code should return a List[List[Int]]in order to allow getting the number of solution (length of the list of lists), the "best" solution (the shortest list), or all the possible solutions.
Here is an example. It is very inefficient, but it is easy to understand.
object Sum extends App {
def sumCombinations(total: Int, numbers: List[Int]): List[List[Int]] = {
def add(x: (Int, List[List[Int]]), y: (Int, List[List[Int]])): (Int, List[List[Int]]) = {
(x._1 + y._1, x._2 ::: y._2)
}
def sumCombinations(resultAcc: List[List[Int]], sumAcc: List[Int], total: Int, numbers: List[Int]): (Int, List[List[Int]]) = {
if (numbers.isEmpty || total < 0) {
(0, resultAcc)
} else if (total == 0) {
(1, sumAcc :: resultAcc)
} else {
add(sumCombinations(resultAcc, sumAcc, total, numbers.tail), sumCombinations(resultAcc, numbers.head :: sumAcc, total - numbers.head, numbers))
}
}
sumCombinations(Nil, Nil, total, numbers.sortWith(_ > _))._2
}
println(sumCombinations(15, List(1, 2, 5, 10)) mkString "\n")
}
When run, it displays:
List(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
List(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2)
List(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2)
List(1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2)
List(1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2)
List(1, 1, 1, 1, 1, 2, 2, 2, 2, 2)
List(1, 1, 1, 2, 2, 2, 2, 2, 2)
List(1, 2, 2, 2, 2, 2, 2, 2)
List(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5)
List(1, 1, 1, 1, 1, 1, 1, 1, 2, 5)
List(1, 1, 1, 1, 1, 1, 2, 2, 5)
List(1, 1, 1, 1, 2, 2, 2, 5)
List(1, 1, 2, 2, 2, 2, 5)
List(2, 2, 2, 2, 2, 5)
List(1, 1, 1, 1, 1, 5, 5)
List(1, 1, 1, 2, 5, 5)
List(1, 2, 2, 5, 5)
List(5, 5, 5)
List(1, 1, 1, 1, 1, 10)
List(1, 1, 1, 2, 10)
List(1, 2, 2, 10)
List(5, 10)
The sumCombinations() function may be used by itself, and the result may be further analyzed to display the "best" solution (the shortest list), or the number of solutions (the number of lists).
Note that even like this, the requirements may not be fully satisfied. It might happen that the order of each list in the solution be significant. In such a case, each list would have to be duplicated as many time as there are combination of its elements. Or we might be interested only in the combinations that are different.
For example, we might consider that List(5, 10) should give two combinations: List(5, 10) and List(10, 5). For List(5, 5, 5) it could give three combinations or one only, depending on the requirements. For integers, the three permutations are equivalent, but if we are dealing with coins, like in the "coin changing problem", they are not.
Also not stated in the requirements is the question of whether each number (or coin) may be used only once or many times. We could (and we should!) generalize the problem to a list of lists of occurrences of each number. This translates in real life into "what are the possible ways to make an certain amount of money with a set of coins (and not a set of coin values)". The original problem is just a particular case of this one, where we have as many occurrences of each coin as needed to make the total amount with each single coin value.
A Javascript version:
function subsetSum(numbers, target, partial) {
var s, n, remaining;
partial = partial || [];
// sum partial
s = partial.reduce(function (a, b) {
return a + b;
}, 0);
// check if the partial sum is equals to target
if (s === target) {
console.log("%s=%s", partial.join("+"), target)
}
if (s >= target) {
return; // if we reach the number why bother to continue
}
for (var i = 0; i < numbers.length; i++) {
n = numbers[i];
remaining = numbers.slice(i + 1);
subsetSum(remaining, target, partial.concat([n]));
}
}
subsetSum([3,9,8,4,5,7,10],15);
// output:
// 3+8+4=15
// 3+5+7=15
// 8+7=15
// 5+10=15
In Haskell:
filter ((==) 12345 . sum) $ subsequences [1,5,22,15,0,..]
And J:
(]#~12345=+/#>)(]<##~[:#:#i.2^#)1 5 22 15 0 ...
As you may notice, both take the same approach and divide the problem into two parts: generate each member of the power set, and check each member's sum to the target.
There are other solutions but this is the most straightforward.
Do you need help with either one, or finding a different approach?
There are a lot of solutions so far, but all are of the form generate then filter. Which means that they potentially spend a lot of time working on recursive paths that do not lead to a solution.
Here is a solution that is O(size_of_array * (number_of_sums + number_of_solutions)). In other words it uses dynamic programming to avoid enumerating possible solutions that will never match.
For giggles and grins I made this work with numbers that are both positive and negative, and made it an iterator. It will work for Python 2.3+.
def subset_sum_iter(array, target):
sign = 1
array = sorted(array)
if target < 0:
array = reversed(array)
sign = -1
# Checkpoint A
last_index = {0: [-1]}
for i in range(len(array)):
for s in list(last_index.keys()):
new_s = s + array[i]
if 0 < (new_s - target) * sign:
pass # Cannot lead to target
elif new_s in last_index:
last_index[new_s].append(i)
else:
last_index[new_s] = [i]
# Checkpoint B
# Now yield up the answers.
def recur(new_target, max_i):
for i in last_index[new_target]:
if i == -1:
yield [] # Empty sum.
elif max_i <= i:
break # Not our solution.
else:
for answer in recur(new_target - array[i], i):
answer.append(array[i])
yield answer
for answer in recur(target, len(array)):
yield answer
And here is an example of it being used with an array and target where the filtering approach used in other solutions would effectively never finish.
def is_prime(n):
for i in range(2, n):
if 0 == n % i:
return False
elif n < i * i:
return True
if n == 2:
return True
else:
return False
def primes(limit):
n = 2
while True:
if is_prime(n):
yield(n)
n = n + 1
if limit < n:
break
for answer in subset_sum_iter(primes(1000), 76000):
print(answer)
This prints all 522 answers in under 2 seconds. The previous approaches would be lucky to find any answers in the current lifetime of the universe. (The full space has 2^168 = 3.74144419156711e+50 possible combinations to run through. That...takes a while.)
Explanation
I was asked to explain the code, but explaining data structures is usually more revealing. So I'll explain the data structures.
Let's consider subset_sum_iter([-2, 2, -3, 3, -5, 5, -7, 7, -11, 11], 10).
At checkpoint A, we have realized that our target is positive so sign = 1. And we've sorted our input so that array = [-11, -7, -5, -3, -2, 2, 3, 5, 7, 11]. Since we wind up accessing it by index a lot, here the the map from indexes to values:
0: -11
1: -7
2: -5
3: -3
4: -2
5: 2
6: 3
7: 5
8: 7
9: 11
By checkpoint B we have used Dynamic Programming to generate our last_index data structure. What does it contain?
last_index = {
-28: [4],
-26: [3, 5],
-25: [4, 6],
-24: [5],
-23: [2, 4, 5, 6, 7],
-22: [6],
-21: [3, 4, 5, 6, 7, 8],
-20: [4, 6, 7],
-19: [3, 5, 7, 8],
-18: [1, 4, 5, 6, 7, 8],
-17: [4, 5, 6, 7, 8, 9],
-16: [2, 4, 5, 6, 7, 8],
-15: [3, 5, 6, 7, 8, 9],
-14: [3, 4, 5, 6, 7, 8, 9],
-13: [4, 5, 6, 7, 8, 9],
-12: [2, 4, 5, 6, 7, 8, 9],
-11: [0, 5, 6, 7, 8, 9],
-10: [3, 4, 5, 6, 7, 8, 9],
-9: [4, 5, 6, 7, 8, 9],
-8: [3, 5, 6, 7, 8, 9],
-7: [1, 4, 5, 6, 7, 8, 9],
-6: [5, 6, 7, 8, 9],
-5: [2, 4, 5, 6, 7, 8, 9],
-4: [6, 7, 8, 9],
-3: [3, 5, 6, 7, 8, 9],
-2: [4, 6, 7, 8, 9],
-1: [5, 7, 8, 9],
0: [-1, 5, 6, 7, 8, 9],
1: [6, 7, 8, 9],
2: [5, 6, 7, 8, 9],
3: [6, 7, 8, 9],
4: [7, 8, 9],
5: [6, 7, 8, 9],
6: [7, 8, 9],
7: [7, 8, 9],
8: [7, 8, 9],
9: [8, 9],
10: [7, 8, 9]
}
(Side note, it is not symmetric because the condition if 0 < (new_s - target) * sign stops us from recording anything past target, which in our case was 10.)
What does this mean? Well, take the entry, 10: [7, 8, 9]. It means that we can wind up at a final sum of 10 with the last number chosen being at indexes 7, 8, or 9. Namely the last number chosen could be 5, 7, or 11.
Let's take a closer look at what happens if we choose index 7. That means we end on a 5. So therefore before we came to index 7, we had to get to 10-5 = 5. And the entry for 5 reads, 5: [6, 7, 8, 9]. So we could have picked index 6, which is 3. While we get to 5 at indexes 7, 8, and 9, we didn't get there before index 7. So our second to last choice has to be the 3 at index 6.
And now we have to get to 5-3 = 2 before index 6. The entry 2 reads: 2: [5, 6, 7, 8, 9]. Again, we only care about the answer at index 5 because the others happened too late. So the third to last choice is has to be the 2 at index 5.
And finally we have to get to 2-2 = 0 before index 5. The entry 0 reads: 0: [-1, 5, 6, 7, 8, 9]. Again we only care about the -1. But -1 isn't an index - in fact I'm using it to signal we're done choosing.
So we just found the solution 2+3+5 = 10. Which is the very first solution we print out.
And now we get to the recur subfunction. Because it is defined inside of our main function, it can see last_index.
The first thing to note is that it calls yield, not return. This makes it into a generator. When you call it you return a special kind of iterator. When you loop over that iterator, you'll get a list of all of the things it can yield. But you get them as it generates them. If it is a long list, you don't put it in memory. (Kind of important because we could get a long list.)
What recur(new_target, max_i) will yield are all of the ways that you could have summed up to new_target using only elements of array with maximum index max_i. That is it answers: "We have to get to new_target before index max_i+1." It is, of course, recursive.
Therefore recur(target, len(array)) is all solutions that reach target using any index at all. Which is what we want.
C++ version of the same algorithm
#include <iostream>
#include <list>
void subset_sum_recursive(std::list<int> numbers, int target, std::list<int> partial)
{
int s = 0;
for (std::list<int>::const_iterator cit = partial.begin(); cit != partial.end(); cit++)
{
s += *cit;
}
if(s == target)
{
std::cout << "sum([";
for (std::list<int>::const_iterator cit = partial.begin(); cit != partial.end(); cit++)
{
std::cout << *cit << ",";
}
std::cout << "])=" << target << std::endl;
}
if(s >= target)
return;
int n;
for (std::list<int>::const_iterator ai = numbers.begin(); ai != numbers.end(); ai++)
{
n = *ai;
std::list<int> remaining;
for(std::list<int>::const_iterator aj = ai; aj != numbers.end(); aj++)
{
if(aj == ai)continue;
remaining.push_back(*aj);
}
std::list<int> partial_rec=partial;
partial_rec.push_back(n);
subset_sum_recursive(remaining,target,partial_rec);
}
}
void subset_sum(std::list<int> numbers,int target)
{
subset_sum_recursive(numbers,target,std::list<int>());
}
int main()
{
std::list<int> a;
a.push_back (3); a.push_back (9); a.push_back (8);
a.push_back (4);
a.push_back (5);
a.push_back (7);
a.push_back (10);
int n = 15;
//std::cin >> n;
subset_sum(a, n);
return 0;
}
C# version of #msalvadores code answer
void Main()
{
int[] numbers = {3,9,8,4,5,7,10};
int target = 15;
sum_up(new List<int>(numbers.ToList()),target);
}
static void sum_up_recursive(List<int> numbers, int target, List<int> part)
{
int s = 0;
foreach (int x in part)
{
s += x;
}
if (s == target)
{
Console.WriteLine("sum(" + string.Join(",", part.Select(n => n.ToString()).ToArray()) + ")=" + target);
}
if (s >= target)
{
return;
}
for (int i = 0;i < numbers.Count;i++)
{
var remaining = new List<int>();
int n = numbers[i];
for (int j = i + 1; j < numbers.Count;j++)
{
remaining.Add(numbers[j]);
}
var part_rec = new List<int>(part);
part_rec.Add(n);
sum_up_recursive(remaining,target,part_rec);
}
}
static void sum_up(List<int> numbers, int target)
{
sum_up_recursive(numbers,target,new List<int>());
}
Java non-recursive version that simply keeps adding elements and redistributing them amongst possible values. 0's are ignored and works for fixed lists (what you're given is what you can play with) or a list of repeatable numbers.
import java.util.*;
public class TestCombinations {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<>(Arrays.asList(0, 1, 2, 2, 5, 10, 20));
LinkedHashSet<Integer> targets = new LinkedHashSet<Integer>() {{
add(4);
add(10);
add(25);
}};
System.out.println("## each element can appear as many times as needed");
for (Integer target: targets) {
Combinations combinations = new Combinations(numbers, target, true);
combinations.calculateCombinations();
for (String solution: combinations.getCombinations()) {
System.out.println(solution);
}
}
System.out.println("## each element can appear only once");
for (Integer target: targets) {
Combinations combinations = new Combinations(numbers, target, false);
combinations.calculateCombinations();
for (String solution: combinations.getCombinations()) {
System.out.println(solution);
}
}
}
public static class Combinations {
private boolean allowRepetitions;
private int[] repetitions;
private ArrayList<Integer> numbers;
private Integer target;
private Integer sum;
private boolean hasNext;
private Set<String> combinations;
/**
* Constructor.
*
* #param numbers Numbers that can be used to calculate the sum.
* #param target Target value for sum.
*/
public Combinations(ArrayList<Integer> numbers, Integer target) {
this(numbers, target, true);
}
/**
* Constructor.
*
* #param numbers Numbers that can be used to calculate the sum.
* #param target Target value for sum.
*/
public Combinations(ArrayList<Integer> numbers, Integer target, boolean allowRepetitions) {
this.allowRepetitions = allowRepetitions;
if (this.allowRepetitions) {
Set<Integer> numbersSet = new HashSet<>(numbers);
this.numbers = new ArrayList<>(numbersSet);
} else {
this.numbers = numbers;
}
this.numbers.removeAll(Arrays.asList(0));
Collections.sort(this.numbers);
this.target = target;
this.repetitions = new int[this.numbers.size()];
this.combinations = new LinkedHashSet<>();
this.sum = 0;
if (this.repetitions.length > 0)
this.hasNext = true;
else
this.hasNext = false;
}
/**
* Calculate and return the sum of the current combination.
*
* #return The sum.
*/
private Integer calculateSum() {
this.sum = 0;
for (int i = 0; i < repetitions.length; ++i) {
this.sum += repetitions[i] * numbers.get(i);
}
return this.sum;
}
/**
* Redistribute picks when only one of each number is allowed in the sum.
*/
private void redistribute() {
for (int i = 1; i < this.repetitions.length; ++i) {
if (this.repetitions[i - 1] > 1) {
this.repetitions[i - 1] = 0;
this.repetitions[i] += 1;
}
}
if (this.repetitions[this.repetitions.length - 1] > 1)
this.repetitions[this.repetitions.length - 1] = 0;
}
/**
* Get the sum of the next combination. When 0 is returned, there's no other combinations to check.
*
* #return The sum.
*/
private Integer next() {
if (this.hasNext && this.repetitions.length > 0) {
this.repetitions[0] += 1;
if (!this.allowRepetitions)
this.redistribute();
this.calculateSum();
for (int i = 0; i < this.repetitions.length && this.sum != 0; ++i) {
if (this.sum > this.target) {
this.repetitions[i] = 0;
if (i + 1 < this.repetitions.length) {
this.repetitions[i + 1] += 1;
if (!this.allowRepetitions)
this.redistribute();
}
this.calculateSum();
}
}
if (this.sum.compareTo(0) == 0)
this.hasNext = false;
}
return this.sum;
}
/**
* Calculate all combinations whose sum equals target.
*/
public void calculateCombinations() {
while (this.hasNext) {
if (this.next().compareTo(target) == 0)
this.combinations.add(this.toString());
}
}
/**
* Return all combinations whose sum equals target.
*
* #return Combinations as a set of strings.
*/
public Set<String> getCombinations() {
return this.combinations;
}
#Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder("" + sum + ": ");
for (int i = 0; i < repetitions.length; ++i) {
for (int j = 0; j < repetitions[i]; ++j) {
stringBuilder.append(numbers.get(i) + " ");
}
}
return stringBuilder.toString();
}
}
}
Sample input:
numbers: 0, 1, 2, 2, 5, 10, 20
targets: 4, 10, 25
Sample output:
## each element can appear as many times as needed
4: 1 1 1 1
4: 1 1 2
4: 2 2
10: 1 1 1 1 1 1 1 1 1 1
10: 1 1 1 1 1 1 1 1 2
10: 1 1 1 1 1 1 2 2
10: 1 1 1 1 2 2 2
10: 1 1 2 2 2 2
10: 2 2 2 2 2
10: 1 1 1 1 1 5
10: 1 1 1 2 5
10: 1 2 2 5
10: 5 5
10: 10
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2
25: 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2
25: 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2
25: 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2
25: 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2
25: 1 1 1 2 2 2 2 2 2 2 2 2 2 2
25: 1 2 2 2 2 2 2 2 2 2 2 2 2
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 5
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 5
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 5
25: 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 5
25: 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 5
25: 1 1 1 1 1 1 1 1 2 2 2 2 2 2 5
25: 1 1 1 1 1 1 2 2 2 2 2 2 2 5
25: 1 1 1 1 2 2 2 2 2 2 2 2 5
25: 1 1 2 2 2 2 2 2 2 2 2 5
25: 2 2 2 2 2 2 2 2 2 2 5
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 2 5 5
25: 1 1 1 1 1 1 1 1 1 1 1 2 2 5 5
25: 1 1 1 1 1 1 1 1 1 2 2 2 5 5
25: 1 1 1 1 1 1 1 2 2 2 2 5 5
25: 1 1 1 1 1 2 2 2 2 2 5 5
25: 1 1 1 2 2 2 2 2 2 5 5
25: 1 2 2 2 2 2 2 2 5 5
25: 1 1 1 1 1 1 1 1 1 1 5 5 5
25: 1 1 1 1 1 1 1 1 2 5 5 5
25: 1 1 1 1 1 1 2 2 5 5 5
25: 1 1 1 1 2 2 2 5 5 5
25: 1 1 2 2 2 2 5 5 5
25: 2 2 2 2 2 5 5 5
25: 1 1 1 1 1 5 5 5 5
25: 1 1 1 2 5 5 5 5
25: 1 2 2 5 5 5 5
25: 5 5 5 5 5
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 10
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 2 10
25: 1 1 1 1 1 1 1 1 1 1 1 2 2 10
25: 1 1 1 1 1 1 1 1 1 2 2 2 10
25: 1 1 1 1 1 1 1 2 2 2 2 10
25: 1 1 1 1 1 2 2 2 2 2 10
25: 1 1 1 2 2 2 2 2 2 10
25: 1 2 2 2 2 2 2 2 10
25: 1 1 1 1 1 1 1 1 1 1 5 10
25: 1 1 1 1 1 1 1 1 2 5 10
25: 1 1 1 1 1 1 2 2 5 10
25: 1 1 1 1 2 2 2 5 10
25: 1 1 2 2 2 2 5 10
25: 2 2 2 2 2 5 10
25: 1 1 1 1 1 5 5 10
25: 1 1 1 2 5 5 10
25: 1 2 2 5 5 10
25: 5 5 5 10
25: 1 1 1 1 1 10 10
25: 1 1 1 2 10 10
25: 1 2 2 10 10
25: 5 10 10
25: 1 1 1 1 1 20
25: 1 1 1 2 20
25: 1 2 2 20
25: 5 20
## each element can appear only once
4: 2 2
10: 1 2 2 5
10: 10
25: 1 2 2 20
25: 5 20
Thank you.. ephemient
i have converted above logic from python to php..
<?php
$data = array(array(2,3,5,10,15),array(4,6,23,15,12),array(23,34,12,1,5));
$maxsum = 25;
print_r(bestsum($data,$maxsum)); //function call
function bestsum($data,$maxsum)
{
$res = array_fill(0, $maxsum + 1, '0');
$res[0] = array(); //base case
foreach($data as $group)
{
$new_res = $res; //copy res
foreach($group as $ele)
{
for($i=0;$i<($maxsum-$ele+1);$i++)
{
if($res[$i] != 0)
{
$ele_index = $i+$ele;
$new_res[$ele_index] = $res[$i];
$new_res[$ele_index][] = $ele;
}
}
}
$res = $new_res;
}
for($i=$maxsum;$i>0;$i--)
{
if($res[$i]!=0)
{
return $res[$i];
break;
}
}
return array();
}
?>
Another python solution would be to use the itertools.combinations module as follows:
#!/usr/local/bin/python
from itertools import combinations
def find_sum_in_list(numbers, target):
results = []
for x in range(len(numbers)):
results.extend(
[
combo for combo in combinations(numbers ,x)
if sum(combo) == target
]
)
print results
if __name__ == "__main__":
find_sum_in_list([3,9,8,4,5,7,10], 15)
Output: [(8, 7), (5, 10), (3, 8, 4), (3, 5, 7)]
I thought I'd use an answer from this question but I couldn't, so here is my answer. It is using a modified version of an answer in Structure and Interpretation of Computer Programs. I think this is a better recursive solution and should please the purists more.
My answer is in Scala (and apologies if my Scala sucks, I've just started learning it). The findSumCombinations craziness is to sort and unique the original list for the recursion to prevent dupes.
def findSumCombinations(target: Int, numbers: List[Int]): Int = {
cc(target, numbers.distinct.sortWith(_ < _), List())
}
def cc(target: Int, numbers: List[Int], solution: List[Int]): Int = {
if (target == 0) {println(solution); 1 }
else if (target < 0 || numbers.length == 0) 0
else
cc(target, numbers.tail, solution)
+ cc(target - numbers.head, numbers, numbers.head :: solution)
}
To use it:
> findSumCombinations(12345, List(1,5,22,15,0,..))
* Prints a whole heap of lists that will sum to the target *
Excel VBA version below. I needed to implement this in VBA (not my preference, don't judge me!), and used the answers on this page for the approach. I'm uploading in case others also need a VBA version.
Option Explicit
Public Sub SumTarget()
Dim numbers(0 To 6) As Long
Dim target As Long
target = 15
numbers(0) = 3: numbers(1) = 9: numbers(2) = 8: numbers(3) = 4: numbers(4) = 5
numbers(5) = 7: numbers(6) = 10
Call SumUpTarget(numbers, target)
End Sub
Public Sub SumUpTarget(numbers() As Long, target As Long)
Dim part() As Long
Call SumUpRecursive(numbers, target, part)
End Sub
Private Sub SumUpRecursive(numbers() As Long, target As Long, part() As Long)
Dim s As Long, i As Long, j As Long, num As Long
Dim remaining() As Long, partRec() As Long
s = SumArray(part)
If s = target Then Debug.Print "SUM ( " & ArrayToString(part) & " ) = " & target
If s >= target Then Exit Sub
If (Not Not numbers) <> 0 Then
For i = 0 To UBound(numbers)
Erase remaining()
num = numbers(i)
For j = i + 1 To UBound(numbers)
AddToArray remaining, numbers(j)
Next j
Erase partRec()
CopyArray partRec, part
AddToArray partRec, num
SumUpRecursive remaining, target, partRec
Next i
End If
End Sub
Private Function ArrayToString(x() As Long) As String
Dim n As Long, result As String
result = "{" & x(n)
For n = LBound(x) + 1 To UBound(x)
result = result & "," & x(n)
Next n
result = result & "}"
ArrayToString = result
End Function
Private Function SumArray(x() As Long) As Long
Dim n As Long
SumArray = 0
If (Not Not x) <> 0 Then
For n = LBound(x) To UBound(x)
SumArray = SumArray + x(n)
Next n
End If
End Function
Private Sub AddToArray(arr() As Long, x As Long)
If (Not Not arr) <> 0 Then
ReDim Preserve arr(0 To UBound(arr) + 1)
Else
ReDim Preserve arr(0 To 0)
End If
arr(UBound(arr)) = x
End Sub
Private Sub CopyArray(destination() As Long, source() As Long)
Dim n As Long
If (Not Not source) <> 0 Then
For n = 0 To UBound(source)
AddToArray destination, source(n)
Next n
End If
End Sub
Output (written to the Immediate window) should be:
SUM ( {3,8,4} ) = 15
SUM ( {3,5,7} ) = 15
SUM ( {8,7} ) = 15
SUM ( {5,10} ) = 15
Here's a solution in R
subset_sum = function(numbers,target,partial=0){
if(any(is.na(partial))) return()
s = sum(partial)
if(s == target) print(sprintf("sum(%s)=%s",paste(partial[-1],collapse="+"),target))
if(s > target) return()
for( i in seq_along(numbers)){
n = numbers[i]
remaining = numbers[(i+1):length(numbers)]
subset_sum(remaining,target,c(partial,n))
}
}
Perl version (of the leading answer):
use strict;
sub subset_sum {
my ($numbers, $target, $result, $sum) = #_;
print 'sum('.join(',', #$result).") = $target\n" if $sum == $target;
return if $sum >= $target;
subset_sum([#$numbers[$_ + 1 .. $#$numbers]], $target,
[#{$result||[]}, $numbers->[$_]], $sum + $numbers->[$_])
for (0 .. $#$numbers);
}
subset_sum([3,9,8,4,5,7,10,6], 15);
Result:
sum(3,8,4) = 15
sum(3,5,7) = 15
sum(9,6) = 15
sum(8,7) = 15
sum(4,5,6) = 15
sum(5,10) = 15
Javascript version:
const subsetSum = (numbers, target, partial = [], sum = 0) => {
if (sum < target)
numbers.forEach((num, i) =>
subsetSum(numbers.slice(i + 1), target, partial.concat([num]), sum + num));
else if (sum == target)
console.log('sum(%s) = %s', partial.join(), target);
}
subsetSum([3,9,8,4,5,7,10,6], 15);
Javascript one-liner that actually returns results (instead of printing it):
const subsetSum=(n,t,p=[],s=0,r=[])=>(s<t?n.forEach((l,i)=>subsetSum(n.slice(i+1),t,[...p,l],s+l,r)):s==t?r.push(p):0,r);
console.log(subsetSum([3,9,8,4,5,7,10,6], 15));
And my favorite, one-liner with callback:
const subsetSum=(n,t,cb,p=[],s=0)=>s<t?n.forEach((l,i)=>subsetSum(n.slice(i+1),t,cb,[...p,l],s+l)):s==t?cb(p):0;
subsetSum([3,9,8,4,5,7,10,6], 15, console.log);
Here is a Java version which is well suited for small N and very large target sum, when complexity O(t*N) (the dynamic solution) is greater than the exponential algorithm. My version uses a meet in the middle attack, along with a little bit shifting in order to reduce the complexity from the classic naive O(n*2^n) to O(2^(n/2)).
If you want to use this for sets with between 32 and 64 elements, you should change the int which represents the current subset in the step function to a long although performance will obviously drastically decrease as the set size increases. If you want to use this for a set with odd number of elements, you should add a 0 to the set to make it even numbered.
import java.util.ArrayList;
import java.util.List;
public class SubsetSumMiddleAttack {
static final int target = 100000000;
static final int[] set = new int[]{ ... };
static List<Subset> evens = new ArrayList<>();
static List<Subset> odds = new ArrayList<>();
static int[][] split(int[] superSet) {
int[][] ret = new int[2][superSet.length / 2];
for (int i = 0; i < superSet.length; i++) ret[i % 2][i / 2] = superSet[i];
return ret;
}
static void step(int[] superSet, List<Subset> accumulator, int subset, int sum, int counter) {
accumulator.add(new Subset(subset, sum));
if (counter != superSet.length) {
step(superSet, accumulator, subset + (1 << counter), sum + superSet[counter], counter + 1);
step(superSet, accumulator, subset, sum, counter + 1);
}
}
static void printSubset(Subset e, Subset o) {
String ret = "";
for (int i = 0; i < 32; i++) {
if (i % 2 == 0) {
if ((1 & (e.subset >> (i / 2))) == 1) ret += " + " + set[i];
}
else {
if ((1 & (o.subset >> (i / 2))) == 1) ret += " + " + set[i];
}
}
if (ret.startsWith(" ")) ret = ret.substring(3) + " = " + (e.sum + o.sum);
System.out.println(ret);
}
public static void main(String[] args) {
int[][] superSets = split(set);
step(superSets[0], evens, 0,0,0);
step(superSets[1], odds, 0,0,0);
for (Subset e : evens) {
for (Subset o : odds) {
if (e.sum + o.sum == target) printSubset(e, o);
}
}
}
}
class Subset {
int subset;
int sum;
Subset(int subset, int sum) {
this.subset = subset;
this.sum = sum;
}
}
Very efficient algorithm using tables i wrote in c++ couple a years ago.
If you set PRINT 1 it will print all combinations(but it wont be use the efficient method).
Its so efficient that it calculate more than 10^14 combinations in less than 10ms.
#include <stdio.h>
#include <stdlib.h>
//#include "CTime.h"
#define SUM 300
#define MAXNUMsSIZE 30
#define PRINT 0
long long CountAddToSum(int,int[],int,const int[],int);
void printr(const int[], int);
long long table1[SUM][MAXNUMsSIZE];
int main()
{
int Nums[]={3,4,5,6,7,9,13,11,12,13,22,35,17,14,18,23,33,54};
int sum=SUM;
int size=sizeof(Nums)/sizeof(int);
int i,j,a[]={0};
long long N=0;
//CTime timer1;
for(i=0;i<SUM;++i)
for(j=0;j<MAXNUMsSIZE;++j)
table1[i][j]=-1;
N = CountAddToSum(sum,Nums,size,a,0); //algorithm
//timer1.Get_Passd();
//printf("\nN=%lld time=%.1f ms\n", N,timer1.Get_Passd());
printf("\nN=%lld \n", N);
getchar();
return 1;
}
long long CountAddToSum(int s, int arr[],int arrsize, const int r[],int rsize)
{
static int totalmem=0, maxmem=0;
int i,*rnew;
long long result1=0,result2=0;
if(s<0) return 0;
if (table1[s][arrsize]>0 && PRINT==0) return table1[s][arrsize];
if(s==0)
{
if(PRINT) printr(r, rsize);
return 1;
}
if(arrsize==0) return 0;
//else
rnew=(int*)malloc((rsize+1)*sizeof(int));
for(i=0;i<rsize;++i) rnew[i]=r[i];
rnew[rsize]=arr[arrsize-1];
result1 = CountAddToSum(s,arr,arrsize-1,rnew,rsize);
result2 = CountAddToSum(s-arr[arrsize-1],arr,arrsize,rnew,rsize+1);
table1[s][arrsize]=result1+result2;
free(rnew);
return result1+result2;
}
void printr(const int r[], int rsize)
{
int lastr=r[0],count=0,i;
for(i=0; i<rsize;++i)
{
if(r[i]==lastr)
count++;
else
{
printf(" %d*%d ",count,lastr);
lastr=r[i];
count=1;
}
}
if(r[i-1]==lastr) printf(" %d*%d ",count,lastr);
printf("\n");
}
This is similar to a coin change problem
public class CoinCount
{
public static void main(String[] args)
{
int[] coins={1,4,6,2,3,5};
int count=0;
for (int i=0;i<coins.length;i++)
{
count=count+Count(9,coins,i,0);
}
System.out.println(count);
}
public static int Count(int Sum,int[] coins,int index,int curSum)
{
int count=0;
if (index>=coins.length)
return 0;
int sumNow=curSum+coins[index];
if (sumNow>Sum)
return 0;
if (sumNow==Sum)
return 1;
for (int i= index+1;i<coins.length;i++)
count+=Count(Sum,coins,i,sumNow);
return count;
}
}
I ported the C# sample to Objective-c and didn't see it in the responses:
//Usage
NSMutableArray* numberList = [[NSMutableArray alloc] init];
NSMutableArray* partial = [[NSMutableArray alloc] init];
int target = 16;
for( int i = 1; i<target; i++ )
{ [numberList addObject:#(i)]; }
[self findSums:numberList target:target part:partial];
//*******************************************************************
// Finds combinations of numbers that add up to target recursively
//*******************************************************************
-(void)findSums:(NSMutableArray*)numbers target:(int)target part:(NSMutableArray*)partial
{
int s = 0;
for (NSNumber* x in partial)
{ s += [x intValue]; }
if (s == target)
{ NSLog(#"Sum[%#]", partial); }
if (s >= target)
{ return; }
for (int i = 0;i < [numbers count];i++ )
{
int n = [numbers[i] intValue];
NSMutableArray* remaining = [[NSMutableArray alloc] init];
for (int j = i + 1; j < [numbers count];j++)
{ [remaining addObject:#([numbers[j] intValue])]; }
NSMutableArray* partRec = [[NSMutableArray alloc] initWithArray:partial];
[partRec addObject:#(n)];
[self findSums:remaining target:target part:partRec];
}
}
Here is a better version with better output formatting and C++ 11 features:
void subset_sum_rec(std::vector<int> & nums, const int & target, std::vector<int> & partialNums)
{
int currentSum = std::accumulate(partialNums.begin(), partialNums.end(), 0);
if (currentSum > target)
return;
if (currentSum == target)
{
std::cout << "sum([";
for (auto it = partialNums.begin(); it != std::prev(partialNums.end()); ++it)
cout << *it << ",";
cout << *std::prev(partialNums.end());
std::cout << "])=" << target << std::endl;
}
for (auto it = nums.begin(); it != nums.end(); ++it)
{
std::vector<int> remaining;
for (auto it2 = std::next(it); it2 != nums.end(); ++it2)
remaining.push_back(*it2);
std::vector<int> partial = partialNums;
partial.push_back(*it);
subset_sum_rec(remaining, target, partial);
}
}
Deduce 0 in the first place. Zero is an identiy for addition so it is useless by the monoid laws in this particular case. Also deduce negative numbers as well if you want to climb up to a positive number. Otherwise you would also need subtraction operation.
So... the fastest algorithm you can get on this particular job is as follows given in JS.
function items2T([n,...ns],t){
var c = ~~(t/n);
return ns.length ? Array(c+1).fill()
.reduce((r,_,i) => r.concat(items2T(ns, t-n*i).map(s => Array(i).fill(n).concat(s))),[])
: t % n ? []
: [Array(c).fill(n)];
};
var data = [3, 9, 8, 4, 5, 7, 10],
result;
console.time("combos");
result = items2T(data, 15);
console.timeEnd("combos");
console.log(JSON.stringify(result));
This is a very fast algorithm but if you sort the data array descending it will be even faster. Using .sort() is insignificant since the algorithm will end up with much less recursive invocations.
PHP Version, as inspired by Keith Beller's C# version.
bala's PHP version did not work for me, because I did not need to group numbers. I wanted a simpler implementation with one target value, and a pool of numbers. This function will also prune any duplicate entries.
Edit 25/10/2021: Added the precision argument to support floating point numbers (now requires the bcmath extension).
/**
* Calculates a subset sum: finds out which combinations of numbers
* from the numbers array can be added together to come to the target
* number.
*
* Returns an indexed array with arrays of number combinations.
*
* Example:
*
* <pre>
* $matches = subset_sum(array(5,10,7,3,20), 25);
* </pre>
*
* Returns:
*
* <pre>
* Array
* (
* [0] => Array
* (
* [0] => 3
* [1] => 5
* [2] => 7
* [3] => 10
* )
* [1] => Array
* (
* [0] => 5
* [1] => 20
* )
* )
* </pre>
*
* #param number[] $numbers
* #param number $target
* #param array $part
* #param int $precision
* #return array[number[]]
*/
function subset_sum($numbers, $target, $precision=0, $part=null)
{
// we assume that an empty $part variable means this
// is the top level call.
$toplevel = false;
if($part === null) {
$toplevel = true;
$part = array();
}
$s = 0;
foreach($part as $x)
{
$s = $s + $x;
}
// we have found a match!
if(bccomp((string) $s, (string) $target, $precision) === 0)
{
sort($part); // ensure the numbers are always sorted
return array(implode('|', $part));
}
// gone too far, break off
if($s >= $target)
{
return null;
}
$matches = array();
$totalNumbers = count($numbers);
for($i=0; $i < $totalNumbers; $i++)
{
$remaining = array();
$n = $numbers[$i];
for($j = $i+1; $j < $totalNumbers; $j++)
{
$remaining[] = $numbers[$j];
}
$part_rec = $part;
$part_rec[] = $n;
$result = subset_sum($remaining, $target, $precision, $part_rec);
if($result)
{
$matches = array_merge($matches, $result);
}
}
if(!$toplevel)
{
return $matches;
}
// this is the top level function call: we have to
// prepare the final result value by stripping any
// duplicate results.
$matches = array_unique($matches);
$result = array();
foreach($matches as $entry)
{
$result[] = explode('|', $entry);
}
return $result;
}
Example:
$result = subset_sum(array(5, 10, 7, 3, 20), 25);
This will return an indexed array with two number combination arrays:
3, 5, 7, 10
5, 20
Example with floating point numbers:
// Specify the precision in the third argument
$result = subset_sum(array(0.40, 0.03, 0.05), 0.45, 2);
This will return a single match:
0.40, 0.05
To find the combinations using excel - (its fairly easy).
(You computer must not be too slow)
Go to this site
Go to the "Sum to Target" page
Download the "Sum to Target" excel file.
Follow the directions on the website page.
hope this helps.
Swift 3 conversion of Java solution: (by #JeremyThompson)
protocol _IntType { }
extension Int: _IntType {}
extension Array where Element: _IntType {
func subsets(to: Int) -> [[Element]]? {
func sum_up_recursive(_ numbers: [Element], _ target: Int, _ partial: [Element], _ solution: inout [[Element]]) {
var sum: Int = 0
for x in partial {
sum += x as! Int
}
if sum == target {
solution.append(partial)
}
guard sum < target else {
return
}
for i in stride(from: 0, to: numbers.count, by: 1) {
var remaining = [Element]()
for j in stride(from: i + 1, to: numbers.count, by: 1) {
remaining.append(numbers[j])
}
var partial_rec = [Element](partial)
partial_rec.append(numbers[i])
sum_up_recursive(remaining, target, partial_rec, &solution)
}
}
var solutions = [[Element]]()
sum_up_recursive(self, to, [Element](), &solutions)
return solutions.count > 0 ? solutions : nil
}
}
usage:
let numbers = [3, 9, 8, 4, 5, 7, 10]
if let solution = numbers.subsets(to: 15) {
print(solution) // output: [[3, 8, 4], [3, 5, 7], [8, 7], [5, 10]]
} else {
print("not possible")
}
This can be used to print all the answers as well
public void recur(int[] a, int n, int sum, int[] ans, int ind) {
if (n < 0 && sum != 0)
return;
if (n < 0 && sum == 0) {
print(ans, ind);
return;
}
if (sum >= a[n]) {
ans[ind] = a[n];
recur(a, n - 1, sum - a[n], ans, ind + 1);
}
recur(a, n - 1, sum, ans, ind);
}
public void print(int[] a, int n) {
for (int i = 0; i < n; i++)
System.out.print(a[i] + " ");
System.out.println();
}
Time Complexity is exponential. Order of 2^n
I was doing something similar for a scala assignment. Thought of posting my solution here:
def countChange(money: Int, coins: List[Int]): Int = {
def getCount(money: Int, remainingCoins: List[Int]): Int = {
if(money == 0 ) 1
else if(money < 0 || remainingCoins.isEmpty) 0
else
getCount(money, remainingCoins.tail) +
getCount(money - remainingCoins.head, remainingCoins)
}
if(money == 0 || coins.isEmpty) 0
else getCount(money, coins)
}
#KeithBeller's answer with slightly changed variable names and some comments.
public static void Main(string[] args)
{
List<int> input = new List<int>() { 3, 9, 8, 4, 5, 7, 10 };
int targetSum = 15;
SumUp(input, targetSum);
}
public static void SumUp(List<int> input, int targetSum)
{
SumUpRecursive(input, targetSum, new List<int>());
}
private static void SumUpRecursive(List<int> remaining, int targetSum, List<int> listToSum)
{
// Sum up partial
int sum = 0;
foreach (int x in listToSum)
sum += x;
//Check sum matched
if (sum == targetSum)
Console.WriteLine("sum(" + string.Join(",", listToSum.ToArray()) + ")=" + targetSum);
//Check sum passed
if (sum >= targetSum)
return;
//Iterate each input character
for (int i = 0; i < remaining.Count; i++)
{
//Build list of remaining items to iterate
List<int> newRemaining = new List<int>();
for (int j = i + 1; j < remaining.Count; j++)
newRemaining.Add(remaining[j]);
//Update partial list
List<int> newListToSum = new List<int>(listToSum);
int currentItem = remaining[i];
newListToSum.Add(currentItem);
SumUpRecursive(newRemaining, targetSum, newListToSum);
}
}'
Recommended as an answer:
Here's a solution using es2015 generators:
function* subsetSum(numbers, target, partial = [], partialSum = 0) {
if(partialSum === target) yield partial
if(partialSum >= target) return
for(let i = 0; i < numbers.length; i++){
const remaining = numbers.slice(i + 1)
, n = numbers[i]
yield* subsetSum(remaining, target, [...partial, n], partialSum + n)
}
}
Using generators can actually be very useful because it allows you to pause script execution immediately upon finding a valid subset. This is in contrast to solutions without generators (ie lacking state) which have to iterate through every single subset of numbers
I did not like the Javascript Solution I saw above. Here is the one I build using partial applying, closures and recursion:
Ok, I was mainly concern about, if the combinations array could satisfy the target requirement, hopefully this approached you will start to find the rest of combinations
Here just set the target and pass the combinations array.
function main() {
const target = 10
const getPermutationThatSumT = setTarget(target)
const permutation = getPermutationThatSumT([1, 4, 2, 5, 6, 7])
console.log( permutation );
}
the currently implementation I came up with
function setTarget(target) {
let partial = [];
return function permute(input) {
let i, removed;
for (i = 0; i < input.length; i++) {
removed = input.splice(i, 1)[0];
partial.push(removed);
const sum = partial.reduce((a, b) => a + b)
if (sum === target) return partial.slice()
if (sum < target) permute(input)
input.splice(i, 0, removed);
partial.pop();
}
return null
};
}
An iterative C++ stack solution for a flavor of this problem. Unlike some other iterative solutions, it doesn't make unnecessary copies of intermediate sequences.
#include <vector>
#include <iostream>
// Given a positive integer, return all possible combinations of
// positive integers that sum up to it.
std::vector<std::vector<int>> print_all_sum(int target){
std::vector<std::vector<int>> output;
std::vector<int> stack;
int curr_min = 1;
int sum = 0;
while (curr_min < target) {
sum += curr_min;
if (sum >= target) {
if (sum == target) {
output.push_back(stack); // make a copy
output.back().push_back(curr_min);
}
sum -= curr_min + stack.back();
curr_min = stack.back() + 1;
stack.pop_back();
} else {
stack.push_back(curr_min);
}
}
return output;
}
int main()
{
auto vvi = print_all_sum(6);
for (auto const& v: vvi) {
for(auto const& i: v) {
std::cout << i;
}
std::cout << "\n";
}
return 0;
}
Output print_all_sum(6):
111111
11112
1113
1122
114
123
15
222
24
33
function solve(n){
let DP = [];
DP[0] = DP[1] = DP[2] = 1;
DP[3] = 2;
for (let i = 4; i <= n; i++) {
DP[i] = DP[i-1] + DP[i-3] + DP[i-4];
}
return DP[n]
}
console.log(solve(5))
This is a Dynamic Solution for JS to tell how many ways anyone can get the certain sum. This can be the right solution if you think about time and space complexity.

Resources