Cod sursa(job #2247101)

Utilizator preda.andreiPreda Andrei preda.andrei Data 27 septembrie 2018 21:36:18
Problema Evaluarea unei expresii Scor 80
Compilator cpp Status done
Runda Arhiva educationala Marime 2.27 kb
#include <cctype>
#include <fstream>
#include <string>
#include <vector>

using namespace std;

const vector<string> kSigns = {"+-", "*/"};

class Node
{
public:
    Node(int value, char sign) : value_(value), sign_(sign) {}
    Node(int value) : Node(value, '\0') {}
    Node(char sign) : Node(0, sign) {}

    void SetLeft(Node *left) { left_ = left; }
    void SetRight(Node *right) { right_ = right; }

    int Eval() const;

    void Free();

private:
    int value_;
    char sign_;

    Node *left_;
    Node *right_;

    bool has_number() const { return sign_ == '\0'; }
};

int Node::Eval() const
{
    if (has_number()) {
        return value_;
    }

    auto left = left_->Eval();
    auto right = right_->Eval();

    if (sign_ == '+') {
        return left + right;
    } else if (sign_ == '-') {
        return left - right;
    } else if (sign_ == '*') {
        return left * right;
    } else if (sign_ == '/') {
        return left / right;
    }
    return 0;
}

void Node::Free()
{
    if (left_) {
        left_->Free();
    }
    if (right_) {
        right_->Free();
    }
    delete this;
}

int NextNumber(const string &str, size_t &pos)
{
    auto num = 0;
    while (pos < str.size() && isdigit(str[pos])) {
        num = num * 10 + str[pos] - '0';
        pos += 1;
    }
    return num;
}

Node* Parse(const string &str, size_t lev, size_t &pos)
{
    if (lev >= kSigns.size()) {
        if (str[pos] == '(') {
            pos += 1;
            auto root = Parse(str, 0, pos);
            pos += 1;
            return root;
        }
        return new Node(NextNumber(str, pos));
    }

    auto root = Parse(str, lev + 1, pos);
    while (kSigns[lev].find(str[pos]) != string::npos) {
        auto new_node = new Node(str[pos]);
        pos += 1;

        new_node->SetLeft(root);
        new_node->SetRight(Parse(str, lev + 1, pos));
        root = new_node;
    }
    return root;
}

Node* MakeTree(const string &str)
{
    size_t pos = 0;
    return Parse(str, 0, pos);
}

int Calc(const string &str)
{
    auto root = MakeTree(str);
    auto res = root->Eval();
    root->Free();
    return res;
}

int main()
{
    ifstream fin("evaluare.in");
    ofstream fout("evaluare.out");

    string str;
    getline(fin, str);

    auto res = Calc(str);
    fout << res << "\n";

    return 0;
}