📜 ⬆️ ⬇️

Parsing formulas in 40 lines

Sometimes it is interesting to take some small puzzle (the type of those that are given at the interviews) and find an unusual solution for it.
This time, this was the task of Yandex . In the post itself and in the comments several solutions were proposed, the topic of this topic will be the search for a short solution in a functional style.

First we select data structures - this will be the string in the reverse Polish entry . We will not generate the string itself, but we will calculate the result immediately as the source expression is processed. We will use two stacks - for values ​​and for operations. There will also be an associative array that contains the operation and the corresponding function.
Each operation has a priority. When opening the bracket, we will increase the priority of operations in the brackets, and when closing - decrease. The brackets themselves are not placed on the stack. Further, the standard algorithm for processing and calculating the expression in the reverse Polish record.

The resulting code is:
#include <iostream> #include <map> #include <stack> #include <functional> #include <utility> #include <stdlib.h> using namespace std; int main(int argc, char** argv) { stack<double> s; stack< pair<int, char> > ops; auto p = [&s, &ops] (function<double (double, double)>& f) {double r=s.top();s.pop();r=f(s.top(),r);s.pop();s.push(r);ops.pop();}; map< char, pair< int, function<double (double, double)> > > m = {{'+', {1, [](double a, double b){return a+b;}}},{'-', {1, [](double a, double b){return ab;}}}, {'*', {2, [](double a, double b){return a*b;}}},{'/', {2, [](double a, double b){return a/b;}}}}; const int order = 2; int level = 0; for (char* sp = argv[1];; ++sp) { while (*sp == '(') {level += order; ++sp;} s.push(strtod(sp, &sp)); while (*sp == ')') {level -= order; ++sp;} if (!*sp) {while(!ops.empty()) p(m[ops.top().second].second); break;} const int op = m[*sp].first + level; while (!ops.empty() && ops.top().first >= op) p(m[ops.top().second].second); ops.push(make_pair(op, *sp)); } cout << s.top() << endl; return 0; } 


Run:
 ./calc "15/(7-(1+1))*3-(2+(1+1))" 5 

')

Source: https://habr.com/ru/post/216449/


All Articles