4

This is homework! Please do not give me the solution, just a hint!

The problem is to apply a sequence of operations from N to find M. The input is 6 numbers: A, B, C, D, N, M, where A corresponds to addition, B to subtraction, C to multiplication, and D to division. Here is an example:

10 4 2 3
21 32

We will try to find the number 32 starting from 21 using the those operations

ADD 10     // "A" number
SUB 4      // "B" number
MUL By 2   // "C" number
DIV By 3   // "D" number

the possible answer is:

32 = ((((21 * 2) + 10) - 4) / 3) * 2

the program outputs 1 if there is a sequence of operation otherwise 0. Can somebody give me a hint how to solve this?

Vesper
  • 18,599
  • 6
  • 39
  • 61
satyres
  • 377
  • 1
  • 5
  • 17
  • Are you allowed to use the same input number multiple times? Are you allowed not to use one or more of input numbers? Are there any other restrictions? – Alexey Frunze Apr 03 '13 at 10:31
  • @Alexey : no restriction just like the example below we used * 2 Twice ! – satyres Apr 03 '13 at 10:32
  • 32 = 21+3-4+10+2 -- all numbers used once. – Alexey Frunze Apr 03 '13 at 10:32
  • There are multiples solutions ! but the i'm blocked in the algorithm to slove it ! – satyres Apr 03 '13 at 10:34
  • 1
    Then it's not a very meaningful problem because as long as you can get a 0 and a 1 you can construct any number from these two if you repeat multiplication/addition enough times. Are you supposed to find the shortest solution (minimum number of operations)? – Alexey Frunze Apr 03 '13 at 10:34
  • The only restriction that i have in this exercice is this : Time: 0.5s on a 1Ghz PC. Memory: 2000 KB – satyres Apr 03 '13 at 10:36
  • Would 32=2*2*2*2*2 be an acceptable solution as well? – Alexey Frunze Apr 03 '13 at 10:38
  • No we should start from 21 ! – satyres Apr 03 '13 at 10:39
  • Ah, so you're saying that there *is* a limitation, the order in which you must use the numbers and that implies that you must use all of them. That's not readily apparent from the question. Wait... The order isn't perfect. So, what should the order really be? – Alexey Frunze Apr 03 '13 at 10:40
  • @msam We haven't figured out all the applicable conditions/limitations yet. So, it may or may not be possible. The question isn't very clear. – Alexey Frunze Apr 03 '13 at 10:42
  • just realised that if he can use the numbers more than once he can do x/x to get 1 then add until he gets to the target – msam Apr 03 '13 at 10:43
  • @AlexeyFrunze : The only restriction is Time: 0.5s on a 1Ghz PC. Memory: 2000 KB ,there is no problem using all or one operation – satyres Apr 03 '13 at 10:44
  • @msam: it will take so much time i have a restriction : Time: 0.5s on a 1Ghz PC. Memory: 2000 KB – satyres Apr 03 '13 at 10:44
  • But you just said one must begin with 21 (the last number, I suppose, or is it the biggest?). And then which number can/must be chosen? – Alexey Frunze Apr 03 '13 at 10:45
  • @AlexeyFrunze : the next number will be the result of the operation like this 21*2=42| 42+10=52| 52-4=48| 48/3=16| 16*2=32 – satyres Apr 03 '13 at 10:48
  • I'm talking about the input numbers and not about the intermediate results. In which order exactly must you use them? – Alexey Frunze Apr 03 '13 at 10:59
  • Voting to close due to the problem being unclear in terms of exact limitations (other than execution time and memory used). – Alexey Frunze Apr 03 '13 at 11:07
  • @AlexeyFrunze : I swear this is all i have in this exercise: just like i said before ! why voting to close !! try to help each others !to find a solution ! Thanks ! – satyres Apr 03 '13 at 11:11
  • satyres to make this clearer can you confirm if 1. you have 6 input numbers N, from where you start, M the target, {A,B,C,D} set of 4 numbers that you can use any number of times, including 0? 2. you can use any combination of the input numbers with any operator from *-/+ – msam Apr 03 '13 at 11:16
  • @msam : we use ADD 10 | SUB 4 | MUL By 2 | DIV By 3 | we can use it multiple time – satyres Apr 03 '13 at 11:23
  • I don't think we can talk about solutions to a problem when the problem itself isn't fully defined. You are probably expecting that the solutions which people are going to propose will be accepted by whatever judging system there is. Well, what if those solutions are for a different problem? Do you need any solution, even if it's not going to be accepted? – Alexey Frunze Apr 03 '13 at 11:27
  • You can take a look at this answer for a way to evaluate a sequence of operations: http://stackoverflow.com/questions/15293232/how-to-design-an-algorithm-to-calculate-countdown-style-maths-number-puzzle/15356818#15356818 – mitchnull Apr 03 '13 at 11:32
  • Looks like the question has been mostly clarified now. But, one more question: Does the "/" operator perform integer arithmetic or not? i.e. does 3/2 = 1 or 1.5? – Xantix Apr 07 '13 at 23:02
  • I think using a graph search is probably the computer science approach to this, I am going to write this question up for the math.stackexchange since I think that the math question is going to be answered better there. The question here can stand, because it gives good answers of how to implement it in a programming language. I will link to the question once I have it posted. – Xantix Apr 08 '13 at 04:36
  • here's the link to the math.stackexchange question: http://math.stackexchange.com/questions/354625/how-to-compose-given-add-sub-mult-div-functions-to-map-an-integer-m-to-n – Xantix Apr 08 '13 at 06:58
  • @Xantix: Thanks for posting in math.StackExchange ! this will help us a lot to resolve this exercise ! – satyres Apr 09 '13 at 17:11
  • @Xantix : does 3/2 = 1 or 1.5? ==> Answer is 1 (integer part only) – satyres Apr 10 '13 at 09:29

