OR4. S-expression
描述
S-expression is a prefix notation invented for and popularized by the programming language Lisp. Your task is to evaluate some simple S-expressions.输入描述
The first line contains an integer T (1 <= T <= 100), the number of testcases.输出描述
For each testcase output the value of the S-expression or one of the three errors "Division By Zero", "Type Mismatch" and "Unbound Identifier" without quotes.示例1
输入:
2 ( + ( - 3 2 ) ( * 4 5 ) ) ( let ( x 4 ) ( if true x y ) )
输出:
21 4
C++ 解法, 执行用时: 1ms, 内存消耗: 364KB, 提交时间: 2017-07-01
#include<iostream> #include<string> #include<vector> #include<map> #include<set> #include<algorithm> #include<stack> #include<sstream> using namespace std; struct s_expression{ int kind; //kind=1:整数;kind=2:bool型;kind=3:异常 int value; //(bool:false(1);true(2)) (异常:Unbound Identifier(1);Type Mismatch(2);Division By Zero(3)) s_expression(int cur_kind,int cur_value):kind(cur_kind),value(cur_value){} s_expression():kind(1),value(0){} void set(int cur_kind,int cur_value){kind=cur_kind,value=cur_value;} }; map<string,s_expression> vari; void delete_part(stringstream &ss) { string temp; ss>>temp; if(temp=="(") { int left=1,right=0; while(left>right) { string temp; ss>>temp; if(temp=="(") left++; else if(temp==")") right++; } } } s_expression singlepart(stringstream &ss) { string temp; ss>>temp; if(temp!="("){ if(temp>="0"&&temp<="9") return s_expression(1,stoi(temp)); else if(temp=="true") return s_expression(2,2); else if(temp=="false") return s_expression(2,1); else { if(vari.find(temp)==vari.end()) return s_expression(3,1); //Unbound Identifier else return vari[temp]; } } else{ ss>>temp; if(temp=="+"||temp=="-"||temp=="*"||temp=="/"||temp==">"||temp=="<"||temp=="=") { s_expression left=singlepart(ss),right=singlepart(ss),res; if(left.kind==2) res.set(3,2); //Type Mismatch else if (left.kind==3) res=left; else if(right.kind==2) res.set(3,2); //Type Mismatch else if (right.kind==3) res=right; else if(temp=="+") res.set(1,left.value+right.value); else if(temp=="-") res.set(1,left.value-right.value); else if(temp=="*") res.set(1,left.value*right.value); else if(temp=="/") { if(right.value==0) res.set(3,3); //Division By Zero else res.set(1,left.value/right.value); } else if(temp==">") res.set(2,(left.value>right.value)+1); else if(temp=="<") res.set(2,(left.value<right.value)+1); else res.set(2,(left.value==right.value)+1); ss>>temp; return res; } else if(temp=="if") { s_expression res,a_temp=singlepart(ss); if(a_temp.kind==2&&a_temp.value==2){ res=singlepart(ss); delete_part(ss); } else if(a_temp.kind==2&&a_temp.value==1){ delete_part(ss); res=singlepart(ss); } else if(a_temp.kind==1) res.set(3,2); //Type Mismatch else res=a_temp; ss>>temp; return res; } else { string temp1; s_expression res,last_value; ss>>temp; ss>>temp1; bool flag=false; if(vari.find(temp1)!=vari.end()) { flag=true; last_value=vari[temp1]; vari.erase(temp1); } vari.insert(pair<string,s_expression>(temp1,singlepart(ss))); ss>>temp; res=singlepart(ss); vari.erase(temp1); if(flag!=false) vari.insert(pair<string,s_expression>(temp1,last_value)); ss>>temp; return res; } } } int main() { int sum; cin>>sum; cin.ignore(numeric_limits<streamsize>::max(),'\n'); for(int z=0;z!=sum;z++) { vari.clear(); stringstream ss; string input; getline(cin,input); ss<<input; s_expression flag=singlepart(ss); if(flag.kind==1) cout<<flag.value<<endl; else if(flag.kind==2&&flag.value==2) cout<<"true"<<endl; else if(flag.kind==2&&flag.value==1) cout<<"false"<<endl; else if(flag.kind==3&&flag.value==1) cout<<"Unbound Identifier"<<endl; else if(flag.kind==3&&flag.value==2) cout<<"Type Mismatch"<<endl; else cout<<"Division By Zero"<<endl; } return 0; }
C++ 解法, 执行用时: 1ms, 内存消耗: 364KB, 提交时间: 2017-06-30
#include<iostream> #include<string> #include<vector> #include<stack> using namespace std; struct result { int error;//0 noerror 1 typemistach 2 nobound 3 divide error int type;//0 int 1 bool int val; }; struct variable { string name; int type; int val; }; class solution { public: result s_expressions(string& s,int& index, vector<variable> var) { if (index >= s.size()) return result(); while (index<s.size()&&(s[index] == ' ' || s[index] == '(' || s[index] == ')')) ++index; if (s[index] == '+'|| s[index] == '-'|| s[index] == '*'|| s[index] == '/') {// + x y char p = s[index]; ++index; auto x = s_expressions(s, index,var); if (x.error != 0) return x; auto y = s_expressions(s, index,var); if (y.error != 0) return y; if (x.type == 1) {x.error = 1; return x;} if (y.type == 1) { y.error = 1; return y; } result res; res.error = 0; res.type = 0; if (p == '+') res.val = x.val + y.val; else if (p == '-') res.val = x.val - y.val; else if (p == '*') res.val = x.val * y.val; else { if (y.val == 0) { res.error = 3; return res; } res.val = x.val / y.val; } return res; } if (s[index] == '<' || s[index] == '>' || s[index] == '=') { char p = s[index]; ++index; auto x = s_expressions(s, index,var); if (x.error != 0) return x; if (x.type != 0) { x.error = 1; return x; } auto y = s_expressions(s, index,var); if (y.error != 0) return y; if (y.type != 0) { y.error = 1; return y; } result res; res.error = 0; res.type = 1; if (p == '<') res.val = (x.val < y.val); else if(p == '>') res.val = (x.val > y.val); else res.val = (x.val == y.val); return res; } if (s[index] <= '9'&&s[index] >= '0') { result res; res.error = 0; res.type = 0; res.val = 0; while (s[index] <= '9'&&s[index] >= '0') { res.val = res.val * 10 + s[index] - '0'; ++index; } return res; } if (s[index]>='a'&&s[index]<='z') { pair<int, string> str = dealwithString(s,index); result res; if (str.first == 0 || str.first == 1) { res.error = 0; res.type = 1; if (str.second == "true") res.val = 1; else res.val = 0; return res; } else if (str.first == 2) { //let pair<int, string> str = dealwithString(s, index); auto value = s_expressions(s,index,var); if (value.error != 0) return value; auto ptr = findvar(var, str.second); variable tmp; tmp.name = str.second; tmp.type = value.type; tmp.val = value.val; if (ptr == var.end()) var.push_back(tmp); else *ptr = tmp; return s_expressions(s,index,var); } else if (str.first == 3) { //if auto flag = s_expressions(s,index,var); if (flag.error != 0) return flag; if (flag.type == 0) { flag.error = 1; return flag; } result res; if (flag.val) { res = s_expressions(s,index,var); nnoexec(s,index); } else { nnoexec(s, index); res = s_expressions(s, index,var); } return res; } else if (str.first == 4) { //var auto ptr = findvar(var,str.second); result res; if (ptr == var.end()) { res.error = 2; return res; } res.error = 0; res.type = ptr->type; res.val = ptr->val; return res; } } return result(); } vector<variable>::iterator findvar(vector<variable>& var,const string& v) { auto ptr = var.begin(); while (ptr!=var.end()) { if ((*ptr).name == v) return ptr; ++ptr; } return var.end(); } pair<int, string> dealwithString(string& s,int& index) { while (s[index] == ' ' || s[index] == '(' || s[index] == ')') ++index; int bec = index; while (s[index] <= 'z'&&s[index] >= 'a') ++index; string res = s.substr(bec,index-bec); if (res == "true") return make_pair(0,res); if(res=="false") return make_pair(1, res); if (res == "let") return make_pair(2,res); if (res == "if") return make_pair(3,res); return make_pair(4,res); } void nnoexec(string& s,int& index) { while (s[index] == ' ' || s[index] == ')') ++index; if (s[index] == '(') { stack<char> tmp; tmp.push('('); while (!tmp.empty()) { ++index; if (s[index] == '(') tmp.push('('); else if (s[index] == ')') tmp.pop(); } ++index; } else { while ((s[index] <= '9'&&s[index] >= '0') || (s[index] <= 'z'&&s[index] >= 'a')) { ++index; if (index == s.size()) break; } } } }; int main() { int n = 0; char buf[210]; buf[0] = 0; cin >> n; getchar(); while (n!=0) { cin.getline(buf, 210); string s(buf); solution sl; int index = 0; auto res = sl.s_expressions(s, index, vector<variable>()); if (res.error == 0) { if (res.type == 0) cout << res.val << endl; else if (res.type == 1) { if (res.val == 1) cout << "true" << endl; else cout << "false" << endl; } } else if (res.error == 1) cout << "Type Mismatch" << endl; else if (res.error == 2) cout << "Unbound Identifier" << endl; else cout << "Division By Zero" << endl; --n; } }
C++ 解法, 执行用时: 1ms, 内存消耗: 368KB, 提交时间: 2017-10-16
#include <iostream> #include <string> #include <cstdio> #include <sstream> #include <cstdlib> #include <map> using namespace std; static const string ERROR[] = {"Division By Zero", "Type Mismatch", "Unbound Identifier"}; map<string, string> variable; bool is_atom(const string &exp) { if(exp != "(" && exp != ")" && exp.find(' ') == string::npos) return true; else return false; } bool get_atom(const string &exp, string &sval) { if(exp == "true" || exp == "false" || isdigit(exp[0])) sval = exp; else{ map<string, string>::iterator iter = variable.find(exp); if(iter == variable.end()) { cout<<ERROR[2]<<endl; return false; }else sval = iter->second; } return true; } void get_sub_exp(stringstream &sin, string &sub) { int left_c = 0; string s; sub = ""; do{ sin>>s; if(s == "(") ++left_c; else if(s == ")") --left_c; sub += " " + s; }while(left_c != 0); sub = sub.substr(1); } bool eval(const string &exp, string &sval) { if(is_atom(exp)) { return get_atom(exp, sval); }else{ stringstream sin(exp); string parenthsis, reversed; sin>>parenthsis>>reversed; string sub1, sub2, sval1, sval2; if(reversed == "let") { string x; sin>>parenthsis>>x, get_sub_exp(sin, sub1), sin>>parenthsis; get_sub_exp(sin, sub2); if(eval(sub1, sval1)) { variable[x] = sval1; if(eval(sub2, sval2)) { sval = sval2; return true; }else return false; }else return false; }else if(reversed == "if") { string cond, sbool; get_sub_exp(sin, cond); get_sub_exp(sin, sub1); get_sub_exp(sin, sub2); if(eval(cond, sbool)) { if(sbool == "true") return eval(sub1, sval); else if(sbool == "false") return eval(sub2, sval); else{ cout<<ERROR[1]<<endl; return false; } }else return false; }else{ char op = reversed[0]; get_sub_exp(sin, sub1); get_sub_exp(sin, sub2); int val1, val2; if(eval(sub1, sval1) && eval(sub2, sval2)) { if(isdigit(sval1[0]) && isdigit(sval2[0])) { val1 = atoi(sval1.c_str()); val2 = atoi(sval2.c_str()); }else{ cout<<ERROR[1]<<endl; return false; } }else return false; char str[20]; switch(op) { case '+': sprintf(str, "%d", val1+val2); sval = string(str); break; case '-': sprintf(str, "%d", val1-val2); sval = string(str); break; case '*': sprintf(str, "%d", val1*val2); sval = string(str); break; case '/': if(val2 == 0) { cout<<ERROR[0]<<endl; return false; } sprintf(str, "%d", val1/val2); sval = string(str); break; case '>': if(val1 > val2) sval = "true"; else sval = "false"; break; case '<': if(val1 < val2) sval = "true"; else sval = "false"; break; case '=': if(val1 == val2) sval = "true"; else sval = "false"; break; } } sin>>parenthsis; return true; } } int main() { int T; string s_exp; cin>>T, getline(cin, s_exp); while(T--) { getline(cin, s_exp); string sval; if(eval(s_exp, sval)) cout<<sval<<endl; } return 0; }
C++ 解法, 执行用时: 1ms, 内存消耗: 368KB, 提交时间: 2017-07-19
#include <iostream> #include <string> #include <vector> #include <utility> #include <map> using namespace std; void goo() { string s; vector<string> stk; for(;;) { cin >> s; if(s=="(") stk.push_back(s); else if(s==")") { stk.pop_back(); if(stk.empty()) return; } else if(stk.empty()) { if(s[0]>='0'&&s[0]<='9') { return ; } else if(s=="true" || s=="false") { return ; } else if(s!="if"&&s!="let") { return; } } } return ; } map<string,vector<pair<int,string> > > vars; pair<int,string> go() { string s; vector<string> stk; pair<int,string> res; for(;;) { cin >> s; // cout <<"debug: " << s << endl; if(s=="(") stk.push_back(s); else if(s==")") { stk.pop_back(); // cout << "rt: " << res.first << " " << res.second << endl; return res; } else { if(s[0]>='0'&&s[0]<='9') { return make_pair(atoi(s.c_str()),"N"); } else if(s=="true" || s=="false") { return make_pair(0,"B"+s); } else if(s=="+") { pair<int,string> a,b; a = go(); if(a.second[0]=='E') return a; if(a.second[0]!='N') return make_pair(0,"EType Mismatch"); b = go(); if(b.second[0]=='E') return b; if(b.second[0]!='N') return make_pair(0,"EType Mismatch"); res = make_pair(a.first + b.first, "N"); } else if(s=="-") { pair<int,string> a,b; a = go(); if(a.second[0]=='E') return a; if(a.second[0]!='N') return make_pair(0,"EType Mismatch"); b = go(); if(b.second[0]=='E') return b; if(b.second[0]!='N') return make_pair(0,"EType Mismatch"); res = make_pair(a.first - b.first, "N"); } else if(s=="*") { pair<int,string> a,b; a = go(); if(a.second[0]=='E') return a; if(a.second[0]!='N') return make_pair(0,"EType Mismatch"); b = go(); if(b.second[0]=='E') return b; if(b.second[0]!='N') return make_pair(0,"EType Mismatch"); res = make_pair(a.first * b.first, "N"); } else if(s=="/") { pair<int,string> a,b; a = go(); if(a.second[0]=='E') return a; if(a.second[0]!='N') return make_pair(0,"EType Mismatch"); b = go(); if(b.second[0]=='E') return b; if(b.second[0]!='N') return make_pair(0,"EType Mismatch"); if(b.first==0) return make_pair(0,"EDivision By Zero"); res = make_pair(a.first / b.first, "N"); } else if(s=="if") { pair<int,string> a,b,c; a = go(); if(a.second[0]=='E') return a; // cout << "ifa: " << a.first << " " << a.second << endl; if(a.second[0]!='B') return make_pair(0,"EType Mismatch"); if(a.second[1]=='t') { b = go(); if(b.second[0]=='E') return b; // cout << "ifb: " << b.first << " " << b.second << endl; goo(); res = b; } else { goo(); b = go(); if(b.second[0]=='E') return b; // cout << "ifc: " << b.first << " " << b.second << endl; res = b; } } else if(s=="let") { string tmp; cin >> tmp; // ( string var; cin >> var; pair<int,string> a,b; a = go(); if(a.second[0]=='E') return a; cin >> tmp; // ) // cout << "let:" << var << "=" << a.first << " " << a.second << endl; vars[var].push_back(a); b = go(); if(b.second[0]=='E') return b; vars[var].pop_back(); res = b; } else if(s=="<") { pair<int,string> a,b; a = go(); if(a.second[0]=='E') return a; if(a.second[0]!='N') return make_pair(0,"EType Mismatch"); b = go(); if(b.second[0]=='E') return b; if(b.second[0]!='N') return make_pair(0,"EType Mismatch"); if(a.first<b.first) res = make_pair(0,"Btrue"); else res = make_pair(0,"Bfalse"); } else if(s==">") { pair<int,string> a,b; a = go(); if(a.second[0]=='E') return a; if(a.second[0]!='N') return make_pair(0,"EType Mismatch"); b = go(); if(b.second[0]=='E') return b; if(b.second[0]!='N') return make_pair(0,"EType Mismatch"); if(a.first>b.first) res = make_pair(0,"Btrue"); else res = make_pair(0,"Bfalse"); } else if(s=="=") { pair<int,string> a,b; a = go(); if(a.second[0]=='E') return a; if(a.second[0]!='N') return make_pair(0,"EType Mismatch"); b = go(); if(b.second[0]=='E') return b; if(b.second[0]!='N') return make_pair(0,"EType Mismatch"); if(a.first==b.first) res = make_pair(0,"Btrue"); else res = make_pair(0,"Bfalse"); } else { if(vars[s].empty()) return make_pair(0,"EUnbound Identifier"); return vars[s].back(); } } } return make_pair(0,"Eerror"); } void S_expressions() { pair<int,string> r = go(); string s; if(r.second[0]=='E') getline(cin,s); if(r.second[0]!='N') cout << r.second.substr(1) << endl; else cout << r.first << endl; } int main() { ios::sync_with_stdio(false); cin.tie(0); int T; cin >> T; for(;T--;) { S_expressions(); } return 0; }
C++ 解法, 执行用时: 2ms, 内存消耗: 344KB, 提交时间: 2020-10-31
#include <iostream> #include <string> #include <cstdio> #include <sstream> #include <cstdlib> #include <map> using namespace std; static const string ERROR[] = {"Division By Zero", "Type Mismatch", "Unbound Identifier"}; map<string, string> variable; bool is_atom(const string &exp) { if(exp != "(" && exp != ")" && exp.find(' ') == string::npos) return true; else return false; } bool get_atom(const string &exp, string &sval) { if(exp == "true" || exp == "false" || isdigit(exp[0])) sval = exp; else{ map<string, string>::iterator iter = variable.find(exp); if(iter == variable.end()) { cout<<ERROR[2]<<endl; return false; }else sval = iter->second; } return true; } void get_sub_exp(stringstream &sin, string &sub) { int left_c = 0; string s; sub = ""; do{ sin>>s; if(s == "(") ++left_c; else if(s == ")") --left_c; sub += " " + s; }while(left_c != 0); sub = sub.substr(1); } bool eval(const string &exp, string &sval) { if(is_atom(exp)) { return get_atom(exp, sval); }else{ stringstream sin(exp); string parenthsis, reversed; sin>>parenthsis>>reversed; string sub1, sub2, sval1, sval2; if(reversed == "let") { string x; sin>>parenthsis>>x, get_sub_exp(sin, sub1), sin>>parenthsis; get_sub_exp(sin, sub2); if(eval(sub1, sval1)) { variable[x] = sval1; if(eval(sub2, sval2)) { sval = sval2; return true; }else return false; }else return false; }else if(reversed == "if") { string cond, sbool; get_sub_exp(sin, cond); get_sub_exp(sin, sub1); get_sub_exp(sin, sub2); if(eval(cond, sbool)) { if(sbool == "true") return eval(sub1, sval); else if(sbool == "false") return eval(sub2, sval); else{ cout<<ERROR[1]<<endl; return false; } }else return false; }else{ char op = reversed[0]; get_sub_exp(sin, sub1); get_sub_exp(sin, sub2); int val1, val2; if(eval(sub1, sval1) && eval(sub2, sval2)) { if(isdigit(sval1[0]) && isdigit(sval2[0])) { val1 = atoi(sval1.c_str()); val2 = atoi(sval2.c_str()); }else{ cout<<ERROR[1]<<endl; return false; } }else return false; char str[20]; switch(op) { case '+': sprintf(str, "%d", val1+val2); sval = string(str); break; case '-': sprintf(str, "%d", val1-val2); sval = string(str); break; case '*': sprintf(str, "%d", val1*val2); sval = string(str); break; case '/': if(val2 == 0) { cout<<ERROR[0]<<endl; return false; } sprintf(str, "%d", val1/val2); sval = string(str); break; case '>': if(val1 > val2) sval = "true"; else sval = "false"; break; case '<': if(val1 < val2) sval = "true"; else sval = "false"; break; case '=': if(val1 == val2) sval = "true"; else sval = "false"; break; } } sin>>parenthsis; return true; } } int main() { int T; string s_exp; cin>>T, getline(cin, s_exp); while(T--) { getline(cin, s_exp); string sval; if(eval(s_exp, sval)) cout<<sval<<endl; } return 0; }