1102-Calculation of Expressions
http://rose.u-aizu.ac.jp/onlinejudge/ProblemSet/description.jsp?id=1102
問題概要
虚数(i)と+,*,-が含まれた式が与えられるので
式をパースしてその結果を答える。
ただし、実部・虚部ともに絶対値が10000を超えることがあったらオーバーフローと表示する。
このときかけ算の途中で超えて、かけ算の最終結果で超えていなかったらオーバーフローでは無い。
例:(10*i+100)*(101+20*i)=10100-20*10+(2000+1010)*i=9900+3010i
考え方
パーサーを実装する。
後は出力部分に気をつければ難しい所は無いと思う。
実装(C++)
#include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <climits> #include <cctype> #include <ctime> #include <cassert> #include <cwchar> #include <cstdarg> #include <cwctype> #include <queue> #include <stack> #include <algorithm> #include <list> #include <vector> #include <set> #include <map> #include <iostream> #include <deque> #include <complex> #include <string> #include <functional> #include <iomanip> #include <sstream> using namespace std; namespace VBString{ int Len(string Expression); string Left(string Expression,int Length); string Right(string Expression,int Length); string Mid(string Expression,int start,int length); string Mid(string Expression,int start); int InStr(int Start,string String1,string String2); string Replace(string Expression,string Str1,string Str2,int Start,int Count); string Replace(string Expression,string Str1,string Str2); string String(int Number,string Character); int Len(string Expression){ return Expression.size(); } string Left(string Expression,int Length){ if(Length>=0){ return Expression.substr(0,Length); } else { return ""; } } string Right(string Expression,int Length){ if(Length>=0){ return Expression.substr(Len(Expression)-Length>=0?Len(Expression)-Length:0,Length); } else { return ""; } } string Mid(string Expression,int start,int length){ if(start<1||start>Len(Expression)||length<=0){ return ""; } else { return Expression.substr(start-1,length); } } string Mid(string Expression,int start){ return Mid(Expression,start,Len(Expression)); } int InStr(int Start,string String1,string String2){ return String1.find(String2,Start-1)+1; } string Replace(string Expression,string Str1,string Str2,int Start,int Count){ int t,c;string tStr; if(Start>1)Expression=Right(Expression,Len(Expression)-Start+1<0?0:Len(Expression)-Start+1); c=0;t=InStr(1,Expression,Str1); while(t>0){tStr=Left(Expression, t - 1)+Str2;Expression=tStr+Right(Expression, Len(Expression) - t + 1 - Len(Str1)); t=InStr(Len(tStr)+1,Expression,Str1);c++; if(c>=Count&&Count!=-1)break; } return Expression; } string Replace(string Expression,string Str1,string Str2){ return Replace(Expression,Str1,Str2,1,-1); } } typedef long long int lli; typedef unsigned int uint; const complex<lli> OVERFLOWED(9999999,9999999); void calc(stack<char> &ope,stack<complex<lli> > &v){ complex<lli> a,b; a=v.top();v.pop();b=v.top();v.pop(); switch(ope.top()){ case '*' : v.push(b*a);break; case '+' : v.push(b+a);break; case '-' : v.push(b-a);break; } ope.pop(); } complex<lli> calc(string p){ int pri[256];int L=p.length(); memset(pri,-1,sizeof(pri)); pri[')']=1;pri['(']=4; pri['*']=3; pri['+']=2;pri['-']=2; stack<complex<lli> > v; stack<char> ope; int i=0; while(i<L){ if(p[i]>='0'&&p[i]<='9'){ lli t=0; while(i<L&&(p[i]>='0'&&p[i]<='9')){ t*=10; t+=p[i]-'0'; if(t>10000)return OVERFLOWED; i++; } if(i<L&&p[i]=='i'){ v.push(complex<lli>(0,t)); i++; }else{ v.push(complex<lli>(t,0)); } }else if(p[i]=='i'){ i++; v.push(complex<lli>(0,1)); }else{ while(!ope.empty() && pri[p[i]]<=pri[ope.top()] && ope.top()!='('){ calc(ope,v); if(abs(v.top().real())>10000)return OVERFLOWED; if(abs(v.top().imag())>10000)return OVERFLOWED; } if(p[i]!=')'){ ope.push(p[i]); }else{ ope.pop(); } i++; } } while(!ope.empty()){ calc(ope,v); if(abs(v.top().real())>10000)return OVERFLOWED; if(abs(v.top().imag())>10000)return OVERFLOWED; } return v.top(); } int main(){ complex<lli> res; string expression; for(;cin>>expression;){ if(expression[0]=='-')expression="0"+expression; expression=VBString::Replace(expression,"(-","(0-"); res=calc(expression); if(res==OVERFLOWED){ cout<<"overflow"<<endl; }else if(res.real()==0&&res.imag()==0){ cout<<0<<endl; }else if(res.real()==0){ cout<<res.imag()<<"i"<<endl; }else if(res.imag()==0){ cout<<res.real()<<endl; }else{ cout<<res.real()<<(res.imag()>0?"+":"")<<res.imag()<<"i"<<endl; } } return 0; }