It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I've just taken a test for a graduate C++ developer with the question below. It didn't go too well as I couldn't decide on a clear way of completing the task. Time limit didn't help either. I'm interested in how experienced developers would have tackled the follow problem - in pseudo or sample code:
Evaluate
Write a function in C or C++ that evaluates the result of a simple expression.
The function should ignore whitespace, but stop at the first non valid character.
Valid tokens are listed in the table below:
0-9 - Only integers are allowed in expressions
() - Nested expressions should be evaluated first.
+, -, *, / - Basic operators are addition, subtraction, multiplication and division.
The expression should be parsed from left to right. It is not necessary to consider operator precedence in your solution (e.g. 1 + 3 * 4 = 16). If there is an error in the expression, the function should return false.
Suggested prototype for function:
Example:
bool evaluate(const char *expression, int &result)
{
...
}
**Input**
1+3
(1 + (12 * 2)
**Result**
4
N/A
**Return code**
true
false (missing bracket)
In addition, this is the 2nd C++ that I've failed to complete successfully. Have had 1 year intership experiece and 1 year academic experiece using C++, but I'm not prepared for some of these tests. Are there any recommended resources where I can attept to solve problems such as this one in order to gain more 'testing' experience?
The problem here is mostly parsing, which would be covered in a compiler course probably in second or third year. Once you can parse expressions to build up a recursive data structure representing the input (called a syntax tree) it's pretty trivial to evaluate such expressions. A recursive decent parser can also evaluate the expression as it goes without actually building a syntax tree.
For a full treatment you'd want a book on compilers, such as the dragon book. Also IIRC the book Programming: Principals and Practice using C++ covers an example like this.
You could also wait for chapter ten of The Art of Computer Programming to be published, which will cover parsing. It's scheduled to be out around 2020.
Here is my shortest attempt. It took about 40 minutes to type up, you can play with it on ideone (link).
The code is very straightforward, assuming that you have at least a cursory familiarity with the basic recursive descent parsing technique.
#include <iostream>
#include <cctype>
using namespace std;
bool eval_expr(const char **pe, int &lhs, bool inside = false);
// gets the next char after skipping optional whitespace
char skip_ws(const char **pe) {
while (**pe == ' ') ++(*pe);
return **pe;
}
// evaluates a parenthesized expression or a number
bool eval_prim(const char **pe, int &res) {
char c = skip_ws(pe);
if (c == '(') {
++(*pe);
if (!eval_expr(pe, res, true)) return false;
++(*pe);
return true;
}
if (isdigit(c)) {
res = 0;
while (isdigit(c)) {
res = 10*res + c - '0';
c = *(++(*pe));
}
return true;
}
return false;
}
// evaluates a chain of + - * / operations
bool eval_expr(const char **pe, int &lhs, bool inside) {
if (!eval_prim(pe, lhs)) return false;
char op;
while ((op = skip_ws(pe)) && (op == '+' || op == '-' || op == '*' || op == '/')) {
++(*pe);
int rhs;
if (!eval_prim(pe, rhs)) return false;
switch (op) {
case '+': lhs += rhs; break;
case '-': lhs -= rhs; break;
case '*': lhs *= rhs; break;
case '/': lhs /= rhs; break;
}
}
return inside ? op == ')' : !op;
}
// wrapper API to hide an extra level of indirection
bool evaluate(const char *e, int &result) {
return eval_expr(&e, result);
}
Begin with a simple grammar:
expr: n-expr {o-expr} | p-expr {o-expr}
n-expr: [0-9]n-expr
p-expr: ( expr )
o-expr: op expr
op: + | - | * | /
This is probably the largest hurdle for the question. You want to be able to write a simple top down recursive descent parser, so your grammar needs to be written in a way to allow that to happen.
Then, the implementation from there is fairly straightforward:
bool expr (const char *&s, int &result, int eos = 0) {
while (isspace(*s)) ++s;
if (*s == eos) return false;
if (isdigit(*s)) {
if (!n_expr(s, result)) return false;
} else if (*s == '(') {
if (!p_expr(s, result)) return false;
} else return false;
while (isspace(*s)) ++s;
if (*s == eos) return true;
return o_expr(s, result, eos);
}
bool n_expr (const char *&s, int &result) {
int n = 0;
while (isdigit(*s)) n = 10 * n + (*s++ - '0');
result = n;
return true;
}
bool p_expr (const char *&s, int &result) {
if (expr(++s, result, ')')) {
++s;
return true;
}
return false;
}
bool o_expr (const char *&s, int &result, int eos) {
int oresult = 0;
const char *op = strchr("+-*/", *s);
if (op == 0) return false;
if (!expr(++s, oresult, eos)) return false;
switch (*op) {
case '+': result += oresult; break;
case '-': result -= oresult; break;
case '*': result *= oresult; break;
case '/': result /= oresult; break;
default: return false;
}
return true;
}
This is a simple scan push apply (the twist is the braces).
Look for a number:
If you see a number push onto stack
if you see a '(' push it onto stack and goto 1
Otherwise an error.
Look for an op:
If you see an op push it onto stack
Otherwise an error
Look for a number:
If you see a number push onto stack
If you see a '(' push onto stack and goto 1
Otherwise an error
pop last three items from the stack (should be number op number)
do the operation and push the result onto the stack.
Now the complex bit:
Peek to see if the next character is a ')' if it is goto "PopCode" below.
If no more input goto 7.
Otherewise goto 2
If only one item on the stack you have your result.
Otherwise an error.
PopCode
Pop last two values from the stack. Should be '( Number'
If it is not then an error
Throw away the '('
If the top of the stack is an op push value goto 4 (above)
Otherwise push the value onto the stack goto 5 (above)
When finished there should be one number on the stack.
Example:
1+3
Rule 1: push 1 stack = '1'
Rule 2: push + stack = '1 +'
Rule 3: push 3 stack = '1 + 3'
Rule 4: pop and do: stack = '4'
Rule 5: Nothing stack = '4'
Rule 6: goto 7 stack = '4'
Rule 7: stack = '4'
(1 + (12 * 2)
Rule 1: push ( goto 1 stack = '('
Rule 1: push 1 stack = '( 1'
Rule 2: push + stack = '( 1 +'
Rule 3: push ( goto 1 stack = '( 1 + ('
Rule 1: push 12 stack = '( 1 + ( 12'
Rule 2: push * stack = '( 1 + ( 12 *'
Rule 3: push 2 stack = '( 1 + ( 12 * 2'
Rule 4: Pop and do: stack = '( 1 + ( 24'
Rule 5: Do 'PopCode' stack = '( 1 + ( 24'
Pop 1: Pop 2 stack = '( 1 +'
Pop 2: Holding 24 stack = '( 1 +'
Pop 3: push 24 goto 4 stack = '( 1 + 24'
Rule 4: Pop and do stack = '( 25'
Rule 5: Nothing stack = '( 25'
Rule 6: goto 7 stacj = '( 25'
Rule 7: More than 1 item error
Re-Doing with correct formula
(1 + (12 * 2))
Rule 1: push ( goto 1 stack = '('
Rule 1: push 1 stack = '( 1'
Rule 2: push + stack = '( 1 +'
Rule 3: push ( goto 1 stack = '( 1 + ('
Rule 1: push 12 stack = '( 1 + ( 12'
Rule 2: push * stack = '( 1 + ( 12 *'
Rule 3: push 2 stack = '( 1 + ( 12 * 2'
Rule 4: Pop and do: stack = '( 1 + ( 24'
Rule 5: Do 'PopCode' stack = '( 1 + ( 24'
Pop 1: Pop 2 stack = '( 1 +'
Pop 2: Holding 24 stack = '( 1 +'
Pop 3: push 24 goto 4 stack = '( 1 + 24'
Rule 4: Pop and do stack = '( 25'
Rule 5: Do 'PopCode' stack = '( 25'
Pop 1: Pop 2 stack = ''
Pop 2: holding 25 stack = ''
Pop 3: Nothing. stack = ''
Pop 4: push 25 goto 5 stack = '25'
Rule 5: Nothing stack = '25'
Rule 6: goto 7 stack = '25'
Rule 7: Result = 25
The easiest way to solve a (not necessarily) simple mathematical expression is to use the Shunting Yard algorithm to convert it to Reverse Polish Notation, which is almost trivial to parse using a stack. Of course it might not be feasible to do so for an assignment or an interview (perhaps unless a SY algorithm reference is available).
Related
I am spending my evening doing some programming problems from Kattis. There is one part of the problem 4 thought that I am stuck on.
Given a number, the program is supposed to return the operations (+, -, * or /) required between 4 fours to achieve that number.
For example, the input
9
would result in the output
4 + 4 + 4 / 4 = 9
My solution (not efficient, but simple) is to evaluate all possible ways to combine the operators above and see if any of the combinations achieve the wanted result.
To do this I have written the function seen below. It takes in an array of chars which are the operators to be evaluated (uo[3], could look like {+, /, *}), and the wanted result as an integer (expRes).
bool check(char uo[3], int expRes) {
int res = 4;
for(int oPos = 2; oPos >= 0; oPos--) {
switch (uo[oPos]) {
case '+' : res += 4; break;
case '-' : res -= 4; break;
case '*' : res *= 4; break;
case '/' : res /= 4; break;
}
}
return res == expRes;
}
I realized that this "sequential" approach comes with a problem: it doesn't follow the order of operations. If I was to call the function with
uo = {+, -, /}
and
expRes = 7 it would return false since 4 + 4 = 8, 8 - 4 = 4, 4 / 4 = 1.
The real answer is obviously true, since 4 + 4 - 4 / 4 = 7.
Can any of you think of a way to rewrite the function so that the evaluation follows the order of operations?
Thanks in advance!
Its an easy problem if you look at it.
You are restricted with four 4's and three operators in between, that is you already know your search space. So one solution is to generate the complete search space which is O(n^3) = 4^3 = 64 total equations, where n is the number of operators. Keep the answer to these solutions as a <key, value> pair so that look up to the input of test case is O(1).
Step wise you'd do.
Generate Complete Sequence and store them as key, value pairs
Take Input from test cases
Check if key exists, if yes print the sequence, else print that the sequence doesn't exist
Solution would take 64*1000 operations, which can easily be computed with in a second and would avoid Time Limit Exceeded Error that usually these competitions have
in Code form (most of it is incomplete):
// C++ Syntax
map<int, string> mp;
void generateAll() {
// generate all equations
}
void main () {
generateAll();
int n, t; scanf("%d", &t);
while (t--) {
scanf("%d", &n);
if ( mp.find(n) != mp.end() )
// equation exists to the input
else
// equation doesn't exist for the input
}
}
I've got a problem with converting types in C++. I've got an expression: string wholeExpression = "44*2"; and I want to separate numbers from operators.
If it is a operator, I use this part of code:
string subExpression;
char skladnik;
subExpression = wholeExpression.substr(poczatek, lenght);
skladnik = subExpression[0];
if it is a number:
subExpression = wholeExpression.substr(poczatek, lenght);
skladnik = atoi(subExpression.c_str());
#EDIT
switch (skladnik)
{
case '+':
case '-':
{
while (topOfStack > 0 && stack[topOfStack - 1] != '(')
{
outPut += stack[topOfStack - 1] + przecinek;
stack.resize(topOfStack - 1);
topOfStack--;
}
stack += skladnik;
topOfStack++;
break;
}
case '/':
case '*':
{
while (topOfStack > 0 && (stack[topOfStack - 1] == '*' || stack[topOfStack - 1] == '/'))
{
outPut += stack[topOfStack - 1] + przecinek;
stack.resize(topOfStack - 1);
topOfStack--;
}
stack += skladnik;
topOfStack++;
break;
}
case '(':
{
stack += skladnik;
topOfStack++;
break;
}
case ')':
{
while (stack[topOfStack - 1] != '(')
{
outPut += stack[topOfStack - 1] + przecinek;
stack.resize(topOfStack - 1);
topOfStack--;
}
if (stack[topOfStack - 1] == '(')
{
stack.resize(topOfStack - 1);
topOfStack--;
}
break;
}
default:
{
outPut += to_string(skladnik) + przecinek;
break;
}
}
}
But suddenly I've got problem with a numbers from 40 to 43 and 45 and 47 -> which are operators (in ASCII code). They are probably interpret by the switch not as numbers but as oparators. Another numbers work perfectly. How can i solve this problem?
You've answered your own question. The char for the number 40 doesn't exist. It's two char variables: 4 and 0. Because you are putting an int into a char with atoi, it is going to use the ASCII code. Without knowing the value of lenght, it's hard to say that this is indeed your problem, but here are two possible solutions:
Don't use atoi upfront. Instead interpret each number char into an actual integer after your switch statement (4 and 0 would be
atoi('4') * 10 + atoi('0'))
use an int orlong or double variable to hold your numbers.
You are using your variable skladnik in two different ways. In one code path it refers to a decoded integer, in the second code path it refers to a character. Once you've conflated the meaning like this, there's no way to tell once you're at the switch which meaning it has.
You should use two different variables, one for decoded numbers and one for operator characters. Then there will be no confusion.
I am asking the user to input an expression which will be evaluated in postfix notation. The beginning of the expression is the variable name where the answer of the evaluated expression will be stored. Ex: A 4 5 * 6 + 2 * 1 – 6 / 4 2 + 3 * * = where A is the variable name and the equal sign means the answer to the expression will be stored in the variable A. The OUT A statement means that the number stored in the variable A will be printed out.
What I need help with is that when I input the second expression, I do not get the right answer. For example, my first expression A 4 5 * 6 + 2 * 1 – 6 / 4 2 + 3 * * = will evaluate to 153 and then when I input my second expression B A 10 * 35.50 + =, it has to evaluate to 1565.5, but it doesn't. It evaluates to 35.5. I cannot figure out why I am getting the wrong answer. Also, I need help with the OUT statement.
else if (isalpha(expr1[i]))
{
stackIt.push(mapVars1[expr1[i]]);
}
Will place the variable, or zero if the variable has not been set, onto the stack.
else if (isalpha(expr1[i]))
{
map<char, double>::iterator found = mapVars1.find(expr1[i]);
if (found != mapVars1.end())
{
stackIt.push(found->second);
}
else
{
// error message and exit loop
}
}
Is probably better.
Other suggestions:
Compilers are pretty sharp these days, but you may get a bit out of char cur = expr1[i]; and then using cur (or suitably descriptive variable name) in place of the remaining expr1[i]s in the loop.
Consider using isdigit instead of expr1[i] >= '0' && expr1[i] <= '9'
Test your code for expressions with multiple spaces in a row or a space after an operator. It looks like you will re-add the last number you parsed.
Test for input like 123a456. You might not like the result.
If spaces after each token in the expression are specified in the expression protocol, placing your input string into a stringstream will allow you to remove a great deal of your parsing code.
stringstream in(expr1);
string token;
while (in >> token)
{
if (token == "+" || token == "-'" || ...)
{
// operator code
}
else if (token == "=")
{
// equals code
}
else if (mapVars1.find(token) != mapVars1.end())
{
// push variable
}
else if (token.length() > 0)
{
char * endp;
double val = strtod(token.c_str(), &endp);
if (*endp == '\0')
{
// push val
}
}
}
To use previous symbol names in subsequent expressions add this to the if statements in your parsing loop:
else if (expr1[i] >= 'A' && expr1[i] <= 'Z')
{
stackIt.push(mapVars1[expr[i]]);
}
Also you need to pass mapVars by reference to accumulate its contents across Eval calls:
void Eval(string expr1, map<char, double> & mapVars1)
For the output (or any) other command I would recommend parsing the command token that's at the front of the string first. Then call different evaluators based on the command string. You are trying to check for OUT right now after you have already tried to evaluate the string as an arithmetic assignment command. You need to make that choice first.
I have this Code in which I am using character array to store each expression but it doesnt work with numbers >9 my current code is:
int main(){
int i,n,c,k,l;
char buf[200];
cin>>n;
IntStack s(n);
i=0;
while(i<n)
{
cin>>buf[i];
if(buf[i]=='*')
{
k=s.pop();
l=s.pop();
k=k*l;
s.push(k);
}
else if(buf[i]=='+')
{
k=s.pop();
l=s.pop();
k=k+l;
s.push(k);
}
else if(buf[i]=='-')
{
k=s.pop();
l=s.pop();
k=l-k;
s.push(k);
}
else if(buf[i]=='/')
{
k=s.pop();
l=s.pop();
k=l/k;
s.push(k);
}
else
{
c=(buf[i]-48);
s.push(c);
}
i++;
}
k=s.pop();
if(s.isempty())
{
cout<<k;
}
else
{
cout<<"INVALID";
}
return 0;
}
Input:
11
1 2 + 3 * 6 + 2 3 + / <-Working
11
3 5 * 2 / 11 3 / 7 * + <-not Working because of 11 in input
Kindley help solving this problem or give an better logic to differentiate between numbers and operators.
Complete Code can be viewed here.
To read the input, and split it into what compiler theory calls "tokens", you need a simple lexical analyzer, or scanner, but slightly more advanced than the just-read-a-character version you have.
A technique used in the simple scanner given in (the previous edition of) the "dragon book" (Aho, Sethi, Ullman: Compilers - Principles, Techniques, and Tools, 1986) is to read a character, and if it is a digit put it back in the input (with ungetc in C), and then read an integer normally. If it is not a digit, handle it as an operator.
Before applying any operand, you are just popping one digit. There should be a loop to pop all digits until another operator is found, and concatenate the digits to make a number. For example:
1+23+3
After first '+' operator, there should be a loop to pop both 2 and 3 ( generally until next operator is found). Then convert it to number 23 and apply the operator to 1 and 23.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I would like to evaluate(not convert) infix expression in C++. If you posses algorithm or even implementation of such algorithm(may be not C++, any language... I will try to rewrite it to C++) share please.
Evaluation means give the value of expression. (2+2)*3 is 12
I am sorry, I forgot that I am talking about stack solution, cause I know the tree solution and It is not suitable this time : (.
How do you got the expression? If you got it like (3 + 4) - (1 * 2) + 1 =
+
/ \
- 1
/ \
+ *
/ \ / \
3 4 1 2
http://cboard.cprogramming.com/cplusplus-programming/32682-inserting-infix-into-binary-tree.html
do a tree transversal of the tree like Left Root Right so it will be sth like this: 3 + 4 the result - the result of 1 * 2 the result + 1.
If you got the expression like 34+12*-1+ you can simulate assembly like do a stack and if you get to an operator pop the last 2 elements in the stack and apply the operator: put 3 in stack, put 4 in stack, get op. + so pop the last 2 elements and use the operator. Now you got only 7 in stack. Now read until get an operator so in the stack you will have 7 1 2 after op. * in stack you got 7 2 after op. - you get only 5 in stack add 1 in stack: Stack 5 1, use the last operator + and get the final result 6.
Ok, here is the code:
#include <STACK>
int GetResult( char * rpn )
{
std::stack<int> myStack;
int nr1, nr2; int length = strlen(rpn);
for (int i = 0; i < length; i++)
{
if (isdigit(rpn[i]))
{
myStack.push(rpn[i] - '0');
}
else
{
switch(rpn[i])
{
case '+':
nr1 = myStack.top();
myStack.pop();
nr2 = myStack.top();
myStack.pop();
myStack.push(nr2 + nr1);
break;
case '-':
nr1 = myStack.top();
myStack.pop();
nr2 = myStack.top();
myStack.pop();
myStack.push(nr2 - nr1);
break;
case '*':
nr1 = myStack.top();
myStack.pop();
nr2 = myStack.top();
myStack.pop();
myStack.push(nr2 * nr1);
break;
case '/':
nr1 = myStack.top();
myStack.pop();
nr2 = myStack.top();
myStack.pop();
myStack.push(nr2 / nr1);
break;
default:
break;
}
}
}
return myStack.top();
}
int main(int argc, char* argv[])
{
char *rpn = "34+12*-1+";
int rez = GetResult(rpn);
printf("%i", rez);
return 0;
}
By far the easiest way is to convert the infix expression to postfix notation using Dijkstra's Shunting-yard algorithm, and evaulate the result, which is, like, trivial. There are code samples of this all over the internet (take a look at Rosetta code or LiteratePrograms).
Alternatively, if you'd like to learn, and you'd like to enter the magical world of parsing and a bit of compiler theory, write a recursive descent parser. It's great fun.
Oh and, if you'd like something more robust, you could take a look at Pratt parsing, which is awesome. Here's a great article about it.