AOJ2613 Unordered Operators

2015/06/21 (Sun) AOJ 構文解析

問題

問題文

方針

$3$ つの演算子を $a,b,c$ とすると,優先順位は以下の 4 通りしかない. これら全てのパーサを実装する.

  • $a > b > c$
  • $a = b > c$
  • $a > b = c$
  • $a = b = c$

もっと頭のいい実装方法もあります.

実装

#include <bits/stdc++.h>
using namespace std;
 
#define loop(i,a,b) for(int i=(a);i<int(b);i++)
#define rep(i,b) loop(i,0,b)
#define CR const &
 
typedef long long Val;
 
Val operate(Val a, Val b, char r){
    if(r != '+' && r != '-' && r != '*'){
        printf(" %c\n",r);
        assert(false);
    }
    return r=='+' ? a+b : r=='-' ? a-b : a*b;
}
 
namespace AAA {
    pair<Val,int> A(int pos, const char * s);
    pair<Val,int> B(int pos, const char * s);
    pair<Val,int> A(int pos, const char * s){
        Val res;
        tie(res,pos) = B(pos,s);
        while(s[pos] && (s[pos] == '+' || s[pos] == '-' || s[pos] == '*')){
            char op = s[pos];
            pos++;
            Val rhs;
            tie(rhs,pos) = B(pos,s);
            res = operate(res,rhs,op);
        }
        return make_pair(res,pos);
    }
    pair<Val,int> B(int pos, const char * s){
        if(s[pos] == '('){
            pos++;
            pair<Val,int> res = A(pos,s);
            res.second++;
            return res;
        }
        if(isdigit(s[pos])){
            Val res = 0;
            while(isdigit(s[pos])){
                res = res*10 + s[pos++]-'0';
            }
            return make_pair(res,pos);
        }
        printf(" %d %s %c\n", pos, s, s[pos]);
        assert(false);
    }
}
 
namespace AAB {
    char a1,a2,b;
    pair<Val,int> A(int pos, const char * s);
    pair<Val,int> B(int pos, const char * s);
    pair<Val,int> C(int pos, const char * s);
    pair<Val,int> A(int pos, const char * s){
        Val res;
        tie(res,pos) = B(pos,s);
        while(s[pos] && (s[pos] == a1 || s[pos] == a2)){
            char op = s[pos];
            pos++;
            Val rhs;
            tie(rhs,pos) = B(pos,s);
            res = operate(res,rhs,op);
        }
        return make_pair(res,pos);
    }
    pair<Val,int> B(int pos, const char * s){
        Val res;
        tie(res,pos) = C(pos,s);
        while(s[pos] && s[pos] == b){
            char op = s[pos];
            pos++;
            Val rhs;
            tie(rhs,pos) = C(pos,s);
            res = operate(res,rhs,op);
        }
        return make_pair(res,pos);
    }
    pair<Val,int> C(int pos, const char * s){
        if(s[pos] == '('){
            pair<Val,int> res = A(pos+1,s);
            res.second++;
            return res;
        }
        if(isdigit(s[pos])){
            Val res = 0;
            while(isdigit(s[pos])){
                res = res*10 + s[pos++]-'0';
            }
            return make_pair(res,pos);
        }
        assert(false);
    }
}
 
namespace ABB {
    char a,b1,b2;
    pair<Val,int> A(int pos, const char * s);
    pair<Val,int> B(int pos, const char * s);
    pair<Val,int> C(int pos, const char * s);
    pair<Val,int> A(int pos, const char * s){
        Val res;
        tie(res,pos) = B(pos,s);
        while(s[pos] && s[pos] == a){
            char op = s[pos];
            pos++;
            Val rhs;
            tie(rhs,pos) = B(pos,s);
            res = operate(res,rhs,op);
        }
        return make_pair(res,pos);
    }
    pair<Val,int> B(int pos, const char * s){
        Val res;
        tie(res,pos) = C(pos,s);
        while(s[pos] && (s[pos] == b1 || s[pos] == b2)){
            char op = s[pos];
            pos++;
            Val rhs;
            tie(rhs,pos) = C(pos,s);
            res = operate(res,rhs,op);
        }
        return make_pair(res,pos);
    }
    pair<Val,int> C(int pos, const char * s){
        if(s[pos] == '('){
            pair<Val,int> res = A(pos+1,s);
            res.second++;
            return res;
        }
        if(isdigit(s[pos])){
            Val res = 0;
            while(isdigit(s[pos])){
                res = res*10 + s[pos++]-'0';
            }
            return make_pair(res,pos);
        }
        assert(false);
    }
}
 
namespace ABC {
    char a,b,c;
    pair<Val,int> A(int pos, const char * s);
    pair<Val,int> B(int pos, const char * s);
    pair<Val,int> C(int pos, const char * s);
    pair<Val,int> D(int pos, const char * s);
    pair<Val,int> A(int pos, const char * s){
        Val res;
        tie(res,pos) = B(pos,s);
        while(s[pos] && s[pos] == a){
            char op = s[pos];
            pos++;
            Val ths;
            tie(ths,pos) = B(pos,s);
            res = operate(res,ths,op);
        }
        return make_pair(res,pos);
    }
    pair<Val,int> B(int pos, const char * s){
        Val res;
        tie(res,pos) = C(pos,s);
        while(s[pos] && s[pos] == b){
            char op = s[pos];
            pos++;
            Val rhs;
            tie(rhs,pos) = C(pos,s);
            res = operate(res,rhs,op);
        }
        return make_pair(res,pos);
    }
    pair<Val,int> C(int pos, const char * s){
        Val res;
        tie(res,pos) = D(pos,s);
        while(s[pos] && s[pos] == c){
            char op = s[pos];
            pos++;
            Val rhs;
            tie(rhs,pos) = D(pos,s);
            res = operate(res,rhs,op);
        }
        return make_pair(res,pos);
    }
    pair<Val,int> D(int pos, const char * s){
        if(s[pos] == '('){
            pair<Val,int> res = A(pos+1,s);
            res.second++;
            return res;
        }
        if(isdigit(s[pos])){
            Val res = 0;
            while(isdigit(s[pos])){
                res = res*10 + s[pos++]-'0';
            }
            return make_pair(res,pos);
        }
        assert(false);
    }
}
 
int main(){
    string s;
    while(cin >> s){
        Val ans = numeric_limits<Val>::min();
        char op[] = "+-*";
        sort(op,op+3);
        do {
            AAB::a1 = ABB::a  = ABC::a = op[0];
            AAB::a2 = ABB::b1 = ABC::b = op[1];
            AAB::b  = ABB::b2 = ABC::c = op[2];
            ans = max(ans, AAA::A(0,s.c_str()).first);
            ans = max(ans, AAB::A(0,s.c_str()).first);
            ans = max(ans, ABB::A(0,s.c_str()).first);
            ans = max(ans, ABC::A(0,s.c_str()).first);
        }while(next_permutation(op,op+3));
        cout << ans << endl;
    }
}