Advertisement
ludaludaed

ArithmeticTree

Nov 3rd, 2022 (edited)
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.56 KB | None | 0 0
  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4.  
  5. template<typename TValue>
  6. class Cloneable {
  7. public:
  8.     using value_type = TValue;
  9.     using pointer = TValue *;
  10.  
  11.     virtual pointer clone() const = 0;
  12. };
  13.  
  14. class BaseNode : public Cloneable<BaseNode> {
  15. protected:
  16.     BaseNode *left_;
  17.     BaseNode *right_;
  18.  
  19. public:
  20.     BaseNode()
  21.             :
  22.             left_(nullptr),
  23.             right_(nullptr) {}
  24.  
  25.     BaseNode(const BaseNode &other)
  26.             :
  27.             left_(nullptr),
  28.             right_(nullptr) {
  29.         if (other.left_ != nullptr) {
  30.             left_ = other.left_->clone();
  31.         }
  32.         if (other.right_ != nullptr) {
  33.             right_ = other.right_->clone();
  34.         }
  35.     }
  36.  
  37.     BaseNode(BaseNode &&other)
  38.             :
  39.             left_(other.left_),
  40.             right_(other.right_) {
  41.         other.left_ = nullptr;
  42.         other.right_ = nullptr;
  43.     }
  44.  
  45.     virtual ~BaseNode() {
  46.         delete left_;
  47.         delete right_;
  48.     }
  49.  
  50.     virtual double operator()() const = 0;
  51.  
  52.     virtual std::string to_string() const = 0;
  53.  
  54.     void setLeft(BaseNode *left) {
  55.         left_ = left;
  56.     }
  57.  
  58.     void setRight(BaseNode *right) {
  59.         right_ = right;
  60.     }
  61. };
  62.  
  63. class NilNode : public BaseNode {
  64. public:
  65.     double operator()() const override {
  66.         return left_->operator()();
  67.     }
  68.  
  69.     std::string to_string() const override {
  70.         return left_->to_string();
  71.     }
  72.  
  73.     BaseNode *clone() const override {
  74.         BaseNode *self = new NilNode;
  75.  
  76.         if (left_ != nullptr) {
  77.             self->setLeft(left_->clone());
  78.         }
  79.         if (right_ != nullptr) {
  80.             self->setRight(right_->clone());
  81.         }
  82.         return self;
  83.     }
  84. };
  85.  
  86. class PlusNode : public BaseNode {
  87. public:
  88.     double operator()() const override {
  89.         if (left_ == nullptr && right_ == nullptr) {
  90.             return 0;
  91.         } else if (left_ == nullptr) {
  92.             return right_->operator()();
  93.         } else if (right_ == nullptr) {
  94.             return left_->operator()();
  95.         } else {
  96.             return left_->operator()() + right_->operator()();
  97.         }
  98.     }
  99.  
  100.     std::string to_string() const override {
  101.         if (left_ == nullptr && right_ == nullptr) {
  102.             return "";
  103.         } else if (left_ == nullptr) {
  104.             return right_->to_string();
  105.         } else if (right_ == nullptr) {
  106.             return left_->to_string();
  107.         } else {
  108.             return "(" + left_->to_string() + "+" + right_->to_string() + ")";
  109.         }
  110.     }
  111.  
  112.     BaseNode *clone() const override {
  113.         BaseNode *self = new PlusNode;
  114.  
  115.         if (left_ != nullptr) {
  116.             self->setLeft(left_->clone());
  117.         }
  118.         if (right_ != nullptr) {
  119.             self->setRight(right_->clone());
  120.         }
  121.         return self;
  122.     }
  123. };
  124.  
  125. class MinusNode : public BaseNode {
  126. public:
  127.     double operator()() const override {
  128.         if (left_ == nullptr && right_ == nullptr) {
  129.             return 0;
  130.         } else if (left_ == nullptr) {
  131.             return right_->operator()() * -1;
  132.         } else if (right_ == nullptr) {
  133.             return left_->operator()() * -1;
  134.         } else {
  135.             return left_->operator()() - right_->operator()();
  136.         }
  137.     }
  138.  
  139.     std::string to_string() const override {
  140.         if (left_ == nullptr && right_ == nullptr) {
  141.             return "";
  142.         } else if (left_ == nullptr) {
  143.             return "-" + right_->to_string();
  144.         } else if (right_ == nullptr) {
  145.             return "-" + left_->to_string();
  146.         } else {
  147.             return "(" + left_->to_string() + "-" + right_->to_string() + ")";
  148.         }
  149.     }
  150.  
  151.     BaseNode *clone() const override {
  152.         BaseNode *self = new MinusNode;
  153.  
  154.         if (left_ != nullptr) {
  155.             self->setLeft(left_->clone());
  156.         }
  157.         if (right_ != nullptr) {
  158.             self->setRight(right_->clone());
  159.         }
  160.         return self;
  161.     }
  162. };
  163.  
  164. class MultiplyNode : public BaseNode {
  165. public:
  166.     double operator()() const override {
  167.         return left_->operator()() * right_->operator()();
  168.     }
  169.  
  170.     std::string to_string() const override {
  171.         return "(" + left_->to_string() + "*" + right_->to_string() + ")";
  172.     }
  173.  
  174.     BaseNode *clone() const override {
  175.         BaseNode *self = new MultiplyNode;
  176.  
  177.         if (left_ != nullptr) {
  178.             self->setLeft(left_->clone());
  179.         }
  180.         if (right_ != nullptr) {
  181.             self->setRight(right_->clone());
  182.         }
  183.         return self;
  184.     }
  185. };
  186.  
  187. class DivisionNode : public BaseNode {
  188. public:
  189.     double operator()() const override {
  190.         return left_->operator()() / right_->operator()();
  191.     }
  192.  
  193.     std::string to_string() const override {
  194.         return "(" + left_->to_string() + "/" + right_->to_string() + ")";
  195.     }
  196.  
  197.     BaseNode *clone() const override {
  198.         BaseNode *self = new DivisionNode;
  199.  
  200.         if (left_ != nullptr) {
  201.             self->setLeft(left_->clone());
  202.         }
  203.         if (right_ != nullptr) {
  204.             self->setRight(right_->clone());
  205.         }
  206.         return self;
  207.     }
  208. };
  209.  
  210. class DegreeNode : public BaseNode {
  211. public:
  212.     double operator()() const override {
  213.         return std::pow(left_->operator()(), right_->operator()());
  214.     }
  215.  
  216.     std::string to_string() const override {
  217.         return "(" + left_->to_string() + "^" + right_->to_string() + ")";
  218.     }
  219.  
  220.     BaseNode *clone() const override {
  221.         BaseNode *self = new DegreeNode;
  222.  
  223.         if (left_ != nullptr) {
  224.             self->setLeft(left_->clone());
  225.         }
  226.         if (right_ != nullptr) {
  227.             self->setRight(right_->clone());
  228.         }
  229.         return self;
  230.     }
  231. };
  232.  
  233. class ConstantNode : public BaseNode {
  234. public:
  235.     double constant;
  236.  
  237.     explicit ConstantNode(double constant)
  238.             :
  239.             BaseNode(),
  240.             constant(constant) {}
  241.  
  242.     double operator()() const override {
  243.         return constant;
  244.     }
  245.  
  246.     std::string to_string() const override {
  247.         return std::to_string(constant);
  248.     }
  249.  
  250.     BaseNode *clone() const override {
  251.         BaseNode *self = new ConstantNode(constant);
  252.  
  253.         if (left_ != nullptr) {
  254.             self->setLeft(left_->clone());
  255.         }
  256.         if (right_ != nullptr) {
  257.             self->setRight(right_->clone());
  258.         }
  259.         return self;
  260.     }
  261. };
  262.  
  263.  
  264. class ArithmeticTree {
  265.     NilNode nil_;
  266.  
  267. public:
  268.     ArithmeticTree() = default;
  269.  
  270.     ArithmeticTree(const ArithmeticTree &other) = default;
  271.  
  272.     ArithmeticTree(ArithmeticTree &&other) noexcept
  273.             : nil_(std::move(other.nil_)) {}
  274.  
  275.     double process() const {
  276.         return nil_.operator()();
  277.     }
  278.  
  279.     std::string to_string() const {
  280.         return nil_.to_string();
  281.     }
  282.  
  283.     static ArithmeticTree parse(const std::string &source) {
  284.         ArithmeticTree tree;
  285.         std::vector<std::string> tokens(std::move(toTokens(source)));
  286.         tree.nil_.setLeft(build(tokens, 0, tokens.size() - 1));
  287.         return tree;
  288.     }
  289.  
  290. private:
  291.     static std::vector<std::string> toTokens(const std::string &source) {
  292.         std::vector<std::string> tokens;
  293.         std::string number_str;
  294.         for (char i: source) {
  295.             if (i == '(' || i == ')' ||
  296.                 i == '^' ||
  297.                 i == '*' || i == '/' ||
  298.                 i == '+' || i == '-') {
  299.                 if (!number_str.empty()) {
  300.                     tokens.push_back(number_str);
  301.                     number_str.clear();
  302.                 }
  303.                 tokens.emplace_back(1, i);
  304.             } else {
  305.                 if (isdigit(i) || i == '.' || i == ',') {
  306.                     number_str += i;
  307.                 }
  308.             }
  309.         }
  310.         if (!number_str.empty()) {
  311.             tokens.push_back(number_str);
  312.         }
  313.         return std::move(tokens);
  314.     }
  315.  
  316.     static BaseNode *build(const std::vector<std::string> &tokens, int start, int end) {
  317.         if (end < start) {
  318.             return nullptr;
  319.         }
  320.         int inflection_index;
  321.         if (end - start == 1) {
  322.             if (tokens[start] == "(" || tokens[start] == ")") {
  323.                 inflection_index = end;
  324.             } else {
  325.                 inflection_index = start;
  326.             }
  327.         } else {
  328.             inflection_index = static_cast<int>(inflectionPoint(tokens, start, end));
  329.         }
  330.  
  331.         BaseNode *new_node;
  332.         if (tokens[inflection_index] == "+") {
  333.             new_node = new PlusNode;
  334.         } else if (tokens[inflection_index] == "-") {
  335.             new_node = new MinusNode;
  336.         } else if (tokens[inflection_index] == "*") {
  337.             new_node = new MultiplyNode;
  338.         } else if (tokens[inflection_index] == "/") {
  339.             new_node = new DivisionNode;
  340.         } else if (tokens[inflection_index] == "^") {
  341.             new_node = new DegreeNode;
  342.         } else {
  343.             new_node = new ConstantNode(std::strtod(tokens[inflection_index].data(), nullptr));
  344.         }
  345.  
  346.         new_node->setLeft(build(tokens, start, inflection_index - 1));
  347.         new_node->setRight(build(tokens, inflection_index + 1, end));
  348.         return new_node;
  349.     }
  350.  
  351.     static size_t inflectionPoint(const std::vector<std::string> &tokens, size_t start, size_t end) {
  352.         size_t result_index = start;
  353.         int maximum_by_priority = std::numeric_limits<int>::min();
  354.         int degree_of_nesting = 0;
  355.         for (size_t i = start; i <= end; ++i) {
  356.             int8_t priority = getPriority(tokens[i]);
  357.             if (priority == 0) {
  358.                 if (tokens[i] == "(") {
  359.                     degree_of_nesting++;
  360.                 } else if (tokens[i] == ")") {
  361.                     degree_of_nesting--;
  362.                 }
  363.             } else {
  364.                 if (maximum_by_priority <= priority - 3 * degree_of_nesting) {
  365.                     maximum_by_priority = priority - 3 * degree_of_nesting;
  366.                     result_index = i;
  367.                 }
  368.             }
  369.         }
  370.         return result_index;
  371.     }
  372.  
  373.     static int8_t getPriority(const std::string &operation) {
  374.         if (operation == "+" || operation == "-") {
  375.             return 3;
  376.         } else if (operation == "*" || operation == "/") {
  377.             return 2;
  378.         } else if (operation == "^") {
  379.             return 1;
  380.         } else {
  381.             return 0;
  382.         }
  383.     }
  384. };
  385.  
  386. int main() {
  387.     std::string expression;
  388.     std::cin >> expression;
  389.     ArithmeticTree tree = ArithmeticTree::parse(expression);
  390.     std::cout << tree.to_string() << std::endl;
  391.     std::cout << tree.process();
  392.     return 0;
  393. }
  394.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement