// Author: lukyj #include #include #include #include #include class TreeNode; class TreeNodeConstant; class TreeNodeVar; class TreeNodePlus; class TreeNodeMinus; class TreeNodeTimes; using TreeNodePtr = std::unique_ptr; class TreeNode { public: TreeNode(TreeNodePtr left, TreeNodePtr right) : left_(std::move(left)), right_(std::move(right)) {} virtual TreeNodePtr derivate() const = 0; virtual TreeNodePtr evaluate() const = 0; virtual ~TreeNode() {} virtual void PrintInPostFix(std::ostream&) const = 0; protected: TreeNodePtr left_; TreeNodePtr right_; }; class TreeNodeConstant : public TreeNode { public: TreeNodeConstant(int value) : TreeNode(nullptr, nullptr), value_(value) {} virtual TreeNodePtr derivate() const override { return TreeNodePtr(new TreeNodeConstant(0)); } int value() { return value_; } virtual TreeNodePtr evaluate() const override { return TreeNodePtr(new TreeNodeConstant(value_)); } virtual void PrintInPostFix(std::ostream& output) const override { output << value_ << " "; } private: int value_; }; class TreeNodeVar : public TreeNode { public: TreeNodeVar() : TreeNode(nullptr, nullptr) {} virtual TreeNodePtr derivate() const override { TreeNodePtr result = TreeNodePtr(new TreeNodeConstant(1)); return result; } virtual TreeNodePtr evaluate() const override { return TreeNodePtr(new TreeNodeVar()); } virtual void PrintInPostFix(std::ostream& stream) const override { stream << "x "; } }; class TreeNodePlus : public TreeNode { public: TreeNodePlus(TreeNodePtr left, TreeNodePtr right) : TreeNode(std::move(left), std::move(right)) {} virtual TreeNodePtr derivate() const override { TreeNodePtr left = left_->derivate(); TreeNodePtr right = right_->derivate(); return TreeNodePtr(new TreeNodePlus(std::move(left), std::move(right))); } virtual TreeNodePtr evaluate() const override { TreeNodePtr left = left_->evaluate(); TreeNodePtr right = right_->evaluate(); TreeNodeConstant* leftConstant = dynamic_cast(&*left); TreeNodeConstant* rightConstant = dynamic_cast(&*right); if (leftConstant != nullptr && rightConstant != nullptr) { return TreeNodePtr(new TreeNodeConstant(leftConstant->value() + rightConstant->value())); } else { return TreeNodePtr(new TreeNodePlus(std::move(left), std::move(right))); } } virtual void PrintInPostFix(std::ostream& stream) const override { left_->PrintInPostFix(stream); right_->PrintInPostFix(stream); stream << "+ "; } }; class TreeNodeMinus : public TreeNode { public: TreeNodeMinus(TreeNodePtr child) : TreeNode(std::move(child), nullptr) {} virtual TreeNodePtr derivate() const override { TreeNodePtr child = left_->derivate(); return TreeNodePtr(new TreeNodeMinus(std::move(child))); } virtual TreeNodePtr evaluate() const override { TreeNodePtr child = left_->evaluate(); TreeNodeConstant* childConstant = dynamic_cast(&*child); if (childConstant != nullptr ) { return TreeNodePtr(new TreeNodeConstant(childConstant->value() * - 1)); } else { return TreeNodePtr(new TreeNodeMinus(std::move(child))); } } virtual void PrintInPostFix(std::ostream& stream) const override { left_->PrintInPostFix(stream); stream << "- "; } }; class TreeNodeTimes : public TreeNode { public: TreeNodeTimes(TreeNodePtr left, TreeNodePtr right) : TreeNode(std::move(left), std::move(right)) {} virtual TreeNodePtr derivate() const override { TreeNodePtr leftDerivative = left_->derivate(); TreeNodePtr rightDerivative = right_->derivate(); TreeNodePtr left = TreeNodePtr(new TreeNodeTimes(std::move(leftDerivative), std::move(right_->evaluate()))); TreeNodePtr right = TreeNodePtr(new TreeNodeTimes(std::move(rightDerivative), std::move(left_->evaluate()))); return TreeNodePtr(new TreeNodePlus(std::move(left), std::move(right))); } virtual TreeNodePtr evaluate() const override { TreeNodePtr left = left_->evaluate(); TreeNodePtr right = right_->evaluate(); TreeNodeConstant* leftConstant = dynamic_cast(&*left); TreeNodeConstant* rightConstant = dynamic_cast(&*right); if (leftConstant != nullptr && rightConstant != nullptr) { return TreeNodePtr(new TreeNodeConstant(leftConstant->value() * rightConstant->value())); } else { return TreeNodePtr(new TreeNodeTimes(std::move(left), std::move(right))); } } virtual void PrintInPostFix(std::ostream& stream) const override { left_->PrintInPostFix(stream); right_->PrintInPostFix(stream); stream << "* "; } }; inline void PrintInputError() { std::cout << "Error input line!" << std::endl; } int main() { std::string token; std::stack stack; while (std::getline(std::cin, token, ' ')) { int size = token.size(); if (size > 0 && token[0] == '\n') { token = token.substr(1); } if (token == "+") { if (stack.size() < 2) { PrintInputError(); break; } TreeNodePtr right = std::move(stack.top()); stack.pop(); TreeNodePtr left = std::move(stack.top()); stack.pop(); stack.emplace(new TreeNodePlus(std::move(left), std::move(right))); } else if (token == "*") { if (stack.size() < 2) { PrintInputError(); break; } TreeNodePtr right = std::move(stack.top()); stack.pop(); TreeNodePtr left = std::move(stack.top()); stack.pop(); stack.emplace(new TreeNodeTimes(std::move(left), std::move(right))); } else if (token == "-") { if (stack.size() < 1) { PrintInputError(); break; } TreeNodePtr child = std::move(stack.top()); stack.pop(); stack.emplace(new TreeNodeMinus(std::move(child))); } else if (token == "x") { stack.emplace(new TreeNodeVar()); } else if (token == "d") { if (stack.size() < 1) { PrintInputError(); break; } TreeNodePtr top = std::move(stack.top()); stack.pop(); TreeNodePtr result = top->derivate(); stack.push(std::move(result)); } else if (token == "end") { break; } else if (token == ".") { if (stack.size() != 1) { PrintInputError(); break; } else { stack.top()->evaluate()->PrintInPostFix(std::cout); stack.pop(); std::cout << std::endl; } } else { int value = 0; try { value = std::stoi(token); } catch (...) { PrintInputError(); break; } stack.emplace(new TreeNodeConstant(value)); } } }