いろいろがんばりたいブログ

情報科学科の人がいろいろ書きます。

AOJ 2255 6/2(1+2)

方針は、演算子でまず区切って、区切ったLHSとRHSを再帰的に区切っていく。 eagletmtさんの方針とほぼ同じで、詳しくかかれていたのでそちらを参照のこと。

http://eagletmt.github.io/contests/blog/aoj-2255/

#include <iostream>
#include <vector>
#include <set>
#include <numeric>
#include <algorithm>
#include <cctype>
#include <string>
#include <sstream>

using namespace std;

// for debug.
template<class T>
ostream& operator<<(ostream& os,const vector<T>& vec){
    for(int i=0;i<vec.size();i++){
        os << vec[i];
        if(i != vec.size()-1) os << " ";
    }
    return os;
}

int to_int(string s){
    stringstream ss;
    ss << s;
    int ret;
    ss >> ret;
    return ret;
}

set<int> eval(const string& str){
    vector<string> terms;
    vector<char> ops;
    for(size_t i=0;i<str.size();i++){
        if(isdigit(str[i])){
            string num = "";
            for(;i<str.size() and isdigit(str[i]);i++){
                num += str[i];
            }
            i--;
            terms.push_back(num);
        }else if(str[i] == '('){
            int p = 0;
            int  from = i,to = -1;
            for(;i<str.size();i++){
                if(str[i] == '('){
                    p++;
                }else if(str[i] == ')'){
                    if(p == 1){
                        to = i;
                        break;
                    }
                    p--;
                }
            }
            terms.push_back(str.substr(from,to-from+1));
        }else{
            ops.push_back(str[i]);
        }
    }
    //cerr << "terms:" << terms << endl;
    //cerr << "ops:" << ops << endl;
    set<int> ret;
    if(terms.size() == 1){
        string now = terms[0];
        if(now[0] == '('){
            ret = eval(now.substr(1,now.size()-2));
        }else{
            ret.insert(to_int(now));
        }
        return ret;
    }else{
        // look
        for(size_t i=0;i<ops.size();i++){
            string lhs,rhs;
            for(size_t j=0;j<ops.size();j++){
                if(i >= j){
                    lhs += terms[j];
                    if(i != j){
                        lhs += ops[j];
                    }
                }else{
                    rhs += terms[j];
                    rhs += ops[j];
                }
            }
            rhs += terms.back();
            //cerr << "lhs:" << lhs << endl;
            //cerr << "rhs:" << rhs << endl;
            set<int> le = eval(lhs);
            set<int> re = eval(rhs);
            for(set<int>::iterator lit=le.begin();lit!=le.end();++lit){
                for(set<int>::iterator rit=re.begin();rit!=re.end();++rit){
                    if(ops[i] == '+'){
                        ret.insert(*lit + *rit);
                    }else if(ops[i] == '-'){
                        ret.insert(*lit - *rit);
                    }else if(ops[i] == '*'){
                        ret.insert(*lit * *rit);
                    }else if(ops[i] == '/'){
                        if(*rit == 0) continue;
                        ret.insert(*lit / *rit);
                    }
                }
            }
        }
        return ret;
    }
}

int main(){
    while(true){
        string s;
        cin >> s;
        if(s == "#") break;
        set<int> ret = eval(s);
        cout << ret.size() << endl;
    }
    return 0;
}