Cod sursa(job #2925351)

Utilizator ILikeitN Stef ILikeit Data 14 octombrie 2022 21:56:57
Problema Evaluarea unei expresii Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.25 kb
#include <bits/stdc++.h>
using namespace std;

ifstream f("evaluare.in");
ofstream g("evaluare.out");
#define cin f
#define cout g

map<char, long long> priority = {
    { '*', 2 },
    { '/', 2 },
    { '+', 1 },
    { '-', 1 },
};

struct ParseResult {
    string result;
    long long index;
    friend ostream& operator<< (ostream& os, const ParseResult& p) { return os << p.result << ' ' << p.index; }
    ParseResult(string r = "", long long i = 0) :
        result(r), index(i) {};
};
ParseResult mainParser(string, long long);

long long evaluate(long long left, char op, long long right) {
    switch (op) {
    case '*': return left * right;
    case '/':
        if (right == 0) assert(("Are you fuckning idiot!?", 0));
        return left / right;
    case '+': return left + right;
    case '-': return left - right;
    default: assert(("You stink", 0));
    };
    return 0;
}

ParseResult numberParser(string s, long long i) {
    string result = "";
    while (s[i] && isdigit(s[i])) result += s[i++];
    return ParseResult(result, i);
}

ParseResult betweenParser(string s, const char delim[2], long long i) {
    auto updateState = [&](char c) {
        if (c == delim[0]) return 1;
        else if (c == delim[1]) return -1;
        else return 0;
    };
    long long state = 0;
    string result = "";
    do {
        state += updateState(s[i]);
        result += s[i++];
    } while (s[i] && state != 0);

    result.erase(result.begin());
    result.erase(result.end() - 1);

    return ParseResult(result, i);
}

ParseResult mainParser(string s, long long i) {
    stack<char> operators;
    stack<long long> operands;
    long long result = 0;

    while (s[i]) {
        if (isspace(s[i])) {
            i++;
            continue;
        }
        else if (isdigit(s[i])) {
            auto _ = numberParser(s, i);
            operands.push(stoll(_.result));
            i = _.index;
        }
        else if (s[i] == '(') {
            auto _ = betweenParser(s, "()", i);
            operands.push(stoll(mainParser(_.result, 0).result));
            i = _.index;
        }
        else /* is operator */ {
            char op = s[i];
            if (operators.empty() || priority[op] > priority[operators.top()])
                operators.push(op);
            else {
                while (!operators.empty() && priority[op] <= priority[operators.top()]) {
                    long long right = operands.top(); operands.pop();
                    long long left = operands.top(); operands.pop();
                    operands.push(evaluate(left, operators.top(), right));
                    operators.pop();
                }
                operators.push(op);
            }
            i++;
        }
    }

    while (!operators.empty()) {
        char op = operators.top(); operators.pop();
        long long right = operands.top(); operands.pop();
        long long left = operands.top(); operands.pop();
        operands.push(evaluate(left, op, right));
    }

    if (operands.empty()) throw runtime_error("You stink");
    return ParseResult(to_string(operands.top()), i);
}

int main()
{
    string s; getline(cin, s);
    cout << mainParser(s, 0).result;

    return 0;
}