How do I maximise and minimize the mathematical expression using recursion? - algorithm

Expression consists of numbers (0-9) seperated by one of the two operators '*' and '+'. There are no spaces between the characters.
Example: 1+2*3+4*5
We need to find out the maximum and minimum value we can get by using brackets at appropriate places.
Maximum value:105 = (1+2)*(3+4)*5
Minimum value: 27 = 1+2*3+4*5
I am looking for a recursive way to do it? Any ideas would be appreciated.

Minimization:
The main idea of the solution: instead of thinking how to add parentheses, let's think about which operation was the last one. Let's write a recursive function minimize(expr). What should it do? If it is given one number, it should just return it. Otherwise, we can iterate over all operators in it, call minimize for the part expression to the left and to the right of the operator and combine the result. Now we just need to pick the smallest value.
Here is some pseudo code:
int minimize(string expr)
if isNumber(expr) then // If it is one number, return it.
return value(expr)
int res = infinity
for int i <- 0 .. lenght expr - 1
if expr[i] == '+' then
res = min(res, minimize(expr[0 .. i - 1]) +
minimize(expr[i + 1 .. length expr - 1])
if expr[i] == '*' then
res = min(res, minimize(expr[0 .. i - 1]) *
minimize(expr[i + 1 .. length expr - 1])
return res
Maximization:
Pretty much the same, but we should take maximum instead of minimum at each step.
Why is it correct? When we multiply and add non-negative numbers, the larger(the smaller) the operands are, the larger(the smaller) the result is.
We can also use memoization to avoid recomputing result for the same expression twice(or more times) and obtain polynomial time complexity.

Related

The algorithm to generate binary numbers from 1 to n in lexicographical order

Is there any efficient algorithm to do so ,I have tried to produce all binary numbers and store them in an array then sort them, if we can directly generate the binary numbers in lexicographical order the code will be much faster.
For eg : n=7 produces 1,10,100,101,11,110,111
The key property here is, 0 will always come before 1, so you can use recursion to solve this. The algorithm would look like:
Start recursion from 1
If current number > n, ignore it
Else, add it to the output list. Call recursion(curr_number + "0") and recursion(curr_number + "1")
This is a simple algorithm, which can be easily implemented in most languages.
Edit: Python implementation:
def dfs(current_string, current_number, n):
if current_number > n:
return []
strings = [current_string]
strings.extend(dfs(current_string + "0", current_number << 1, n))
strings.extend(dfs(current_string + "1", (current_number << 1)+1, n))
return strings
print(dfs("1", 1, 7))
If you number a complete binary tree row by row, from 1 to 2^d-1, the enumeration of the nodes in lexicographical order is the preorder traversal. Now as the two children of a node carry the value of the parent followed by 0 or by 1, we have the recursive enumeration
n= ...
def Emit(m):
print(bin(m))
if 2 * m <= n:
Emit(2 * m)
if 2 * m + 1 <= n:
Emit(2 * m + 1)
Emit(1)
(You can also obtain the binary representations by concatenating 0's or 1's as you go.)
There are a few rules you can follow to generate the next item in a lexicographical ordering of any set of strings:
The first symbol that changes must increase (otherwise you'll get an earlier symbol)
The first symbols that changes must be as far right as possible (otherwise there would be a smaller lexicographical change); and
The symbols after the first change must be made as small as possible (otherwise again there would be a smaller lexicographical change).
For ordering the binary strings, these rules are easy to apply. In each iteration:
If you can append a zero without exceeding n, then do so;
Otherwise, find the rightmost possible 0, change it to a 1, and remove the remainder. The "rightmost possible 0" in this case is rightmost one that produces a result <= n. This is not necessarily the rightmost one if n is not 2x-1.
This iteration is pretty easy to implement with bitwise operators, leading to this nice quick algorithm. To simplify step (2), we assume that n is 2x-1 and just check our outputs:
def printLexTo(n):
val=1
while True:
if val<=n:
print("{0:b}".format(val))
if 2*val <= n:
val *= 2
else:
# get the smallest 0 bit
bit = (val+1) & ~val
# set it to 1 and remove the remainder
val = (val+1)//bit
if val==1:
# there weren't any 0 bits in the string
break
Try it online
As is often the case, this iterative algorithm is a lot faster than recursive ones, but coming up with it requires a deeper understanding of the structure of the solution.

Maximum sum of sequence

Suppose we have sequence of x numbers and x-1 operators (+ or -), where the order of the numbers and the operators are fixed. For example 5-2-1+3. By different parentheses you get different values. For example (5 - 2)-1+3 = 5, 5-(2-1)+3=7 and so on. I am now interested in the maximum sum and best in linear run-time/memory space.
I think that this problem can be solved with dynamic programming, but I simply don't find a meaningful variant.
What you need here is certainly a dynamic algorithm.
This would work in a recursive way, finding the maximum value that can be gotten for every range.
Algorithm:
You could separate the numbers and the operators into different lists (if the first number is positive add + to the list first).
max_sum(expression, operators):
if len(expression) == 1: return expression
max_value = -float('inf') # minus infinity
length = len(expression)
for i in range(length):
left_exp = max_sum(expression[0:i], operators[0:i])
right_exp = max_sum(expression[i:length], operators[i:length])
value = operator[i].apply(left_exp, right_exp)
if value >= max_value:
max_value = value
return max_value
The main idea of the algorithm is that it checks the maximum sums in every possible range division, goes all the way down recursively and then returns the maximum sum it got.
The pseudo-code doesn't take into account a case where you could get a maximum value by substracting the minimum value of the right expression, but with a few tweaks I think you could fix it pretty fast.
I tried to make the pseudo-code as easy to convert to code as possible out of my head, I hope this helps you.
Let an expression be a sequence of operator-number pairs: it starts with an operator followed by a number, and ends with an operator followed by a number. Your example 5-2-1+3 can be made into an expression by placing a + at the beginning: +5-2-1+3.
Let the head of an expression be its first operator-number pair, and its tail, the rest. The head of +5-2-1+3 is +5 and the tail, -2-1+3.
In this context, let parenthesizing an expression mean placing an opening parenthesis just after the first operator and a closing parenthesis at the end of the expression, like so: +(5-2-1+3). Parenthesizing an expression with a positive head doesn't do anything. Parenthesizing an expression with a negative head is equivalent to changing every sign of its tail: -(5 -2-1+3) = -5 +2+1-3.
If you want to get an extremum by parenthesizing some of its subexpressions, then you can first make some simplifications. It's easy to see that any subexpression of the form +x1+x2+...+xn won't be split: all of its elements will be used together towards the extremum. Similarly, any subexpression of the form -x1-x2-...-xn won't be split, but may be parenthesized (-(x1-x2-...-xn)). Therefore, you can first simplify any subexpression of the first form into +X, where X is the sum of its elements, and any subexpression of the second form into -x1-X, where X is the sum of its tail elements.
The resulting expression cannot have 3 consecutive - operators or 2 consecutive + operators. Now, start from the end, find the first subexpression of the form -a-b, -a+b-c, or -a+b, and compute its potential minimum and its potential maximum:
min(-a-b) = -a-b
max(-a-b) = -(a-b)
min(-a+b-c) = -(a+b)-c
max(-a+b-c) = -a+b-c if b>=c, max(-a+b-c) = -(a+b-c) if b<=c
min(-a+b) = -(a+b)
max(-a+b) = -a+b
Repeat by treating that subexpression as a single operator-number pair in the next one, albeit with two possible values (its two extrema). This way, the extrema of each subsequent subexpression is computed until you get to the main expression, of which you can simply compute the maximum. Note that the main expression may have a positive first pair, which makes it a special case, but that's easy to take into account: just add it to the maximum.

What would be a good way to perform crossover with dependencies in GA?

I'm writing a genetic algorithm to find an expression that expresses a target number, i.e. if the target number is 10 a solution would be 2*5. For now I'm using fixed size chromosomes and I want to change it to random length but only after I will find a way to perform crossover.
The following are possible chromosomes, obeying the rules that numbers and operators appears in the string alternately, in a way that no two digits or two operators are adjacent. A legal string would start with a digit or +/- operators. The expression would be calculated from left to right as-is (ignoring the order of arithmetic operations):
1/2+3+5
-2+4+1+8
-7+6*2+8
+2/5-1+8 2+1*2-2
+2*7*7+3
+1/2/2/6 5/5*9*1
+3-1+1*8 3-8+7*1
Trying to implement a crossover I have tried the following (in pseudo-code):
crossover(chrom-a, chrom-b):
min_length = min(length(chrom-a), length(chrom-b))
locus = random(1, min_length-1)
while (chrom-a[locus] & chrom-b[locus] aren't both digit or operator)
ocus = random(1, min_length-1)
chrom-a = chrom-a[:locus] + chrom-b[locus:]
chrom-b = chrom-b[:locus] + chrom-a[locus:]
return chrom-a, chrom-b
But the function isn't working as expected, it sometimes takes too much time to find the right locus. I must find a way to make the crossover work with random sized chromosomes but I can't figure how (and of course make sure there's no division by zero).
Long processing time is most probably because of small probability of an event that two chromosomes have different types (operator or digit) of characters on the same position. Note that for 1 digit numbers two chromosomes will always have the same type on the same position. The solution is to find splitting points in each chromosome separately:
find_loci(chrom-a, chrom-b):
return pair(random(1, length(chrom-a)-1), random(1, length(chrom-b)-1))
crossover(chrom-a, chrom-b):
locus-a, locus-b = find_loci(chrom-a, chrom-b)
while (chrom-a[locus-a] & chrom-b[locus-b] aren't both digit or operator)
locus-a, locus-b = find_loci(chrom-a, chrom-b)
chrom-a = chrom-a[:locus-a] + chrom-b[locus-b:]
chrom-b = chrom-b[:locus-a] + chrom-a[:locus-b]
chrom-c = chrom-a[locus-a:] + chrom-b[locus-b:]
chrom-d = chrom-b[locus-a:] + chrom-a[:locus-b]
return chrom-a, chrom-b, chrom-c, chrom-d
The consequence is of course that you'll have four possible results, not two. You can use all, or ignore half of them.
Another fix is to first enumerate all possible splitting points:
enumerate_possible_loci(chrom-a, chrom-b):
for all indexes i in (1, chrom-a):
for all indexes j in (1, chrom-b):
if type(chrom-a[i]) != type(chrom-b[j]):
yield return pair(i, j)
crossover(chrom-a, chrom-b):
possible_loci = enumerate_possible_loci(chrom-a, chrom-b)
locus_pair = possible_loci[random(0, length(possible_loci) - 1)]
locus-a = locus_pair[0]
locus-b = locus_pair[1]
chrom-a = chrom-a[:locus-a] + chrom-b[locus-b:]
chrom-b = chrom-b[:locus-a] + chrom-a[:locus-b]
chrom-c = chrom-a[locus-a:] + chrom-b[locus-b:]
chrom-d = chrom-b[locus-a:] + chrom-a[:locus-b]
return chrom-a, chrom-b, chrom-c, chrom-d
If you have always only 1-digit numbers, then the algorithm for enumerating possible loci is even easier, because it will always return all possible pairs when one index is even and the other odd, and vice-versa.

Efficient Algorithm to find combination of numbers for an answer [duplicate]

I'm working on a homework problem that asks me this:
Tiven a finite set of numbers, and a target number, find if the set can be used to calculate the target number using basic math operations (add, sub, mult, div) and using each number in the set exactly once (so I need to exhaust the set). This has to be done with recursion.
So, for example, if I have the set
{1, 2, 3, 4}
and target 10, then I could get to it by using
((3 * 4) - 2)/1 = 10.
I'm trying to phrase the algorithm in pseudo-code, but so far haven't gotten too far. I'm thinking graphs are the way to go, but would definitely appreciate help on this. thanks.
This isn't meant to be the fastest solution, but rather an instructive one.
It recursively generates all equations in postfix notation
It also provides a translation from postfix to infix notation
There is no actual arithmetic calculation done, so you have to implement that on your own
Be careful about division by zero
With 4 operands, 4 possible operators, it generates all 7680 = 5 * 4! * 4^3
possible expressions.
5 is Catalan(3). Catalan(N) is the number of ways to paranthesize N+1 operands.
4! because the 4 operands are permutable
4^3 because the 3 operators each have 4 choice
This definitely does not scale well, as the number of expressions for N operands is [1, 8, 192, 7680, 430080, 30965760, 2724986880, ...].
In general, if you have n+1 operands, and must insert n operators chosen from k possibilities, then there are (2n)!/n! k^n possible equations.
Good luck!
import java.util.*;
public class Expressions {
static String operators = "+-/*";
static String translate(String postfix) {
Stack<String> expr = new Stack<String>();
Scanner sc = new Scanner(postfix);
while (sc.hasNext()) {
String t = sc.next();
if (operators.indexOf(t) == -1) {
expr.push(t);
} else {
expr.push("(" + expr.pop() + t + expr.pop() + ")");
}
}
return expr.pop();
}
static void brute(Integer[] numbers, int stackHeight, String eq) {
if (stackHeight >= 2) {
for (char op : operators.toCharArray()) {
brute(numbers, stackHeight - 1, eq + " " + op);
}
}
boolean allUsedUp = true;
for (int i = 0; i < numbers.length; i++) {
if (numbers[i] != null) {
allUsedUp = false;
Integer n = numbers[i];
numbers[i] = null;
brute(numbers, stackHeight + 1, eq + " " + n);
numbers[i] = n;
}
}
if (allUsedUp && stackHeight == 1) {
System.out.println(eq + " === " + translate(eq));
}
}
static void expression(Integer... numbers) {
brute(numbers, 0, "");
}
public static void main(String args[]) {
expression(1, 2, 3, 4);
}
}
Before thinking about how to solve the problem (like with graphs), it really helps to just look at the problem. If you find yourself stuck and can't seem to come up with any pseudo-code, then most likely there is something that is holding you back; Some other question or concern that hasn't been addressed yet. An example 'sticky' question in this case might be, "What exactly is recursive about this problem?"
Before you read the next paragraph, try to answer this question first. If you knew what was recursive about the problem, then writing a recursive method to solve it might not be very difficult.
You want to know if some expression that uses a set of numbers (each number used only once) gives you a target value. There are four binary operations, each with an inverse. So, in other words, you want to know if the first number operated with some expression of the other numbers gives you the target. Well, in other words, you want to know if some expression of the 'other' numbers is [...]. If not, then using the first operation with the first number doesn't really give you what you need, so try the other ops. If they don't work, then maybe it just wasn't meant to be.
Edit: I thought of this for an infix expression of four operators without parenthesis, since a comment on the original question said that parenthesis were added for the sake of an example (for clarity?) and the use of parenthesis was not explicitly stated.
Well, you didn't mention efficiency so I'm going to post a really brute force solution and let you optimize it if you want to. Since you can have parantheses, it's easy to brute force it using Reverse Polish Notation:
First of all, if your set has n numbers, you must use exactly n - 1 operators. So your solution will be given by a sequence of 2n - 1 symbols from {{your given set}, {*, /, +, -}}
st = a stack of length 2n - 1
n = numbers in your set
a = your set, to which you add *, /, +, -
v[i] = 1 if the NUMBER i has been used before, 0 otherwise
void go(int k)
{
if ( k > 2n - 1 )
{
// eval st as described on Wikipedia.
// Careful though, it might not be valid, so you'll have to check that it is
// if it evals to your target value great, you can build your target from the given numbers. Otherwise, go on.
return;
}
for ( each symbol x in a )
if ( x isn't a number or x is a number but v[x] isn't 1 )
{
st[k] = x;
if ( x is a number )
v[x] = 1;
go(k + 1);
}
}
Generally speaking, when you need to do something recursively it helps to start from the "bottom" and think your way up.
Consider: You have a set S of n numbers {a,b,c,...}, and a set of four operations {+,-,*,/}. Let's call your recursive function that operates on the set F(S)
If n is 1, then F(S) will just be that number.
If n is 2, F(S) can be eight things:
pick your left-hand number from S (2 choices)
then pick an operation to apply (4 choices)
your right-hand number will be whatever is left in the set
Now, you can generalize from the n=2 case:
Pick a number x from S to be the left-hand operand (n choices)
Pick an operation to apply
your right hand number will be F(S-x)
I'll let you take it from here. :)
edit: Mark poses a valid criticism; the above method won't get absolutely everything. To fix that problem, you need to think about it in a slightly different way:
At each step, you first pick an operation (4 choices), and then
partition S into two sets, for the left and right hand operands,
and recursively apply F to both partitions
Finding all partitions of a set into 2 parts isn't trivial itself, though.
Your best clue about how to approach this problem is the fact that your teacher/professor wants you to use recursion. That is, this isn't a math problem - it is a search problem.
Not to give too much away (it is homework after all), but you have to spawn a call to the recursive function using an operator, a number and a list containing the remaining numbers. The recursive function will extract a number from the list and, using the operation passed in, combine it with the number passed in (which is your running total). Take the running total and call yourself again with the remaining items on the list (you'll have to iterate the list within the call but the sequence of calls is depth-first). Do this once for each of the four operators unless Success has been achieved by a previous leg of the search.
I updated this to use a list instead of a stack
When the result of the operation is your target number and your list is empty, then you have successfully found the set of operations (those that traced the path to the successful leaf) - set the Success flag and unwind. Note that the operators aren't on a list nor are they in the call: the function itself always iterates over all four. Your mechanism for "unwinding" the operator sequence from the successful leaf to get the sequence is to return the current operator and number prepended to the value returned by recursive call (only one of which will be successful since you stop at success - that, obviously, is the one to use). If none are successful, then what you return isn't important anyhow.
Update This is much harder when you have to consider expressions like the one that Daniel posted. You have combinatorics on the numbers and the groupings (numbers due to the fact that / and - are order sensitive even without grouping and grouping because it changes precedence). Then, of course, you also have the combinatorics of the operations. It is harder to manage the differences between (4 + 3) * 2 and 4 + (3 * 2) because grouping doesn't recurse like operators or numbers (which you can just iterate over in a breadth-first manner while making your (depth-first) recursive calls).
Here's some Python code to get you started: it just prints all the possible expressions, without worrying too much about redundancy. You'd need to modify it to evaluate expressions and compare to the target number, rather than simply printing them.
The basic idea is: given a set S of numbers, partition S into two subsets left and right in all possible ways (where we don't care about the order or the elements in left and right), such that left and right are both nonempty. Now for each of these partitions, find all ways of combining the elements in left (recursively!), and similarly for right, and combine the two resulting values with all possible operators. The recursion bottoms out when a set has just one element, in which case there's only one value possible.
Even if you don't know Python, the expressions function should be reasonably easy to follow; the splittings function contains some Python oddities, but all it does is to find all the partitions of the list l into left and right pieces.
def splittings(l):
n = len(l)
for i in xrange(2**n):
left = [e for b, e in enumerate(l) if i & 2**b]
right = [e for b, e in enumerate(l) if not i & 2**b]
yield left, right
def expressions(l):
if len(l) == 1:
yield l[0]
else:
for left, right in splittings(l):
if not left or not right:
continue
for el in expressions(left):
for er in expressions(right):
for operator in '+-*/':
yield '(' + el + operator + er + ')'
for x in expressions('1234'):
print x
pusedo code:
Works(list, target)
for n in list
tmp=list.remove(n)
return Works(tmp,target+n) or Works(tmp,target-n) or Works(tmp, n-target) or ...
then you just have to put the base case in. I think I gave away to much.

Computing target number from numbers in a set

I'm working on a homework problem that asks me this:
Tiven a finite set of numbers, and a target number, find if the set can be used to calculate the target number using basic math operations (add, sub, mult, div) and using each number in the set exactly once (so I need to exhaust the set). This has to be done with recursion.
So, for example, if I have the set
{1, 2, 3, 4}
and target 10, then I could get to it by using
((3 * 4) - 2)/1 = 10.
I'm trying to phrase the algorithm in pseudo-code, but so far haven't gotten too far. I'm thinking graphs are the way to go, but would definitely appreciate help on this. thanks.
This isn't meant to be the fastest solution, but rather an instructive one.
It recursively generates all equations in postfix notation
It also provides a translation from postfix to infix notation
There is no actual arithmetic calculation done, so you have to implement that on your own
Be careful about division by zero
With 4 operands, 4 possible operators, it generates all 7680 = 5 * 4! * 4^3
possible expressions.
5 is Catalan(3). Catalan(N) is the number of ways to paranthesize N+1 operands.
4! because the 4 operands are permutable
4^3 because the 3 operators each have 4 choice
This definitely does not scale well, as the number of expressions for N operands is [1, 8, 192, 7680, 430080, 30965760, 2724986880, ...].
In general, if you have n+1 operands, and must insert n operators chosen from k possibilities, then there are (2n)!/n! k^n possible equations.
Good luck!
import java.util.*;
public class Expressions {
static String operators = "+-/*";
static String translate(String postfix) {
Stack<String> expr = new Stack<String>();
Scanner sc = new Scanner(postfix);
while (sc.hasNext()) {
String t = sc.next();
if (operators.indexOf(t) == -1) {
expr.push(t);
} else {
expr.push("(" + expr.pop() + t + expr.pop() + ")");
}
}
return expr.pop();
}
static void brute(Integer[] numbers, int stackHeight, String eq) {
if (stackHeight >= 2) {
for (char op : operators.toCharArray()) {
brute(numbers, stackHeight - 1, eq + " " + op);
}
}
boolean allUsedUp = true;
for (int i = 0; i < numbers.length; i++) {
if (numbers[i] != null) {
allUsedUp = false;
Integer n = numbers[i];
numbers[i] = null;
brute(numbers, stackHeight + 1, eq + " " + n);
numbers[i] = n;
}
}
if (allUsedUp && stackHeight == 1) {
System.out.println(eq + " === " + translate(eq));
}
}
static void expression(Integer... numbers) {
brute(numbers, 0, "");
}
public static void main(String args[]) {
expression(1, 2, 3, 4);
}
}
Before thinking about how to solve the problem (like with graphs), it really helps to just look at the problem. If you find yourself stuck and can't seem to come up with any pseudo-code, then most likely there is something that is holding you back; Some other question or concern that hasn't been addressed yet. An example 'sticky' question in this case might be, "What exactly is recursive about this problem?"
Before you read the next paragraph, try to answer this question first. If you knew what was recursive about the problem, then writing a recursive method to solve it might not be very difficult.
You want to know if some expression that uses a set of numbers (each number used only once) gives you a target value. There are four binary operations, each with an inverse. So, in other words, you want to know if the first number operated with some expression of the other numbers gives you the target. Well, in other words, you want to know if some expression of the 'other' numbers is [...]. If not, then using the first operation with the first number doesn't really give you what you need, so try the other ops. If they don't work, then maybe it just wasn't meant to be.
Edit: I thought of this for an infix expression of four operators without parenthesis, since a comment on the original question said that parenthesis were added for the sake of an example (for clarity?) and the use of parenthesis was not explicitly stated.
Well, you didn't mention efficiency so I'm going to post a really brute force solution and let you optimize it if you want to. Since you can have parantheses, it's easy to brute force it using Reverse Polish Notation:
First of all, if your set has n numbers, you must use exactly n - 1 operators. So your solution will be given by a sequence of 2n - 1 symbols from {{your given set}, {*, /, +, -}}
st = a stack of length 2n - 1
n = numbers in your set
a = your set, to which you add *, /, +, -
v[i] = 1 if the NUMBER i has been used before, 0 otherwise
void go(int k)
{
if ( k > 2n - 1 )
{
// eval st as described on Wikipedia.
// Careful though, it might not be valid, so you'll have to check that it is
// if it evals to your target value great, you can build your target from the given numbers. Otherwise, go on.
return;
}
for ( each symbol x in a )
if ( x isn't a number or x is a number but v[x] isn't 1 )
{
st[k] = x;
if ( x is a number )
v[x] = 1;
go(k + 1);
}
}
Generally speaking, when you need to do something recursively it helps to start from the "bottom" and think your way up.
Consider: You have a set S of n numbers {a,b,c,...}, and a set of four operations {+,-,*,/}. Let's call your recursive function that operates on the set F(S)
If n is 1, then F(S) will just be that number.
If n is 2, F(S) can be eight things:
pick your left-hand number from S (2 choices)
then pick an operation to apply (4 choices)
your right-hand number will be whatever is left in the set
Now, you can generalize from the n=2 case:
Pick a number x from S to be the left-hand operand (n choices)
Pick an operation to apply
your right hand number will be F(S-x)
I'll let you take it from here. :)
edit: Mark poses a valid criticism; the above method won't get absolutely everything. To fix that problem, you need to think about it in a slightly different way:
At each step, you first pick an operation (4 choices), and then
partition S into two sets, for the left and right hand operands,
and recursively apply F to both partitions
Finding all partitions of a set into 2 parts isn't trivial itself, though.
Your best clue about how to approach this problem is the fact that your teacher/professor wants you to use recursion. That is, this isn't a math problem - it is a search problem.
Not to give too much away (it is homework after all), but you have to spawn a call to the recursive function using an operator, a number and a list containing the remaining numbers. The recursive function will extract a number from the list and, using the operation passed in, combine it with the number passed in (which is your running total). Take the running total and call yourself again with the remaining items on the list (you'll have to iterate the list within the call but the sequence of calls is depth-first). Do this once for each of the four operators unless Success has been achieved by a previous leg of the search.
I updated this to use a list instead of a stack
When the result of the operation is your target number and your list is empty, then you have successfully found the set of operations (those that traced the path to the successful leaf) - set the Success flag and unwind. Note that the operators aren't on a list nor are they in the call: the function itself always iterates over all four. Your mechanism for "unwinding" the operator sequence from the successful leaf to get the sequence is to return the current operator and number prepended to the value returned by recursive call (only one of which will be successful since you stop at success - that, obviously, is the one to use). If none are successful, then what you return isn't important anyhow.
Update This is much harder when you have to consider expressions like the one that Daniel posted. You have combinatorics on the numbers and the groupings (numbers due to the fact that / and - are order sensitive even without grouping and grouping because it changes precedence). Then, of course, you also have the combinatorics of the operations. It is harder to manage the differences between (4 + 3) * 2 and 4 + (3 * 2) because grouping doesn't recurse like operators or numbers (which you can just iterate over in a breadth-first manner while making your (depth-first) recursive calls).
Here's some Python code to get you started: it just prints all the possible expressions, without worrying too much about redundancy. You'd need to modify it to evaluate expressions and compare to the target number, rather than simply printing them.
The basic idea is: given a set S of numbers, partition S into two subsets left and right in all possible ways (where we don't care about the order or the elements in left and right), such that left and right are both nonempty. Now for each of these partitions, find all ways of combining the elements in left (recursively!), and similarly for right, and combine the two resulting values with all possible operators. The recursion bottoms out when a set has just one element, in which case there's only one value possible.
Even if you don't know Python, the expressions function should be reasonably easy to follow; the splittings function contains some Python oddities, but all it does is to find all the partitions of the list l into left and right pieces.
def splittings(l):
n = len(l)
for i in xrange(2**n):
left = [e for b, e in enumerate(l) if i & 2**b]
right = [e for b, e in enumerate(l) if not i & 2**b]
yield left, right
def expressions(l):
if len(l) == 1:
yield l[0]
else:
for left, right in splittings(l):
if not left or not right:
continue
for el in expressions(left):
for er in expressions(right):
for operator in '+-*/':
yield '(' + el + operator + er + ')'
for x in expressions('1234'):
print x
pusedo code:
Works(list, target)
for n in list
tmp=list.remove(n)
return Works(tmp,target+n) or Works(tmp,target-n) or Works(tmp, n-target) or ...
then you just have to put the base case in. I think I gave away to much.

Resources