Skip to Content

Eval

template<class T> struct _eval { string ops = "+-*/%()"; bool is_op(char c) { return ops.find(c) != string::npos; } bool is_op(string c) { return sz(c) == 1 && is_op(c[0]); } T run_op(T a, T b, char op) { if (op == '+') return a + b; else if (op == '-') return a - b; else if (op == '*') return a * b; else if (op == '/') return a / b; else return a % b; } T run_op(T a, T b, string op) { return run_op(a, b, op[0]); } int op_priority(string op) { if (op == "*" || op == "/" || op == "%") return 3; else if (op == "+" || op == "-") return 2; else return 1; } T calc_infix(const string &s) { return calc_postfix(to_postfix(s)); } T calc_postfix(const vector<string> &s) { vector<T> t; for (auto &c: s) { if (is_op(c)) { T val = run_op(t[sz(t) - 2], t[sz(t) - 1], c[0]); t.pop_back(), t.pop_back(), t.push_back(val); } else { // Warning: long long conversion will cause crash on bigint usage t.push_back(stoll(c)); } } return t[0]; } vector<string> to_postfix(const vector<string> &s) { vector<string> ret, op; for (auto &c: s) { if (is_op(c)) { if (c == "(") op.push_back("("); else if (c == ")") { while (sz(op) && op.back() != "(") ret.pb(op.back()), op.pop_back(); op.pop_back(); } else { while (sz(op) && op_priority(op.back()) >= op_priority(c)) ret.pb(op.back()), op.pop_back(); op.push_back(c); } } else { ret.pb(c); } } while (sz(op)) ret.pb(op.back()), op.pop_back(); return ret; } vector<string> to_postfix(const string &s) { return to_postfix(parse(s)); } vector<string> parse(const string &s) { vector<string> ret; string tmp; for (int i = 0; i < sz(s); i++) { if (is_op(s[i])) ret.pb(string(1, s[i])); else if (i == sz(s) - 1 || is_op(s[i + 1])) ret.pb(tmp + s[i]), tmp = ""; else tmp += s[i]; } if (sz(ret) && ret[0] == "-") { // leading negative operator ret[1] = "-" + ret[1]; ret.erase(ret.begin()); } return ret; } string to_raw(const vector<string> &s) { string ret; for (auto &c: s) ret += c; return ret; } }; _eval<ll> eval;
Last updated on