4 Answers4

2

You could do some kind of graph search, but with four numbers and four possible operations to perform with those numbers there are going to be 16 branches at every node and it'll probably get big quickly.

James
  • 3,957
  • 4
  • 37
  • 82
  • I'm also thinking about graph but it will be so big like you said ! – satyres Apr 03 '13 at 11:05
  • 1
    @satyres By the way, I really expect that those 4 numbers you speak of directly correspond to operations (first one is ADD, second is SUB, third is MUL, fourth is DIV). So only 4 branches per node, this is more viable. – Vesper Apr 03 '13 at 12:04
  • @satyres If so, add a dictionary type structure that will hold links to your building graph, so that if you'd encounter a number that already exists, you can query that structure for O(1) time, and stop evolving that graph by that branch. This helps performance. – Vesper Apr 03 '13 at 13:58
  • In fact the main trouble will be determining if there is NO answer to the question. I guess it's not this easy. It's also quite possible that you would satiate with only DIV and ADD operations, if that DIV rounds the result to an int. Say, `9 6 2 3 3 329` will result in a sequence of ((3/3)+9+9-6-6)/3+9+9+9... that is, if you can add 1 to the result via only ADD/SUB operations, you're already golden, you output 1. Otherwise, search if you can receive `target mod NOD(ADD,SUB)` as a result, if so, output 1 too. – Vesper Apr 03 '13 at 14:04
1

It seems that the biggest problem will be to determine if there is no answer. If GCD(A, B) is 1, then the answer is 1, because this means there IS a sequence of ADD A and SUB B operation that increments or decrements the source value by 1, so if you repeat this sequence enough times, you will reach ANY number from ANY other number. If it's not 1, and your DIV operation rounds the value, search if you can reach target mod GCD(A,B) value using all 4 operations. This value should be fairly small, so you can do the aforementioned graph search, clipping the result of next step via mod LCM(A,B) AND equalling branches that produce equal value of modulo GCD(A,B) operation. So, if you would reach a single value that equals target mod GCD(A,B), you can output a 1, if none reached, output a 0. The graph walk will eventually cease, as there is a fixed amount of different values in (0, LCM(A,B)-1) interval, and if properly programmed, will satisfy both memory and time requirements.

Yes, you have to take care about special situations, like A=0, B=0, C=1, or D=1. For example, a sequence 0 3 1 3 81 5 will result in an 1, while 0 3 1 3 81 29 in a 0. Edit: revised the modulo in clipping, and posted correct abbreviation functions of A and B.

