POJ 1686 - Lazy Math Instructor

http://poj.org/problem?id=1686

概要

からなる数式が2つ与えられるので、それらが数式として等しいかどうかを答える。

注意

解法

かけ算があるため、真面目に文字式として等しいかどうかチェックするのは大変なので、 適当な乱数を何度か代入してみて等しいかどうかをチェックして済ませる。

  1 #include <iostream>
  2 #include <algorithm>
  3 using namespace std;
  4 
  5 bool ws_p(char c) { return c == ' ' || c == '\t'; }
  6 bool digit_p(char c) { return '0' <= c && c <= '9'; }
  7 bool op_p(char c) { return c == '+' || c == '-' || c == '*'; }
  8 
  9 typedef string::const_iterator Iterator;
 10 
 11 struct expr
 12 {
 13   char c;
 14   int n;
 15   expr *l, *r;
 16   expr(int x) : c(0), n(x), l(0), r(0) {}
 17   expr(char x) : c(x), n(0), l(0), r(0) {}
 18   expr(char o, expr *a, expr *b) : c(o), n(0), l(a), r(b) {}
 19   ~expr() { delete l; delete r; }
 20   int eval(const int *env) const
 21   {
 22     switch (c) {
 23       case 0: return n;
 24       case '+': return l->eval(env) + r->eval(env);
 25       case '-': return l->eval(env) - r->eval(env);
 26       case '*': return l->eval(env) * r->eval(env);
 27       default:  return env[c-'a'];
 28     }
 29   }
 30 };
 31 
 32 expr *parse_expr(Iterator& it, const Iterator& last);
 33 
 34 expr *parse_term(Iterator& it, const Iterator& last)
 35 {
 36   if (*it == '(') {
 37     ++it;
 38     expr *e = parse_expr(it, last);
 39     if (*it != ')') {
 40       throw ")";
 41     }
 42     ++it;
 43     return e;
 44   } else if (digit_p(*it)) {
 45     expr *e = new expr(int(*it-'0'));
 46     ++it;
 47     return e;
 48   } else {
 49     expr *e = new expr(char(*it));
 50     ++it;
 51     return e;
 52   }
 53 }
 54 
 55 expr *parse_expr(Iterator& it, const Iterator& last)
 56 {
 57   expr *l = parse_term(it, last);
 58   while (it != last && op_p(*it)) {
 59     char op = *it;
 60     ++it;
 61     expr *r = parse_term(it, last);
 62     l = new expr(op, l, r);
 63   }
 64   return l;
 65 }
 66 
 67 struct xorshift
 68 {
 69   unsigned x, y, z, w;
 70   xorshift() : x(123456789), y(362436069), z(521288629), w(88675123) {}
 71   unsigned operator()()
 72   {
 73     unsigned t = x ^ (x << 11);
 74     x = y; y = z; z = w;
 75     return (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8))) % 100;
 76   }
 77 };
 78 
 79 bool same_p(expr *a, expr *b)
 80 {
 81   xorshift rng;
 82   for (int i = 0; i < 100; i++) {
 83     int env[26];
 84     for (int j = 0; j < 26; j++) {
 85       env[j] = rng();
 86     }
 87     if (a->eval(env) != b->eval(env)) {
 88       return false;
 89     }
 90   }
 91   return true;
 92 }
 93 
 94 int main()
 95 {
 96   int N;
 97   cin >> N;
 98   cin.ignore();
 99   while (N-- > 0) {
100     expr *e[2];
101     for (int i = 0; i < 2; i++) {
102       string s;
103       getline(cin, s);
104       s.erase(remove_if(s.begin(), s.end(), ws_p), s.end());
105       Iterator it = s.begin(), last = s.end();
106       e[i] = parse_expr(it, last);
107     }
108     cout << (same_p(e[0], e[1]) ? "YES" : "NO") << endl;
109     delete e[0];
110     delete e[1];
111   }
112   return 0;
113 }
poj/1686.cc