Last active
November 12, 2017 20:26
-
-
Save izanbf1803/05c3a45a0528dcefbd3ce2043e518324 to your computer and use it in GitHub Desktop.
Postfix notation (Reverse Polish notation) evaluator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <stack> | |
#include <vector> | |
#include <unordered_map> | |
#include <cassert> | |
#include <cmath> | |
using namespace std; | |
#define NUMBER 0 | |
#define ARITHMETIC_OP 1 | |
#define FUNCTION 2 | |
const string OPERATORS = "+-*/^"; | |
const unordered_map<string, int> FUNCTIONS = { // data = {name, arg_n}; | |
{"sin", 1}, | |
{"cos", 1}, | |
}; | |
typedef struct { | |
string val; | |
int type; | |
} Token; | |
int tokenType(const string& token) | |
{ | |
if (token.size() == 1 and OPERATORS.find(token[0]) != string::npos) | |
return ARITHMETIC_OP; | |
if ((token[0] >= '0' and token[0] <= '9')) | |
return NUMBER; | |
if (FUNCTIONS.find(token) != FUNCTIONS.end()) | |
return FUNCTION; | |
return -1; // Error | |
} | |
vector<Token> parseInput(const string& input) | |
{ | |
vector<Token> v; | |
Token token; | |
for (int i = 0; i < input.size(); i++) { | |
if (input[i] == ' ' and token.val.size() > 0) { | |
token.type = tokenType(token.val); | |
v.push_back(token); | |
token = {"", -1}; // Reset values for next token | |
} | |
else { | |
token.val += input[i]; | |
} | |
} | |
if (token.val.size() > 0) { | |
token.type = tokenType(token.val); | |
v.push_back(token); | |
} | |
return v; | |
} | |
double arithmeticOp(const string& sb, const string& sa, char op) | |
{ | |
double a = stod(sa); | |
double b = stod(sb); | |
switch (op) { | |
case '+': | |
return a + b; | |
case '-': | |
return a - b; | |
case '*': | |
return a * b; | |
case '/': | |
return a / b; | |
case '^': | |
return pow(a, b); | |
} | |
} | |
dobule function(const vector<string>& sargs, string func) | |
{ | |
assert(FUNCTION[func] == sargs.size()); // Check number of args is correct | |
vector<double> args(sargs.size(), 0); | |
for (int i = 0; i < sargs.size(); i++) { | |
args[i] = stod(sargs[i]); | |
} | |
if (func == "sin") | |
return sin(args[0]); | |
else if (func == "cos") | |
return sin(args[0]); | |
assert(false); // Unknown function | |
} | |
int main() | |
{ | |
string input; | |
getline(cin, input); | |
vector<Token> v = parseInput(input); | |
stack<Token> s; | |
for (int i = 0; i < v.size(); i++) { | |
Token t = v[i]; | |
assert(t.type != -1); // If type == -1, Syntax error | |
switch (t.type) { | |
case NUMBER: | |
s.push(t); | |
break; | |
case ARITHMETIC_OP: | |
assert(s.size() >= 2); // If args.size < 2, syntax error | |
Token arg1 = s.top(); s.pop(); | |
Token arg2 = s.top(); s.pop(); | |
double result = arithmeticOp(arg1.val, arg2.val, t.val[0]); | |
s.push({to_string(result), NUMBER}); // Push result to stack | |
break; | |
} | |
} | |
cout << "Result: " << stod(s.top().val) << endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment