#include #include #include #include #include #include #include class Action { public: virtual ~Action() = default; virtual void evaluate(std::stack& stack) const = 0; virtual Action* clone() const = 0; }; class Literal : public Action { public: Literal(int value) : value { value } { } void evaluate(std::stack& stack) const override { stack.push(value); } Action* clone() const override { return new Literal { value }; } private: int value; }; class Print : public Action { public: Print(std::ostream& os) : os { os } { } void evaluate(std::stack& stack) const override { os << stack.top() << std::endl; stack.pop(); } Action* clone() const override { return new Print { os }; } private: std::ostream& os; }; template class Operator : public Action { public: Operator(Callable const& function) : function { function } { } void evaluate(std::stack& stack) const override { int lhs { stack.top() }; stack.pop(); int rhs { stack.top() }; stack.pop(); stack.push(function(lhs, rhs)); } Action* clone() const override { return new Operator { function }; } private: Callable function; }; Action* make_literal(int value) { return new Literal { value }; } Action* make_print(std::ostream& os) { return new Print { os }; } template Action* make_operator(Callable const& function) { return new Operator { function }; } void evaluate_expression(std::vector const& expression) { std::stack stack { }; for (Action* action : expression) { action->evaluate(stack); } } std::map const parse_table { { "." , make_print(std::cout) }, { "+" , make_operator([](int x, int y) { return x + y; }) }, { "-" , make_operator([](int x, int y) { return x - y; }) }, { "*" , make_operator([](int x, int y) { return x * y; }) }, { "/" , make_operator([](int x, int y) { return x / y; }) }, { "min", make_operator([](int x, int y) { return std::min(x, y); }) }, { "max", make_operator([](int x, int y) { return std::max(x, y); }) } }; Action* parse_token(std::string const& token) { auto it = parse_table.find(token); if (token == std::end(parse_table)) { int value { std::stoi(token) }; return make_literal(value); } return it->second->clone(); } std::vector parse_expression(std::istream& is) { std::vector expression { }; std::string token; while (is >> token) { expression.push_back(parse_token(token)); } return expression; } int main() { std::string line; std::getline(std::cin, line); std::istringstream iss { line }; auto expression = parse_expression(iss); evaluate_expression(expression); for (Action* action : expression) { delete action; } for (auto [key, action] : parse_table) { delete action; } }