0

Here's the problem.

Write the given number N, as sum of the given numbers, using only additioning and subtracting.

Here's an example:

N = 20
Integers = 8, 15, 2, 9, 10

20 = 8 + 15 - 2 + 9 - 10.

Here's my idea;

First idea was to use brute force, alternating plus and minus. First I calculate the number of combinations and its 2^k (where k is the nubmer of integers), because I can alternate only minus and plus. Then I run through all numbers from 1 to 2^k and I convert it to binary form. And for any 1 I use plus and for any 0 I use minus. You'll get it easier with an example (using the above example).

The number of combinations is: 2^k = 2^5 = 32.
Now I run through all numbers from 1 to 32. 
So i get: 1=00001, that means: -8-15-2-9+10 = -24 This is false so I go on.
2 = 00010, which means: -8-15-2+9-10 = -26. Also false.

This method works good, but when the number of integers is too big it takes too long.

Here's my code in C++:

#include <iostream>
#include <cmath>
using namespace std;
int convertToBinary(int number) {
    int remainder;
    int binNumber = 0;
    int i = 1;
    while(number!=0)
    {
        remainder=number%2;
        binNumber=binNumber + (i*remainder);
        number=number/2;
        i=i*10;
    }
    return binNumber;
}
int main()
{
    int N, numberOfIntegers, Combinations, Binary, Remainder, Sum;
    cin >> N >> numberOfIntegers;
    int Integers[numberOfIntegers];
    for(int i = 0; i<numberOfIntegers; i++)
    {
        cin >>Integers[i];
    }
    Combinations = pow(2.00, numberOfIntegers);
    for(int i = Combinations-1; i>=Combinations/2; i--) // I use half of the combinations, because 10100 will compute the same sum as 01011, but in with opposite sign.
    {
        Sum = 0;
        Binary = convertToBinary(i);
        for(int j = 0; Binary!=0; j++)
        {
            Remainder = Binary%10;
            Binary = Binary/10;
            if(Remainder==1)
            {
                Sum += Integers[numberOfIntegers-1-j];
            }
            else
            {
                Sum -= Integers[numberOfIntegers-1-j];
            }
        }
        if(N == abs(Sum))
        {
            Binary = convertToBinary(i);
            for(int j = 0; Binary!=0; j++)
            {
                Remainder = Binary%10;
                Binary = Binary/10;
                if(Sum>0)
                {
                    if(Remainder==1)
                    {
                        cout << "+" << Integers[numberOfIntegers-1-j];
                    }
                    else
                    {
                        cout << "-" << Integers[numberOfIntegers-1-j];
                    }
                }
                else
                {
                    if(Remainder==1)
                    {
                        cout << "-" << Integers[numberOfIntegers-1-j];
                    }
                    else
                    {
                        cout << "+" << Integers[numberOfIntegers-1-j];
                    }
                }
            }
            break;
        }
    }
    return 0;
}
Mat
  • 202,337
  • 40
  • 393
  • 406
