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.
Related
I've got this task, which I honestly don't understand what exactly to do.
It my be because of my English level, or mathmatics level, but this is really something I can not make sense of. Could you help be at least to understand the task ?
My php knowledge is very well, at least I thought so...
The task is this :
"Carry" is a term of an elementary arithmetic. It's a digit that you transfer to column with higher significant digits when adding numbers.
This task is about getting the sum of all carried digits.
You will receive an array of two numbers, like in the example. The function should return the sum of all carried digits.
function carry($arr) {
// ...
}
carry([123, 456]); // 0
carry([555, 555]); // 3 (carry 1 from ones column, carry 1 from tens column, carry 1 from hundreds column)
carry([123, 594]); // 1 (carry 1 from tens column)
Support of arbitrary number of operands will be a plus:
carry([123, 123, 804]); // 2 (carry 1 from ones column, carry 1, carry 1 from hundreds column)
Background information on "carry": https://en.m.wikipedia.org/wiki/Carry_(arithmetic)
For this task, we don't actually need the numbers written under the equals line, just the numbers which are carried. Importantly, the carried numbers need to be used when calculating subsequent columns.
Before looping each column of integers, reverse the order of the columns so that looping from left-to-right also iterates the lowest unit column and progresses to higher unit columns (ones, then tens, then hundreds, etc).
For flexibility, my snippet is designed to handle numbers of dynamic length. If processing potential float numbers, you could merely multiply all number by a power of 10 to convert all values to integers. My snippet is not designed to handled signed integers.
Code: (Demo)
function sumCarries(array $array) {
$columns = ['carries' => []];
// prepare matrix of 1-digit integers in columns -- ones, tens, hundreds, etc
foreach ($array as $integer) {
$columns[] = str_split(strrev($integer));
}
// sum column values in ascending order and populate carry values
// subsequent column sums need to include carried value
for ($i = 0, $len = strlen(max($array)); $i < $len; ++$i) {
$columns['carries'][$i + 1] = (int)(array_sum(array_column($columns, $i)) / 10);
}
// sum all populated carry values
return array_sum($columns['carries']);
}
$tests = [
[123, 456], // no carries in any column
[555, 555], // 1 ones, 1 tens, 1 hundreds
[123, 594], // 1 tens
[123, 123, 804], // 1 ones, 1 hundreds
[99, 9, 99, 99, 99], // 4 ones, 4 hundreds
[9,9,9,9,9,9,9,9,9,9,9,9], // 10 ones
];
var_export(array_map('sumCarries', $tests));
Output:
array (
0 => 0,
1 => 3,
2 => 1,
3 => 2,
4 => 8,
5 => 10,
)
Since it's homework, I'm not going to fully answer the question, but explain the pieces you seem confused about so that you can put them together.
1 11 111 111 <- these are the carry digits
555 555 555 555 555
+ 555 -> + 555 -> + 555 -> + 555 -> + 555
----- ----- ----- ----- -----
0 10 110 1110
For a better example of two digits, let's use 6+6. To get the carry digit you can use the modulus operator where 12 % 10 == 2. So, (12 - (12 % 10)) / 10 == 1.
Thank you again. #Sammitch
I got it to make it work. Actually the problem was my English Math Level. The term "Carry digits" had no meaning at all for me. I was completely focusing on something else.
Here is my code : It may be far from perfect, but it does the job :)
function carry($arr) {
$sum_ones = 0;
$sum_tens = 0;
$sum_hunds = 0;
$arrCount = count($arr);
foreach($arr as $key){
$stri = (string)$key;
$foo[] = array(
"hunds" => $stri[0],
"tens" => $stri[1],
"ones" => $stri[2]
);
}
$fooCount = count($foo);
for($i=0; $i<$fooCount; $i++) {
$sum_ones+= $foo[$i]["ones"];
$sum_tens+= $foo[$i]["tens"];
$sum_hunds+= $foo[$i]["hunds"];
}
$sum1 = ($sum_ones - ($sum_ones % 10)) / 10;
$sum10 = ($sum_tens - ($sum_tens % 10)) / 10;
$sum100 = ($sum_hunds - ($sum_hunds % 10)) / 10;
return ($sum1 + $sum10 + $sum100);
}
$arr = array(555, 515, 111);
echo carry($arr);
I am trying to code the codility les 13 ladder.php exercise.
You have to calc using the fibonacci numers the total ways you can climb a ladder when you can do 1 or 2 rungs at the time.
I made a loop creating the first 50 fibonacci numbers like this:
$total = 50;
$fibonacci[0]=0;
$fibonacci[1]=1;
for($i=2;$i<=$total;$i++){
$fibonacci[$i] = $fibonacci[($i-1)] + $fibonacci[($i-2)];
}
This works well if you can do 1 or 2 rungs at the time.
But how do i adjust this loop to give me the first 50 fibonacci numbers if you can take 1, 2 or 3 rungs at the time.
if you can take 1 or 2 rungs you use: Fx = F[(x-1)] + F[(x-2)];
if you can do 1, 2 and 3 you use: Fx = F[(x-1)] + F[(x-2)] + F[(x-3)];
if you can do 1, 2, 3 and 4 you use: Fx = F[(x-1)] + F[(x-2)] + F[(x-3)] + F[(x-4)];
Then you can make as many numbers or calculate as many numbers as you wish.
But you always need the first few numbers to be able to make the calculations.
I hope this table makes clear what i mean:
2 3 4 5 6
1 1 1 1 1 1
2 2 2 2 2 2
3 3 4 4 4 4
4 5 7 8 8 8
5 8 13 15 16 16
6 13 24 29 31 32
The row below 2 is the basic fibonacci
Below 3 I would need number 1 to 3 to be able to calculate #4 and so on
Below 4 I need the first 4 to be able to calc #5 and so on
Can anyone help me create a loop to create the first say 10 numbers for row 4 and 5 and 6?
Thanks
Here you are a function returns a part of fibonacci numbers. You can set a start element (0 - based) and how many elements you need.
function takeFibonacci($start, $length)
{
$fibonacci = array(0, 1);
$result = array();
$position = 0;
do {
if (!isset($fibonacci[$position])) {
$fibonacci[$position] = $fibonacci[$position - 1] + $fibonacci[$position - 2];
}
if ($position >= $start) {
$result[] = $fibonacci[$position];
}
$position++;
} while ($position < $start + $length);
return $result;
}
$fib = takeFibonacci(5, 5);
var_dump($fib);
Code above returns this result
array(5) { [0]=> int(5) [1]=> int(8) [2]=> int(13) [3]=> int(21) [4]=> int(34) }
What I need is to create five random integer (say rand(1,5)). Then, I generate a score based on these numbers. For instance, if I get a result of 1,2,3,4,5 then that would equal a zero score, but if I got 1,1,3,4,5 that would be 1 as we have a pair. Similar to a poker kind of scoring, so five of the same number would be a "full house" thus resulting in the highest score.
How would I go about the scoring system, even if it is just the mathematical equation?
More detail:
1-5 will hold separate images and then will be fought against "The House" which will have identical code to the user to determine the winner. Here's some example draws and the score they would receive:
1,2,3,4,5 = score 0
1,1,2,3,4 = score 1 (1 pair)
1,1,2,2,4 = score 2 (2 pair)
1,1,1,3,4 = score 3 (3 of a kind)
1,1,1,1,5 = score 4 (4 of a kind)
1,1,1,3,3 = score 5 (full house)
1,1,1,1,1 = score 6 (5 of a kind)
The combination of numbers is irreverent if they score 6 and the house scores 6, it's a tie.
if (isset($_POST['play'])) {
$rand1 = rand(1, 5);
$rand2 = rand(1, 5);
$rand3 = rand(1, 5);
$rand4 = rand(1, 5);
$rand5 = rand(1, 5);
if ($_POST['bet'] <= $user_data['coins']) {
if ($_POST['bet'] < 999999999) {
if ($_POST['bet'] > 0.99) {
if ($user_data['coins'] >= 1) {
$array = array($rand1,$rand2,$rand3,$rand4,$rand5);
print_r(array_count_values($array));
echo $rand1.', '.$rand2.', '.$rand3.', '.$rand4.', '.$rand5;
Array( // Here I don't understand
1 => 3,//
2 => 1,//
3 => 1 //
);
}
}
}
}
}
This outputs ; Array ( [5] => 2 [4] => 2 [1] => 1 ) 5, 5, 4, 4, 1
Use array_count_value function for this.
$array = array(1,1,1,2,5);
print_r(array_count_values($array));
Array(
1 => 3,
2 => 1,
3 => 1
);
Here's the approach I would consider, building on #Lele's answer. Warning: this is a bit confusing, so sit down with a cup of tea for this one.
Build a set of five buckets, [1] to [5], and scan a player's numbers, so that the count for each number is stored in the corresponding bucket
Then count the numbers you are left with into a new bucket system, with each position representing the number of counts you have for something.
So, if your score is this:
1 1 2 2 4
Then your first buckets are:
2 2 0 1 0
That's because you have two ones, two twos, and one four. And your second buckets are:
1 2 0 0 0
That's because you have two two-counts, and one one-count. Here, you disregard the first position (since a one-count for something does not score anything) and score for the others. So, test for two twos, and score that two.
If you score is this:
5 5 5 5 1
Then your first buckets are:
1 0 0 0 4
That's one one and four fives. So your second buckets are:
1 0 0 1 0
Your lookup table for this could be:
x 1 0 0 0 -> one pair
x 2 0 0 0 -> two pairs
x 0 1 0 0 -> three of a kind
x 1 1 0 0 -> full house
x 0 0 1 0 -> four of a kind
x 0 0 0 1 -> five of a kind
The 'x' means that you don't match on this. So, your lookup table matches four numbers to a score.
I was rather interested in this problem, so I have written some code to do the above. You'll still need to do the lookup table, but that is relatively trivial, and will be good practice for you. Here is a demo, with comments (run code here):
<?php
function counting(array $array) {
// Input figures
print_r($array);
// Run the figures twice through the bucket-counter
$firstBuckets = bucketCounter($array);
$secondBuckets = bucketCounter($firstBuckets);
// Ignore counts of 1
array_shift($secondBuckets);
// Output, just need to do the lookup now
echo ' converts to ';
print_r($secondBuckets);
echo "<br />";
}
/**
* Bucket counter
*/
function bucketCounter(array $array) {
$result = array(0, 0, 0, 0, 0, );
foreach($array as $value) {
if ($value > 0) {
$result[$value - 1]++;
}
}
return $result;
}
// Try some demos here!
counting(array(1, 2, 3, 4, 5));
counting(array(1, 1, 2, 4, 2));
counting(array(1, 1, 1, 1, 1));
?>
The demos I've included seem to work, but do hunt for bugs!
If the range is quite small, you can use counting sort approach. For each number, provide a "bucket" to count how many times a number appear. Scan once to fill in the buckets. Then another scan, but this time against the bucket to get the highest value. That's your score.
Why is the answer, 13 as given. I just cannot get my head around it.
What does the following function return, if the given input is 7:
function foo($bar) {
if ($bar == 1) return 1;
elseif ($bar == 0) return 0;
else return foo($bar - 1) + foo($bar - 2);
}
Correct Answer: D. 13
nneonneo should have just posted his comment as the answer, but, this is is how the concept of recursion works:
foo(7)
= foo(6) + foo(5)
But wait, what're those equal to?
foo(6) = foo(5) + foo(4)
Sonofagun!
foo(5) = foo(4) + foo(3)
Hmm .. a pattern emerging ..
foo(4) = foo(3) + foo(2)
foo(3) = foo(2) + foo(1)
foo(2) = foo(1) + foo(0)
foo(1) = 1
and
foo(0) = 0.
So now you can figure out backwards back to the values, but (and this the more important question) what's really happening when you increase $bar by 1 again?
How does foo(8) compare to foo(7)?
And the answer is that foo (8) equals foo(7) + foo(6). In other words, it is equal to 13 + 8 - the sum of the two previous outputs of foo .. hey, that sounds familiar ... is there some famous sequence that is equal to the sum of the previous two numbers?
1, 2, 3, 5, 8, 13 ...
That's right, this is how you can calculate the Fibonacci sequence recursively. And if you think about how you build up the Fibonacci sequence, it's really
1, 1 + 1, 2 + 1, 3 + 2, 5 + 3, 8 +5
Which is just
1, 1 + 1, (1 + 1) + 1, (2 + 1) + (1 + 1), etc.
By "seeding" the initial values (position "0" is 0, position 1 is 1) and then adding them together, you are able to derive each number in the sequence using just the original seeds and a lot of addition.
So in this case, bar represents the bar position in the Fibonacci sequence. So the 7th number in the sequence is 13.
It is very simple, just trace the sequence by hand. When using this type of recursion it helps to think of it more as a mathematical function than a programming procedure. If you want to get to know it more naturally, playing with a functional language *ML or some LISP would help you a lot and very quickly.
When you have a recursion on a data structure (Stack/Queue), then it is a bit different, but functional programming experience helps for that too.
foo(0) = 0
foo(1) = 1
foo(2) = foo(1) + foo(0) = 1 + 0 = 1
foo(3) = foo(2) + foo(1) = 1 + 1 = 2
foo(4) = 2 + 1 = 3
foo(5) = 3 + 2 = 5
foo(6) = 5 + 3 = 8
foo(7) = 8 + 5 = 13
I am trying trying to sort a list into columns with uksort.
The array already alpha sorted, so it is like array('A','B','C','D','E','F','G','H','I','J','K','L','M')
Which gets displayed in html, as floated elements:
A B C D
E F G H
I J K L
M
I want it reordered so it displays like this:
A E H K
B F I L
C G J M
D
So the sorted array would be: array('A','E','H','K','B','F','I','L','C','G','J','M','D'
Basically, the same as Sorting a list alphabetically with a modulus but for php. I've tried taking the solution for javascript and convert it into php, but I'm not getting something right. Anyone have any ideas of how to do this in php?
This is what I have tried:
function cmp_nav_by4($a, $b) {
if (($a % 5) < ($b % 5)) {
return 1;
} elseif (($a % 4) > ($b % 4)) {
return -1;
} else {
return $a < $b ? 1 : -1;
}
}
$result = uksort($thearray, "cmp_nav_by4");
Setting up the following:
$array = range('A', 'M');
$columns = 4;
$length = count($array);
print_matrix($array, $columns);
Which outputs each member and it's key by index (row and colum) and as well the elements order on top:
One row - A B C D E F G H I J K L M
A[ 0] B[ 1] C[ 2] D[ 3]
E[ 4] F[ 5] G[ 6] H[ 7]
I[ 8] J[ 9] K[10] L[11]
M[12]
The javascript code linked could be easily converted to PHP. However, if you look closely to that question/answer, it becomes clear that it only work with full rows, like with my previous attempt:
function callback_sort($array, $columns)
{
$sort = function($columns)
{
return function($a, $b) use ($columns)
{
$bycol = ($a % $columns) - ($b % $columns);
return $bycol ? : $a - $b;
};
};
uksort($array, $sort(4));
return $array;
}
Output:
One row - A E I M B F J C G K D H L
A[ 0] E[ 4] I[ 8] M[12]
B[ 1] F[ 5] J[ 9] C[ 2]
G[ 6] K[10] D[ 3] H[ 7]
L[11]
So it's just that the function provided in the other question does not work.
But as the array is already sorted, you don't need to sort it again but just to change the order or elements. But which order? If the matrix is not complete e.g. n x n fully filled, per each column, a different new index needs to be calculated. Taken the example with 13 elements (A-M) gives you the following distribution of rows per column:
column: 1 2 3 4
rows: 4 3 3 3
So per each column, the value differs. For example at index 12, the 13th element is in the 4th row. On the way coming to that position, it has been passed 4 times through column 1 and 3 times in the other columns 2-4. So to get the virtual index of the iterated index, you need so sum how often you've been in each column to find out how many numbers in the original index you were going forward. If you go over the maximum number of members, you continue over at 0.
So this could be iteratively solved by stepping forward per each index to distribute the calculation over the indexes:
Index 0:
No column: 0
Index 1:
1x in column is which has 4 rows: 4
Index 2:
1x in column 1 (4 rows) and 1x in other columns (3 rows): 4 + 3
... and so on. If the virtual index goes over 12, it will start at 0, for example for the 5th Element (index 4) the virtual index would calculate 13:
Index 4:
1x 4 rows and 3x 3 rows = 13 (4 + 9)
13 > 12 => 1 (13 - 12)
Now filling a new array by starting with the virtual index 0 and giving the appropriate offset each time (look in which column you are, add the number of rows of that column, wrap around if necessary) will give the desired output:
One row - A E H K B F I L C G J M D
A[ 0] E[ 4] H[ 7] K[10]
B[ 1] F[ 5] I[ 8] L[11]
C[ 2] G[ 6] J[ 9] M[12]
D[ 3]
Written in code, that's a simple foreach over the original indexes. By maintaining an index of keys as well, this works with any array, even those with string keys:
$floor = floor($length/$columns);
$modulo = $length % $columns;
$max = $length-1;
$virtual = 0;
$keys = array_keys($array);
$build = array();
foreach($keys as $index => $key)
{
$vkey = $keys[$virtual];
$build[$vkey] = $array[$vkey];
$virtual += $floor + ($index % $columns < $modulo);
($virtual>$max) && $virtual %= $max;
}
print_matrix($build, $columns);
And that's it: Demo, Gist.
#hakre has the correct code answer. The why:
The underlying sort function, Zend_qsort, does not actually reorder the elements and keys. Instead, it reorders the internal array buckets the zend engine uses. If you ksort a numerically indexed array, then iterate over with $q = count($array);for($i=0; $i<$q); $i++) it will return the values exactly as before; if you iterate with for($key in $array) you will get they new key ordering.