Skip to content

Instantly share code, notes, and snippets.

@izanbf1803
Last active November 12, 2017 20:26
Show Gist options
  • Save izanbf1803/05c3a45a0528dcefbd3ce2043e518324 to your computer and use it in GitHub Desktop.
Save izanbf1803/05c3a45a0528dcefbd3ce2043e518324 to your computer and use it in GitHub Desktop.
Postfix notation (Reverse Polish notation) evaluator
#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