Stefan4024
  • 694
  • 1
  • 10
  • 21
  • 1
    Please search existing questions, since I remember seeing this problem several times before. – Ben Voigt Mar 27 '13 at 19:09
  • Closely related to http://stackoverflow.com/q/6493120/103167 – Ben Voigt Mar 27 '13 at 19:11
  • As Ben said, this (or similar) has been asked many times before. – JBentley Mar 27 '13 at 19:11
  • Seems like a similar problem to the [travelling salesman problem](http://en.wikipedia.org/wiki/Travelling_salesman_problem). – JBentley Mar 27 '13 at 19:12
  • possible duplicate of [Dynamic programming sum](http://stackoverflow.com/questions/10464963/dynamic-programming-sum) and http://stackoverflow.com/questions/4355955/subset-sum-algorithm – Ben Voigt Mar 27 '13 at 19:12
  • And also http://stackoverflow.com/questions/14218882/a-number-as-its-prime-number-parts – Ben Voigt Mar 27 '13 at 19:17
  • 1
    I've seen all the examples you've posted, but I think thsi one is a little bit different. Almost every example is subset problem. This one is using all the numbers given and get the wanted number. Also i never really found example when you can subtract. – Stefan4024 Mar 27 '13 at 19:19
  • Is your question about optimization or correctness? – Thomas Matthews Mar 27 '13 at 19:20
  • @Stefan4024: There's not much difference between "include a number or not" vs "add a number or subtract it". You can, for example, start with the negative sum of all the numbers and then "include twice the number or not". – Ben Voigt Mar 27 '13 at 19:21
  • 1
    Why are you converting the combination number to binary and dividing by 10 decimal? – Thomas Matthews Mar 27 '13 at 19:25
  • @ThomasMatthews Example: Combination 31 in binary is 11111. Then i just get the last digit. We have to divide by 10 beacuse we are still working with decimal system, and 11111 is the binary form of 31. – Stefan4024 Mar 27 '13 at 19:29
  • Looks like a better approach would be to create a binary tree where the left branch represents '+' and the right branch represents '-'. Perform 2 steps: construct tree then traverse the tree to find the path that equals the sum. Print out the path. – Thomas Matthews Mar 27 '13 at 19:30
  • This method works, but the time it take is too long. So can anybody give me a better method, that will work quicker for bigger numbers. – Stefan4024 Mar 27 '13 at 19:37
  • @Stefan, read the last question I linked to. You can use the same approach, and it requires fewer operations (in most cases) than exhaustive combination. – Ben Voigt Mar 27 '13 at 23:27
  • possible duplicate of [Finding all possible combinations of numbers to reach a given sum](http://stackoverflow.com/questions/4632322/finding-all-possible-combinations-of-numbers-to-reach-a-given-sum) – Reno Mar 28 '13 at 07:03

3 Answers3

0

Since this is typical homework, I'm not going to give the complete answer. But consider this:

K = +a[1] - a[2] - a[3] + a[4]

can be rewritten as

a[0] = K
a[0] + a[2] + a[3] = a[1] + a[4]

You now have normal subset sums on both sides.

MSalters
  • 173,980
  • 10
  • 155
  • 350
0

So what you are worried about is you complexity .

Lets analyse what optimisations can be done.

Given n numbers in a[n] and target Value T;

And it is sure one combination of adding and subtracting gives you T ;

So Sigma(m*a[k]) =T where( m =(-1 or 1) and 0 >= k >= n-1 )

This just means ..

It can written as

(sum of Some numbers in array) = (Sum of remaining numbers in array) + T

Like in your case..

8+15-2+9-10=20 can be written as

8+15+9= 20+10+2

So Sum of all numbers including target = 64 // we can cal that .. :)

So half of it is 32 as

Which if further written as 20+(somthing)=32 which is 12 (2+10) in this case.

Your problem can be reduced to Finding the numbers in an array whose sum is 12 in this case

So your problem now can be reduced as find the combination of numbers whose sum is k (which you can calculate as described above k=12 .) For Which the complexity is O(log (n )) n as size of array , Keep in mind that you have to sort array and use binary search based algo for getting O(log(n)).

So as complexity can be made from O(2^n) to O((N+1)logN)as sorting included.

MissingNumber
  • 1,142
  • 15
  • 29
  • How can I check which combination computes sum of 12? It reduces the time, which is obvious, but still not enough to check every combination. Anyway thank for helping me – Stefan4024 Mar 30 '13 at 17:56
  • Let Sorted numbers are ..!! 1,2,8,9,10,12,14,21 Let suppose you need to compute sum of 25 A) Start to find the number less then or equal to Target (here 25) it is 21 here.. Repeat the step A for Target as (25-21) you cant find 4 or less so go to next number which is 14 Step A(11 as target 25-14) Step A(11 -10(as 10 is less then to 11 yo can find..)) Step A(target is 1) is found so Sum 25 that we can get with the ( 1, 10, 14) – MissingNumber Mar 30 '13 at 21:43
0

This takes static input as you have provided and i have written using core java

  public static void main(String[] args) {

    System.out.println("Enter number");

    Scanner sc = new Scanner(System.in);

    int total = 0;

    while (sc.hasNext()) {


        int[] array = new int[5] ;

        for(int m=0;m<array.length;m++){
            array[m] = sc.nextInt();
        }

         int res =array[0];
            for(int i=0;i<array.length-1;i++){

                    if((array[i]%2)==1){
                            res = res - array[i+1];
                    }
                    else{
                    res =res+array[i+1];
                    }
            }
            System.out.println(res);
    }
}
Code
  • 184
  • 1
  • 8
  • Please don't answer C++ questions with Java code (or the other way around). It's also much better to give an explanation of what the code you've provided does and why/how it solves the asker's problem/question. – Mat May 10 '13 at 08:10