Advertisement
Guest User

foil evaluator

a guest
Apr 22nd, 2012
94
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.09 KB | None | 0 0
  1. #include <vector>
  2. #include <iterator>
  3. #include <algorithm>
  4. #include <string>
  5. #include <set>
  6. #include <sstream>
  7. #include <iostream>
  8. #include <cassert>
  9. #include <cstring>
  10. #include <map>
  11. #include <utility>
  12.  
  13. class exp_parser
  14. {
  15. private:
  16.     typedef std::string::size_type str_size;
  17.    
  18. public:
  19.     exp_parser() : operator_str("+-")
  20.     {
  21.         operators =  {'+', '-'};
  22.     }
  23.    
  24.     ~exp_parser() = default;
  25.     exp_parser(const exp_parser& rhs) = default;
  26.     exp_parser& operator=(const exp_parser& rhs) = default;
  27.    
  28.     std::string simplify(const std::string& expression);
  29.  
  30. private:
  31.     std::set<char> operators;
  32.     std::string operator_str;
  33.    
  34.     void break_expression(const std::string& expression, std::vector<std::vector<std::string>>& vec);
  35.    
  36.     std::string reduce(const std::vector<std::vector<std::string>>& vec);
  37.     std::string multiply(const std::string& s1, const std::string& s2);
  38.     str_size last_digit(const std::string& s);
  39.     std::string simplify_power(const std::string& expression);
  40.     std::string group_like_terms(const std::string& expression);
  41.    
  42.     std::pair<char, str_size> find_any_of(const std::string& expression, const std::string& values, str_size start_pos = 0);
  43.    
  44.     std::string remove_duplicate_symbols(const std::string& expression);
  45. };
  46.  
  47. int safe_atoi(const std::string& input)
  48. {
  49.     int temp;
  50.     std::stringstream ss(input);
  51.     ss >> temp;
  52.     return temp;
  53. }
  54.  
  55. using namespace std;
  56.  
  57. void exp_parser::break_expression(const string& expression, vector<vector<string>>& vec)
  58. {
  59.     size_t i = 0;
  60.     stringstream ss, op;
  61.    
  62.     string::const_iterator it = expression.begin() + 1;
  63.     while(it != expression.end()) {
  64.         if((*it) == ')') {
  65.             vec[i].push_back(ss.str());
  66.             ss.str("");
  67.             ++i;
  68.         }
  69.         else if(operators.find(*it) != operators.end()) {
  70.             vec[i].push_back(ss.str());
  71.             op << *it;
  72.             vec[i].push_back(op.str());
  73.             ss.str("");
  74.             op.str("");
  75.         }
  76.         else if((*it) != '(' && (*it) != ' ') {
  77.             ss << *it;
  78.         }
  79.         ++it;
  80.     }
  81. }
  82.  
  83. string exp_parser::reduce(const vector<vector<string>>& vec)
  84. {
  85.     if(vec.size() == 2) {
  86.         stringstream ss;
  87.         auto it = vec.begin();
  88.         auto it2 = vec.begin() + 1;
  89.         char curr_op = '+';
  90.        
  91.         for(auto str_it = it->begin(); str_it != it->end(); ++str_it) {
  92.             if(operators.find(str_it->at(0)) != operators.end()) {
  93.                 ss << *str_it;
  94.                 curr_op = str_it->at(0);
  95.             } else {
  96.                 for(auto str_it2 = it2->begin(); str_it2 != it2->end(); ++str_it2) {
  97.                     if(operators.find(str_it2->at(0)) != operators.end()) {
  98.                         ss << curr_op << *str_it2;
  99.                     } else {
  100.                         ss << multiply(*str_it, *str_it2);
  101.                     }
  102.                 }
  103.             }
  104.         }
  105.         return ss.str();
  106.     }
  107.     else {
  108.         //Reduce the first two in the set
  109.         stringstream reduce_1;
  110.         vector<vector<string>> first_set(vec.begin(), vec.begin() + 2);
  111.         reduce_1 << "(" << reduce(first_set) << ")";
  112.         string dupes_removed = remove_duplicate_symbols(reduce_1.str());
  113.        
  114.         //Now we can create a system with (n-1) expressions to evaluate
  115.         //and recurse on that (since polynomial multiplication is closed)
  116.         //to get down to our base case
  117.         vector<vector<string>> smaller_by_one(vec.size() - 1);
  118.         break_expression(dupes_removed, smaller_by_one);
  119.         auto it = vec.begin() + 2;
  120.         size_t i = 1;
  121.        
  122.         while(it != vec.end()) {
  123.             smaller_by_one[i] = *it;
  124.             ++i;
  125.             ++it;
  126.         }
  127.  
  128.         return reduce(smaller_by_one);
  129.     }
  130. }
  131.  
  132. string exp_parser::simplify_power(const string& expression)
  133. {
  134.     int power = 1;
  135.    
  136.     stringstream ss;
  137.     char start;
  138.     string::const_iterator it = expression.begin();
  139.    
  140.     while(it != expression.end()) {
  141.         if(operators.find(*it) == operators.end()) {
  142.             if(!isdigit(*it)) {
  143.                 start = *it;
  144.                 auto it2 = it;
  145.                 while(it2 != expression.end() && *(++it2) == start) {
  146.                     ++power;
  147.                 }
  148.                 if(power > 1) {
  149.                     ss << start << "^" << power;
  150.                     power = 1;
  151.                     it = it2;
  152.                 } else {
  153.                     while(it != it2) {
  154.                         ss << *it;
  155.                         ++it;
  156.                     }
  157.                 }
  158.             } else {
  159.                 ss << *it;
  160.                 ++it;
  161.             }  
  162.         } else {
  163.             ss << *it;
  164.             ++it;
  165.         }
  166.     }
  167.    
  168.     return ss.str();
  169. }
  170.  
  171. string exp_parser::group_like_terms(const string& expression)
  172. {
  173.     map<string, int> term_map;
  174.     stringstream ss, digit_ss;
  175.     auto it = expression.begin();
  176.     exp_parser::str_size next_operator =  0;
  177.     char current_op;
  178.     pair<char, exp_parser::str_size> next_op;
  179.    
  180.     (expression[0] == '-') ? (current_op = '-') : (current_op = '+');
  181.        
  182.     while(next_operator != expression.size()) {
  183.         next_op = find_any_of(expression, operator_str, next_operator + 1);
  184.         next_operator = next_op.second;
  185.         digit_ss << current_op;
  186.         current_op = next_op.first;
  187.        
  188.         if(next_operator == string::npos) {
  189.             next_operator = expression.size();
  190.         }
  191.  
  192.         auto it2 = expression.begin() + next_operator;
  193.        
  194.         while(isdigit(*it)) {
  195.             digit_ss << *it;
  196.             ++it;
  197.         }
  198.        
  199.         string key(it, it2);
  200.         term_map[key] += safe_atoi(digit_ss.str());
  201.         digit_ss.str("");
  202.         it = it2 + 1;  
  203.     }  
  204.    
  205.     for(auto it = term_map.begin(); it != term_map.end(); ++it) {
  206.         ss << it->second << it->first << "+";
  207.     }
  208.     string to_ret = ss.str();
  209.     return string(to_ret.begin(), to_ret.end() - 1);
  210. }
  211.  
  212. pair<char, exp_parser::str_size> exp_parser::find_any_of(const string& expression, const string& values, exp_parser::str_size start_pos)
  213. {
  214.     if(start_pos > expression.size()) {
  215.         return pair<char, exp_parser::str_size>(static_cast<char>(0), string::npos);
  216.     }
  217.    
  218.     for(auto it = expression.begin() + start_pos; it != expression.end(); ++it) {
  219.         for(auto it2 = values.begin(); it2 != values.end(); ++it2) {
  220.             if(*it == *it2) {
  221.                 return pair<char, exp_parser::str_size>(*it, start_pos);
  222.             }
  223.         }
  224.         ++start_pos;
  225.     }
  226.    
  227.     return pair<char, exp_parser::str_size>(static_cast<char>(0), string::npos);
  228. }
  229.  
  230. string exp_parser::remove_duplicate_symbols(const std::string& expression)
  231. {
  232.     stringstream ss;
  233.     auto it = expression.begin();
  234.    
  235.     while(it != expression.end() - 1) {
  236.         if(operators.find(*it) != operators.end() && operators.find(*(it+1)) != operators.end()) {
  237.             if(*it == '-' && *(it+1) == '-') {
  238.                 ss << '+';
  239.             }
  240.             else if(*it == '-') {
  241.                 ss << '-';
  242.             }
  243.             else if(*(it+1) == '-') {
  244.                 ss << "-";
  245.             } else {
  246.                 ss << "+";
  247.             }
  248.             it += 2;
  249.         } else {
  250.             ss << *it;
  251.             ++it;
  252.         }
  253.     }
  254.    
  255.     ss << *(expression.end() - 1);
  256.     return ss.str();
  257. }
  258.    
  259. string exp_parser::multiply(const string& s1, const string& s2)
  260. {
  261.     if(s1.size() < 1 || s2.size() < 1) { return ""; }
  262.    
  263.     stringstream result_ss;
  264.     exp_parser::str_size non_digit1 = last_digit(s1);
  265.     exp_parser::str_size non_digit2 = last_digit(s2);
  266.    
  267.     int s1_intval = safe_atoi(string(s1.begin(), s1.begin() + non_digit1));
  268.     int s2_intval = safe_atoi(string(s2.begin(), s2.begin() + non_digit2));
  269.     int final_int_value = s1_intval * s2_intval;
  270.     result_ss << final_int_value;
  271.     int final_int_length = result_ss.str().size();
  272.    
  273.     for_each(s1.begin() + non_digit1, s1.end(), [&result_ss](char v) { result_ss << v; });
  274.     for_each(s2.begin() + non_digit2, s2.end(), [&result_ss](char v) { result_ss << v; });
  275.    
  276.     string result = result_ss.str();
  277.     sort(result.begin() + final_int_length, result.end());
  278.     return result;
  279. }
  280.  
  281. exp_parser::str_size exp_parser::last_digit(const string& s)
  282. {
  283.     exp_parser::str_size non_digit = s.find_first_not_of("-+0123456789");
  284.     if(non_digit == string::npos) { return s.size(); }
  285.     return non_digit;
  286. }
  287.  
  288. //An expression below is defined as anything delineated by (), thus (2x+1),
  289. //(3x+4y+z), and so on are all expressions.
  290.  
  291. string exp_parser::simplify(const std::string& expression)
  292. {
  293.     //Since we need to allocate the exact amount of space for our
  294.     //vector of vectors (as we're using [], not push_back),
  295.     //we need some way to see how many expressions we have.
  296.     //Utilize the count of '(' for this - thus if we have an unbalanced
  297.     //expression, everything will fall over
  298.     ptrdiff_t vec_size = count(expression.begin(), expression.end(), '(');
  299.    
  300.     //If we have 0 or 1 brakcets, then we have either a constant expression
  301.     //or an expression like (ax+b), which is already simplified
  302.     if(vec_size <= 1) { return expression; }
  303.    
  304.     //Allocate our vector of vectors with the proper amount of space
  305.     vector<vector<string>> pv(vec_size);
  306.     //Breaks each of our expressions into the component parts,
  307.     //adding the parts of expression number i to the vector contained in
  308.     //pv[i]
  309.     break_expression(expression, pv);
  310.     //This collapses all the expressions down into a single
  311.     //expression
  312.     string reduced = reduce(pv);
  313.     //Because of the way reduce is implemented, we will get repeated
  314.     //operators, like +-, -+, -- or ++. This replaces each of these with
  315.     //their single operator equivalents.
  316.     string de_duplicated = remove_duplicate_symbols(reduced);
  317.     //Our expression then needs all the like terms grouped,
  318.     //for example, 6x + 5y + 5x + 6y == 11x + 11y
  319.     string grouped = group_like_terms(de_duplicated);
  320.     //Finally, anything with repeated values such as 3xxx is
  321.     //converted to its proper power form, thus 3x^3
  322.     string simple = simplify_power(grouped);
  323.     //Some of the above methods may re-introduce duplicate operators
  324.     //along the way, so we require a final cull
  325.     return remove_duplicate_symbols(simple);
  326. }
  327.  
  328. int main()
  329. {
  330.     exp_parser parser;
  331.     string simplified = parser.simplify("(2x+3)(4x+2)(5x+1)(6x+5)");
  332.     std::cout << simplified << "\n";
  333.     return 0;
  334. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement