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;
}
}