40行の数式の解析

面接で与えられたような小さなタスクを取り、そのための珍しい解決策を見つけることが面白い場合があります。

今回は、Yandexからこのようなタスクになりました。 投稿およびコメントでは、いくつかのソリューションオプションが提案されました。このトピックのトピックは、機能的なスタイルでの短いソリューションの検索です。



まず、データ構造を選択します-これは逆ポーランドエントリの行になります。 文字列自体は生成しませんが、元の式を処理する過程で結果をすぐに計算します。 値用と操作用の2つのスタックを使用します。 操作と対応する関数を含む連想配列もあります。

各操作には優先順位があります。 角かっこを開くと、角かっこ内の操作の優先順位が高くなり、閉じると、低くなります。 ブラケット自体はスタックにプッシュされません。 さらに、標準の処理アルゴリズムと逆ポーランド記法での式の計算。



結果のコードは次のとおりです。

#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; }
      
      







打ち上げ:

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






All Articles