Advertisement
Guest User

Untitled

a guest
Jun 23rd, 2014
661
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.65 KB | None | 0 0
  1. #include <iostream>
  2. #include <fstream>
  3. #include <algorithm>
  4. #include <vector>
  5. #include <string>
  6. #include <ctime>
  7. #include <memory>
  8. #include <boost/rational.hpp>
  9. #include <boost/shared_ptr.hpp>
  10.  
  11. bool is_valid_rpn_form(const std::vector<bool> &s){
  12.     int n = 0;
  13.     for (const auto &c : s){
  14.         if (!c)
  15.             n++;
  16.         else
  17.             n--;
  18.         if (n < 1)
  19.             return 0;
  20.     }
  21.     return n == 1;
  22. }
  23.  
  24. std::vector<std::vector<bool> > generate_all_partial_expressions(unsigned operands){
  25.     std::vector<std::vector<bool> > ret;
  26.     std::vector<bool> s;
  27.     if (!operands){
  28.         ret.push_back(s);
  29.         return ret;
  30.     }
  31.     s.push_back(0);
  32.     if (operands == 1){
  33.         ret.push_back(s);
  34.         return ret;
  35.     }
  36.     s.push_back(0);
  37.     unsigned operators = operands - 1;
  38.     operands -= 2;
  39.     for (unsigned i = 0; i < operands; i++)
  40.         s.push_back(0);
  41.     for (unsigned i = 0; i < operators; i++)
  42.         s.push_back(1);
  43.     ret.push_back(s);
  44.     while (std::next_permutation(s.begin() + 2, s.end())){
  45.         if (!is_valid_rpn_form(s))
  46.             continue;
  47.         ret.push_back(s);
  48.     }
  49.     return ret;
  50. }
  51.  
  52. enum class Operation{
  53.     ADD = 0,
  54.     SUB = 1,
  55.     MUL = 2,
  56.     DIV = 3,
  57. };
  58.  
  59. #if 1
  60. typedef boost::rational<int> main_type;
  61. #elif 0
  62. typedef double main_type;
  63. #else
  64. typedef int main_type;
  65. #endif
  66.  
  67. struct sol_t{
  68.     bool is_number;
  69.     main_type value;
  70. };
  71.  
  72. const unsigned OPERAND_COUNT = 6;
  73.  
  74. class Searcher{
  75.     std::vector<std::vector<std::vector<bool> > > expression_trees;
  76.     main_type operands[OPERAND_COUNT];
  77.     main_type result;
  78.  
  79.     void level0(){
  80.         //Search possible operand combinations.
  81.         auto m = OPERAND_COUNT;
  82.         const unsigned n = 1 << m;
  83.         for (unsigned i = 1; i < n; i++){
  84.             std::vector<main_type> current_operands;
  85.             {
  86.                 unsigned copy_i = i;
  87.                 for (unsigned j = 0; j < m; j++, copy_i >>= 1)
  88.                     if (copy_i & 1)
  89.                         current_operands.push_back(this->operands[j]);
  90.             }
  91.             std::sort(current_operands.begin(), current_operands.end());
  92.             this->level1(current_operands);
  93.         }
  94.     }
  95.     void level1(std::vector<main_type> &current_operands){
  96.         const unsigned n = 1 << ((current_operands.size() - 1) * 2);
  97.         //Search multiple operator orders.
  98.         for (unsigned operator_order = 0; operator_order < n; operator_order++)
  99.             this->level2(current_operands, operator_order);
  100.     }
  101.     void level2(std::vector<main_type> &current_operands, unsigned operator_order){
  102.         //Search multiple operand orders.
  103.         auto it = current_operands.begin();
  104.         auto end = it + current_operands.size();
  105.         while (std::next_permutation(it, end))
  106.             this->level3(current_operands, operator_order);
  107.     }
  108.     void level3(const std::vector<main_type> &current_operands, unsigned operator_order){
  109.         auto &possible_expression_trees = this->expression_trees[current_operands.size()];
  110.         for (auto &expr : possible_expression_trees)
  111.             this->evaluate(current_operands, operator_order, expr);
  112.     }
  113.     void evaluate(const std::vector<main_type> &current_operands, unsigned operator_order, const std::vector<bool> &current_expression);
  114. public:
  115.     std::vector<sol_t> all_solutions;
  116.     Searcher(const int operands[OPERAND_COUNT], int result): result(result){
  117.         std::copy(operands, operands + OPERAND_COUNT, this->operands);
  118.         std::sort(this->operands, this->operands + 5);
  119.         for (unsigned i = 0; i <= OPERAND_COUNT; i++){
  120.             auto exprs = generate_all_partial_expressions(i);
  121.             this->expression_trees.push_back(exprs);
  122.         }
  123.     }
  124.     void search(){
  125.         this->level0();
  126.     }
  127. };
  128.  
  129. void Searcher::evaluate(const std::vector<main_type> &current_operands, unsigned operator_order, const std::vector<bool> &current_expression){
  130.     unsigned operators = operator_order;
  131.     sol_t solution[OPERAND_COUNT * 2 - 1];
  132.     int solution_size = 0;
  133.     main_type stack[6];
  134.     int stack_end = -1;
  135.     int n = 0;
  136.     for (const auto &op : current_expression){
  137.         if (!op){
  138.             auto operand = current_operands[n++];
  139.             solution[solution_size].is_number = 1;
  140.             solution[solution_size].value = operand;
  141.             solution_size++;
  142.             stack[++stack_end] = operand;
  143.         }else{
  144.             unsigned op = operators & 3;
  145.             operators >>= 2;
  146.  
  147.             solution[solution_size].is_number = 0;
  148.             solution[solution_size].value = op + 1;
  149.             solution_size++;
  150.  
  151.             auto operand = stack[stack_end--];
  152.             auto &operand2 = stack[stack_end];
  153.             switch ((Operation)op){
  154.                 case Operation::ADD:
  155.                     operand2 += operand;
  156.                     break;
  157.                 case Operation::SUB:
  158.                     operand2 -= operand;
  159.                     break;
  160.                 case Operation::MUL:
  161.                     operand2 *= operand;
  162.                     break;
  163.                 case Operation::DIV:
  164.                     if (!operand)
  165.                         return;
  166.                     operand2 /= operand;
  167.                     break;
  168.             }
  169.         }
  170.     }
  171.     if (stack[stack_end] != this->result)
  172.         return;
  173.     for (int i = 0; i < solution_size; i++)
  174.         this->all_solutions.push_back(solution[i]);
  175.     sol_t temp = { 0, 0 };
  176.     this->all_solutions.push_back(temp);
  177. }
  178.  
  179. int to_int(int x){
  180.     return x;
  181. }
  182.  
  183. int to_int(float x){
  184.     return (int)x;
  185. }
  186.  
  187. int to_int(double x){
  188.     return (int)x;
  189. }
  190.  
  191. int to_int(const boost::rational<int> &x){
  192.     return x.numerator();
  193. }
  194.  
  195. class TreeElement{
  196. public:
  197.     virtual ~TreeElement(){}
  198.     virtual main_type get_value() = 0;
  199.     virtual void output(std::vector<sol_t> &) = 0;
  200.     virtual void output(std::ostream &) = 0;
  201.     virtual void output_rpn(std::ostream &) = 0;
  202.     virtual unsigned get_precedence() = 0;
  203.     virtual bool is_constant() const{
  204.         return 0;
  205.     }
  206. };
  207.  
  208. class NumberTreeElement : public TreeElement{
  209. public:
  210.     int value;
  211.     NumberTreeElement(int value): value(value){}
  212.     main_type get_value(){
  213.         return this->value;
  214.     }
  215.     void output(std::vector<sol_t> &dst){
  216.         sol_t temp = {
  217.             1,
  218.             this->value,
  219.         };
  220.         dst.push_back(temp);
  221.     }
  222.     void output(std::ostream &stream){
  223.         stream <<value;
  224.     }
  225.     void output_rpn(std::ostream &stream){
  226.         this->output(stream);
  227.     }
  228.     unsigned get_precedence(){
  229.         return UINT_MAX;
  230.     }
  231.     bool is_constant() const{
  232.         return 1;
  233.     }
  234. };
  235.  
  236. class OperatorTreeElement : public TreeElement{
  237.     bool computed;
  238.     main_type value;
  239.     typedef boost::shared_ptr<TreeElement> op_t;
  240. public:
  241.     Operation op;
  242.     op_t left,
  243.         right;
  244.     OperatorTreeElement(Operation op, boost::shared_ptr<TreeElement> left, boost::shared_ptr<TreeElement> right): op(op), left(left), right(right), computed(0){}
  245.     main_type get_value(){
  246.         if (!this->computed){
  247.             switch (this->op){
  248.                 case Operation::ADD:
  249.                     this->value = this->left->get_value() + this->right->get_value();
  250.                     break;
  251.                 case Operation::SUB:
  252.                     this->value = this->left->get_value() - this->right->get_value();
  253.                     break;
  254.                 case Operation::MUL:
  255.                     this->value = this->left->get_value() * this->right->get_value();
  256.                     break;
  257.                 case Operation::DIV:
  258.                     this->value = this->left->get_value() / this->right->get_value();
  259.                     break;
  260.             }
  261.             this->computed = 1;
  262.         }
  263.         return this->value;
  264.     }
  265.     void output(std::vector<sol_t> &dst){
  266.         this->left->output(dst);
  267.         this->right->output(dst);
  268.         sol_t temp = {
  269.             0,
  270.             (int)this->op + 1,
  271.         };
  272.         dst.push_back(temp);
  273.     }
  274.     void output(std::ostream &stream){
  275.         bool l = this->left->get_precedence() < this->get_precedence();
  276.         bool r = this->right->get_precedence() < this->get_precedence() || ((int)this->op % 2 && !this->right->is_constant());
  277.         if (l)
  278.             stream <<'(';
  279.         this->left->output(stream);
  280.         if (l)
  281.             stream <<')';
  282.         static const char char_operators[] = "+-*/";
  283.         stream <<' '<<char_operators[(int)this->op]<<' ';
  284.         if (r)
  285.             stream <<'(';
  286.         this->right->output(stream);
  287.         if (r)
  288.             stream <<')';
  289.     }
  290.     void output_rpn(std::ostream &stream){
  291.         this->left->output_rpn(stream);
  292.         stream <<' ';
  293.         this->right->output_rpn(stream);
  294.         static const char char_operators[] = "+-*/";
  295.         stream <<' '<<char_operators[(int)this->op];
  296.     }
  297.     unsigned get_precedence(){
  298.         return (unsigned)this->op / 2;
  299.     }
  300. };
  301.  
  302. boost::shared_ptr<TreeElement> build_tree(sol_t *&list){
  303.     boost::shared_ptr<TreeElement> stack[OPERAND_COUNT * 2 - 1];
  304.     int stack_end = -1;
  305.     while (1){
  306.         if (list->is_number){
  307.             stack[++stack_end].reset(new NumberTreeElement(to_int(list->value)));
  308.         }else{
  309.             if (!to_int(list->value)){
  310.                 list++;
  311.                 return stack[stack_end];
  312.             }
  313.  
  314.             auto operand2 = stack[stack_end--];
  315.             auto operand = stack[stack_end--];
  316.             auto op = (Operation)(to_int(list->value) - 1);
  317.             stack[++stack_end].reset(new OperatorTreeElement(op, operand, operand2));
  318.         }
  319.         list++;
  320.     }
  321. }
  322.  
  323. int main(){
  324.     int operands[] = { 3, 7, 8, 10, 50, 100 };
  325.     Searcher searcher(operands, 315);
  326.     auto t0 = clock();
  327.     searcher.search();
  328.     auto t1 = clock();
  329.     {
  330.         std::ofstream rpn_file("rpn.txt");
  331.         std::ofstream infix_file("infix.txt");
  332.         for (auto p = &searcher.all_solutions[0]; p < &searcher.all_solutions.back() + 1;){
  333.             auto p2 = build_tree(p);
  334.             p2->output_rpn(rpn_file);
  335.             p2->output(infix_file);
  336.             rpn_file <<std::endl;
  337.             infix_file <<std::endl;
  338.         }
  339.     }
  340.     std::cout <<"Done in "<<double(t1 - t0)/double(CLOCKS_PER_SEC)<<std::endl;
  341.    
  342.     return 0;
  343. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement