#include<bits/stdc++.h> using namespace std; enum Atom_type{NUMBER=1,LETTER=2,OPERATOR=3}; const int MAX_PARA=20; int sign[128],prio[128],n_para; vector<double> para_list_all[MAX_PARA]; //double para_list[MAX_PARA]; vector<string> parameters; int gcd(int n,int m){ if(n<0)n=-n; if(m<0)m=-m; while(m){ n=n%m; swap(n,m); } return n; } struct Mocular{ pair<int,int> coef; int cnt_pow[MAX_PARA]; Mocular(){ coef.first=coef.second=0; memset(cnt_pow,0,sizeof cnt_pow); } Mocular(const Mocular &a){ coef=a.coef; for(int i=0;i<n_para;++i)cnt_pow[i]=a.cnt_pow[i]; } Mocular(int n){ coef={1,1}; memset(cnt_pow,0,sizeof cnt_pow); if(n%10==NUMBER)coef={n/10,1}; else cnt_pow[n/10]++; } void reduce(){ int n_gcd=gcd(coef.first,coef.second); if(n_gcd){ coef.first/=n_gcd; coef.second/=n_gcd; } if(coef.second<0){ coef.first*=(-1); coef.second*=(-1); } } Mocular operator * (const Mocular &a){ Mocular ret(*this); ret.coef.first*=a.coef.first; ret.coef.second*=a.coef.second; for(int i=0;i<n_para;++i)ret.cnt_pow[i]+=a.cnt_pow[i]; ret.reduce(); return ret; } Mocular operator / (const Mocular &a){ Mocular ret(*this); ret.coef.first*=a.coef.second; ret.coef.second*=a.coef.first; for(int i=0;i<n_para;++i)ret.cnt_pow[i]-=a.cnt_pow[i]; ret.reduce(); return ret; } bool operator == (const Mocular &a){ bool flag=true; for(int i=0;i<n_para;++i) if(cnt_pow[i]!=a.cnt_pow[i])flag=false; return flag; } void print(){ int a=coef.first,b=coef.second; if(a==0)return; if(a>0)cout<<'+'; else{ cout<<'-'; a=-a; } cout<<" "; if(a!=1&&b==1)cout<<a<<" "; else if(b!=1)cout<<a<<"/"<<b<<" "; bool flag=true; for(int i=0;i<n_para;++i) if(cnt_pow[i]){ cout<<parameters[i]; if(cnt_pow[i]!=1)cout<<'^'<<cnt_pow[i]; cout<<" "; flag=false; } if(flag&&a==1&&b==1)cout<<"1 "; } }; struct Expression{ vector<Mocular> exp; Expression(){exp.clear();} Expression(const Expression &a){ exp.clear(); for(auto &x: a.exp)exp.emplace_back(x); } Expression(const Mocular &a){ exp.clear(); exp.emplace_back(a); } Expression operator + (const Expression &a){ Expression ret(*this); for(auto &x: a.exp){ bool flag=true; for(auto &y: ret.exp) if(y==x){ y.coef.first=y.coef.first*x.coef.second+y.coef.second*x.coef.first; y.coef.second*=x.coef.second; y.reduce(); flag=false; break; } if(flag)ret.exp.push_back(x); } return ret; } Expression operator - (const Expression &a){ Expression ret(a); for(auto &x: ret.exp)x.coef.first*=(-1); return *this+ret; } Expression operator * (const Expression &a){ Expression ret; for(auto &x: exp) for(auto &y: a.exp) ret=ret+Expression(x*y); return ret; } Expression operator / (const Expression &a){ Expression ret; for(auto &x: exp) ret=ret+Expression(x/a.exp[0]); return ret; } Expression power(int n){ Expression ret(Mocular(11)),a(*this); if(n==0)return ret; while(n){ if(n&1)ret=ret*a; a=a*a; n>>=1; } return ret; } void print(){ for(auto &x: exp)x.print(); cout<<endl; } }; void init(){ for(int i=1;i<128;++i)sign[i]=LETTER; for(int i='0';i<='9';++i)sign[i]=NUMBER; sign['.']=NUMBER; sign[0]=sign['+']=sign['-']=sign['*']=sign['/']=sign['^']=sign['(']=sign[')']=OPERATOR; prio['+']=prio['-']=1; prio['*']=prio['/']=2; prio['^']=3; } bool format(string &s,vector<int> &v){ string tps,rts; v.clear(); //formating s to a standard expression as well as detecting all errors if(sign[s[0]]==OPERATOR){ switch(s[0]){ case '+':s.erase(s.begin());break; case '-':s.insert(s.begin(),'0');break; case '*':case '/':case '^':case ')':return false; default:break; } } for(int i=0,n_b=0;i<s.size();){ switch(sign[s[i]]){ case NUMBER: if(rts.size()&&rts.back()==')')return false; for(;sign[s[i]]==NUMBER;++i)rts+=s[i]; break; case LETTER: if(rts.size()&&rts.back()==')')return false; if(rts.size()&&sign[rts.back()]==NUMBER)rts+='*'; tps.clear(); if(s[i]=='['){ for(;i<s.size();++i){ rts+=s[i],tps+=s[i]; if(s[i]==']')break; } if(i==(int)s.size())return false; else i++; }else for(;sign[s[i]]!=OPERATOR;++i)rts+=s[i],tps+=s[i]; parameters.emplace_back(tps); break; case OPERATOR: if(s[i]=='(')n_b++; else if(s[i]==')')n_b--; if(n_b<0)return false; if(sign[rts.back()]==OPERATOR){ switch(s[i]){ case '+':case '-': if(rts.back()!='('&&rts.back()!=')')return false; if(rts.back()=='(')rts+='0'; break; case '*':case '/':case '^':if(rts.back()!=')')return false;break; case '(':if(rts.back()==')')rts+='*';break; case ')': if(rts.back()=='(')rts.pop_back(); else if(rts.back()!=')')return false; break; } }else if(s[i]=='(')rts+='*'; rts+=s[i++]; break; } } if(sign[rts.back()]==OPERATOR&&rts.back()!=')')return false; s=rts; //prepare parameters sort(parameters.begin(),parameters.end()); n_para=unique(parameters.begin(),parameters.end())-parameters.begin(); parameters.resize(n_para); //to code for(int i=0,n;i<s.size();){ switch(sign[s[i]]){ case NUMBER: for(n=0;sign[s[i]]==NUMBER;++i) n=n*10+s[i]-'0'; v.push_back(n*10+NUMBER); break; case LETTER: tps.clear(); if(s[i]=='['){ for(;i<s.size();++i){ tps+=s[i]; if(s[i]==']')break; } i++; }else for(;sign[s[i]]!=OPERATOR;++i)tps+=s[i]; n=lower_bound(parameters.begin(),parameters.end(),tps)-parameters.begin(); v.push_back(n*10+LETTER); break; case OPERATOR: n=s[i++]; v.push_back(n*10+OPERATOR); break; } } return true; } void RPN(vector<int> &v){ vector<int> v1,v2; for(auto &x: v){ switch(x%10){ case NUMBER: case LETTER: v2.push_back(x); break; case OPERATOR: if(char(x/10)=='(')v1.push_back(x); else if(char(x/10)==')'){ while(char(v1.back()/10)!='('){ v2.push_back(v1.back()); v1.pop_back(); } v1.pop_back(); }else if(v1.empty())v1.push_back(x); else if(prio[v1.back()/10]<prio[x/10])v1.push_back(x); else{ while(!v1.empty()&&prio[v1.back()/10]>=prio[x/10]){ v2.push_back(v1.back()); v1.pop_back(); } v1.push_back(x); } break; } } while(!v1.empty()){ v2.push_back(v1.back()); v1.pop_back(); } v=v2; } void simplificate(vector<int> &v){ vector<Expression> v1; Expression t1,t2; for(auto &x: v){ switch(x%10){ case NUMBER: case LETTER: v1.emplace_back(Mocular(x)); break; case OPERATOR: t2=v1.back();v1.pop_back(); t1=v1.back();v1.pop_back(); switch(char(x/10)){ case '+':v1.push_back(t1+t2);break; case '-':v1.push_back(t1-t2);break; case '*':v1.push_back(t1*t2);break; case '/':v1.push_back(t1/t2);break; case '^':v1.push_back(t1.power(t2.exp[0].coef.first));break; } break; } } v1[0].print(); } void calculate(vector<int> &v,vector<double> ¶_list){ vector<double> v1; double t1,t2; for(auto &x: v){ switch(x%10){ case NUMBER: v1.emplace_back(double(x/10)); break; case LETTER: v1.emplace_back(para_list[x/10]); break; case OPERATOR: t2=v1.back();v1.pop_back(); t1=v1.back();v1.pop_back(); switch(char(x/10)){ case '+':v1.push_back(t1+t2);break; case '-':v1.push_back(t1-t2);break; case '*':v1.push_back(t1*t2);break; case '/':v1.push_back(t1/t2);break; case '^':v1.push_back(pow(t1,t2));break; } break; } } cout<<v1[0]<<endl; } char get_num_char(string &s){//for get_num() char _head=s[0]; if((_head>='0'&&_head<='9')||_head=='-'||_head=='+'||_head=='.'||_head=='e'||_head=='E'){ s.erase(s.begin()); return _head; }else return 0; } double get_num_double(string &s){ int figure=0,power=0,fixed=0,sig_figure=1,sig_power=1; bool power_mode=false,exist_error=false; char ch; double ret; while(ch=get_num_char(s)){ if(ch=='-'&&!power_mode)sig_figure=-1; else if(ch=='-'&&power_mode)sig_power=-1; else if(ch=='+'&&!power_mode)sig_power=1; else if(ch=='+'&&power_mode)sig_power=1; else if(ch>='0'&&ch<='9'&&!power_mode)figure=figure*10+ch-'0'; else if(ch>='0'&&ch<='9'&&power_mode)power=power*10+ch-'0'; else if(ch=='.'&&!power_mode&&fixed==0){ while(s[fixed]>='0'&&s[fixed]<='9')fixed++; }else if(tolower(ch)=='e'&&!power_mode&&power==0)power_mode=true; else{ exist_error=true; break; } } //return {sig_figure*figure,sig_power*power-fixed}; ret=sig_figure*figure; fixed=sig_power*power-fixed; while(fixed>0){ ret*=10; fixed--; } while(fixed<0){ ret/=10; fixed++; } return ret; } vector<double> tmp_para_list; void dfs_calculate(vector<int> &v,int n=0){ if(n==n_para){ cout<<"F("; for(int i=0;i<n_para;++i){ cout<<parameters[i]<<"="<<tmp_para_list[i]; if(i!=n_para-1)cout<<","; else cout<<") = "; } calculate(v,tmp_para_list); return; } for(auto x: para_list_all[n]){ tmp_para_list.push_back(x); dfs_calculate(v,n+1); tmp_para_list.pop_back(); } } int main(){ ios::sync_with_stdio(0); string s; double _from,_to,_step; vector<int> v; init(); cout<<"FBI Warning : power should be positive integer, denominator should be as simple as possible, or simplification may not be correct\n"; while(cin>>s){ parameters.clear(); n_para=0; if(format(s,v)){ cout<<"| Your input: "<<s<<endl<<"| Parameters:\n"; for(int i=0;i<n_para;++i)cout<<"| "<<i<<" - "<<parameters[i]<<endl; //cout<<"| Tansformed code: "; //for(auto &x: v)cout<<x<<" ";cout<<endl; RPN(v); //cout<<"| RPN Code: "; //for(auto &x: v)cout<<x<<" ";cout<<endl; simplificate(v); cout<<"| "; for(auto &x: parameters)cout<<x<<" ";cout<<endl; for(int i=0;i<n_para;++i){ para_list_all[i].clear(); cin>>s; if(s[0]>='0'&&s[0]<='9')para_list_all[i].push_back(get_num_double(s)); else if(s[0]=='{'){ s.erase(s.begin()); while(_from=get_num_double(s)){ para_list_all[i].push_back(_from); if(s[0]=='}')break; else s.erase(s.begin()); } }else if(s[0]=='['){ s.erase(s.begin()); _from=get_num_double(s); s.erase(s.begin()); _to=get_num_double(s); s.erase(s.begin()); _step=get_num_double(s); for(;_from<_to+1e-7;_from+=_step)para_list_all[i].push_back(_from); } } //for(auto x: para_list_all[0])cout<<x<<" ";cout<<endl; tmp_para_list.clear(); dfs_calculate(v); } else cout<<"error\n"; cout<<endl; } return 0; }