Cod sursa(job #2925354)

Utilizator ILikeitN Stef ILikeit Data 14 octombrie 2022 23:06:00
Problema Evaluarea unei expresii Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.61 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;
	
}