Hello everyone.
While working on some other things, like my MSc thesis, I saw a simple problem on a form to apply for a job, and I wanted to solve it. The problem is quite simple, but I enjoyed it and wanted to share my solution with the whole Internet; moreover the main reason I thought about modifying my ArgumentList class derives from this problem :)
The problem
Given a sequence of digits in some order, print all the expressions obtainable inserting a + (plus), – (minus), * (multiplication) or nothing, that evaluate to a given number. The solution should be written in C++ using the std library.
My solution
The solution is straightforward and is composed by two steps: generating all the possible expressions and then evaluate them.
To generate all the possible expressions what I did is the following. I used a pair to represent an expression: the pair is formed by an integer, representing the element after which the operators can be inserted, and a string, representing the expression to operate on. The first pair is just (0, sequence), where sequence is the one provided as input.
Now it is possible to use a queue to iteratively get a pair, evaluate the expression in it, and then generate the new expressions and put them into the queue to get successively evaluated.
The code is the following:
while ( !queue.empty() ) {
pair< unsigned int, string > *toEvaluate = queue.back();
if ( evaluate(target, toEvaluate->second) ) {
found.insert(toEvaluate->second);
}
if ( toEvaluate->first < (toEvaluate->second).length() - 1 ) {
queue.push_front(new pair< unsigned int, string >(toEvaluate->first + 1, toEvaluate->second));
for ( unsigned int i(0); i < NR_OPERATORS; i++ ) {
queue.push_front(new pair< unsigned int, string>(toEvaluate->first + 2, (toEvaluate->second).substr(0, toEvaluate->first + 1) + operators[i] + (toEvaluate->second).substr(toEvaluate->first + 1)));
}
}
queue.pop_back();
}
The evaluation is quite simple too. When an expression has to be evaluated is first parsed and divided into two components: the operands and the operators. After that each operator is applied to its operands (starting with the multiplication in our case) and a total is computed. If it matches with the goal number the boolean value true is returned.
The code is the following:
bool evaluate(int target, string &item) {
vector< int > operands;
vector< char > operators;
unsigned int i(0);
while ( i < item.length() ) {
unsigned int counter(i);
while ( counter < item.length() && isdigit(item.at(counter)) ) {
counter++;
}
operands.push_back(atoi((item.substr(i, counter - i)).c_str()));
if ( counter < item.length() ) {
operators.push_back(item.at(counter));
}
i = counter + 1;
}
// Performs the multiplies first
for ( unsigned int op(0); op < operators.size(); op++ ) {
if ( operators[op] == '*' ) {
operands[op] *= operands[op + 1];
operands[op + 1] = 1;
}
}
int total(operands[0]);
unsigned int opCounter(0);
for ( unsigned int i(1); i < operands.size(); i++ ) {
switch( operators[opCounter++] ) {
case '+':
total += operands[i];
break;
case '-':
total -= operands[i];
break;
case '*':
total *= operands[i];
break;
}
}
if ( total == target ) {
return true;
}
return false;
}
Notes
The original problem was less general and asked just to print all the expressions evaluating the number 3141 given the sequence 987654321, I generalized it for the sake of fun.
The complete code, with a Makefile, is available here. It needs to have my ArgumentList installed to work.
Post scriptum
The answer of the original question are the expressions “9*8*7*6+54+3*21” and “987-6+5*432*1” :)


