Official

F - インタプリタをつくろう/Simple Interpreter Editorial by MMNMM


式 \(S\) をそれぞれの項に分けて、それらが表す値を合計する方針でこの問題を解くことができます。

例えば \(S={}\)2+a-7 \(\ (a=18)\) のとき、2, +a,-7 の値はそれぞれ \(2,18,-7\) です。 それぞれの値は例えば次のような手順で求めることができます。

  • 符号を除いた値を求める
    • 数字ならばそのままの値、変数なら入力で与えられた対応する値を求める
  • 符号を確認し、必要ならば \(-1\) 倍する

実装の際は、\(S\) の先頭に + を追加したり、文字 0\(,\) 1\(,\ldots,\) 9 の値 \(0,1,\ldots,9\) を英小文字の変数と同じ形式で保存したりなどの前処理を行うとより場合分けが少なくシンプルになります。

#include <string>
#include <iostream>
#include <map>

int main() {
    std::string S;
    std::cin >> S;
    // 先頭に + を追加しておくことで項を 2 文字ごとで取れる
    S = '+' + S;
    
    unsigned N;
    std::cin >> N;
    
    std::map<char, int> values; // 変数 → 値の対応
    // 数字に対応する値も入れておく
    for(unsigned i = 0; i < 10; ++i)
        values['0' + i] = i;
    
    for(unsigned i = 0; i < N; ++i){
        char c;
        int v;
        std::cin >> c >> v;
        values[c] = v; // 変数 c の値は v
    }
    
    int ans = 0;
    for(unsigned i = 0; i < size(S); i += 2){ // 2 文字ごとに見る
        if(S[i] == '+') // 符号が + なら
            ans += values[S[i + 1]]; // 変数の値を足す
        else // 符号が - なら
            ans -= values[S[i + 1]]; // 変数の値を引く
    }
    
    std::cout << ans << std::endl;
    
    return 0;
}

少し裏技的ですが、Python などの eval 関数を使うこともできます。

S = input()

N = int(input())

for _ in range(N):
    exec(input().replace(' ', '=')) # 変数に代入して

print(eval(S)) # 計算

posted:
last update: