-2

I have and array with some elements like

5, 3, 7

and an initial int A (eg 5 in first case). I have to do addition and subtraction on this number from the array elements to get the maximum number less than or equal to M (10 in this case). The results of intermediate operations cannot exceed M . I can only use an array element once.

For example, the solution for this case would be

A = 5

A - 5 = 0
0 + 3 = 3
3 + 7 = 10

10 is equal to M, the final result.

What algorithm can use to solve this problem? I am making this program in C++.

intcreator
  • 4,206
  • 4
  • 21
  • 39
Aman
  • 17
  • 3
  • Ask for algorithms at a math-site. If you can't implement the algorithm then ask at this site. – Support Ukraine Oct 15 '15 at 20:27
  • I just want a an algorithm to solve this .... – Aman Oct 15 '15 at 20:30
  • Then ask the math-guys e.g. at http://math.stackexchange.com/ Here we discuss programming issues. – Support Ukraine Oct 15 '15 at 20:31
  • oo... i don'nt know about that ... thanks ... – Aman Oct 15 '15 at 20:35
  • 1
    @StillLearning: this is a controversial point. Some agree with you, but it's a fact that the [help center](http://stackoverflow.com/help/on-topic) says that a question that covers a a software algorithm is ok. Sure, it also says that they feel the best questions should have a bit of source code, but it isn't indicated as a strict requirement. The OP hasn't shown any code, but neither has he asked for some. He wants to have an algorithm, then he will code it on his own. I think this question is fine, though it would be good to add the tag [tag:algorithm]. – Fabio says Reinstate Monica Oct 15 '15 at 22:48
  • @brandaemon your edit made the post a lot clearer, but you modified an important part: the OP wants the *maximum* number that doesn't exceed M, not *any* number. Please edit it again. – Fabio says Reinstate Monica Oct 16 '15 at 00:48
  • @FabioTurati Sorry about that, it was a lot to sort through. I'll update my answer too. – intcreator Oct 16 '15 at 00:51
  • @brandaemon No problem, it can happen, and since you've just fixed it, everything is fine. Tomorrow I will also have a look at your answer. – Fabio says Reinstate Monica Oct 16 '15 at 01:21
  • @brandaemon thanks a lot for editing my post and making it readable for others . – Aman Oct 22 '15 at 18:27
  • @Aman is it still accurate? If not, feel free to edit it again to clarify. – intcreator Oct 22 '15 at 19:20
  • You edited it perfectly ... – Aman Oct 23 '15 at 11:14

2 Answers2

1

Here is a possible algorithm:

A = 5
M = 10
highest number = 0
array of numbers = {5, 3, 7}

function()
    call recursive function(empty string, index 0, A)
    print highest number

recursive function(string of operations used so far, int current element index, int sum so far)
    if the length of the string of operations == number of ints in array
        if sum so far > highest number
            highest number = sum so far
        return
    B = sum so far + current element
    C = sum so far - current element

    if B <= M
        recursive function(string of operations plus appended '+', int current element index + 1, B)

    if C <= M
        recursive function(string of operations plus appended '-', int current element index + 1, C)

The basic idea: use recursion to keep track of addition and subtraction operations. Here I simply appended + and - to a string and when the string got to be the size of the array, I checked if the sum was higher than the current highest. You can see a demo done in Java here. Feel free to play with the numbers in the demo a bit to see how it works.

intcreator
  • 4,206
  • 4
  • 21
  • 39
  • 1
    Nice answer. I'm not sure why you are checking that `B` and `C` are >= 0; I think the only requirement is that they don't exceed 10. But in any case the modification is trivial. Then you are also printing something different from what I would print, that is, you print all the possible solutions, not just the one(s) that gives the highest result. But this is just a choice. I like your answer. Well done! – Fabio says Reinstate Monica Oct 16 '15 at 08:45
  • @FabioTurati I suppose it's just a bit odd to use all those negative numbers considering the other strict requirements. I modified the condition to accept negatives now. As for what I print, it can be easily modified to print whatever the user needs, but both the algorithm and the demo should print the highest number now. – intcreator Oct 16 '15 at 15:05
1

I don't think there is a "smart" algorithm that can solve this in linear, or even polynomial, time. I'm afraid the only viable approach is to try all the possible combinations, and choose the best one. You can, though, use some techniques that conceptually are like branch and bound to get to the result faster.

I would do it like this.

Basic algorithm

First, I would generate all the possible combinations. For each of your N number you can choose to sum it or to subtract it, so you have 2 choices. That means that overall you have a total of 2^N possible choices. In your example, with N=3, these would be: ---, --+, -+-, -++, +--, +-+, ++-, +++. (This is like counting in binary, from 0 = 000 to 7 = 111).

At this point you have to "execute" each sequence. With these numbers (5, 3, 7), the first sequence means -5 -3 -7. You must run it one step at a time, and each time check that you aren't exceeding the target M, because it is required. Since your initial value A is 5, this would lead to: 5-5=0, and since 0<10 you can continue. Then, 0-3=-3, which is less than 10, so it's ok. Then, -3-7=-10 and since this is the last operation we don't have to check that it is less than 10. So the sequence is valid, and we have that for --- the result is -10. This is the best result so far (as it is the only one), so let's save the sequence as best sequence and the final result.

Then, let's move to the next sequence, --+. Again it's valid and the final result is 4. This is the best result so far, so we can save this sequence --+, overwriting the previous best result.

Going on, at -++ we will find the best result, 10, which can't be improved, thus we could stop there. If we don't reach M, we have to evaluate all the sequences, and at the end we will have the best one. There might be more than one that leads to the best result, for example if you have duplicate numbers (3 3 can be either +3 -3 or -3 +3, the sequences are different but the result is obviously the same), so you might want to store the best solutions in a vector, instead of keeping just one.

This would be the basic algorithm. Now, let's try to optimize it a little.

Optimized algorithm

Until now we have generated all the possible sequences (from --- to +++) and evaluated them all, one at a time. In some cases, though, evaluating them all is a waste of time. For example, let's say that the initial number is again A=5 and the target is M=10. If the sequence was like 6 3 4, at a certain point we would try to evaluate +--, but that would immediately fail because the first intermediate result would exceed the maximum value (5+6=11). Following the basic algorithm we would move on to evaluate +-+, but it doesn't make sense: it will obviously fail, for the same reason, at the same step (the first digit, that is, 5+6). The invalid sequence started with +, and all the successive choices of sign don't matter: all the sequences starting with + are necessarily invalid and can be discarded. So it means that if we find an invalid sequence, we can discard all the others that start like it.

To do this we can save all the sequences in a tree, which relates each choice of a sign to the previous one. Then, once we find an invalid solution we can discard all the others that begin like that one. For example, the tree could be saved like:

                               Root
                             /      \
                            /        \
                           /          \
                          /            \
                         /              \
                        -                +
                     /     \          /     \
                    -       +        -       +
                   / \     / \      / \     / \
                  -   +   -   +    -   +   -   +

and each sequence corresponds to the series of nodes that must be explored to reach one of the leaves. When you visit the tree, for every node you can calculate and store the value of the sequence so far. So when you reach the + at the first level you see that 5+6=11, which is too much, and you mark the entire node as invalid, thus avoiding to explore all the possible variants. Of course, with N=3 numbers it won't make much difference, as there are only a total of 2^3=8 sequences. But for N=20 they would be one million, and the time savings could be significant.

  • @FabioTuarti , Your answer was not perfect for my question , but after sorting the array and using your tree concept solved my problem. .. Thanks a lot – Aman Oct 22 '15 at 18:31