user2939446
user2939446

Reputation: 71

Algorithm for Adding/Subtracting numbers to find if number can be made?

I was wondering if there is an efficient premade algorithm for determining if the sum/difference of a group of numbers can equal a different number. Example:

5, 8, 10, 2, using + or -, to equal 9. 5 - 8 = -3 + 10 = 7 + 2 = 9

If there is a preexisting algorithm, what is it called. If not, I can figure out how to program it, though it may not be efficient.

Thank you!

Upvotes: 4

Views: 2701

Answers (3)

Akash Yellappa
Akash Yellappa

Reputation: 2314

I actually wrote a simple java program, I was not actually aware of knapsack strategies. This is my own solution. Hope this helps

import java.util.ArrayList;
import java.util.List;

public class Puzzle {

    public static void main(String[] args) {

        int targetNumber = 0;
        int min = 2147483647;

        int[] numbers = {-10, -30, -20, -50};
        //int[] numbers = {0,0,0,0};
        //int[] numbers = {7, 2, 10};
        //int[] numbers = {1, 2, 3, 4, 5};
        //int[] numbers = {1000, 2, 3, 4, 100};
        char set[] = {'+', '-'};
        min = getNumberClosestToTarget(numbers, set, min, targetNumber);
        System.out.println(String.format(" %d is closest to %d", min, targetNumber));
    }

    private static int getNumberClosestToTarget(int[] numbers, char[] set, int min, int targetNumber) {

        List<String> operators = new ArrayList<>();

        computeAllOperatorsCombination(set, "", set.length, numbers.length - 1, operators);

        for (String operatorString : operators) {
            String[] ops = operatorString.split("");
            int sum = computeSum(numbers, ops, numbers.length - 1);
            min = getClosestToTarget(min, targetNumber, sum);
        }

        return min;
    }


    static int computeSum(int[] numbers, String[] operators, int index) {

        int result = numbers[index];

        if (index == 0) {
            return result;
        } else {
            switch (operators[index - 1]) {
                case "+":
                    return computeSum(numbers, operators, index - 1) + result;
                case "-":
                    return computeSum(numbers, operators, index - 1) - result;
            }

            return result;
        }
    }

    static void computeAllOperatorsCombination(char set[], String prefix, int n, int k, List<String> result) {
        if (k == 0) {
            result.add(prefix);
            return;
        }

        for (int i = 0; i < n; i++) {
            String newPrefix;
            newPrefix = prefix + set[i];
            computeAllOperatorsCombination(set, newPrefix, n, k - 1, result);
        }
    }

    private static int getClosestToTarget(int min, int targetNumber, int r) {
        int distance = Math.abs(targetNumber - r) < Math.abs(r - targetNumber) ? Math.abs(targetNumber - r) : Math.abs(r - targetNumber);
        if (distance < Math.abs(min)) {
            min = distance;

            if (r < 0) {
                min = -distance;
            }
        }
        return min;
    }
}

Upvotes: 0

Michael Iyaniwura
Michael Iyaniwura

Reputation: 1

its not an NP problem, if the problem is to find a given number from adding or subtracting each elements of a list/array. if you think about AP. here is a sample code in C++

    int Np( int mn, list<int>a, int c )
{
    int size = a.size(), rst = 0, maxI = 0;
    std::list<int>::iterator it;
    while( size > c )
    {
        a.sort();
        maxI += a.back();
        a.pop_back();
        rst = 0;
        for( auto ele : a )
        {
           rst += ele;
            cout << rst << endl;
        }
        if( (rst - maxI) == mn or (maxI - rst) == mn or (maxI + rst) == mn )
        {
            return mn;
        }
        size--;
    }
   return rst; 
}

this should help. i think.

Upvotes: 0

libik
libik

Reputation: 23029

Yeah, this is basically knapsack problem, but it can be computed in pseudopolynomial time using dynamic programming.

I did it few month ago, so maybe this java code can help you, if you want to implement it :

public void solve() {
    while (this.isEnd() == false) {
        int priceSum = this.getItemsInstance().getTotalPrice()/divide;
        int numOfItems = this.getItemsInstance().itemCount();
        int maxWeight = this.getItemsInstance().getMaxWeight();

        int[][] array = new int[numOfItems + 1][priceSum + 1];
        boolean[][] arrayCounted = new boolean[numOfItems + 1][priceSum + 1];

        for (int i = 0; i < numOfItems + 1; i++) {
            array[i][0] = 0;
            arrayCounted[i][0] = true;
        }

        int max = 0;
        int price = 0;
        for (int j = 1; j < priceSum + 1; j++) {
            for (int i = 1; i < numOfItems + 1; i++) {
                int temp = W(i, j, array, arrayCounted);
                if (temp <= maxWeight) {
                    max = temp;
                    price = j;
                }
            }
        }
    }
}

private int W(int i, int c, int[][] array, boolean[][] arrayCounted) {
    if (c < 0) {
        return MAX_PRICE / divide;
    }
    if (i == 0) {
        if (c == 0) {
            return 0;
        } else {
            return MAX_PRICE / divide;
        }
    }

    if (arrayCounted[i][c]) {
        return array[i][c];
    }

    arrayCounted[i][c] = true;
    array[i][c] = Math.min(W(i - 1, c, array, arrayCounted), W(i - 1, c - this.items[i - 1].price/divide, array, arrayCounted) + this.items[i - 1].weight);
    return array[i][c];
}

Upvotes: 2

Related Questions