1233-Equals are Equals
問題概要
二つの数式が等しいか比較せよ
解法
構文解析.
非常にバグを作りやすい問題だった.
実装(C++)
#include <algorithm> #include <iostream> #include <string> #include <vector> #include <map> using namespace std; typedef map<string,int> expression; #define REP(i,x) for(int i=0;i<(int)(x);i++) #define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++) expression operator+(const expression &a,const expression &b){ expression res(a); FOR(it,b){ res[it->first]+=it->second; } return res; } expression operator-(const expression &a,const expression &b){ expression res(a); FOR(it,b){ res[it->first]-=it->second; } return res; } expression operator*(const expression &a,const expression &b){ expression res; FOR(it1,a){ FOR(it2,b){ string t=(it1->first)+(it2->first); sort(t.begin(),t.end()); res[t]+=(it1->second)*(it2->second); } } return res; } bool operator==(expression a,expression b){ FOR(it,b){ if(a[it->first]!=it->second) return false; } return true; } expression Expr(const string &s,int &p); expression Factor(const string &s,int &p); expression Term(const string &s,int &p); expression Value(const string &s,int &p); expression Expr(const string &s,int &p){ expression res=Factor(s,p); while(s[p]=='+'||s[p]=='-'){ char op=s[p]; p++; expression right=Factor(s,p); if(op=='+')res=res+right; else res=res-right; } return res; } expression Factor(const string &s,int &p){ expression res=Term(s,p); while(s[p]=='*'){ p++; expression right=Term(s,p); res=res*right; } return res; } expression Term(const string &s,int &p){ expression res=Value(s,p); if(s[p]=='^'){ p++; expression right=Value(s,p); expression rv=res; res=expression(); res[""]=1; REP(i,right[""]){ res=res*rv; } } return res; } expression Value(const string &s,int &p){ if(s[p]=='('){ p++; expression res=Expr(s,p); p++; return res; }else if(isdigit(s[p])){ int v=0; while(isdigit(s[p])){ v=v*10+(s[p++]-'0'); } expression res; res[""]=v; return res; }else if(isalpha(s[p])){ expression res; string t; t+=s[p]; res[t]=1; p++; return res; }else{ exit(-1); } } string init(string a){ string res; if(a[0]!=' ')res.push_back(a[0]); for(int i=1;i<(int)a.size();i++){ if(isdigit(a[i-1])&&isalpha(a[i])){ res.push_back('*'); }else if(isalpha(a[i-1])&&isalnum(a[i])){ res.push_back('*'); }else if(isalnum(a[i-1])&&a[i]=='('){ res.push_back('*'); }else if(isalnum(a[i])&&a[i-1]==')'){ res.push_back('*'); }else if(a[i]=='('&&a[i-1]==')'){ res.push_back('*'); }else if(a[i-1]==' '&&a[i]==' ')continue; res.push_back(a[i]); } a=""; for(int i=0;i<(int)res.size();i++){ if(res[i]==' '){ if(i+1<(int)res.size()){ if(isalnum(res[i-1])&&isalnum(res[i+1])){ a.push_back('*'); }else if(isalnum(res[i-1])&&res[i+1]=='('){ a.push_back('*'); }else if(isalnum(res[i+1])&&res[i-1]==')'){ a.push_back('*'); }else if(res[i-1]==')'&&res[i+1]=='('){ a.push_back('*'); } } }else{ a.push_back(res[i]); } } return a; } ostream& operator<<(ostream &os,const expression &a){ FOR(it,a){ os<<it->first<<","<<it->second<<endl; } return os; } int main() { string in; while(1){ getline(cin,in); if(in==".")break; in=init(in); int q=0; expression left=Expr(in,q); while(1){ string in2; getline(cin,in); if(in==".")break; in=init(in); q=0; expression right=Expr(in,q); if(left==right&&right==left){ cout<<"yes"<<endl; }else{ cout<<"no"<<endl; } } cout<<"."<<endl; } return 0; }