Vesper
  • 18,599
  • 6
  • 39
  • 61
0

you can solve that with brute force, if you use polymorphic functors for the operations and just go on trying. you would need a good break criteria though (like limit the number of applied operations to 10 or something like that).

answer on functors: C++ Functors - and their uses

polymorphism should be findable on the web.

example:

class operation {
public:
    enum TYPE { ADD = 0, SUB };

    virtual int operator()(int left, int right) = 0;
}

class add : public operation {
public:
    int operator()(int left, int right) {
        return left + right;
    }
}

class sub : public operation {
public:
    int operator()(int left, int right) {
        return left - right;
    }
}

int main() {
    std::vector<operation*> foo;
    foo[0] = new add();
    foo[1] = new sub();
    foo[2] = new add();


    int bar = 21;
    for (auto& op : foo) {
        bar = (*op)(bar, 2);
        std::cout << bar << std::endl;
    }
}

those classes are functors. Using such constructs, you can treat algorithms or basic operatios like variable, that you can assign or shuffle or randomize or whatever you like. since the have all the same interface inherited from operation, they all know what () means, but act differently.

having such things allows you to store and backtrack the used operations and simple loop through the permutations. while you do that, you should be aware, that you should limit the number of possible maxumum combinations of operations for each set, or you will run into endless loops / recursion.

Community
  • 1
  • 1
scones
  • 3,317
  • 23
  • 34
  • Sorry it's a little bit hard for me can you explain more or give a site to learn about it thanks – satyres Apr 03 '13 at 11:04
0

This answer is based on the accepted answer to this question on math.stackexchange:

https://math.stackexchange.com/questions/354625/how-to-compose-given-add-sub-mult-div-functions-to-map-an-integer-m-to-n

Given the six inputs (a, b, c, d, M, N)

  • a: the number we can add
  • b: the number we can subtract
  • c: the number we can multiply
  • d: the number we can divide
  • M: the starting number
  • N: the ending number

I assume they are all integers, and a > 0, b > 0, c could be positive or negative, d not equal to 0.

Then there is a way to transform M to N by applying add, sub, mult, div,

if and only if

there exist integers m and n such that

M*(c^m) is equiv to N*(d^n) all mod gcd(a,b)

So, the first thing to do is to find the greatest common divisor of a and b (I recommend Euclid's algorithm as described here. Call the gcd "g".

The mod is applied to both sides to verify equality.

So, start making a list of possible values the left hand side can take for different m:

(M*( Pow(c,m) )) % g

Then, start making a list of possible values the right hand side can take for different n:

(N*( Pow(d,n) )) % g

You will want to start m and n at zero and work your way up.

Eventually, both sides will start repeating, since you are using mod.

If at any time you find a match, i.e. left hand side equals some right hand side, return 1.

Otherwise, once you have exhausted all left hand values and right hand values, with no matches, return 0.

Note, that the mod operator (%) in C++ does behave different for negative numbers than the above math describes. You will need to adjust the results of mod to always be in the range 0 <= result < g

Lastly, this only works fully for cases where division acts according to normal math, i.e. 3 / 2 = 1.5 and so on.

In your case, you would need to modify the formula slightly to accept integer division. In particular the right hand side of the equation deals with division. Kind of like how the following equation works, we can take a divide, move it to the other side and it becomes a multiply.

x / 3 = 1

x = 1*3

You will need to allow the rhs to take multiple values each time you perform a power on d. For example, in the above example, we need to allow 1*3 to equal 3,4, or 5.

So, if d = 3, then

  • Pow(d,0) = 1.
  • Pow(d,1) = 3 or 4 or 5.
  • Pow(d,2) = 9 or 10 or 11     or     12 or 13 or 14     or     15 or 16 or 17

You will see that 9 = 3*3, 12 = 4*3, and 15 = 5*3. So the pattern should be easy to replicate, even for different values of d.

I haven't tried this last part out, so I'm not entirely sure this exactly covers all cases of the integer division, but I think it does, although it is kind of tedious.

Community
  • 1
  • 1
Xantix
  • 3,321
  • 1
  • 14
  • 28