Problem:
Equation
恒等式
English text is not available in this practice contest.
論理演算では，値は T と F の2種類だけを扱う．
"-"を単項演算子（入力が 1 つの演算を表す記号），
"*", "+", "->" を 2 項演算子（入力が 2 つの演算を表す記号）とする．
"-" は論理否定(NOT)，
"*" は論理積(AND)，
"+" は論理和(OR)，
"->" は論理包含(IMP)を表す演算子である．
これらの論理演算の真理値表を下の表に示す．
x
y
-x
(x*y)
(x+y)
(x->y)
T
T
F
T
T
T
T
F
F
F
T
F
F
T
T
F
T
T
F
F
T
F
F
T
論理式は以下のいずれかの形式である．
X, Yは論理式とし， 2 項演算子は必ず括弧で囲むものとする．
定数: T, F
変数: a, b, c, d, e, f, g, h, i, j, k
論理否定: -X
論理積: (X*Y)
論理和: (X+Y)
論理包含: (X->Y)
2 つの論理式を等号 "=" で結合した等式が与えられる．
恒等式とは，式に現れる変数がどのような値であっても成立する等式のことである．
与えられた等式が恒等式であるかを判定するプログラムを作りたい．
Input
入力は複数の行で構成され，各行は 1 つのデータセットである．
データセットはT, F, a, b, c, d, e, f, g, h, i, j, k, (, ), =, -, +, *, > から成る文字列であり， 空白など他の文字を含まない．
1 行の文字数は 1000 文字以下と仮定してよい．
1 つのデータセットは等式ひとつを含む．
等式の文法は次の BNF で与えられる．
すべての等式はこの構文規則に従う．
<equation> ::= <formula> "=" <formula>
<formula>  ::= "T" | "F" |
"a" | "b" | "c" | "d" | "e" | "f" |
"g" | "h" | "i" | "j" | "k" |
"-" <formula> |
"(" <formula> "*" <formula> ")" |
"(" <formula> "+" <formula> ")" |
"(" <formula> "->" <formula> ")"
入力の終わりは "#" だけからなる行で示されており，この行はデータセットではない．
Output
各データセットについて，等式が恒等式であれば“YES”を， そうでなければ“NO”をそれぞれ1行に出力しなさい． 出力には余分な文字を含んではならない．
Sample Input
-(a+b)=(-a*-b)
(a->b)=(-a+b)
((a*T)+b)=(-c+(a*-b))
#
Output for Sample Input
YES
YES
NO

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/tag_and_trait.hpp>
using namespace std;
using namespace __gnu_pbds;


struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
    
    size_t operator()(int x) const {
        return splitmix64(x);
    }
    
    size_t operator()(const string& x) const {
        uint64_t hash = 0;
        for (char c : x) {
            hash = hash * 31 + c;
        }
        return splitmix64(hash);
    }
    
    size_t operator()(const pair<int, int>& p) const {
        return splitmix64(((uint64_t)p.first << 32) | (uint64_t)p.second);
    }
};


template<typename T, typename S, typename Hash = custom_hash>
using hash_table = gp_hash_table<T, S, Hash>;
template<typename T, typename Hash = custom_hash>
using hash_set = gp_hash_table<T, null_type, Hash>;


class parser;


struct node {
    int symbol_id;
    string value;
    vector<node*> values;
    
private:
    const parser* parser_ptr;
    
public:
    node(int s, const parser* p = nullptr) : symbol_id(s), value(""), parser_ptr(p) {}
    node(int s, const string &v, const parser* p = nullptr) : symbol_id(s), value(v), parser_ptr(p) {}
    
    
    void set_parser(const parser* p) {
        parser_ptr = p;
        
        for (auto child : values) {
            if (child) {
                child->set_parser(p);
            }
        }
    }
    
    
    string get_token_name() const;
    
    
    void add_child(node* child) {
        if (child && parser_ptr) {
            child->set_parser(parser_ptr);
        }
        values.push_back(child);
    }
};


struct LRItem {
    int lhs;
    vector<int> rhs;
    int dot_pos;
    
    LRItem(int l, const vector<int> &r, int d) : lhs(l), rhs(r), dot_pos(d) {}
    
    bool operator==(const LRItem &other) const {
        return lhs == other.lhs && rhs == other.rhs && dot_pos == other.dot_pos;
    }
    
    int next_symbol() const {
        if (dot_pos < (int)rhs.size()) return rhs[dot_pos];
        return -1;
    }
    
    bool is_complete() const {
        return dot_pos >= (int)rhs.size();
    }
};


struct LRItemHash {
    size_t operator()(const LRItem &item) const {
        size_t h1 = custom_hash{}(item.lhs);
        size_t h2 = 0;
        for (int s : item.rhs) {
            h2 ^= custom_hash{}(s) + 0x9e3779b9 + (h2 << 6) + (h2 >> 2);
        }
        size_t h3 = custom_hash{}(item.dot_pos);
        return h1 ^ (h2 << 1) ^ (h3 << 2);
    }
};


enum class ActionType { SHIFT, REDUCE, ACCEPT, ERROR };

struct Action {
    ActionType type;
    int value;
    
    Action() : type(ActionType::ERROR), value(-1) {}
    Action(ActionType t, int v) : type(t), value(v) {}
    
    string to_string() const {
        switch (type) {
            case ActionType::SHIFT: return "SHIFT " + std::to_string(value);
            case ActionType::REDUCE: return "REDUCE " + std::to_string(value);
            case ActionType::ACCEPT: return "ACCEPT";
            case ActionType::ERROR: return "ERROR";
        }
        return "UNKNOWN";
    }
};


struct Production {
    int lhs;
    vector<int> rhs;
    
    Production(int l, const vector<int> &r) : lhs(l), rhs(r) {}
};

class parser {
private:
    
    vector<string> id_to_name;
    hash_table<string, int> name_to_id;
    
    
    vector<string> terminal_patterns;
    vector<int> terminal_order;
    hash_set<int> terminals;
    hash_set<int> nonterminals;
    vector<Production> productions;
    
    
    hash_table<int, hash_set<int>> first_sets;
    hash_table<int, hash_set<int>> follow_sets;
    
    
    vector<hash_set<LRItem, LRItemHash>> states;
    hash_table<pair<int, int>, Action> action_table;
    hash_table<pair<int, int>, int> goto_table;
    
    int start_symbol_id = -1;
    int augmented_start_id = -1;
    bool debug_mode = false;
    
    
    int get_or_create_symbol_id(const string &name) {
        auto it = name_to_id.find(name);
        if (it != name_to_id.end()) {
            return it->second;
        }
        int id = (int)id_to_name.size();
        id_to_name.push_back(name);
        name_to_id[name] = id;
        return id;
    }
    
    int get_or_create_symbol_id_const(const string &name) const {
        auto it = name_to_id.find(name);
        if (it != name_to_id.end()) {
            return it->second;
        }
        return -1;
    }
    
    
    int resolve_symbol_reference(int symbol_id) const {
        if (symbol_id == -1 || symbol_id >= (int)id_to_name.size()) return symbol_id;
        const string &name = id_to_name[symbol_id];
        if (name.length() > 0 && name[0] == '#') {
            string actual_name = name.substr(1);
            auto it = name_to_id.find(actual_name);
            if (it != name_to_id.end()) {
                return it->second;
            }
        }
        return symbol_id;
    }
    
    bool is_terminal_symbol(int symbol_id) const {
        int resolved_id = resolve_symbol_reference(symbol_id);
        if (resolved_id == -1) return false;
        return terminals.find(resolved_id) != terminals.end() && 
               nonterminals.find(resolved_id) == nonterminals.end();
    }
    
    bool is_nonterminal_symbol(int symbol_id) const {
        int resolved_id = resolve_symbol_reference(symbol_id);
        if (resolved_id == -1) return false;
        return nonterminals.find(resolved_id) != nonterminals.end();
    }
    
    
    string production_to_string(const Production &prod) const {
        string result = get_symbol_name(prod.lhs) + " ::= ";
        for (int symbol_id : prod.rhs) {
            int resolved_id = resolve_symbol_reference(symbol_id);
            result += get_symbol_name(resolved_id) + " ";
        }
        return result;
    }
    
    
    vector<string> split_by_semicolon(const string &text) {
        vector<string> rules;
        stringstream ss(text);
        string rule;
        
        while (getline(ss, rule, ';')) {
            rule.erase(0, rule.find_first_not_of(" \t\r\n"));
            rule.erase(rule.find_last_not_of(" \t\r\n") + 1);
            
            if (!rule.empty()) {
                rules.push_back(rule);
            }
        }
        
        return rules;
    }
    
    
    
void parse_bnf(const string &bnf_text) {
    regex terminal_pattern(R"(^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*?)\s*$)");
    regex production_pattern(R"(^\s*([A-Za-z_][A-Za-z0-9_]*)\s*::=\s*(.*?)\s*$)");
    
    vector<string> rules = split_by_semicolon(bnf_text);
    
    
    for (size_t rule_idx = 0; rule_idx < rules.size(); rule_idx++) {
        const string &rule = rules[rule_idx];
        check_bnf_warnings(rule, rule_idx + 1);
    }
    
    
    for (const string &rule : rules) {
        smatch match;
        if (regex_match(rule, match, terminal_pattern)) {
            string name = match[1].str();
            string pattern = match[2].str();
            
            int id = get_or_create_symbol_id(name);
            if ((int)terminal_patterns.size() <= id) {
                terminal_patterns.resize(id + 1);
            }
            terminal_patterns[id] = pattern;
            terminal_order.push_back(id);
            terminals.insert(id);
        }
    }
    
    
    for (const string &rule : rules) {
        smatch match;
        if (regex_match(rule, match, production_pattern)) {
            string lhs = match[1].str();
            string rhs_all = match[2].str();
            
            int lhs_id = get_or_create_symbol_id(lhs);
            nonterminals.insert(lhs_id);
            
            if (lhs == "START") {
                start_symbol_id = lhs_id;
            }
            
            istringstream rhs_stream(rhs_all);
            string rhs_part;
            while (getline(rhs_stream, rhs_part, '|')) {
                rhs_part.erase(0, rhs_part.find_first_not_of(" \t"));
                rhs_part.erase(rhs_part.find_last_not_of(" \t") + 1);
                
                if (!rhs_part.empty()) {
                    vector<int> rhs_ids;
                    istringstream symbol_stream(rhs_part);
                    string symbol;
                    while (symbol_stream >> symbol) {
                        int symbol_id = get_or_create_symbol_id(symbol);
                        rhs_ids.push_back(symbol_id);
                    }
                    productions.emplace_back(lhs_id, rhs_ids);
                    
                    
                    check_production_warnings(lhs, rhs_part, productions.size());
                }
            }
        }
    }
}

private:
    
    void check_bnf_warnings(const string &rule, int rule_number) {
        
        int equals_count = 0;
        int define_equals_count = 0;
        bool in_escape = false;
        
        for (size_t i = 0; i < rule.length(); i++) {
            char c = rule[i];
            
            if (in_escape) {
                in_escape = false;
                continue;
            }
            
            if (c == '\\') {
                in_escape = true;
                continue;
            }
            
            
            if (i + 2 < rule.length() && rule.substr(i, 3) == "::=") {
                define_equals_count++;
                i += 2; 
            } 
            
            else if (c == '=' && (i == 0 || rule[i-1] != ':') && (i + 1 >= rule.length() || rule[i+1] != '=')) {
                equals_count++;
            }
        }
    }
    
    
    void check_production_warnings(const string &lhs, const string &rhs, int production_number) {
        
        istringstream symbol_stream(rhs);
        string symbol;
        vector<string> symbols_without_hash;
        
        while (symbol_stream >> symbol) {
            if (!symbol.empty() && symbol[0] != '#') {
                
                symbols_without_hash.push_back(symbol);
            }
        }
    }
    
    
    bool contains_unescaped_hash(const string &text) {
        bool in_escape = false;
        
        for (size_t i = 0; i < text.length(); i++) {
            char c = text[i];
            
            if (in_escape) {
                in_escape = false;
                continue;
            }
            
            if (c == '\\') {
                in_escape = true;
                continue;
            }
            
            if (c == '#') {
                return true;
            }
        }
        
        return false;
    }
    
    
    void compute_first_sets() {
        
        for (int term_id : terminals) {
            first_sets[term_id].insert(term_id);
        }
        
        
        for (int nonterm_id : nonterminals) {
            first_sets[nonterm_id] = hash_set<int>();
        }
        
        bool changed = true;
        while (changed) {
            changed = false;
            
            for (const auto &prod : productions) {
                int lhs = prod.lhs;
                const auto &rhs = prod.rhs;
                
                hash_set<int> first_rhs = compute_first_of_sequence(rhs);
                
                for (int sym : first_rhs) {
                    if (first_sets[lhs].find(sym) == first_sets[lhs].end()) {
                        first_sets[lhs].insert(sym);
                        changed = true;
                    }
                }
            }
        }
    }
    
    
    hash_set<int> compute_first_of_sequence(const vector<int> &sequence) {
        hash_set<int> result;
        
        if (sequence.empty()) {
            result.insert(-1); 
            return result;
        }
        
        for (int i = 0; i < (int)sequence.size(); i++) {
            int symbol_id = sequence[i];
            int resolved_id = resolve_symbol_reference(symbol_id);
            
            if (is_terminal_symbol(symbol_id)) {
                result.insert(resolved_id);
                break;
            } else if (is_nonterminal_symbol(symbol_id)) {
                bool has_epsilon = false;
                for (int sym : first_sets[resolved_id]) {
                    if (sym == -1) {
                        has_epsilon = true;
                    } else {
                        result.insert(sym);
                    }
                }
                
                if (!has_epsilon) {
                    break;
                }
                
                if (i == (int)sequence.size() - 1) {
                    result.insert(-1); 
                }
            }
        }
        
        return result;
    }
    
    
    void compute_follow_sets() {
        int eof_id = get_or_create_symbol_id("$");
        follow_sets[start_symbol_id].insert(eof_id);
        
        bool changed = true;
        while (changed) {
            changed = false;
            
            for (const auto &prod : productions) {
                for (int i = 0; i < (int)prod.rhs.size(); i++) {
                    int symbol_id = prod.rhs[i];
                    int resolved_id = resolve_symbol_reference(symbol_id);
                    
                    if (is_nonterminal_symbol(symbol_id)) {
                        vector<int> beta(prod.rhs.begin() + i + 1, prod.rhs.end());
                        hash_set<int> first_beta = compute_first_of_sequence(beta);
                        
                        for (int sym : first_beta) {
                            if (sym != -1 && follow_sets[resolved_id].find(sym) == follow_sets[resolved_id].end()) {
                                follow_sets[resolved_id].insert(sym);
                                changed = true;
                            }
                        }
                        
                        if (first_beta.find(-1) != first_beta.end()) {
                            for (int sym : follow_sets[prod.lhs]) {
                                if (follow_sets[resolved_id].find(sym) == follow_sets[resolved_id].end()) {
                                    follow_sets[resolved_id].insert(sym);
                                    changed = true;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
    
    hash_set<LRItem, LRItemHash> closure(const hash_set<LRItem, LRItemHash> &items) {
        hash_set<LRItem, LRItemHash> result = items;
        bool changed = true;
        
        while (changed) {
            changed = false;
            vector<LRItem> new_items;
            
            for (const auto &item : result) {
                int next_sym = item.next_symbol();
                if (next_sym != -1 && is_nonterminal_symbol(next_sym)) {
                    int resolved_id = resolve_symbol_reference(next_sym);
                    
                    for (int prod_idx = 0; prod_idx < (int)productions.size(); prod_idx++) {
                        const auto &prod = productions[prod_idx];
                        if (prod.lhs == resolved_id) {
                            LRItem new_item(prod.lhs, prod.rhs, 0);
                            if (result.find(new_item) == result.end()) {
                                bool found = false;
                                for (const auto &ni : new_items) {
                                    if (ni == new_item) {
                                        found = true;
                                        break;
                                    }
                                }
                                if (!found) {
                                    new_items.push_back(new_item);
                                    changed = true;
                                }
                            }
                        }
                    }
                }
            }
            
            for (const auto &item : new_items) {
                result.insert(item);
            }
        }
        
        return result;
    }
    
    
    hash_set<LRItem, LRItemHash> goto_func(const hash_set<LRItem, LRItemHash> &items, int symbol_id) {
        hash_set<LRItem, LRItemHash> goto_items;
        
        for (const auto &item : items) {
            if (item.next_symbol() == symbol_id) {
                LRItem new_item(item.lhs, item.rhs, item.dot_pos + 1);
                goto_items.insert(new_item);
            }
        }
        
        if (goto_items.empty()) {
            return goto_items;
        }
        
        return closure(goto_items);
    }
    
    
    bool states_equal(const hash_set<LRItem, LRItemHash> &a, const hash_set<LRItem, LRItemHash> &b) const {
        if (a.size() != b.size()) return false;
        for (const auto &item : a) {
            if (b.find(item) == b.end()) return false;
        }
        return true;
    }
    
    
    int find_state_id(const hash_set<LRItem, LRItemHash> &target_state) const {
        for (int i = 0; i < (int)states.size(); i++) {
            if (states_equal(states[i], target_state)) {
                return i;
            }
        }
        return -1;
    }
    
    
    void build_slr1_states() {
        if (start_symbol_id == -1) {
            throw runtime_error("Start symbol 'START' not found in grammar");
        }
        
        compute_first_sets();
        compute_follow_sets();
        
        augmented_start_id = get_or_create_symbol_id("_START");
        productions.insert(productions.begin(), Production(augmented_start_id, {start_symbol_id}));
        nonterminals.insert(augmented_start_id);
        
        
        hash_set<LRItem, LRItemHash> initial_items;
        LRItem initial_item(augmented_start_id, {start_symbol_id}, 0);
        initial_items.insert(initial_item);
        
        hash_set<LRItem, LRItemHash> initial_state = closure(initial_items);
        states.push_back(initial_state);
        
        queue<int> worklist;
        worklist.push(0);
        
        while (!worklist.empty()) {
            int current_state_id = worklist.front();
            worklist.pop();
            auto current_state = states[current_state_id];
            
            hash_set<int> symbols;
            for (const auto &item : current_state) {
                int next_sym = item.next_symbol();
                if (next_sym != -1) {
                    symbols.insert(next_sym);
                }
            }
            
            for (int symbol_id : symbols) {
                auto next_state = goto_func(current_state, symbol_id);
                if (next_state.empty()) continue;
                
                int next_state_id = find_state_id(next_state);
                if (next_state_id == -1) {
                    next_state_id = (int)states.size();
                    states.push_back(next_state);
                    worklist.push(next_state_id);
                }
                
                if (is_terminal_symbol(symbol_id)) {
                    int resolved_id = resolve_symbol_reference(symbol_id);
                    action_table[{current_state_id, resolved_id}] = Action(ActionType::SHIFT, next_state_id);
                } else if (is_nonterminal_symbol(symbol_id)) {
                    int resolved_id = resolve_symbol_reference(symbol_id);
                    goto_table[{current_state_id, resolved_id}] = next_state_id;
                }
            }
        }
        
        
        for (int state_id = 0; state_id < (int)states.size(); state_id++) {
            for (const auto &item : states[state_id]) {
                if (item.is_complete()) {
                    if (item.lhs == augmented_start_id) {
                        int eof_id = get_or_create_symbol_id("$");
                        action_table[{state_id, eof_id}] = Action(ActionType::ACCEPT, 0);
                    } else {
                        int prod_id = find_production_id(item.lhs, item.rhs);
                        if (prod_id != -1) {
                            
                            for (int follow_sym : follow_sets[item.lhs]) {
                                pair<int, int> key = {state_id, follow_sym};
                                auto existing = action_table.find(key);
                                
                                action_table[key] = Action(ActionType::REDUCE, prod_id);
                            }
                        }
                    }
                }
            }
        }
    }
    
    int find_production_id(int lhs, const vector<int> &rhs) {
        for (int i = 0; i < (int)productions.size(); i++) {
            if (productions[i].lhs == lhs && productions[i].rhs == rhs) {
                return i;
            }
        }
        return -1;
    }
    
    
    struct Token {
        int type_id;
        string value;
        Token(int t, const string &v) : type_id(t), value(v) {}
    };
    
    enum class TokenizeResult {
        SUCCESS,
        INVALID_REGEX,
        UNRECOGNIZED_CHARACTER
    };
    
    
TokenizeResult tokenize(const string &input, vector<Token> &tokens) {
    tokens.clear();
    vector<regex> patterns;
    vector<int> type_ids;
    
    for (int term_id : terminal_order) {
        if (terminals.find(term_id) != terminals.end() && term_id < (int)terminal_patterns.size()) {
            try {
                patterns.push_back(regex(terminal_patterns[term_id]));
                type_ids.push_back(term_id);
            } catch (const regex_error &e) {
                return TokenizeResult::INVALID_REGEX;
            }
        }
    }
    
    auto start = input.cbegin();
    while (start != input.cend()) {
        if (isspace(*start)) {
            ++start;
            continue;
        }
        
        
        int best_match_length = 0;
        int best_match_type = -1;
        string best_match_value = "";
        
        for (size_t i = 0; i < patterns.size(); i++) {
            smatch match;
            if (regex_search(start, input.cend(), match, patterns[i]) && match.position() == 0) {
                int match_length = (int)match.length();
                
                
                if (match_length > best_match_length || 
                    (match_length == best_match_length && best_match_type == -1)) {
                    best_match_length = match_length;
                    best_match_type = type_ids[i];
                    best_match_value = match.str();
                }
            }
        }
        
        if (best_match_type == -1) {
            return TokenizeResult::UNRECOGNIZED_CHARACTER;
        }
        
        tokens.emplace_back(best_match_type, best_match_value);
        start += best_match_length;
    }
    
    return TokenizeResult::SUCCESS;
}
    
public:
    parser(const string &bnf_text, bool debug = false) : debug_mode(debug) {
        parse_bnf(bnf_text);
        build_slr1_states();
    }
    
    node* parse(const string &input) {
        vector<Token> tokens;
        TokenizeResult tokenize_result = tokenize(input, tokens);
        
        if (tokenize_result != TokenizeResult::SUCCESS) {
            return nullptr;
        }
        
        int eof_id = get_or_create_symbol_id("$");
        tokens.emplace_back(eof_id, "$");
        
        vector<int> state_stack = {0};
        vector<node*> symbol_stack;
        int token_pos = 0;
        
        while (true) {
            if (state_stack.empty() || token_pos >= (int)tokens.size()) {
                return nullptr;
            }
            
            int current_state = state_stack.back();
            int current_token_type = tokens[token_pos].type_id;
            string current_token_value = tokens[token_pos].value;
            
            auto action_key = make_pair(current_state, current_token_type);
            auto action_it = action_table.find(action_key);
            
            if (action_it == action_table.end()) {
                return nullptr;
            }
            
            Action action = action_it->second;
            
            if (action.type == ActionType::SHIFT) {
                state_stack.push_back(action.value);
                node* new_node = new node(current_token_type, current_token_value, this);
                symbol_stack.push_back(new_node);
                token_pos++;
            } else if (action.type == ActionType::REDUCE) {
                if (action.value < 0 || action.value >= (int)productions.size()) {
                    return nullptr;
                }
                
                Production &prod = productions[action.value];
                node* new_node = new node(prod.lhs, this);
                
                int pop_count = (int)prod.rhs.size();
                if (pop_count > (int)symbol_stack.size() || pop_count > (int)state_stack.size()) {
                    return nullptr;
                }
                
                for (int i = 0; i < pop_count; i++) {
                    node* child = symbol_stack.back();
                    new_node->values.insert(new_node->values.begin(), child);
                    symbol_stack.pop_back();
                    state_stack.pop_back();
                }
                
                for (auto child : new_node->values) {
                    if (child) {
                        child->set_parser(this);
                    }
                }
                
                symbol_stack.push_back(new_node);
                
                if (state_stack.empty()) {
                    return nullptr;
                }
                
                auto goto_key = make_pair(state_stack.back(), prod.lhs);
                auto goto_it = goto_table.find(goto_key);
                if (goto_it == goto_table.end()) {
                    return nullptr;
                }
                
                state_stack.push_back(goto_it->second);
            } else if (action.type == ActionType::ACCEPT) {
                if (symbol_stack.empty()) {
                    return nullptr;
                }
                node* result = symbol_stack.back();
                if (result) {
                    result->set_parser(this);
                }
                return result;
            } else {
                return nullptr;
            }
        }
    }
    
    string get_symbol_name(int symbol_id) const {
        if (symbol_id < 0 || symbol_id >= (int)id_to_name.size()) return "";
        return id_to_name[symbol_id];
    }
};


string node::get_token_name() const {
    if (!parser_ptr) return "";
    return parser_ptr->get_symbol_name(symbol_id);
}

using ll = long long;
bool eval(node* root, int j){
    if (root == nullptr) return 0;
    
    string symbol_name = root->get_token_name();
    if (symbol_name == "START"){
        return eval(root->values[0], j) == eval(root->values[2], j);
    }

    if (symbol_name == "EXPR"){
        if (root->values.size() == 1) {
            return eval(root->values[0], j);
        }

        if (root->values.size() == 2){
            return !eval(root->values[1], j);
        }

        if (root->values[2]->get_token_name() == "AND") {
            bool b1 = eval(root->values[1], j);
            if (!b1) return 0;
            bool b2 = eval(root->values[3], j);
            return b2;
        }

        if (root->values[2]->get_token_name() == "OR") {
            bool b1 = eval(root->values[1], j);
            if (b1) return 1;
            bool b2 = eval(root->values[3], j);
            return b2;
        }

        if (root->values[2]->get_token_name() == "TO") {
            bool b1 = eval(root->values[1], j);
            if (!b1) return 1;
            bool b2 = eval(root->values[3], j);
            return b2;
        }
    }

    if (symbol_name == "ATOM") {
        if (root->value == "T") return 1;
        if (root->value == "F") return 0;
        if (root->value.length() == 1) {
            return (j >> (root->value[0] - 'a')) & 1;
        }
    }

    return 0;
}

int main() {
    
    bool debug = false;
    
    auto parser0 = parser(
        "ATOM = T|F|[a-k];"
        "NOT = -;"
        "AND = \\*;"
        "OR = \\+;"
        "TO = ->;"
        "EQ = \\=;"
        "LPAR = \\(;"
        "RPAR = \\);"
        "START ::= #EXPR #EQ #EXPR;"
        "EXPR ::= #NOT #EXPR | #LPAR #EXPR #AND #EXPR #RPAR | "
        "#LPAR #EXPR #OR #EXPR #RPAR | #LPAR #EXPR #TO #EXPR #RPAR | #ATOM;",
        debug
    );
    
    while (1){
        string s;
        cin >> s;
        if (s == "#") break;

        bool f = 1;
        auto result = parser0.parse(s);
        assert(result != nullptr);
        for (int i = 0; i < (1<<11); i++){
            if (!eval(result, i)){
                cout << "NO" << endl;
                f = 0;
                break;
            }
        }
        if (f) cout << "YES" << endl;
    }
    
    return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 4708
final_rank: 20

code_snippet: #include<bits/stdc++.h>
using namespace std;

string S;

bool var[11];

bool read_for(int &i);

bool read_equ(int &i){
  // cerr << i << "!\n";
  bool ret1 = read_for(i);
  assert(S[i++] == '=');
  bool ret2 = read_for(i);
  return ret1 == ret2;
}

bool read_for(int &i){
  // cerr << i << "\n";
  if(S[i] == 'T'){
    i++;
    return true;
  }else if(S[i] == 'F'){
    i++;
    return false;
  }else{
    if('a' <= S[i] && S[i] <= 'k'){
      return var[S[i++] - 'a'];
    }else{
      if(S[i] == '-'){
        i++;
        return !read_for(i);
      }else{
        assert(S[i++] == '(');
        bool ret1 = read_for(i);
        char op = S[i++];
        if(op == '-'){
          assert(S[i] == '>');
          i++;
        }
        bool ret2 = read_for(i);
        assert(S[i++] == ')');
        if(op == '*'){
          return ret1 & ret2;
        }else if(op == '+'){
          return ret1 | ret2;
        }else{
          assert(op == '-');
          return (!ret1) | ret2;
        }

      }
    }
  }
}

int main(){
  while(true){
    cin >> S;
    if(S == "#"){
      break;
    }
    string ans = "YES";
    for(int i = 0; i < 2048; i++){
      for(int j = 0; j < 11; j++){
        if((i >> j) & 1){
          var[j] = true;
        }else{
          var[j] = false;
        }
      }
      int index = 0;
      if(!read_equ(index)){
        ans = "NO";
      }
    }
    cout << ans << "\n";
  }

}
accuracy: 1
time_ms: 40
memory_kb: 3584
final_rank: 12

code_snippet: // #pragma GCC target("avx2")
// #pragma GCC optimize("O3")
// #pragma GCC optimize("unroll-loops")

#include <bits/stdc++.h>
using namespace std;

// #include <atcoder/all>
// using namespace atcoder;

#define rep(i, n) for (int i = 0; i < (n); ++i)
using ll = long long;

// #include "titan_cpplib/others/print.cpp"


class Parser {
public:
    using T = char;

    string s;
    int n, ptr;

    Parser() {}
    Parser(string s) : s(s), n(s.size()), ptr(0) {}

    void consume(char expected) {
        if (next() != expected) {
            printf("Parser::Error: Expected `%c` but got `%c`\n", expected, next());
            assert(false);
        }
        ptr++;
    }

    char next() const {
        assert(ptr < n);
        return s[ptr];
    }

    bool done() const {
        return ptr == n;
    }

    bool is_digit(char c) const {
        return '0' <= c && c <= '9';
    }

    int number() {
        // cerr << "number-start" << endl;
        ll ret = 0;
        while (!done() && is_digit(next())) {
            char v = next();
            ret *= 10;
            ret += v - '0';
            consume(v);
        }
        // cerr << "number-fin : " << ret << endl;
        return ret;
    }

    // ------------------------------------

    void init() { ptr = 0; }

    T expression() {
        return expr(0);
    }

    T expr(int level) {
        // rep(_, level) {
        //     cerr << "  ";
        // }
        // cerr << " " << next() << endl;

        assert(0 <= level && level <= 1);
        if (level <= 0) {
            T ret = expr(level+1);
            while (!done()) {
                if (next() == '*') {
                    consume('*');
                    T nxt = expr(level+1);
                    if (ret == 'T' && nxt == 'T') {
                        ret = 'T';
                    } else {
                        ret = 'F';
                    }
                } else if (next() == '+') {
                    consume('+');
                    T nxt = expr(level+1);
                    if (ret == 'F' && nxt == 'F') {
                        ret = 'F';
                    } else {
                        ret = 'T';
                    }
                } else if (next() == '-' && s[ptr+1] == '>') {
                    consume('-');
                    consume('>');
                    T nxt = expr(level+1);
                    if (ret == 'T' && nxt == 'F') {
                        ret = 'F';
                    } else {
                        ret = 'T';
                    }
                } else {
                    break;
                }
            }
            return ret;
        } else {
            if (next() == '(') {
                consume('(');
                T ret = expr(0);
                consume(')');
                return ret;
            } else if (next() == '-') {
                // 前置の単項演算子
                consume('-');
                T nxt = expr(level);
                if (nxt == 'T') return 'F';
                if (nxt == 'F') return 'T';
            } else if (next() == 'T' || next() == 'F') {
                char x = next();
                consume(x);
                return x;
            }
        }
        assert(false);
    }

    T parse() {
        return expression();
    }
};

void solve() {
    string s;
    cin >> s;
    if (s == "#") {
        exit(0);
    }
    int n = s.size();
    string left, right;
    bool upd = false;
    rep(i, n) {
        if (s[i] == '=') {
            upd = true;
            continue;
        }
        if (!upd) {
            left += s[i];
        } else {
            right += s[i];
        }
    }
    // cerr << left << " " << right << endl;

    int cnt = 11;
    rep(bit, (1<<cnt)-1) {
        string left_t = left;
        string right_t = right;
        rep(i, left.size()) {
            rep(j, cnt) {
                if (left[i] == 'a'+j) {
                    left_t[i] = (bit>>j&1) ? 'T' : 'F';
                }
            }
        }
        rep(i, right.size()) {
            rep(j, cnt) {
                if (right[i] == 'a'+j) {
                    right_t[i] = (bit>>j&1) ? 'T' : 'F';
                }
            }
        }

        // cerr << left_t << endl;
        Parser p(left_t);
        char pres = p.parse();
        // cerr << "pres=" << pres << endl;

        // cerr << right_t << endl;
        Parser q(right_t);
        char qres = q.parse();
        // cerr << "qres=" << qres << endl;

        if (pres != qres) {
            cout << "NO" << endl;
            return;
        }
    }

    cout << "YES" << endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout << fixed << setprecision(15);
    cerr << fixed << setprecision(15);

    int t = 1e9;// cin >> t;
    for (int i = 0; i < t; ++i) {
        solve();
    }

    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 3584
final_rank: 15

code_snippet: #pragma region // comavius::competitive library


#pragma region // inclusion and optimization
#include <bits/stdc++.h>
#ifdef IS_TEST
static const bool IS_TEST_ENVIROMENT = true;
#else
static const bool IS_TEST_ENVIROMENT = false;
#endif
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma endregion // inclusion and optimization

namespace comavius::competitive
{ // typedefs

#pragma region // long long
    typedef long long ll;
    typedef std::vector<ll> vll;
    typedef std::vector<vll> vvll;
    typedef std::vector<vvll> vvvll;
    typedef std::map<ll, ll> mll;
    typedef std::map<ll, mll> mmll;
    typedef std::pair<ll, ll> pll;
    typedef std::vector<pll> vpll;
#pragma endregion // long long

#pragma region // long double
    typedef long double ld;
    typedef std::vector<ld> vld;
    typedef std::vector<vld> vvld;
    typedef std::vector<vvld> vvvld;
#pragma endregion // long double

#pragma region // std::string
    typedef std::string str;
    typedef std::vector<str> vstr;
    typedef std::vector<vstr> vvstr;
    typedef std::vector<vvstr> vvvstr;
#pragma endregion // std::string

#pragma region // bool
    typedef std::vector<bool> vb;
    typedef std::vector<vb> vvb;
    typedef std::vector<vvb> vvvb;
#pragma endregion // bool

#pragma region // char
    typedef std::vector<char> vc;
    typedef std::vector<vc> vvc;
    typedef std::vector<vvc> vvvc;
#pragma endregion // char

#pragma region // container of std
#pragma region // std::vector
    template <typename T>
    using vec = std::vector<T>;
    template <typename T>
    using vec2 = std::vector<std::vector<T>>;
    template <typename T>
    using vec3 = std::vector<std::vector<std::vector<T>>>;
    template <typename T>
    using vec4 = std::vector<std::vector<std::vector<std::vector<T>>>>;
    template <typename T>
    using vec5 = std::vector<std::vector<std::vector<std::vector<std::vector<T>>>>>;
    template <typename T>
    using vec6 = std::vector<std::vector<std::vector<std::vector<std::vector<std::vector<T>>>>>>;
    template <typename T>
    using vec7 = std::vector<std::vector<std::vector<std::vector<std::vector<std::vector<std::vector<T>>>>>>>;
#pragma endregion // std::vector
#pragma endregion // container of std

} // namespace comavius::competitive typedefs

namespace comavius::competitive::sfinae
{ // SFINAE : breaking changes are prohibited

#pragma region // has_mul_op
    template <typename T, typename = void>
    struct has_multiply_operator : std::false_type
    {
    };
    template <typename T>
    struct has_multiply_operator<T, std::void_t<decltype(std::declval<T>() * std::declval<T>())>> : std::true_type
    {
    };
#pragma endregion // has_mul_op

#pragma region // has_forward_iterator
    template <typename T, typename = void>
    struct has_forward_iterator
    {
        static constexpr bool value = false;
    };

    template <typename T>
    struct has_forward_iterator<T, std::void_t<
                                       decltype(std::begin(std::declval<T &>())),
                                       decltype(std::end(std::declval<T &>())),
                                       typename T::iterator, // Tがiterator型を持つ
                                       decltype(++std::declval<typename T::iterator &>()),
                                       decltype(*std::declval<typename T::iterator &>()),
                                       decltype(std::declval<typename T::iterator &>() == std::declval<typename T::iterator &>()),
                                       decltype(std::declval<typename T::iterator &>() != std::declval<typename T::iterator &>()),
                                       decltype(std::declval<typename T::iterator &>() = std::declval<const typename T::iterator &>())>>
    {
        static constexpr bool value = true;
    };
#pragma endregion // has_forward_iterator
}

namespace comavius::competitive::algebraic_structures
{
    // work in progress
    /*
    template <typename T>
    struct Monoid {

    };
    */
}

namespace comavius::competitive
{ // BFS

    class BFS
    {
        std::vector<std::vector<long long>> adjacency_list;
        long long number_of_nodes;

    public:
        BFS(std::vector<std::vector<long long>> adjacency_list_, long long number_of_nodes_)
        {
            this->adjacency_list = adjacency_list_;
            this->number_of_nodes = number_of_nodes_;
        }

        long long run(long long start_node, long long end_node)
        {
            std::vector<bool> visited(number_of_nodes, false);
            std::vector<long long> current_queue(1, start_node), next_queue;
            visited[start_node] = true;
            long long distance = 0;
            if (start_node == end_node)
            {
                return distance;
            }
            while (current_queue.size() != 0)
            {
                distance++;
                next_queue.clear();
                for (auto i : current_queue)
                {
                    if (i == end_node)
                    {
                        return distance;
                    }
                    for (auto j : adjacency_list[i])
                    {
                        if (!visited[j])
                        {
                            visited[j] = true;
                            next_queue.push_back(j);
                            if (j == end_node)
                            {
                                return distance;
                            }
                        }
                    }
                }
                current_queue = next_queue;
            }
            return (long long)-1;
        }
    };
} // namespace comavius::competitive::BFS

namespace comavius::competitive
{ // UnionFind

    class UnionFind
    {
        std::vector<long long> parent;
        std::vector<long long> rank;
        std::vector<long long> size;
        std::vector<long long> edge_count;

    public:
        UnionFind(long long num_nodes)
        {
            parent.resize(num_nodes, -1);
            rank.resize(num_nodes, 0);
            size.resize(num_nodes, 1);
            edge_count.resize(num_nodes, 0);
        }

        long long root_of(long long x)
        {
            if (parent[x] == -1)
            {
                return x;
            }
            else
            {
                return parent[x] = root_of(parent[x]);
            }
        }

        void unite(long long x, long long y)
        {
            long long rx = root_of(x);
            long long ry = root_of(y);
            if (rx == ry)
            {
                edge_count[rx]++;
                return;
            }
            else if (rank[rx] < rank[ry])
            {
                parent[rx] = ry;
                size[ry] += size[rx];
                edge_count[ry] += edge_count[rx] + 1;
            }
            else
            {
                parent[ry] = rx;
                size[rx] += size[ry];
                if (rank[rx] == rank[ry])
                    rank[rx]++;
                edge_count[rx] += edge_count[ry] + 1;
            }
            return;
        }

        bool is_same(long long x, long long y)
        {
            return root_of(x) == root_of(y);
        }

        long long size_of(long long x)
        {
            return size[root_of(x)];
        }
        bool is_cycle(long long x)
        {
            return edge_count[root_of(x)] >= size[root_of(x)];
        }
    };
} // namespace comavius::competitive::UnionFind

namespace comavius::competitive
{ // get_primes

    std::vector<long long> get_primes(long long n)
    {
        std::vector<bool> is_prime(n + 1, true);
        std::vector<long long> primes;
        is_prime[0] = false;
        is_prime[1] = false;
        for (long long i = 2; i <= n; i++)
        {
            if (is_prime[i])
            {
                primes.push_back(i);
                for (long long j = 2 * i; j <= n; j += i)
                {
                    is_prime[j] = false;
                }
            }
        }
        return primes;
    }
} // namespace comavius::competitive::get_primes

namespace comavius::competitive
{ // fast pow (repeated squaring)

    template <typename T>
    T fast_pow(T base, T neutral, long long exponent)
    {
        // check if T has multiply operator
        static_assert(sfinae::has_multiply_operator<T>::value, "comavius::competitive::fast_pow : T must have operator*");
        T ans = neutral;
        while (exponent > 0)
        {
            if (exponent % 2 == 1)
            {
                ans *= base;
            }
            base *= base;
            exponent /= 2;
        }
        return ans;
    }
} // namespace comavius::competitive::fast_pow

namespace comavius::competitive
{ // bipartite matching
    /*
    class BipartiteMatching {
        long long size, size_u, size_v;
        std::vector<long long> nodes_u, nodes_v;
        std::vector<std::vector<long long>> adjacency_list;

    };
    */
}

namespace comavius::competitive
{ // chmax/chmin
    template <typename T>
    concept HasMaxOverload = requires(T a, T b) {
        {
            std::max(a, b)
        } -> std::convertible_to<T>;
    };
    template <typename T>
    concept HasMinOverload = requires(T a, T b) {
        {
            std::min(a, b)
        } -> std::convertible_to<T>;
    };

    template <HasMaxOverload T>
    void chmax(T &a, T b)
    {
        a = std::max(a, b);
    }

    template <HasMinOverload T>
    void chmin(T &a, T b)
    {
        a = std::min(a, b);
    }

}

namespace comavius::competitive
{ // Print(stdout, stderr)

#pragma region // formatting various type of values
    // is_vector structure
    template <typename T>
    struct is_vector : std::false_type
    {
    };
    template <typename T>
    struct is_vector<std::vector<T>> : std::true_type
    {
    };
    // is_pair structure
    template <typename T>
    struct is_pair : std::false_type
    {
    };
    template <typename T, typename U>
    struct is_pair<std::pair<T, U>> : std::true_type
    {
    };
    // is_iterator structure
    template <typename T, typename = void>
    struct is_iterator : std::false_type
    {
    };
    template <typename T>
    struct is_iterator<
        T,
        typename std::enable_if<
            !std::is_same<
                typename std::iterator_traits<T>::value_type,
                void>::value>::type> : std::true_type
    {
    };
    // generate std::string for stdout/stderr
    // std::string
    std::string generate_string(std::string s)
    {
        return s + " ";
    }
    // char
    std::string generate_string(char c)
    {
        return std::string(1, c) + " ";
    }
    // eger types
    template <typename T>
    typename std::enable_if_t<std::is_integral<T>::value, std::string>
    generate_string(T t)
    {
        return std::to_string(t) + " ";
    }
    // floating point types
    template <typename T>
    typename std::enable_if_t<std::is_floating_point<T>::value, std::string>
    generate_string(T t)
    {
        return std::to_string(t) + " ";
    }
    // container with forward iterator
    template <typename T>
    typename std::enable_if_t<sfinae::has_forward_iterator<T>::value, std::string>
    generate_string(T t)
    {
        std::string s = "";
        for (auto i = t.begin(); i != t.end(); i++)
        {
            s += generate_string(*i);
            s += " ";
        }
        s += "\n";
        return s;
    }
    // std::pair
    template <typename T>
    typename std::enable_if_t<is_pair<T>::value, std::string>
    generate_string(T t)
    {
        return generate_string(t.first) + generate_string(t.second);
    }
    // std::iterator
    template <typename T>
    typename std::enable_if_t<is_iterator<T>::value, std::string>
    generate_string(T begin, T end)
    {
        std::string s = "";
        for (auto i = begin; i != end; i++)
        {
            s += generate_string(*i);
            s += " ";
        }
        s += "\n";
        return s;
    }
#pragma endregion // formatting various type of values

    // color enum-class
    enum class Color
    {
        BLACK,
        RED,
        GREEN,
        YELLOW,
        BLUE,
        MAGENTA,
        CYAN,
        WHITE,
        DEFAULT
    };

    // ansi code color
    std::string get_ansi_color(Color color)
    {
        if (IS_TEST_ENVIROMENT)
        {
            std::string ansi_code;
            switch (color)
            {
            case Color::BLACK:
                ansi_code = "\033[30m\033[1m";
                break;
            case Color::RED:
                ansi_code = "\033[31m\033[1m";
                break;
            case Color::GREEN:
                ansi_code = "\033[32m\033[1m";
                break;
            case Color::YELLOW:
                ansi_code = "\033[33m\033[1m";
                break;
            case Color::BLUE:
                ansi_code = "\033[34m\033[1m";
                break;
            case Color::MAGENTA:
                ansi_code = "\033[35m\033[1m";
                break;
            case Color::CYAN:
                ansi_code = "\033[36m\033[1m";
                break;
            case Color::WHITE:
                ansi_code = "\033[37m";
                break;
            case Color::DEFAULT:
                ansi_code = "\033[0m";
                break;
            }
            return ansi_code;
        }
        else
        {
            return "";
        }
    }

#pragma region // Print to stdout
    // default color(native)
    template <typename T>
    void print(T t)
    {
        std::cout << generate_string(t);
    }
    // with iterator range
    template <typename T>
    void print(T begin, T end)
    {
        std::cout << generate_string(begin, end);
    }
    // print"ln"
    template <typename T>
    void println(T t)
    {
        print(t);
        std::cout << "\n";
    }
    // print"ln" with iterator range
    template <typename T>
    void println(T begin, T end)
    {
        print(begin, end);
        std::cout << "\n";
    }
    // yes or no
    void yneos(bool a)
    {
        if (a)
        {
            println("Yes");
        }
        else
        {
            println("No");
        }
    }
#pragma endregion // Print to stdout

#pragma region // ePrint to stderr
    // default color(Color::CYAN)
    template <typename T>
    void errprint(T t)
    {
        if (IS_TEST_ENVIROMENT)
        {
            std::cerr << get_ansi_color(Color::RED) << generate_string(t) << get_ansi_color(Color::DEFAULT);
        }
    }
    // set color
    template <typename T>
    void errprint(T t, Color color)
    {
        if (IS_TEST_ENVIROMENT)
        {
            std::cerr << get_ansi_color(color) << generate_string(t) << get_ansi_color(Color::DEFAULT);
        }
    }
    // print"ln"
    template <typename T>
    void errprintln(T t)
    {
        if (IS_TEST_ENVIROMENT)
        {
            errprint(t);
            std::cerr << "\n";
        }
    }
    template <typename T>
    void errprintln(T t, Color color)
    {
        if (IS_TEST_ENVIROMENT)
        {
            errprint(t, color);
            std::cerr << "\n";
        }
    }
    // print"ln" with iterator range
    template <typename T>
    void errprintln(T begin, T end)
    {
        if (IS_TEST_ENVIROMENT)
        {
            errprint(begin, end);
            std::cerr << "\n";
        }
    }
    template <typename T>
    void errprintln(T begin, T end, Color color)
    {
        if (IS_TEST_ENVIROMENT)
        {
            errprint(begin, end, color);
            std::cerr << "\n";
        }
    }
    // debug print
    void debug()
    {
        errprintln("DEBUG", Color::MAGENTA);
    }
#pragma endregion // ePrint to stderr

} // namespace comavius::competitive print



namespace comavius::competitive
{ // initial settings
    void initial_settings()
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        std::cout << std::setprecision(15);
        std::cerr << std::setprecision(15);
    }
} // namespace comavius::competitive::initial_settings

#pragma region // Read macro
#define GET_1_ARG(TYPE, ARG) \
    ;                        \
    TYPE ARG;                \
    std::cin >> ARG;
#define GET_2_ARG(TYPE, ARG, ...) GET_1_ARG(TYPE, ARG) GET_1_ARG(TYPE, __VA_ARGS__)
#define GET_3_ARG(TYPE, ARG, ...) GET_1_ARG(TYPE, ARG) GET_2_ARG(TYPE, __VA_ARGS__)
#define GET_4_ARG(TYPE, ARG, ...) GET_1_ARG(TYPE, ARG) GET_3_ARG(TYPE, __VA_ARGS__)
#define GET_5_ARG(TYPE, ARG, ...) GET_1_ARG(TYPE, ARG) GET_4_ARG(TYPE, __VA_ARGS__)
#define GET_6_ARG(TYPE, ARG, ...) GET_1_ARG(TYPE, ARG) GET_5_ARG(TYPE, __VA_ARGS__)
#define GET_7_ARG(TYPE, ARG, ...) GET_1_ARG(TYPE, ARG) GET_6_ARG(TYPE, __VA_ARGS__)
#define GET_8_ARG(TYPE, ARG, ...) GET_1_ARG(TYPE, ARG) GET_7_ARG(TYPE, __VA_ARGS__)
#define GET_9_ARG(TYPE, ARG, ...) GET_1_ARG(TYPE, ARG) GET_8_ARG(TYPE, __VA_ARGS__)
#define GET_10_ARG(TYPE, ARG, ...) GET_1_ARG(TYPE, ARG) GET_9_ARG(TYPE, __VA_ARGS__)

#define GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, NAME, ...) NAME
#define read(TYPE, ...) GET_MACRO(__VA_ARGS__, GET_10_ARG, GET_9_ARG, GET_8_ARG, GET_7_ARG, GET_6_ARG, GET_5_ARG, GET_4_ARG, GET_3_ARG, GET_2_ARG, GET_1_ARG)(TYPE, __VA_ARGS__)

#define readv(TYPE, NAME, SIZE)          \
    std::vector<TYPE> NAME(SIZE);        \
    for (long long i = 0; i < SIZE; i++) \
        std::cin >> NAME[i];
#define readvv(TYPE, NAME, H, W)                                  \
    std::vector<std::vector<TYPE>> NAME(H, std::vector<TYPE>(W)); \
    for (long long i = 0; i < H; i++)                             \
        for (long long j = 0; j < W; j++)                         \
            std::cin >> NAME[i][j];
#pragma endregion // Read macro

#pragma region // Other macro
#define rep(i, n) for (ll i = 0; i < n; i++)
#define reps(i, start, goal, diff) for (ll i = start; i != goal; i += diff)
#define all(a) a.begin(), a.end()
//    #define chmax(a, b) a = std::max(a, b)
//    #define chmin(a, b) a = std::min(a, b)
#pragma endregion // Other macro

#pragma region // namespace expansion
using namespace std;
using namespace comavius::competitive;
#pragma endregion // namespace expansion

#pragma endregion // comavius::competitive library

//#include <atcoder/all>
//using namespace atcoder;
//using mint = modint998244353;
using vvpll = vec<vec<pll>>;

using namespace std;

str replace(str s, ll bits) {
    str vs = "abcedfghijk";
    ll n = s.size();
    rep(i, n) {
        rep(j, vs.size()) {
            if (s[i] == vs[j]) {
                if (((bits >> j) & 1) == 0) {
                    s[i] = 'T';
                }
                else {
                    s[i] = 'F';
                }
            }
        }
    }
    str s2;
    rep(i, n){
        if (s[i] == '-' && i != n-1 && s[i+1] == '>') {
            s2.push_back('&');
            i++;
        }
        else {
            s2.push_back(s[i]);
        }
    }
    return s2;
}

char myminus(char c) {
    if (c == 'T') {
        return 'F';
    }
    else {
        return 'T';
    }
}

char myprod(char l, char r) {
    if (l == 'T' && r == 'T') {
        return 'T';
    }
    else {
        return 'F';
    }
}

char myadd(char l, char r) {
    if (l == 'T' || r == 'T') {
        return 'T';
    }
    else {
        return 'F';
    }
}

char myimply(char l, char r) {
    if (l == 'T' && r == 'F') {
        return 'F';
    }
    else {
        return 'T';
    }
}

bool eval(str s) {
    ll n = s.size();
    str stack;
    reverse(all(s));
    while (s.size()) {
        char c = s.back();
        s.pop_back();
        if (c == 'T' || c == 'F') {
            if (stack.size() != 0) {
                if (stack.back() == '(') {
                    stack.push_back(c);
                }
                else {
                    char op = stack.back();
                    stack.pop_back();
                    if (op == '-') {
                        s.push_back(myminus(c));
                    }
                    else {
                        char left = stack.back();
                        stack.pop_back();
                        if (op == '*') {
                            s.push_back(myprod(left, c));
                        }
                        else if (op == '+') {
                            s.push_back(myadd(left, c));
                        }
                        else {
                            s.push_back(myimply(left, c));
                        }
                    }
                }
            }
            else {
                stack.push_back(c);
            }
        }
        else if (c == ')') {
            char prev = stack.back();
            stack.pop_back();
            stack.pop_back();
            s.push_back(prev);
        }
        else {
            stack.push_back(c);
        }
        //cerr << stack << " " << s << endl;
    }
    //cerr <<"finally "<<stack << endl;
    if (stack[0] == 'T') {
        return true;
    }
    else {
        return false;
    }
}

int main() {
    read(str, s);
    do {
        ll n = s.size();
        ll eqidx;
        rep(i, n) {
            if (s[i] == '=') {
                eqidx = i;
            }
        }
        str left = s.substr(0, eqidx);
        str right = s.substr(eqidx+1, n - eqidx);
        //cerr << left << "\n" << right << endl;
        bool ok = true;
        rep(bits, (1ll << 11)) {
            str l = replace(left, bits);
            str r = replace(right, bits);
            //cerr << l << endl;
            bool l_b = eval(l);
            bool r_b = eval(r);
            if (l_b != r_b) {
                ok = false;
                break;
            }
        }
        if (ok) {
            cout << "YES\n";
        }
        else {
            cout << "NO\n";
        }
        cin >> s;
    } while (s != "#");
}
accuracy: 1
time_ms: 60
memory_kb: 3584
final_rank: 13

code_snippet: #pragma region // comavius::competitive library


#pragma region // inclusion and optimization
#include <bits/stdc++.h>
#ifdef IS_TEST
static const bool IS_TEST_ENVIROMENT = true;
#else
static const bool IS_TEST_ENVIROMENT = false;
#endif
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma endregion // inclusion and optimization

namespace comavius::competitive
{ // typedefs

#pragma region // long long
    typedef long long ll;
    typedef std::vector<ll> vll;
    typedef std::vector<vll> vvll;
    typedef std::vector<vvll> vvvll;
    typedef std::map<ll, ll> mll;
    typedef std::map<ll, mll> mmll;
    typedef std::pair<ll, ll> pll;
    typedef std::vector<pll> vpll;
#pragma endregion // long long

#pragma region // long double
    typedef long double ld;
    typedef std::vector<ld> vld;
    typedef std::vector<vld> vvld;
    typedef std::vector<vvld> vvvld;
#pragma endregion // long double

#pragma region // std::string
    typedef std::string str;
    typedef std::vector<str> vstr;
    typedef std::vector<vstr> vvstr;
    typedef std::vector<vvstr> vvvstr;
#pragma endregion // std::string

#pragma region // bool
    typedef std::vector<bool> vb;
    typedef std::vector<vb> vvb;
    typedef std::vector<vvb> vvvb;
#pragma endregion // bool

#pragma region // char
    typedef std::vector<char> vc;
    typedef std::vector<vc> vvc;
    typedef std::vector<vvc> vvvc;
#pragma endregion // char

#pragma region // container of std
#pragma region // std::vector
    template <typename T>
    using vec = std::vector<T>;
    template <typename T>
    using vec2 = std::vector<std::vector<T>>;
    template <typename T>
    using vec3 = std::vector<std::vector<std::vector<T>>>;
    template <typename T>
    using vec4 = std::vector<std::vector<std::vector<std::vector<T>>>>;
    template <typename T>
    using vec5 = std::vector<std::vector<std::vector<std::vector<std::vector<T>>>>>;
    template <typename T>
    using vec6 = std::vector<std::vector<std::vector<std::vector<std::vector<std::vector<T>>>>>>;
    template <typename T>
    using vec7 = std::vector<std::vector<std::vector<std::vector<std::vector<std::vector<std::vector<T>>>>>>>;
#pragma endregion // std::vector
#pragma endregion // container of std

} // namespace comavius::competitive typedefs

namespace comavius::competitive::sfinae
{ // SFINAE : breaking changes are prohibited

#pragma region // has_mul_op
    template <typename T, typename = void>
    struct has_multiply_operator : std::false_type
    {
    };
    template <typename T>
    struct has_multiply_operator<T, std::void_t<decltype(std::declval<T>() * std::declval<T>())>> : std::true_type
    {
    };
#pragma endregion // has_mul_op

#pragma region // has_forward_iterator
    template <typename T, typename = void>
    struct has_forward_iterator
    {
        static constexpr bool value = false;
    };

    template <typename T>
    struct has_forward_iterator<T, std::void_t<
                                       decltype(std::begin(std::declval<T &>())),
                                       decltype(std::end(std::declval<T &>())),
                                       typename T::iterator, // Tがiterator型を持つ
                                       decltype(++std::declval<typename T::iterator &>()),
                                       decltype(*std::declval<typename T::iterator &>()),
                                       decltype(std::declval<typename T::iterator &>() == std::declval<typename T::iterator &>()),
                                       decltype(std::declval<typename T::iterator &>() != std::declval<typename T::iterator &>()),
                                       decltype(std::declval<typename T::iterator &>() = std::declval<const typename T::iterator &>())>>
    {
        static constexpr bool value = true;
    };
#pragma endregion // has_forward_iterator
}

namespace comavius::competitive::algebraic_structures
{
    // work in progress
    /*
    template <typename T>
    struct Monoid {

    };
    */
}

namespace comavius::competitive
{ // BFS

    class BFS
    {
        std::vector<std::vector<long long>> adjacency_list;
        long long number_of_nodes;

    public:
        BFS(std::vector<std::vector<long long>> adjacency_list_, long long number_of_nodes_)
        {
            this->adjacency_list = adjacency_list_;
            this->number_of_nodes = number_of_nodes_;
        }

        long long run(long long start_node, long long end_node)
        {
            std::vector<bool> visited(number_of_nodes, false);
            std::vector<long long> current_queue(1, start_node), next_queue;
            visited[start_node] = true;
            long long distance = 0;
            if (start_node == end_node)
            {
                return distance;
            }
            while (current_queue.size() != 0)
            {
                distance++;
                next_queue.clear();
                for (auto i : current_queue)
                {
                    if (i == end_node)
                    {
                        return distance;
                    }
                    for (auto j : adjacency_list[i])
                    {
                        if (!visited[j])
                        {
                            visited[j] = true;
                            next_queue.push_back(j);
                            if (j == end_node)
                            {
                                return distance;
                            }
                        }
                    }
                }
                current_queue = next_queue;
            }
            return (long long)-1;
        }
    };
} // namespace comavius::competitive::BFS

namespace comavius::competitive
{ // UnionFind

    class UnionFind
    {
        std::vector<long long> parent;
        std::vector<long long> rank;
        std::vector<long long> size;
        std::vector<long long> edge_count;

    public:
        UnionFind(long long num_nodes)
        {
            parent.resize(num_nodes, -1);
            rank.resize(num_nodes, 0);
            size.resize(num_nodes, 1);
            edge_count.resize(num_nodes, 0);
        }

        long long root_of(long long x)
        {
            if (parent[x] == -1)
            {
                return x;
            }
            else
            {
                return parent[x] = root_of(parent[x]);
            }
        }

        void unite(long long x, long long y)
        {
            long long rx = root_of(x);
            long long ry = root_of(y);
            if (rx == ry)
            {
                edge_count[rx]++;
                return;
            }
            else if (rank[rx] < rank[ry])
            {
                parent[rx] = ry;
                size[ry] += size[rx];
                edge_count[ry] += edge_count[rx] + 1;
            }
            else
            {
                parent[ry] = rx;
                size[rx] += size[ry];
                if (rank[rx] == rank[ry])
                    rank[rx]++;
                edge_count[rx] += edge_count[ry] + 1;
            }
            return;
        }

        bool is_same(long long x, long long y)
        {
            return root_of(x) == root_of(y);
        }

        long long size_of(long long x)
        {
            return size[root_of(x)];
        }
        bool is_cycle(long long x)
        {
            return edge_count[root_of(x)] >= size[root_of(x)];
        }
    };
} // namespace comavius::competitive::UnionFind

namespace comavius::competitive
{ // get_primes

    std::vector<long long> get_primes(long long n)
    {
        std::vector<bool> is_prime(n + 1, true);
        std::vector<long long> primes;
        is_prime[0] = false;
        is_prime[1] = false;
        for (long long i = 2; i <= n; i++)
        {
            if (is_prime[i])
            {
                primes.push_back(i);
                for (long long j = 2 * i; j <= n; j += i)
                {
                    is_prime[j] = false;
                }
            }
        }
        return primes;
    }
} // namespace comavius::competitive::get_primes

namespace comavius::competitive
{ // fast pow (repeated squaring)

    template <typename T>
    T fast_pow(T base, T neutral, long long exponent)
    {
        // check if T has multiply operator
        static_assert(sfinae::has_multiply_operator<T>::value, "comavius::competitive::fast_pow : T must have operator*");
        T ans = neutral;
        while (exponent > 0)
        {
            if (exponent % 2 == 1)
            {
                ans *= base;
            }
            base *= base;
            exponent /= 2;
        }
        return ans;
    }
} // namespace comavius::competitive::fast_pow

namespace comavius::competitive
{ // bipartite matching
    /*
    class BipartiteMatching {
        long long size, size_u, size_v;
        std::vector<long long> nodes_u, nodes_v;
        std::vector<std::vector<long long>> adjacency_list;

    };
    */
}

namespace comavius::competitive
{ // chmax/chmin
    template <typename T>
    concept HasMaxOverload = requires(T a, T b) {
        {
            std::max(a, b)
        } -> std::convertible_to<T>;
    };
    template <typename T>
    concept HasMinOverload = requires(T a, T b) {
        {
            std::min(a, b)
        } -> std::convertible_to<T>;
    };

    template <HasMaxOverload T>
    void chmax(T &a, T b)
    {
        a = std::max(a, b);
    }

    template <HasMinOverload T>
    void chmin(T &a, T b)
    {
        a = std::min(a, b);
    }

}

namespace comavius::competitive
{ // Print(stdout, stderr)

#pragma region // formatting various type of values
    // is_vector structure
    template <typename T>
    struct is_vector : std::false_type
    {
    };
    template <typename T>
    struct is_vector<std::vector<T>> : std::true_type
    {
    };
    // is_pair structure
    template <typename T>
    struct is_pair : std::false_type
    {
    };
    template <typename T, typename U>
    struct is_pair<std::pair<T, U>> : std::true_type
    {
    };
    // is_iterator structure
    template <typename T, typename = void>
    struct is_iterator : std::false_type
    {
    };
    template <typename T>
    struct is_iterator<
        T,
        typename std::enable_if<
            !std::is_same<
                typename std::iterator_traits<T>::value_type,
                void>::value>::type> : std::true_type
    {
    };
    // generate std::string for stdout/stderr
    // std::string
    std::string generate_string(std::string s)
    {
        return s + " ";
    }
    // char
    std::string generate_string(char c)
    {
        return std::string(1, c) + " ";
    }
    // eger types
    template <typename T>
    typename std::enable_if_t<std::is_integral<T>::value, std::string>
    generate_string(T t)
    {
        return std::to_string(t) + " ";
    }
    // floating point types
    template <typename T>
    typename std::enable_if_t<std::is_floating_point<T>::value, std::string>
    generate_string(T t)
    {
        return std::to_string(t) + " ";
    }
    // container with forward iterator
    template <typename T>
    typename std::enable_if_t<sfinae::has_forward_iterator<T>::value, std::string>
    generate_string(T t)
    {
        std::string s = "";
        for (auto i = t.begin(); i != t.end(); i++)
        {
            s += generate_string(*i);
            s += " ";
        }
        s += "\n";
        return s;
    }
    // std::pair
    template <typename T>
    typename std::enable_if_t<is_pair<T>::value, std::string>
    generate_string(T t)
    {
        return generate_string(t.first) + generate_string(t.second);
    }
    // std::iterator
    template <typename T>
    typename std::enable_if_t<is_iterator<T>::value, std::string>
    generate_string(T begin, T end)
    {
        std::string s = "";
        for (auto i = begin; i != end; i++)
        {
            s += generate_string(*i);
            s += " ";
        }
        s += "\n";
        return s;
    }
#pragma endregion // formatting various type of values

    // color enum-class
    enum class Color
    {
        BLACK,
        RED,
        GREEN,
        YELLOW,
        BLUE,
        MAGENTA,
        CYAN,
        WHITE,
        DEFAULT
    };

    // ansi code color
    std::string get_ansi_color(Color color)
    {
        if (IS_TEST_ENVIROMENT)
        {
            std::string ansi_code;
            switch (color)
            {
            case Color::BLACK:
                ansi_code = "\033[30m\033[1m";
                break;
            case Color::RED:
                ansi_code = "\033[31m\033[1m";
                break;
            case Color::GREEN:
                ansi_code = "\033[32m\033[1m";
                break;
            case Color::YELLOW:
                ansi_code = "\033[33m\033[1m";
                break;
            case Color::BLUE:
                ansi_code = "\033[34m\033[1m";
                break;
            case Color::MAGENTA:
                ansi_code = "\033[35m\033[1m";
                break;
            case Color::CYAN:
                ansi_code = "\033[36m\033[1m";
                break;
            case Color::WHITE:
                ansi_code = "\033[37m";
                break;
            case Color::DEFAULT:
                ansi_code = "\033[0m";
                break;
            }
            return ansi_code;
        }
        else
        {
            return "";
        }
    }

#pragma region // Print to stdout
    // default color(native)
    template <typename T>
    void print(T t)
    {
        std::cout << generate_string(t);
    }
    // with iterator range
    template <typename T>
    void print(T begin, T end)
    {
        std::cout << generate_string(begin, end);
    }
    // print"ln"
    template <typename T>
    void println(T t)
    {
        print(t);
        std::cout << "\n";
    }
    // print"ln" with iterator range
    template <typename T>
    void println(T begin, T end)
    {
        print(begin, end);
        std::cout << "\n";
    }
    // yes or no
    void yneos(bool a)
    {
        if (a)
        {
            println("Yes");
        }
        else
        {
            println("No");
        }
    }
#pragma endregion // Print to stdout

#pragma region // ePrint to stderr
    // default color(Color::CYAN)
    template <typename T>
    void errprint(T t)
    {
        if (IS_TEST_ENVIROMENT)
        {
            std::cerr << get_ansi_color(Color::RED) << generate_string(t) << get_ansi_color(Color::DEFAULT);
        }
    }
    // set color
    template <typename T>
    void errprint(T t, Color color)
    {
        if (IS_TEST_ENVIROMENT)
        {
            std::cerr << get_ansi_color(color) << generate_string(t) << get_ansi_color(Color::DEFAULT);
        }
    }
    // print"ln"
    template <typename T>
    void errprintln(T t)
    {
        if (IS_TEST_ENVIROMENT)
        {
            errprint(t);
            std::cerr << "\n";
        }
    }
    template <typename T>
    void errprintln(T t, Color color)
    {
        if (IS_TEST_ENVIROMENT)
        {
            errprint(t, color);
            std::cerr << "\n";
        }
    }
    // print"ln" with iterator range
    template <typename T>
    void errprintln(T begin, T end)
    {
        if (IS_TEST_ENVIROMENT)
        {
            errprint(begin, end);
            std::cerr << "\n";
        }
    }
    template <typename T>
    void errprintln(T begin, T end, Color color)
    {
        if (IS_TEST_ENVIROMENT)
        {
            errprint(begin, end, color);
            std::cerr << "\n";
        }
    }
    // debug print
    void debug()
    {
        errprintln("DEBUG", Color::MAGENTA);
    }
#pragma endregion // ePrint to stderr

} // namespace comavius::competitive print



namespace comavius::competitive
{ // initial settings
    void initial_settings()
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        std::cout << std::setprecision(15);
        std::cerr << std::setprecision(15);
    }
} // namespace comavius::competitive::initial_settings

#pragma region // Read macro
#define GET_1_ARG(TYPE, ARG) \
    ;                        \
    TYPE ARG;                \
    std::cin >> ARG;
#define GET_2_ARG(TYPE, ARG, ...) GET_1_ARG(TYPE, ARG) GET_1_ARG(TYPE, __VA_ARGS__)
#define GET_3_ARG(TYPE, ARG, ...) GET_1_ARG(TYPE, ARG) GET_2_ARG(TYPE, __VA_ARGS__)
#define GET_4_ARG(TYPE, ARG, ...) GET_1_ARG(TYPE, ARG) GET_3_ARG(TYPE, __VA_ARGS__)
#define GET_5_ARG(TYPE, ARG, ...) GET_1_ARG(TYPE, ARG) GET_4_ARG(TYPE, __VA_ARGS__)
#define GET_6_ARG(TYPE, ARG, ...) GET_1_ARG(TYPE, ARG) GET_5_ARG(TYPE, __VA_ARGS__)
#define GET_7_ARG(TYPE, ARG, ...) GET_1_ARG(TYPE, ARG) GET_6_ARG(TYPE, __VA_ARGS__)
#define GET_8_ARG(TYPE, ARG, ...) GET_1_ARG(TYPE, ARG) GET_7_ARG(TYPE, __VA_ARGS__)
#define GET_9_ARG(TYPE, ARG, ...) GET_1_ARG(TYPE, ARG) GET_8_ARG(TYPE, __VA_ARGS__)
#define GET_10_ARG(TYPE, ARG, ...) GET_1_ARG(TYPE, ARG) GET_9_ARG(TYPE, __VA_ARGS__)

#define GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, NAME, ...) NAME
#define read(TYPE, ...) GET_MACRO(__VA_ARGS__, GET_10_ARG, GET_9_ARG, GET_8_ARG, GET_7_ARG, GET_6_ARG, GET_5_ARG, GET_4_ARG, GET_3_ARG, GET_2_ARG, GET_1_ARG)(TYPE, __VA_ARGS__)

#define readv(TYPE, NAME, SIZE)          \
    std::vector<TYPE> NAME(SIZE);        \
    for (long long i = 0; i < SIZE; i++) \
        std::cin >> NAME[i];
#define readvv(TYPE, NAME, H, W)                                  \
    std::vector<std::vector<TYPE>> NAME(H, std::vector<TYPE>(W)); \
    for (long long i = 0; i < H; i++)                             \
        for (long long j = 0; j < W; j++)                         \
            std::cin >> NAME[i][j];
#pragma endregion // Read macro

#pragma region // Other macro
#define rep(i, n) for (ll i = 0; i < n; i++)
#define reps(i, start, goal, diff) for (ll i = start; i != goal; i += diff)
#define all(a) a.begin(), a.end()
//    #define chmax(a, b) a = std::max(a, b)
//    #define chmin(a, b) a = std::min(a, b)
#pragma endregion // Other macro

#pragma region // namespace expansion
using namespace std;
using namespace comavius::competitive;
#pragma endregion // namespace expansion

#pragma endregion // comavius::competitive library

//#include <atcoder/all>
//using namespace atcoder;
//using mint = modint998244353;
using vvpll = vec<vec<pll>>;

using namespace std;

str replace(str s, ll bits) {
    str vs = "abcedfghijk";
    ll n = s.size();
    rep(i, n) {
        rep(j, vs.size()) {
            if (s[i] == vs[j]) {
                if ((bits >> j) & 1) {
                    s[i] = 'T';
                }
                else {
                    s[i] = 'F';
                }
            }
        }
    }
    str s2;
    rep(i, n){
        if (s[i] == '-' && i != n-1 && s[i+1] == '>') {
            s2.push_back('&');
            i++;
        }
        else {
            s2.push_back(s[i]);
        }
    }
    return s2;
}

char myminus(char c) {
    if (c == 'T') {
        return 'F';
    }
    else {
        return 'T';
    }
}

char myprod(char l, char r) {
    if (l == 'T' && r == 'T') {
        return 'T';
    }
    else {
        return 'F';
    }
}

char myadd(char l, char r) {
    if (l == 'T' || r == 'T') {
        return 'T';
    }
    else {
        return 'F';
    }
}

char myimply(char l, char r) {
    if (l == 'T' && r == 'F') {
        return 'F';
    }
    else {
        return 'T';
    }
}

bool eval(str s) {
    ll n = s.size();
    str stack;
    reverse(all(s));
    while (s.size()) {
        char c = s.back();
        s.pop_back();
        if (c == 'T' || c == 'F') {
            if (stack.size() != 0) {
                if (stack.back() == '(') {
                    stack.push_back(c);
                }
                else {
                    char op = stack.back();
                    stack.pop_back();
                    if (op == '-') {
                        s.push_back(myminus(c));
                    }
                    else {
                        char left = stack.back();
                        stack.pop_back();
                        if (op == '*') {
                            s.push_back(myprod(left, c));
                        }
                        else if (op == '+') {
                            s.push_back(myadd(left, c));
                        }
                        else {
                            s.push_back(myimply(left, c));
                        }
                    }
                }
            }
            else {
                stack.push_back(c);
            }
        }
        else if (c == ')') {
            char prev = stack.back();
            stack.pop_back();
            stack.pop_back();
            s.push_back(prev);
        }
        else {
            stack.push_back(c);
        }
        //cerr << stack << " " << s << endl;
    }
    //cerr <<"finally "<<stack << endl;
    if (stack[0] == 'T') {
        return true;
    }
    else {
        return false;
    }
}

int main() {
    read(str, s);
    do {
        ll n = s.size();
        ll eqidx;
        rep(i, n) {
            if (s[i] == '=') {
                eqidx = i;
            }
        }
        str left = s.substr(0, eqidx);
        str right = s.substr(eqidx+1, n - eqidx);
        //cerr << left << "\n" << right << endl;
        bool ok = true;
        rep(bits, (1ll << 11)) {
            str l = replace(left, bits);
            str r = replace(right, bits);
            //cerr << l << endl;
            bool l_b = eval(l);
            bool r_b = eval(r);
            if (l_b != r_b) {
                ok = false;
                break;
            }
        }
        if (ok) {
            cout << "YES\n";
        }
        else {
            cout << "NO\n";
        }
        cin >> s;
    } while (s != "#");
}
accuracy: 1
time_ms: 60
memory_kb: 3584
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vi = vector<int>;
using vl = vector<ll>;
#define rep3(i, a, b, c) for (ll i = (a); i < (b); i += (c))
#define rep2(i, a, b) rep3(i, a, b, 1)
#define rep1(i, n) rep2(i, 0, n)
#define rep0(n) rep1(aaaaa, n)
#define ov4(a, b, c, d, name, ...) name
#define rep(...) ov4(__VA_ARGS__, rep3, rep2, rep1, rep0)(__VA_ARGS__)
#define per(i, a, b) for (ll i = (a) - 1; i >= (b); i--)
#define fore(e, v) for (auto&& e : v)
#define all(a) begin(a), end(a)
#define sz(a) (int)(size(a))
#define lb(v, x) (lower_bound(all(v), x) - begin(v))
#define eb emplace_back

template <typename T, typename S>
bool chmin(T& a, const S& b) {
  return a > b ? a = b, 1 : 0;
}
template <typename T, typename S>
bool chmax(T& a, const S& b) {
  return a < b ? a = b, 1 : 0;
}
const int INF = 1e9 + 100;
const ll INFL = 3e18 + 100;
#define i128 __int128_t
struct _ {
  _() { cin.tie(0)->sync_with_stdio(0), cout.tie(0); }
} __;

void solve();
int main(){
  while(1)solve();
}

array<int,11> val;
bool TF(string S){
  // cerr<<S<<endl;
  int N=sz(S);
  if(S[0]=='-'){
    string ns;
    rep(i,1,N)ns.push_back(S[i]);
    return !TF(ns);
  }
  if(N==1){
    switch(S[0]){
      case 'T':return true;
      case 'F':return false;
      default :return val[S[0]-'a'];
    }
  }
  if(!(S[0]=='('&&S.back()==')'))exit(0);
  int c=0;
  string L,R;
  int idx;
  char op='/';
  for(idx=1;idx<N-1;idx++){
    if(c==0&&(S[idx]=='*'||S[idx]=='+'||S.substr(idx,2)=="->")){
      op=S[idx];
      if(op=='-')idx++;
      break;
    }
    if(S[idx]=='(')c++;
    if(S[idx]==')')c--;
    L.push_back(S[idx]);
  }
  for(++idx;idx<N-1;idx++){
    R.push_back(S[idx]);
  }
  bool l=TF(L),r=TF(R);
  if(op=='*')return l&&r;
  if(op=='+')return l||r;
  if(op=='-')return (!l)||r;
  assert(false);
}

void solve(){
  string Si;
  cin>>Si;
  if(Si=="#")exit(0);
  string S;
  fore(i,Si){
    if(!S.empty()&&S.back()=='-'&&i=='-')S.pop_back();
    else S.push_back(i);
  }
  string L,R;
  int idx=0;
  for(;idx<sz(S);idx++){
    if(S[idx]=='='){
      idx++;
      break;
    }
    L.push_back(S[idx]);
  }
  for(;idx<sz(S);idx++){
    R.push_back(S[idx]);
  }
  rep(i,1<<11){
    rep(j,11){
      val[j]=i>>j&1;
      if(TF(L)!=TF(R)){
        cout<<"NO\n";
        return;
      }
    }
  }
  cout<<"YES\n";
}
accuracy: 1
time_ms: 770
memory_kb: 3584
final_rank: 19

code_snippet: /**
	author:  shobonvip
	created: 2025.04.24 17:46:57
**/

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;

#define rep(i, s, n) for (int i = (int)(s); i < (int)(n); i++)
#define rrep(i, s, n) for (int i = (int)(n)-1; i >= (int)(s); i--)
#define all(v) v.begin(), v.end()

template <typename T> bool chmin(T &a, const T &b) {
	if (a <= b) return false;
	a = b;
	return true;
}

template <typename T> bool chmax(T &a, const T &b) {
	if (a >= b) return false;
	a = b;
	return true;
}

template <typename T> T max(vector<T> &a){
	assert(!a.empty());
	T ret = a[0];
	for (int i=0; i<(int)a.size(); i++) chmax(ret, a[i]);
	return ret;
}

template <typename T> T min(vector<T> &a){
	assert(!a.empty());
	T ret = a[0];
	for (int i=0; i<(int)a.size(); i++) chmin(ret, a[i]);
	return ret;
}

template <typename T> T sum(vector<T> &a){
	T ret = 0;
	for (int i=0; i<(int)a.size(); i++) ret += a[i];
	return ret;
}

string so;

string s;
int piv = 0;
int jokyo = 0;

bool formula();

bool formula() {
	if (s[piv]=='T'){
		piv++;
		return true;
	}
	if (s[piv]=='F'){
		piv++;
		return false;
	}

	if ('a'<=s[piv]&&s[piv]<='k') {
		int dar=s[piv]-'a';
		piv++;
		if((jokyo>>dar)&1){
			return true;
		}else{
			return false;
		}
	}

	if (s[piv]=='-'){
		piv++;
		bool ret=formula();
		if(ret)return false;
		else return true;
	}

	if (s[piv]=='(') {

		piv++;
		bool ret1=formula();
		char c=s[piv];
		if(c=='-'){
			piv++;
			c=s[piv];
		}
		piv++;
		bool ret2=formula();
		piv++;
		if(c=='*'){
			if(ret1&&ret2){
				return true;
			}else{
				return false;
			}
		}else if(c=='+'){
			if(ret1||ret2){
				return true;
			}else{
				return false;
			}
		}else{
			if(!ret1)return true;
			if(ret2)return true;
			return false;
		}
	}

	assert(false);
}

void solve() {
	piv = 0;
	string t1 = "";
	string t2 = "";
	bool modes = 0;
	rep(i,0,(int)so.size()) {
		if (so[i]=='=') {
			modes=1;
		}else{
			if(modes){
				t2+=so[i];
			}else{
				t1+=so[i];
			}
		}
	}

	vector<bool> var1(1<<11);
	vector<bool> var2(1<<11);

	s=t1;
	rep(i,0,1<<11){
		jokyo=i;
		piv=0;
		var1[i]=formula();
	}
	s=t2;
	rep(i,0,1<<11){
		jokyo=i;
		piv=0;
		var2[i]=formula();
	}

	if(var1==var2){
		cout<<"YES\n";
	}else{
		cout<<"NO\n";
	}
}

int main(){
    cin.tie(0)->sync_with_stdio(0);
	while(true) {
		cin >> so;
		if (so == "#") break;
		solve();
	}
}
accuracy: 1
time_ms: 10
memory_kb: 3420
final_rank: 3

code_snippet: #include <bits/stdc++.h>

using namespace std;
#define endl '\n'
typedef long long int ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
template <typename T> istream &operator >>(istream &in, pair<T,T> &a) {in >> a.first >> a.second; return in;}
template <typename T> ostream &operator <<(ostream &out, pair<T,T> &a) {out << a.first << ' ' << a.second; return out;}
template <typename T> pair<T,T> operator - (pair<T,T> a, pair<T,T> b){return {a.first-b.first, a.second-b.second};}

void tokenize(const string& s, char delimiter, vector<string> &out) {
	vector<string> tokens;
	stringstream ss(s);
	string token;
	while (getline(ss, token, delimiter)) out.push_back(token);
}

void parse(string &s, string &out)
{
	stack<char> op_stack;
	unordered_map<char, int> precedence = {{'-', 4}, {'*', 3}, {'+', 2}, {'>', 1}, {'(', 0} };

	for ( int i = 0 ; i < s.size() ; i ++ )
	{
		auto c = s[i];
		if ( c == 'T' || c == 'F' || 'a' <= c && c <= 'z' )
			out.push_back(c);
		else if ( c == '(')
			op_stack.emplace('(');
		else if ( c == ')' )
		{
			while (!op_stack.empty() && op_stack.top() != '(') {
				out.push_back(op_stack.top());
				op_stack.pop();
			}
			op_stack.pop();
		}
		else if ( c == '-' || c == '+' || c == '*' )
		{
			if ( i + 1 < s.size() && s[i+1] == '>' ) c = s[++i];
			while (!op_stack.empty() && precedence[op_stack.top()] > precedence[c]) {
				out.push_back(op_stack.top());
				op_stack.pop();
			}
			op_stack.push(c);
		}
	}
	while (!op_stack.empty()) {
		out.push_back(op_stack.top());
		op_stack.pop();
	}
}

bool calc(string &expr, vector<bool> &val)
{
	bool b;
	stack<bool> st;
	for (auto c: expr )
	{
		if ( c == 'T' ) st.push(true);
		else if ( c == 'F' ) st.push(false);
		else if ( 'a' <= c && c <= 'z' ) st.push(val[c-'a']);
		else if ( c == '-' ) st.top() = !st.top();
		else if ( c == '*' )
		{
			b = st.top(); st.pop();
			st.top() = st.top() && b;
		}
		else if ( c == '+' )
		{
			b = st.top(); st.pop();
			st.top() = st.top() || b;
		}
		else if ( c == '>' )
		{
			b = st.top(); st.pop();
			st.top() = ( !st.top() || ( b && st.top() ));
		}
	}
	assert ( st.size() == 1 );
	return st.top();
}
void sol(int Case) {
	string s;
	while ( getline(cin, s) && s != "#")
	{
		vector<string> equations ;
		tokenize(s, '=', equations);
		vector<string> postfix(equations.size());
		for ( int i = 0 ; i < equations.size() ; i ++ )
			parse(equations[i], postfix[i]);

		vector<bool> val(11);
		int MaxN = 1 << 11;

		vector<bool> answer(equations.size());
		bool ans = true;
		for ( int v = 0 ; v < MaxN && ans ; v++ )
		{
			for ( int j = 0 ; j < 11 ; j ++ )
				val[j] = ( ( v >> j ) & 1 ) ? true : false;

			for ( int j = 0 ; j < equations.size() && ans ; j ++ )
				answer[j] = calc(postfix[j], val);

			for ( int j = 1 ; j < equations.size() && ans ; j ++ )
				ans = answer[j-1] == answer[j];
		}
		if ( ans ) cout << "YES\n";
		else cout << "NO\n";
	}
}

int main()
{
#ifdef AJAVA_DEBUG
freopen("input.txt", "rt", stdin);freopen("output.txt", "wt", stdout);
#endif
    cin.tie(nullptr)->sync_with_stdio(false);
	int T=1; 
	// cin >> T;
	for (int i = 1 ; i <= T ; i ++ ) sol(i);
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3492
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep2(i, n) for (ll i = 0; i < (n); i++)
#define rep3(i, a, b) for (ll i = a; i < (b); i++)
#define overload(a, b, c, d, ...) d
#define rep(...) overload(__VA_ARGS__, rep3, rep2)(__VA_ARGS__)
#define all(a) begin(a), end(a)
#define sz(a) ssize(a)
bool chmin(auto& a, auto b) {
    return a > b ? a = b, 1 : 0;
}
bool chmax(auto& a, auto b) {
    return a < b ? a = b, 1 : 0;
}

struct Parser {
    using CopyIter = string::const_iterator;
    using Iter = CopyIter&;
    string line;
    CopyIter ed;
    Parser(string s): line(s) {}
    bool parse() {
        auto it = line.cbegin();
        ed = line.cend();
        return formula(it);
    }
    void skip(Iter it, char c) {
        assert(*it == c);
        // cerr << *it << ' ' << c << endl;
        it++;
    }
    bool formula(Iter it) {
        if (*it == 'T') {
            skip(it, 'T');
            return true;
        } else if (*it == 'F') {
            skip(it, 'F');
            return false;
        } else if (*it == '-') {
            skip(it, '-');
            return true ^ formula(it);
        } else {
            skip(it, '(');
            bool L = formula(it);
            if (*it == '*') {
                skip(it, '*');
                auto R = formula(it);
                L = L && R;
            } else if (*it == '+') {
                skip(it, '+');
                auto R = formula(it);
                L = L || R;
            } else {
                skip(it, '-');
                skip(it, '>');
                auto R = formula(it);
                L = !L || R;
            }
            skip(it, ')');
            return L;
        }
    }
};

bool solve() {
    string s;
    getline(cin, s);
    if (s == "#") return 1;

    string alphabet;
    const int N = 11;
    const string TorF = "TF";
    rep(i, 0, N) alphabet.push_back(i + 'a');

    rep(i, 0, 1 << N) {
        string t = s;
        for (auto& c: t) {
            if ('a' <= c && c <= 'k') {
                c = TorF[(i >> (c - 'a')) & 1];
            }
        }
        int m = find(all(t), '=') - t.begin();
        auto L = t.substr(0, m);
        auto R = t.substr(m + 1);
        if (Parser(L).parse() != Parser(R).parse()) {
            cout << "NO" << '\n';
            return 0;
        }
    }

    cout << "YES" << '\n';
    return 0;
}

int main() {
    cin.tie(0)->sync_with_stdio(0);
    while (!solve());
}
accuracy: 1
time_ms: 10
memory_kb: 3456
final_rank: 5

code_snippet: // #define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
// #include <atcoder/all>
// #include "qitoy/math/binomial.hpp"

#define rep(i, n) for (long long i = 0; i < (n); i++)
#define rep1(i, n) for (long long i = 1; i <= (n); i++)
#define all(v) v.begin(), v.end()
#define decimal(n) cout << fixed << setprecision(n);
using namespace std;
// using namespace atcoder;
using vi = vector<int>; using vvi = vector<vi>; using vs = vector<string>;
using ll = long long; using vl = vector<ll>; using vvl = vector<vl>; 
// using mint = modint998244353;
// const ll MOD = 998244353;
// using mint = modint;
// const ll MOD = 998244353;
// using mint = modint1000000007;
// const ll MOD = 1000000007;
// using vm = vector<mint>; using vvm = vector<vm>;
using vll = vl;
using P = pair<ll, ll>; using T = tuple<ll, ll, ll>;
using vc = vector<char>; using vvc = vector<vc>;
const ll MAX = 2000100; const ll llINF = 2e18;
const int intINF = 2e9; const long double pi = acos(-1);
ll di[] = {0, -1, 0, 1, -1, -1, 1, 1};
ll dj[] = {1, 0, -1, 0, 1, -1, -1, 1};
template<class T>bool chmax(T& a, const T& b) { if (a < b) { a = b; return 1; } return 0; }
template<class T>bool chmin(T& a, const T& b) { if (b < a) { a = b; return 1; } return 0; }

#include <string>
#include <cctype>
typedef string::const_iterator State;
class ParseError {};

// プロトタイプ宣言
bool equation (State &begin);
bool formula (State &begin);
bool element (State &begin);
void consume(State &begin, char expected);


vector<bool> value(11);

// 四則演算の式をパースして、その評価結果を返す。
bool equation (State &begin) {
    bool ret = formula(begin);

    consume(begin, '=');

    bool ret2 = formula(begin);
    return (ret == ret2 ? true : false);
}

// 乗算除算の式をパースして、その評価結果を返す。
bool formula (State &begin) {
    bool ret;
    
    if(*begin == '-') {
        consume(begin, '-');
        ret = !(formula(begin));
    }
    else if(*begin == '(') {
        consume(begin, '(');
        bool temp1 = formula(begin);
        if(*begin == '*') {
            consume(begin, '*');
            bool temp2 = formula(begin);
            ret = (temp1 & temp2);
        }
        else if(*begin == '+') {
            consume(begin, '+');
            bool temp2 = formula(begin);
            ret = (temp1 | temp2);
        }
        else if(*begin == '-') {
            consume(begin, '-');
            consume(begin, '>');
            bool temp2 = formula(begin);
            ret = ((!temp1) | temp2);
        }
        consume(begin, ')');

    }
    else {
        ret = element(begin);
    }

    return ret;
}

bool element (State &begin) {
    if(*begin == 'T') {
        consume(begin, 'T');
        return true;
    }
    else if(*begin == 'F') {
        consume(begin, 'F');
        return false;
    }
    else {
        bool ret = value[*begin - 'a'];
        begin++;
        return ret;
    }
}

// beginがexpectedを指していたらbeginを一つ進める。
void consume(State &begin, char expected) {
    if (*begin == expected) {
        begin++;
    } else {
        cerr << "Expected '" << expected << "' but got '" << *begin << "'"
            << endl;
        cerr << "Rest string is '";
        while (*begin) {
            cerr << *begin++;
        }
        cerr << "'" << endl;
        throw ParseError();
    }
}

int main() {
    while(true) {
        string s;
        cin >> s;
        if(s == "#") break;
        bool flag = true;
        rep(bit, (1ll << 11)) {
            rep(mask, 11) {
                if(bit & (1ll << mask)) value[mask] = true;
                else value[mask] = false;
            }
            State begin = s.begin();
            if(!equation(begin)) {
                flag = false;
                break;
            };
        }
        cout << (flag ? "YES" : "NO") << endl;
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3476
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int INF = 1e9 + 10;
const ll INFL = 4e18;

bool v[11];

using State = string::const_iterator;
class ParseError {};
void consume(State &begin, char expected) {
    if (*begin == expected) {
        begin++;
    } else {
        cerr << "Expected '" << expected << "' but got '" << *begin << "'" << endl;
        cerr << "Rest string is '";
        while (*begin) {
            cerr << *begin++;
        }
        cerr << "'" << endl;
        throw ParseError();
    }
}

bool contain(bool a, bool b) {
    if (a && !b) {
        return false;
    }
    return true;
}

bool formula(State &begin);

bool formula(State &begin) {
    if (*begin == 'T') {
        begin++;
        return true;
    }
    if (*begin == 'F') {
        begin++;
        return false;
    }
    if ('a' <= *begin && *begin <= 'k') {
        bool ret = v[*begin - 'a'];
        begin++;
        return ret;
    }
    if (*begin == '-') {
        begin++;
        return !formula(begin);
    }
    if (*begin == '(') {
        begin++;
        bool ret = formula(begin);
        if (*begin == '+') {
            begin++;
            ret |= formula(begin);
        } else if (*begin == '*') {
            begin++;
            ret &= formula(begin);
        } else if (*begin == '-' && *next(begin) == '>') {
            begin++;
            begin++;
            bool ret2 = formula(begin);
            ret = contain(ret, ret2);
        }
        consume(begin, ')');
        return ret;
    }
    return true;
}

int main() {
    while (true) {
        string S;
        cin >> S;

        if (S == "#") {
            break;
        }

        string A, B;
        int N = S.size();
        {
            int i = 0;
            for (i = 0; i < N; i++) {
                if (S[i] == '=') {
                    i++;
                    break;
                }
                A.push_back(S[i]);
            }
            for (; i < N; i++) {
                B.push_back(S[i]);
            }
        }

        bool ok = true;
        for (int i = 0; i < 1 << 11; i++) {
            for (int j = 0; j < 11; j++) {
                if (i >> j & 1) {
                    v[j] = true;
                } else {
                    v[j] = false;
                }
            }
            State a = A.begin();
            State b = B.begin();

            ok &= formula(a) == formula(b);
        }

        if (ok) {
            cout << "YES" << endl;
        } else {
            cout << "NO" << endl;
        }
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3480
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;

struct Parser{
    string s;
    int var;
    string::const_iterator itr;

    Parser(string s, int var) : s(s), var(var), itr(s.begin()){}

    bool parse(){
        return equation();
    }

    bool val(char ch){
        if(ch == 'T') return true;
        if(ch == 'F') return false;
        return (var & (1 << (ch - 'a'))) > 0;
    }

    bool equation(){
        bool left = formula();
        ++itr;
        bool right = formula();
        return left == right;
    }

    bool formula(){
        bool ret;
        if(*itr == '-'){
            ++itr;
            ret = !formula();
        }
        else if(*itr == '('){
            ++itr;
            bool left = formula(), right;
            if(*itr == '+'){
                ++itr;
                right = formula();
                ret = left | right;
            }
            else if(*itr == '*'){
                ++itr;
                right = formula();
                ret = left & right;
            }
            else{
                ++itr; ++itr;
                right = formula();
                ret = !(left & (!right));
            }
            ++itr;
        }
        else{
            ret = val(*itr);
            ++itr;
        }
        return ret;
    }
};

int main(){
    string s;
    while(getline(cin, s)){
        if(s == "#") break;
        bool ans = true;
        for(int i = 0; i < 1 << 11; ++i){
            ans &= Parser(s, i).parse();
        }
        cout << (ans ? "YES" : "NO") << endl;
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3488
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int INF = (int)1e9 + 1001010;
const ll llINF = (long long)4e18 + 22000020;
const string endn = "\n";
template <class T> inline auto vector2(size_t i, size_t j, const T &init = T()) {return vector(i, vector<T>(j, init));}
const string ELEM_SEPARATION = " ", VEC_SEPARATION = endn;
template<class T> istream& operator >>(istream &i, vector<T> &A) {for(auto &I : A) {i >> I;} return i;}
template<class T> ostream& operator <<(ostream &o, const vector<T> &A) {int i=A.size(); for(const auto &I : A){o << I << (--i ? ELEM_SEPARATION : "");} return o;}
template<class T> ostream& operator <<(ostream &o, const vector<vector<T>> &A) {int i=A.size(); for(const auto &I : A){o << I << (--i ? VEC_SEPARATION : "");} return o;}
template<class T> vector<T>& operator ++(vector<T> &A, int n) {for(auto &I : A) {I++;} return A;}
template<class T> vector<T>& operator --(vector<T> &A, int n) {for(auto &I : A) {I--;} return A;}
template<class T, class U> bool chmax(T &a, const U &b) {return ((a < b) ? (a = b, true) : false);}
template<class T, class U> bool chmin(T &a, const U &b) {return ((a > b) ? (a = b, true) : false);}
ll floor(ll a, ll b){if (b < 0) a = -a, b = -b; if(a >= 0) return a / b; else return (a + 1) / b - 1;}
ll ceil(ll a, ll b){if (b < 0) a = -a, b = -b; if(a > 0) return (a - 1) / b + 1; else return a / b;}
ll bit(unsigned long long val, unsigned long long digit){return (val >> digit) & 1;}
#ifdef DEBUG
#include <debug_slephy.cpp>
#else
#define debug(...)
#endif
// ================================== ここまでテンプレ ==================================

// Parser (T must have constructor T(long long))
template<class T> struct Parser {
    /* basic settings */
    vector<vector<string>> OPERATORS;               // binary operator priority
    function<T(const string&, T, T)> OPERATION;     // binary operation

    /* optional settings */
    function<T(const string&, int&)> GET_LEAF;      // leaf parser
    vector<string> UNARY_OPERATORS;                 // unary operator (ex: "-", "log")
    function<T(const string&, T)> UNARY_OPERATION;  // unary operation
    const string OPERATOR_NUMBER = "num";

    /* result: parse tree */
    int root;                    // vals[root] is the answer
    vector<T> vals;              // value of each node
    vector<string> ops;          // operator of each node
    vector<int> left, right;     // the index of left-node, right-node
    vector<int> ids;             // the node-index of the i-th value

    /* constructor */
    string S;
    Parser() {}
    Parser(const vector<vector<string>> &operators,
           const function<T(const string&, T, T)> operation) {
        init(operators, operation);
    }
    Parser(const vector<vector<string>> &operators,
           const function<T(const string&, T, T)> operation,
           const function<T(const string&, int&)> get_leaf) {
        init(operators, operation, get_leaf);
    }
    Parser(const vector<vector<string>> &operators,
           const function<T(const string&, T, T)> operation,
           const vector<string> &unary_operators,
           const function<T(const string &op, T)> unary_operation) {
        init(operators, operation, unary_operators, unary_operation);
    }
    Parser(const vector<vector<string>> &operators,
           const function<T(const string&, T, T)> operation,
           const function<T(const string&, int&)> get_leaf,
           const vector<string> &unary_operators,
           const function<T(const string &op, T)> unary_operation) {
        init(operators, operation, get_leaf, unary_operators, unary_operation);
    }
    void init(const vector<vector<string>> &operators,
              const function<T(const string&, T, T)> operation) {
        OPERATORS = operators, OPERATION = operation;
    }
    void init(const vector<vector<string>> &operators,
              const function<T(const string&, T, T)> operation,
              const function<T(const string&, int&)> get_leaf) {
        OPERATORS = operators, OPERATION = operation;
        GET_LEAF = get_leaf;
    }
    void init(const vector<vector<string>> &operators,
              const function<T(const string&, T, T)> operation,
              const vector<string> &unary_operators,
              const function<T(const string &op, T)> unary_operation) {
        OPERATORS = operators, OPERATION = operation;
        UNARY_OPERATORS = unary_operators, UNARY_OPERATION = unary_operation;
    }
    void init(const vector<vector<string>> &operators,
              const function<T(const string&, T, T)> operation,
              const function<T(const string&, int&)> get_leaf,
              const vector<string> &unary_operators,
              const function<T(const string &op, T)> unary_operation) {
        OPERATORS = operators, OPERATION = operation;
        GET_LEAF = get_leaf;
        UNARY_OPERATORS = unary_operators, UNARY_OPERATION = unary_operation;
    }
    void clear() {
        S = "";
        vals.clear(), ops.clear(), left.clear(), right.clear(), ids.clear();
    }

    /* eval */
    T eval(const string &str, bool default_parse_numeric = true) {
        clear();
        S = str;
        int p = 0, id = 0;
        root = parse(p, id, default_parse_numeric);
        return vals[root];
    }

    /* node generator */
    // value
    int new_leaf(T val, int &id) {
        vals.push_back(val);
        ops.push_back(OPERATOR_NUMBER);
        left.push_back(-1);
        right.push_back(-1);
        ids.push_back(id++);
        return (int)vals.size() - 1;
    }
    // FUNC(lp)
    int new_node_with_left(T val, const string &op, int lp) {
        vals.push_back(val);
        ops.push_back(op);
        left.push_back(lp);
        right.push_back(-1);
        ids.push_back(-1);
        return (int)vals.size() - 1;
    }
    // (lp) op (rp)
    int new_node_with_left_right(const string &op, int lp, int rp) {
        vals.push_back(OPERATION(op, vals[lp], vals[rp]));
        ops.push_back(op);
        left.push_back(lp);
        right.push_back(rp);
        ids.push_back(-1);
        return (int)vals.size() - 1;
    }

    /* parser */
    int parse(int &p, int &id, bool default_parse_numeric, int depth = 0) {
        assert(p >= 0 && p < (int)S.size());
        string op;
        if (depth < (int)OPERATORS.size()) {
            // recursive descent
            int lp = parse(p, id, default_parse_numeric, depth + 1);
            bool update = false;
            do {
                update = false;
                if (is_in_the_operators(p, op,
                                        OPERATORS[(int)OPERATORS.size() - depth - 1])) {
                    int rp = parse(p, id, default_parse_numeric, depth + 1);
                    lp = new_node_with_left_right(op, lp, rp);
                    update = true;
                }
            } while (p < (int)S.size() && update);
            return lp;
        }
        else if (default_parse_numeric && isdigit(S[p])) {
            return get_number(p, id);
        }
        else if (S[p] == '(') {
            return get_bracket(p, id, default_parse_numeric);
        }
        else if (is_in_the_operators(p, op, UNARY_OPERATORS)) {
            return get_unary_operation(p, id, op, default_parse_numeric);
        }
        else {
            return new_leaf(GET_LEAF(S, p), id);
        }
    }
    bool is_the_operator(int &p, const string &op) {
        if (op != "" && S.substr(p, op.size()) == op) {
            p += op.size();
            return true;
        }
        return false;
    }
    bool is_in_the_operators(int &p, string &res_op, const vector<string> &ops) {
        for (const auto &op : ops) {
            if (is_the_operator(p, op)) {
                res_op = op;
                return true;
            }
        }
        return false;
    }
    int get_number(int &p, int &id) {
        long long val = 0, sign = 1;
        if (S[p] == '-') sign = -1, ++p;
        while (p < (int)S.size() && isdigit(S[p])) {
            val = val * 10 + (int)(S[p++] - '0');
        }
        return new_leaf(T(val * sign), id);
    }
    int get_bracket(int &p, int &id, bool default_parse_numeric) {
        ++p;  // skip "("
        int lp = parse(p, id, default_parse_numeric, 0);
        ++p;  // skip ")"
        return lp;
    }
    int get_unary_operation(int &p, int &id, const string &op,
                            bool default_parse_numeric) {
        int lp;
        if (S[p] == '(') lp = get_bracket(p, id, default_parse_numeric);
        else lp = parse(p, id, default_parse_numeric, (int)OPERATORS.size());
        return new_node_with_left(UNARY_OPERATION(op, vals[lp]), op, lp);
    }

    /* dump */
    void dump() {
        dump_rec(root);
    }
    void dump_rec(int v, string space = "") {
        cout << space << v << ": (" << ops[v] << ", " << vals[v]
             << ") -> left: " << left[v] << ", right: " << right[v] << endl;
        if (left[v] != -1) dump_rec(left[v], space + "  ");
        if (right[v] != -1) dump_rec(right[v], space + "  ");
    }
};

void solve(){
    string s; cin >> s;
    if(s == "#") exit(0);

    string s1, s2;
    {
        int pos = s.find("=");
        s1 = {s.begin(), s.begin()+pos};
        s2 = {s.begin()+pos+1, s.end()};
        debug(s1, s2);
    }

    vector<vector<string>> operators = {{"*", "+", "->"}};
    auto operation = [&](const string &op, bool l, bool r) -> bool {
        if(op == "*") return (l & r);
        else if(op == "+") return (l | r);
        else if(op == "->") return (!l | r);
        else exit(1);
    };

    vector<string> unary_operators = {"-"};
    auto unary_operation = [&](const string &op, bool l) -> bool {
        if(op == "-") return !l;
        else exit(1);
    };


    for(ll bt = 0; bt < (1LL<<11); bt++){
        auto get_leaf = [&](const string &s, int &p) -> bool {
            if(s[p] == 'T'){
                p++;
                return true;
            }
            else if(s[p] == 'F'){
                p++;
                return false;
            }
            else if('a' <= s[p] && s[p] <= 'k'){
                int idx = s[p++] - 'a';
                if(bit(bt, idx)) return true;
                else return false;
            }
            else{
                exit(1);
            }
        };

        Parser<bool> parser(operators, operation, get_leaf, unary_operators, unary_operation);
        bool ans1 = parser.eval(s1, false);
        bool ans2 = parser.eval(s2, false);

        if(ans1 != ans2){
            cout << "NO" << endl;
            return;
        }
    }

    cout << "YES" << endl;
}

int main() {
    while(true) solve();
}
accuracy: 1
time_ms: 180
memory_kb: 3784
final_rank: 16

code_snippet: //
// LL1 再帰降下パーサー
//   計算結果を出力するだけでなく、構文解析木を構築する
//
// verified:
//   AOJ 0109 スマート計算機 (for basic expression)
//     https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0109&lang=jp
//
//   AOJ 2613 Unordered Operators (for operator priority)
//     https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2613
//
//   AOJ 2401 恒等式 (for unary "not" operator)
//     https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2401
//
//   AOJ 1346 Miscalculation (for operator priority)
//     https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1346
//
//   TTPC 2023 F - N^a (log N)^b (for unary "log" operator)
//     https://atcoder.jp/contests/ttpc2023/tasks/ttpc2023_f
//
//   AtCoder codeFlyer E - 数式とクエリ (for parse-tree)
//     https://atcoder.jp/contests/bitflyer2018-final-open/tasks/bitflyer2018_final_e
//


/*
 basic settings:
 　・vector<set<string>> OPERATORS
        - 登場する二項演算子と、その優先順位を設定する
 　・function<T(const string&, T, T)> OPERATION
        - 二項演算子に応じた二項演算の結果を出力する処理を設定する

 optional settings:
 　・function<T(const string&, int&)> GET_LEAF
        - 構文解析木において葉となる部分のパース方法を外部から指示したい場合に設定する
        - 第二引数は文字列中の index を表す
 　・string UNARY_OPERATORS
        - パースする文字列に単項演算子 ("-" や "log" など) が含まれる場合、その関数を表す文字列を設定
 　・function<T(T)> UNARY_OPERATION
        - パースする文字列に単項演算子 ("-" や "log" など) が含まれる場合、その関数の中身を設定

 usage:
 　・eval(const string &str, bool default_parse_numeric = true)
        - 与えられた文字列 S をパースして、計算結果を出力する
        - root, left, right などに構文解析木の構造が格納される (詳細は dump() を参照)
        - 引数 default_parse_numeric について
            - true：文字列 S 中の "927" などの通常の数値情報を long long 型にパースする
            - false：数値情報などをパースする関数オブジェクトを外部で定義して渡す
 　・dump()
        - 文字列 S の構文解析木を出力する
 */


#include <bits/stdc++.h>
using namespace std;


// Parser (T must have constructor T(long long))
template<class T> struct Parser {
    /* basic settings */
    vector<vector<string>> OPERATORS;               // binary operator priority
    function<T(const string&, T, T)> OPERATION;     // binary operation

    /* optional settings */
    function<T(const string&, int&)> GET_LEAF;      // leaf parser
    vector<string> UNARY_OPERATORS;                 // unary operator (ex: "-", "log")
    function<T(const string&, T)> UNARY_OPERATION;  // unary operation
    const string OPERATOR_NUMBER = "num";

    /* result: parse tree */
    int root;                    // vals[root] is the answer
    vector<T> vals;              // value of each node
    vector<string> ops;          // operator of each node
    vector<int> left, right;     // the index of left-node, right-node
    vector<int> ids;             // the node-index of the i-th value

    /* constructor */
    string S;
    Parser() {}
    Parser(const vector<vector<string>> &operators,
           const function<T(const string&, T, T)> operation) {
        init(operators, operation);
    }
    Parser(const vector<vector<string>> &operators,
           const function<T(const string&, T, T)> operation,
           const function<T(const string&, int&)> get_leaf) {
        init(operators, operation, get_leaf);
    }
    Parser(const vector<vector<string>> &operators,
           const function<T(const string&, T, T)> operation,
           const vector<string> &unary_operators,
           const function<T(const string &op, T)> unary_operation) {
        init(operators, operation, unary_operators, unary_operation);
    }
    Parser(const vector<vector<string>> &operators,
           const function<T(const string&, T, T)> operation,
           const function<T(const string&, int&)> get_leaf,
           const vector<string> &unary_operators,
           const function<T(const string &op, T)> unary_operation) {
        init(operators, operation, get_leaf, unary_operators, unary_operation);
    }
    void init(const vector<vector<string>> &operators,
              const function<T(const string&, T, T)> operation) {
        OPERATORS = operators, OPERATION = operation;
    }
    void init(const vector<vector<string>> &operators,
              const function<T(const string&, T, T)> operation,
              const function<T(const string&, int&)> get_leaf) {
        OPERATORS = operators, OPERATION = operation;
        GET_LEAF = get_leaf;
    }
    void init(const vector<vector<string>> &operators,
              const function<T(const string&, T, T)> operation,
              const vector<string> &unary_operators,
              const function<T(const string &op, T)> unary_operation) {
        OPERATORS = operators, OPERATION = operation;
        UNARY_OPERATORS = unary_operators, UNARY_OPERATION = unary_operation;
    }
    void init(const vector<vector<string>> &operators,
              const function<T(const string&, T, T)> operation,
              const function<T(const string&, int&)> get_leaf,
              const vector<string> &unary_operators,
              const function<T(const string &op, T)> unary_operation) {
        OPERATORS = operators, OPERATION = operation;
        GET_LEAF = get_leaf;
        UNARY_OPERATORS = unary_operators, UNARY_OPERATION = unary_operation;
    }
    void clear() {
        S = "";
        vals.clear(), ops.clear(), left.clear(), right.clear(), ids.clear();
    }

    /* eval */
    T eval(const string &str, bool default_parse_numeric = true) {
        clear();
        S = str;
        int p = 0, id = 0;
        root = parse(p, id, default_parse_numeric);
        return vals[root];
    }

    /* node generator */
    // value
    int new_leaf(T val, int &id) {
        vals.push_back(val);
        ops.push_back(OPERATOR_NUMBER);
        left.push_back(-1);
        right.push_back(-1);
        ids.push_back(id++);
        return (int)vals.size() - 1;
    }
    // FUNC(lp)
    int new_node_with_left(T val, const string &op, int lp) {
        vals.push_back(val);
        ops.push_back(op);
        left.push_back(lp);
        right.push_back(-1);
        ids.push_back(-1);
        return (int)vals.size() - 1;
    }
    // (lp) op (rp)
    int new_node_with_left_right(const string &op, int lp, int rp) {
        vals.push_back(OPERATION(op, vals[lp], vals[rp]));
        ops.push_back(op);
        left.push_back(lp);
        right.push_back(rp);
        ids.push_back(-1);
        return (int)vals.size() - 1;
    }

    /* parser */
    int parse(int &p, int &id, bool default_parse_numeric, int depth = 0) {
        assert(p >= 0 && p < (int)S.size());
        string op;
        if (depth < (int)OPERATORS.size()) {
            // recursive descent
            int lp = parse(p, id, default_parse_numeric, depth + 1);
            bool update = false;
            do {
                update = false;
                if (is_in_the_operators(p, op,
                                        OPERATORS[(int)OPERATORS.size() - depth - 1])) {
                    int rp = parse(p, id, default_parse_numeric, depth + 1);
                    lp = new_node_with_left_right(op, lp, rp);
                    update = true;
                }
            } while (p < (int)S.size() && update);
            return lp;
        }
        else if (default_parse_numeric && isdigit(S[p])) {
            return get_number(p, id);
        }
        else if (S[p] == '(') {
            return get_bracket(p, id, default_parse_numeric);
        }
        else if (is_in_the_operators(p, op, UNARY_OPERATORS)) {
            return get_unary_operation(p, id, op, default_parse_numeric);
        }
        else {
            return new_leaf(GET_LEAF(S, p), id);
        }
    }
    bool is_the_operator(int &p, const string &op) {
        if (op != "" && S.substr(p, op.size()) == op) {
            p += op.size();
            return true;
        }
        return false;
    }
    bool is_in_the_operators(int &p, string &res_op, const vector<string> &ops) {
        for (const auto &op : ops) {
            if (is_the_operator(p, op)) {
                res_op = op;
                return true;
            }
        }
        return false;
    }
    int get_number(int &p, int &id) {
        long long val = 0, sign = 1;
        if (S[p] == '-') sign = -1, ++p;
        while (p < (int)S.size() && isdigit(S[p])) {
            val = val * 10 + (int)(S[p++] - '0');
        }
        return new_leaf(T(val * sign), id);
    }
    int get_bracket(int &p, int &id, bool default_parse_numeric) {
        ++p;  // skip "("
        int lp = parse(p, id, default_parse_numeric, 0);
        ++p;  // skip ")"
        return lp;
    }
    int get_unary_operation(int &p, int &id, const string &op,
                            bool default_parse_numeric) {
        int lp;
        if (S[p] == '(') lp = get_bracket(p, id, default_parse_numeric);
        else lp = parse(p, id, default_parse_numeric, (int)OPERATORS.size());
        return new_node_with_left(UNARY_OPERATION(op, vals[lp]), op, lp);
    }

    /* dump */
    void dump() {
        dump_rec(root);
    }
    void dump_rec(int v, string space = "") {
        cout << space << v << ": (" << ops[v] << ", " << vals[v]
             << ") -> left: " << left[v] << ", right: " << right[v] << endl;
        if (left[v] != -1) dump_rec(left[v], space + "  ");
        if (right[v] != -1) dump_rec(right[v], space + "  ");
    }
};



//------------------------------//
// Examples
//------------------------------//

/* user small test */
void small_test() {
    // set parser
    vector<vector<string>> operators = {{"*", "/"}, {"+", "-"}};
    auto operation = [&](const string &op, long long a, long long b) -> long long {
        if (op == "+") return a + b;
        else if (op == "-") return a - b;
        else if (op == "*") return a * b;
        else if (op == "/") return a / b;
        else return 0;
    };
    vector<string> unary_operators = {"-"};
    auto unary_operation = [&](const string &op, long long a) -> long long {
        return -a;
    };
    Parser<long long> ps(operators, operation, unary_operators, unary_operation);

    vector<string> tests = {
        "-(-3)",
        "-(-9+3*(-4))",
        "-5-(-3)",
        "-4-99"
    };
    for (const auto &S : tests) {
        cout << S << " = " << ps.eval(S) << endl;
    }
}


/* AOJ 0109 */
void AOJ_0109() {
    vector<vector<string>> operators = {{"*", "/"}, {"+", "-"}};
    auto operation = [&](const string &op, long long a, long long b) -> long long {
        if (op == "+") return a + b;
        else if (op == "-") return a - b;
        else if (op == "*") return a * b;
        else if (op == "/") return a / b;
        else return 0;
    };
    Parser<long long> ps(operators, operation);

    int N;
    cin >> N;
    for (int i = 0; i < N; ++i) {
        string S;
        cin >> S;
        S.pop_back();
        cout << ps.eval(S) << endl;
    }
}


/* AOJ 2613 */
void AOJ_2613() {
    string S;
    cin >> S;

    // 二項演算を設定
    auto operation = [&](const string &op, long long l, long long r) -> long long {
        if (op == "+") return l + r;
        else if (op == "-") return l - r;
        else return l * r;
    };

    // 演算子の優先順位をすべて試す
    long long res = -LONG_MAX;
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 3; ++j) {
            for (int k = 0; k < 3; ++k) {
                vector<vector<string>> operators(3);
                operators[i].push_back("+");
                operators[j].push_back("-");
                operators[k].push_back("*");
                Parser<long long> ps(operators, operation);
                res = max(res, ps.eval(S));
            }
        }
    }
    cout << res << endl;
}


/* AOJ 2401 */
void AOJ_2401() {
    // parser settings //
    vector<vector<string>> ops = {{"+", "*", "->"}};
    auto operation = [&](const string &op, bool l, bool r) -> bool {
        if (op == "+") return (l || r);
        else if (op == "*") return (l && r);
        else if (op == "->") return (!l || r);
        else exit(1);
    };
    auto get_leaf = [&](const string &S, int &p) -> bool {
        return (S[p++] == 'T' ? true : false);
    };
    vector<string> unary_ops = {"-"};
    auto unary_operation = [&](const string &op, bool l) -> bool {
        if (op == "-") return !l;
        else exit(1);
    };
    Parser<bool> ps1(ops, operation, get_leaf, unary_ops, unary_operation);
    Parser<bool> ps2(ops, operation, get_leaf, unary_ops, unary_operation);

    string S;
    while (cin >> S) {
        if (S == "#") break;
        for (int i = 0; i < S.size(); ++i) if (S[i] == '=') S[i] = ' ';

        bool res = true;
        for (int bit = 0; bit < (1<<11); ++bit) {
            string SS = S;
            for (int i = 0; i < SS.size(); ++i) {
                if (SS[i] >= 'a' && SS[i] <= 'k') {
                    int id = SS[i] - 'a';
                    if (bit & (1<<id)) SS[i] = 'T';
                    else SS[i] = 'F';
                }
            }
            istringstream si(SS);
            string s1, s2;
            si >> s1 >> s2;
            bool r1 = ps1.eval(s1, false), r2 = ps2.eval(s2, false);
            if (r1 != r2) {
                res = false;
            }

        }
        if (res) cout << "YES" << endl;
        else cout << "NO" << endl;
    }
}


/* AOJ 1346 */
void AOJ_1346() {
    // multiplication-rool parser, left-to-right parser
    vector<vector<string>> operator_mul = {{"*"}, {"+"}};
    vector<vector<string>> operator_left_right = {{"+", "*"}};
    auto operation = [&](string op, long long a, long long b) -> long long {
        if (op == "+") return a + b;
        else return a * b;
    };
    Parser<long long> ps_mul(operator_mul, operation);
    Parser<long long> ps_left_right(operator_left_right, operation);

    string S;
    long long ans;
    cin >> S >> ans;

    bool mul = false, left_right = false;
    if (ps_mul.eval(S) == ans) mul = true;
    if (ps_left_right.eval(S) == ans) left_right = true;

    if (mul && left_right) cout << "U" << endl;
    else if (mul) cout << "M" << endl;
    else if (left_right) cout << "L" << endl;
    else cout << "I" << endl;
}


/* TTPC 2023 F */
struct Node {
    long long n, l, val;
    bool eps;
    Node(long long n = 0, long long l = 0, long long e = 0, long long v = 0)
        : n(n), l(l), eps(e), val(v) {}
    friend ostream& operator << (ostream &s, Node node) {
        return s << "(" << node.n << ", " << node.l << ", " << node.eps
                << ", " << node.val << ")";
    }
};

void TTPC_2023_F() {
    // operators
    vector<vector<string>> operators = {{"^"}, {"*"}, {"+"}};

    // define binary operation
    auto operation = [&](const string &op, const Node &l, const Node &r) -> Node {
        if (op == "+") {
            vector<long long> vl({l.n, l.l, (long long)l.eps, l.val});
            vector<long long> vr({r.n, r.l, (long long)r.eps, r.val});
            return (vl > vr ? l : r);
        }
        else if (op == "*") return Node(l.n + r.n, l.l + r.l, l.eps | r.eps, 1);
        else if (op == "^") return Node(l.n * r.val, l.l * r.val, l.eps, 1);
        else return Node();
    };

    // define number process
    auto get_leaf = [&](const string &S, int &p) -> Node {
        if (S[p] == 'N') {
            ++p;
            return Node(1, 0, false, 1);
        } else {
            long long val = 0;
            do {
                val = val * 10 + (int)(S[p++] - '0');
            } while (S[p] >= '0' && S[p] <= '9');
            return Node(0, 0, false, val);
        }
    };

    // define function (log)
    vector<string> unary_operators = {"log"};
    auto unary_operation = [&](const string &op, const Node &node) -> Node {
        if (op == "log") {
            if (node.n >= 1) return Node(0, 1, false, 1);
            else return Node(0, 0, true, 0);
        } else return Node();
    };

    // 入力
    string S;
    cin >> S;
    Parser<Node> ps(operators, operation, get_leaf, unary_operators, unary_operation);
    auto res = ps.eval(S, false);
    //ps.dump();

    if (res.eps) ++res.l;
    cout << res.n << " " << res.l << endl;
}


/* codeFloyer E */
template<int MOD> struct Fp {
    // inner value
    long long val;

    // constructor
    constexpr Fp() : val(0) { }
    constexpr Fp(long long v) : val(v % MOD) {
        if (val < 0) val += MOD;
    }
    constexpr long long get() const { return val; }
    constexpr int get_mod() const { return MOD; }

    // arithmetic operators
    constexpr Fp operator + () const { return Fp(*this); }
    constexpr Fp operator - () const { return Fp(0) - Fp(*this); }
    constexpr Fp operator + (const Fp &r) const { return Fp(*this) += r; }
    constexpr Fp operator - (const Fp &r) const { return Fp(*this) -= r; }
    constexpr Fp operator * (const Fp &r) const { return Fp(*this) *= r; }
    constexpr Fp operator / (const Fp &r) const { return Fp(*this) /= r; }
    constexpr Fp& operator += (const Fp &r) {
        val += r.val;
        if (val >= MOD) val -= MOD;
        return *this;
    }
    constexpr Fp& operator -= (const Fp &r) {
        val -= r.val;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr Fp& operator *= (const Fp &r) {
        val = val * r.val % MOD;
        return *this;
    }
    constexpr Fp& operator /= (const Fp &r) {
        long long a = r.val, b = MOD, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        val = val * u % MOD;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr Fp pow(long long n) const {
        Fp res(1), mul(*this);
        while (n > 0) {
            if (n & 1) res *= mul;
            mul *= mul;
            n >>= 1;
        }
        return res;
    }
    constexpr Fp inv() const {
        Fp res(1), div(*this);
        return res / div;
    }

    // other operators
    constexpr bool operator == (const Fp &r) const {
        return this->val == r.val;
    }
    constexpr bool operator != (const Fp &r) const {
        return this->val != r.val;
    }
    constexpr Fp& operator ++ () {
        ++val;
        if (val >= MOD) val -= MOD;
        return *this;
    }
    constexpr Fp& operator -- () {
        if (val == 0) val += MOD;
        --val;
        return *this;
    }
    constexpr Fp operator ++ (int) const {
        Fp res = *this;
        ++*this;
        return res;
    }
    constexpr Fp operator -- (int) const {
        Fp res = *this;
        --*this;
        return res;
    }
    friend constexpr istream& operator >> (istream &is, Fp<MOD> &x) {
        is >> x.val;
        x.val %= MOD;
        if (x.val < 0) x.val += MOD;
        return is;
    }
    friend constexpr ostream& operator << (ostream &os, const Fp<MOD> &x) {
        return os << x.val;
    }
    friend constexpr Fp<MOD> pow(const Fp<MOD> &r, long long n) {
        return r.pow(n);
    }
    friend constexpr Fp<MOD> inv(const Fp<MOD> &r) {
        return r.inv();
    }
};

void codeFloyer_E() {
    const int MOD = 1000000007;
    using mint = Fp<MOD>;

    // 入力
    string S;
    int Q;
    cin >> S >> Q;
    int N = 0;
    for (int i = 0; i < S.size(); ++i) if (S[i] == 'a') ++N;
    vector<long long> given(N);
    for (int i = 0; i < N; ++i) cin >> given[i];

    // set Parser
    vector<vector<string>> operators = {{"*"}, {"+", "-"}};
    auto operation = [&](const string &op, mint a, mint b) -> mint {
        if (op == "+") return a + b;
        else if (op == "-") return a - b;
        else if (op == "*") return a * b;
        else return 0;
    };
    int id = 0;
    auto get_leaf = [&](const string &S, int &p) -> mint {
        if (S[p] == 'a') {
            ++p;
            return given[id++];
        } else return 0;
    };
    Parser<mint> ps(operators, operation, get_leaf);
    mint base = ps.eval(S);

    // DP
    vector<mint> dp(N);
    auto rec = [&](auto self, int v, mint w) -> void {
        if (ps.ops[v] == ps.OPERATOR_NUMBER) dp[ps.ids[v]] = w;
        else if (ps.ops[v] == "+") {
            self(self, ps.left[v], w);
            self(self, ps.right[v], w);
        }
        else if (ps.ops[v] == "-") {
            self(self, ps.left[v], w);
            self(self, ps.right[v], -w);
        }
        else if (ps.ops[v] == "*") {
            self(self, ps.left[v], w * ps.vals[ps.right[v]]);
            self(self, ps.right[v], w * ps.vals[ps.left[v]]);
        }
    };
    rec(rec, ps.root, mint(1));

    // 出力
    for (int q = 0; q < Q; ++q) {
        long long id, x;
        cin >> id >> x;
        --id;
        mint res = base + dp[id] * (x - given[id]);
        cout << res << endl;
    }
}


int main() {
    // small_test();
    //AOJ_0109();
    //AOJ_2613();
    AOJ_2401();
    //AOJ_1346();
    //TTPC_2023_F();
    //codeFloyer_E();
}
accuracy: 1
time_ms: 310
memory_kb: 3824
final_rank: 17

code_snippet: //
// LL1 再帰降下パーサー
//   計算結果を出力するだけでなく、構文解析木を構築する
//
// verified:
//   AOJ 0109 スマート計算機 (for basic expression)
//     https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0109&lang=jp
//
//   AOJ 2613 Unordered Operators (for operator priority)
//     https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2613
//
//   AOJ 2401 恒等式 (for unary "not" operator)
//     https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2401
//
//   AOJ 1346 Miscalculation (for operator priority)
//     https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1346
//
//   TTPC 2023 F - N^a (log N)^b (for unary "log" operator)
//     https://atcoder.jp/contests/ttpc2023/tasks/ttpc2023_f
//
//   AtCoder codeFlyer E - 数式とクエリ (for parse-tree)
//     https://atcoder.jp/contests/bitflyer2018-final-open/tasks/bitflyer2018_final_e
//


/*
 basic settings:
 　・vector<set<string>> OPERATORS
        - 登場する二項演算子と、その優先順位を設定する
 　・function<T(const string&, T, T)> OPERATION
        - 二項演算子に応じた二項演算の結果を出力する処理を設定する

 optional settings:
 　・function<T(const string&, int&)> GET_LEAF
        - 構文解析木において葉となる部分のパース方法を外部から指示したい場合に設定する
        - 第二引数は文字列中の index を表す
 　・string UNARY_OPERATORS
        - パースする文字列に単項演算子 ("-" や "log" など) が含まれる場合、その関数を表す文字列を設定
 　・function<T(T)> UNARY_OPERATION
        - パースする文字列に単項演算子 ("-" や "log" など) が含まれる場合、その関数の中身を設定

 usage:
 　・eval(const string &str, bool default_parse_numeric = true)
        - 与えられた文字列 S をパースして、計算結果を出力する
        - root, left, right などに構文解析木の構造が格納される (詳細は dump() を参照)
        - 引数 default_parse_numeric について
            - true：文字列 S 中の "927" などの通常の数値情報を long long 型にパースする
            - false：数値情報などをパースする関数オブジェクトを外部で定義して渡す
 　・dump()
        - 文字列 S の構文解析木を出力する
 */


#include <bits/stdc++.h>
using namespace std;


// Parser (T must have constructor T(long long))
template<class T> struct Parser {
    /* basic settings */
    vector<vector<string>> OPERATORS;               // binary operator priority
    function<T(const string&, T, T)> OPERATION;     // binary operation

    /* optional settings */
    function<T(const string&, int&)> GET_LEAF;      // leaf parser
    vector<string> UNARY_OPERATORS;                 // unary operator (ex: "-", "log")
    function<T(const string&, T)> UNARY_OPERATION;  // unary operation
    const string OPERATOR_NUMBER = "num";

    /* result: parse tree */
    int root;                    // vals[root] is the answer
    vector<T> vals;              // value of each node
    vector<string> ops;          // operator of each node
    vector<int> left, right;     // the index of left-node, right-node
    vector<int> ids;             // the node-index of the i-th value

    /* constructor */
    string S;
    Parser() {}
    Parser(const vector<vector<string>> &operators,
           const function<T(const string&, T, T)> operation) {
        init(operators, operation);
    }
    Parser(const vector<vector<string>> &operators,
           const function<T(const string&, T, T)> operation,
           const function<T(const string&, int&)> get_leaf) {
        init(operators, operation, get_leaf);
    }
    Parser(const vector<vector<string>> &operators,
           const function<T(const string&, T, T)> operation,
           const vector<string> &unary_operators,
           const function<T(const string &op, T)> unary_operation) {
        init(operators, operation, unary_operators, unary_operation);
    }
    Parser(const vector<vector<string>> &operators,
           const function<T(const string&, T, T)> operation,
           const function<T(const string&, int&)> get_leaf,
           const vector<string> &unary_operators,
           const function<T(const string &op, T)> unary_operation) {
        init(operators, operation, get_leaf, unary_operators, unary_operation);
    }
    void init(const vector<vector<string>> &operators,
              const function<T(const string&, T, T)> operation) {
        OPERATORS = operators, OPERATION = operation;
    }
    void init(const vector<vector<string>> &operators,
              const function<T(const string&, T, T)> operation,
              const function<T(const string&, int&)> get_leaf) {
        OPERATORS = operators, OPERATION = operation;
        GET_LEAF = get_leaf;
    }
    void init(const vector<vector<string>> &operators,
              const function<T(const string&, T, T)> operation,
              const vector<string> &unary_operators,
              const function<T(const string &op, T)> unary_operation) {
        OPERATORS = operators, OPERATION = operation;
        UNARY_OPERATORS = unary_operators, UNARY_OPERATION = unary_operation;
    }
    void init(const vector<vector<string>> &operators,
              const function<T(const string&, T, T)> operation,
              const function<T(const string&, int&)> get_leaf,
              const vector<string> &unary_operators,
              const function<T(const string &op, T)> unary_operation) {
        OPERATORS = operators, OPERATION = operation;
        GET_LEAF = get_leaf;
        UNARY_OPERATORS = unary_operators, UNARY_OPERATION = unary_operation;
    }
    void clear() {
        S = "";
        vals.clear(), ops.clear(), left.clear(), right.clear(), ids.clear();
    }

    /* eval */
    T eval(const string &str, bool default_parse_numeric = true) {
        clear();
        S = str;
        int p = 0, id = 0;
        root = parse(p, id, default_parse_numeric);
        return vals[root];
    }

    /* node generator */
    // value
    int new_leaf(T val, int &id) {
        vals.push_back(val);
        ops.push_back(OPERATOR_NUMBER);
        left.push_back(-1);
        right.push_back(-1);
        ids.push_back(id++);
        return (int)vals.size() - 1;
    }
    // FUNC(lp)
    int new_node_with_left(T val, const string &op, int lp) {
        vals.push_back(val);
        ops.push_back(op);
        left.push_back(lp);
        right.push_back(-1);
        ids.push_back(-1);
        return (int)vals.size() - 1;
    }
    // (lp) op (rp)
    int new_node_with_left_right(const string &op, int lp, int rp) {
        vals.push_back(OPERATION(op, vals[lp], vals[rp]));
        ops.push_back(op);
        left.push_back(lp);
        right.push_back(rp);
        ids.push_back(-1);
        return (int)vals.size() - 1;
    }

    /* parser */
    int parse(int &p, int &id, bool default_parse_numeric, int depth = 0) {
        assert(p >= 0 && p < (int)S.size());
        string op;
        if (depth < (int)OPERATORS.size()) {
            // recursive descent
            int lp = parse(p, id, default_parse_numeric, depth + 1);
            bool update = false;
            do {
                update = false;
                if (is_in_the_operators(p, op,
                                        OPERATORS[(int)OPERATORS.size() - depth - 1])) {
                    int rp = parse(p, id, default_parse_numeric, depth + 1);
                    lp = new_node_with_left_right(op, lp, rp);
                    update = true;
                }
            } while (p < (int)S.size() && update);
            return lp;
        }
        else if (default_parse_numeric && isdigit(S[p])) {
            return get_number(p, id);
        }
        else if (S[p] == '(') {
            return get_bracket(p, id, default_parse_numeric);
        }
        else if (is_in_the_operators(p, op, UNARY_OPERATORS)) {
            return get_unary_operation(p, id, op, default_parse_numeric);
        }
        else {
            return new_leaf(GET_LEAF(S, p), id);
        }
    }
    bool is_the_operator(int &p, const string &op) {
        if (op != "" && S.substr(p, op.size()) == op) {
            p += op.size();
            return true;
        }
        return false;
    }
    bool is_in_the_operators(int &p, string &res_op, const vector<string> &ops) {
        for (const auto &op : ops) {
            if (is_the_operator(p, op)) {
                res_op = op;
                return true;
            }
        }
        return false;
    }
    int get_number(int &p, int &id) {
        long long val = 0, sign = 1;
        if (S[p] == '-') sign = -1, ++p;
        while (p < (int)S.size() && isdigit(S[p])) {
            val = val * 10 + (int)(S[p++] - '0');
        }
        return new_leaf(T(val * sign), id);
    }
    int get_bracket(int &p, int &id, bool default_parse_numeric) {
        ++p;  // skip "("
        int lp = parse(p, id, default_parse_numeric, 0);
        ++p;  // skip ")"
        return lp;
    }
    int get_unary_operation(int &p, int &id, const string &op,
                            bool default_parse_numeric) {
        int lp;
        if (S[p] == '(') lp = get_bracket(p, id, default_parse_numeric);
        else lp = parse(p, id, default_parse_numeric, (int)OPERATORS.size());
        return new_node_with_left(UNARY_OPERATION(op, vals[lp]), op, lp);
    }

    /* dump */
    void dump() {
        dump_rec(root);
    }
    void dump_rec(int v, string space = "") {
        cout << space << v << ": (" << ops[v] << ", " << vals[v]
             << ") -> left: " << left[v] << ", right: " << right[v] << endl;
        if (left[v] != -1) dump_rec(left[v], space + "  ");
        if (right[v] != -1) dump_rec(right[v], space + "  ");
    }
};



//------------------------------//
// Examples
//------------------------------//

/* user small test */
void small_test() {
    // set parser
    vector<vector<string>> operators = {{"*", "/"}, {"+", "-"}};
    auto operation = [&](const string &op, long long a, long long b) -> long long {
        if (op == "+") return a + b;
        else if (op == "-") return a - b;
        else if (op == "*") return a * b;
        else if (op == "/") return a / b;
        else return 0;
    };
    vector<string> unary_operators = {"-"};
    auto unary_operation = [&](const string &op, long long a) -> long long {
        return -a;
    };
    Parser<long long> ps(operators, operation, unary_operators, unary_operation);

    vector<string> tests = {
        "-(-3)",
        "-(-9+3*(-4))",
        "-5-(-3)",
        "-4-99"
    };
    for (const auto &S : tests) {
        cout << S << " = " << ps.eval(S) << endl;
    }
}


/* AOJ 0109 */
void AOJ_0109() {
    vector<vector<string>> operators = {{"*", "/"}, {"+", "-"}};
    auto operation = [&](const string &op, long long a, long long b) -> long long {
        if (op == "+") return a + b;
        else if (op == "-") return a - b;
        else if (op == "*") return a * b;
        else if (op == "/") return a / b;
        else return 0;
    };
    Parser<long long> ps(operators, operation);

    int N;
    cin >> N;
    for (int i = 0; i < N; ++i) {
        string S;
        cin >> S;
        S.pop_back();
        cout << ps.eval(S) << endl;
    }
}


/* AOJ 2613 */
void AOJ_2613() {
    string S;
    cin >> S;

    // 二項演算を設定
    auto operation = [&](const string &op, long long l, long long r) -> long long {
        if (op == "+") return l + r;
        else if (op == "-") return l - r;
        else return l * r;
    };

    // 演算子の優先順位をすべて試す
    long long res = -LONG_MAX;
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 3; ++j) {
            for (int k = 0; k < 3; ++k) {
                vector<vector<string>> operators(3);
                operators[i].push_back("+");
                operators[j].push_back("-");
                operators[k].push_back("*");
                Parser<long long> ps(operators, operation);
                res = max(res, ps.eval(S));
            }
        }
    }
    cout << res << endl;
}


/* AOJ 2401 */
void AOJ_2401() {
    // parser settings //
    vector<vector<string>> ops = {{"+", "*", "->"}};
    auto operation = [&](const string &op, bool l, bool r) -> bool {
        if (op == "+") return (l || r);
        else if (op == "*") return (l && r);
        else if (op == "->") return (!l || r);
        else return true;
    };
    auto get_leaf = [&](const string &S, int &p) -> bool {
        return (S[p++] == 'T' ? true : false);
    };
    vector<string> unary_ops = {"-"};
    auto unary_operation = [&](const string &op, bool l) -> bool {
        if (op == "-") return !l;
        else return l;
    };
    Parser<bool> ps1(ops, operation, get_leaf, unary_ops, unary_operation);
    Parser<bool> ps2(ops, operation, get_leaf, unary_ops, unary_operation);

    string S;
    while (cin >> S) {
        if (S == "#") break;
        for (int i = 0; i < S.size(); ++i) if (S[i] == '=') S[i] = ' ';

        bool res = true;
        for (int bit = 0; bit < (1<<11); ++bit) {
            string SS = S;
            for (int i = 0; i < SS.size(); ++i) {
                if (SS[i] >= 'a' && SS[i] <= 'k') {
                    int id = SS[i] - 'a';
                    if (bit & (1<<id)) SS[i] = 'T';
                    else SS[i] = 'F';
                }
            }
            istringstream si(SS);
            string s1, s2;
            si >> s1 >> s2;
            bool r1 = ps1.eval(s1, false), r2 = ps2.eval(s2, false);
            if (r1 != r2) {
                res = false;
            }
        }
        if (res) cout << "YES" << endl;
        else cout << "NO" << endl;
    }
}


/* AOJ 1346 */
void AOJ_1346() {
    // multiplication-rool parser, left-to-right parser
    vector<vector<string>> operator_mul = {{"*"}, {"+"}};
    vector<vector<string>> operator_left_right = {{"+", "*"}};
    auto operation = [&](string op, long long a, long long b) -> long long {
        if (op == "+") return a + b;
        else return a * b;
    };
    Parser<long long> ps_mul(operator_mul, operation);
    Parser<long long> ps_left_right(operator_left_right, operation);

    string S;
    long long ans;
    cin >> S >> ans;

    bool mul = false, left_right = false;
    if (ps_mul.eval(S) == ans) mul = true;
    if (ps_left_right.eval(S) == ans) left_right = true;

    if (mul && left_right) cout << "U" << endl;
    else if (mul) cout << "M" << endl;
    else if (left_right) cout << "L" << endl;
    else cout << "I" << endl;
}


/* TTPC 2023 F */
struct Node {
    long long n, l, val;
    bool eps;
    Node(long long n = 0, long long l = 0, long long e = 0, long long v = 0)
        : n(n), l(l), eps(e), val(v) {}
    friend ostream& operator << (ostream &s, Node node) {
        return s << "(" << node.n << ", " << node.l << ", " << node.eps
                << ", " << node.val << ")";
    }
};

void TTPC_2023_F() {
    // operators
    vector<vector<string>> operators = {{"^"}, {"*"}, {"+"}};

    // define binary operation
    auto operation = [&](const string &op, const Node &l, const Node &r) -> Node {
        if (op == "+") {
            vector<long long> vl({l.n, l.l, (long long)l.eps, l.val});
            vector<long long> vr({r.n, r.l, (long long)r.eps, r.val});
            return (vl > vr ? l : r);
        }
        else if (op == "*") return Node(l.n + r.n, l.l + r.l, l.eps | r.eps, 1);
        else if (op == "^") return Node(l.n * r.val, l.l * r.val, l.eps, 1);
        else return Node();
    };

    // define number process
    auto get_leaf = [&](const string &S, int &p) -> Node {
        if (S[p] == 'N') {
            ++p;
            return Node(1, 0, false, 1);
        } else {
            long long val = 0;
            do {
                val = val * 10 + (int)(S[p++] - '0');
            } while (S[p] >= '0' && S[p] <= '9');
            return Node(0, 0, false, val);
        }
    };

    // define function (log)
    vector<string> unary_operators = {"log"};
    auto unary_operation = [&](const string &op, const Node &node) -> Node {
        if (op == "log") {
            if (node.n >= 1) return Node(0, 1, false, 1);
            else return Node(0, 0, true, 0);
        } else return Node();
    };

    // 入力
    string S;
    cin >> S;
    Parser<Node> ps(operators, operation, get_leaf, unary_operators, unary_operation);
    auto res = ps.eval(S, false);
    //ps.dump();

    if (res.eps) ++res.l;
    cout << res.n << " " << res.l << endl;
}


/* codeFloyer E */
template<int MOD> struct Fp {
    // inner value
    long long val;

    // constructor
    constexpr Fp() : val(0) { }
    constexpr Fp(long long v) : val(v % MOD) {
        if (val < 0) val += MOD;
    }
    constexpr long long get() const { return val; }
    constexpr int get_mod() const { return MOD; }

    // arithmetic operators
    constexpr Fp operator + () const { return Fp(*this); }
    constexpr Fp operator - () const { return Fp(0) - Fp(*this); }
    constexpr Fp operator + (const Fp &r) const { return Fp(*this) += r; }
    constexpr Fp operator - (const Fp &r) const { return Fp(*this) -= r; }
    constexpr Fp operator * (const Fp &r) const { return Fp(*this) *= r; }
    constexpr Fp operator / (const Fp &r) const { return Fp(*this) /= r; }
    constexpr Fp& operator += (const Fp &r) {
        val += r.val;
        if (val >= MOD) val -= MOD;
        return *this;
    }
    constexpr Fp& operator -= (const Fp &r) {
        val -= r.val;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr Fp& operator *= (const Fp &r) {
        val = val * r.val % MOD;
        return *this;
    }
    constexpr Fp& operator /= (const Fp &r) {
        long long a = r.val, b = MOD, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        val = val * u % MOD;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr Fp pow(long long n) const {
        Fp res(1), mul(*this);
        while (n > 0) {
            if (n & 1) res *= mul;
            mul *= mul;
            n >>= 1;
        }
        return res;
    }
    constexpr Fp inv() const {
        Fp res(1), div(*this);
        return res / div;
    }

    // other operators
    constexpr bool operator == (const Fp &r) const {
        return this->val == r.val;
    }
    constexpr bool operator != (const Fp &r) const {
        return this->val != r.val;
    }
    constexpr Fp& operator ++ () {
        ++val;
        if (val >= MOD) val -= MOD;
        return *this;
    }
    constexpr Fp& operator -- () {
        if (val == 0) val += MOD;
        --val;
        return *this;
    }
    constexpr Fp operator ++ (int) const {
        Fp res = *this;
        ++*this;
        return res;
    }
    constexpr Fp operator -- (int) const {
        Fp res = *this;
        --*this;
        return res;
    }
    friend constexpr istream& operator >> (istream &is, Fp<MOD> &x) {
        is >> x.val;
        x.val %= MOD;
        if (x.val < 0) x.val += MOD;
        return is;
    }
    friend constexpr ostream& operator << (ostream &os, const Fp<MOD> &x) {
        return os << x.val;
    }
    friend constexpr Fp<MOD> pow(const Fp<MOD> &r, long long n) {
        return r.pow(n);
    }
    friend constexpr Fp<MOD> inv(const Fp<MOD> &r) {
        return r.inv();
    }
};

void codeFloyer_E() {
    const int MOD = 1000000007;
    using mint = Fp<MOD>;

    // 入力
    string S;
    int Q;
    cin >> S >> Q;
    int N = 0;
    for (int i = 0; i < S.size(); ++i) if (S[i] == 'a') ++N;
    vector<long long> given(N);
    for (int i = 0; i < N; ++i) cin >> given[i];

    // set Parser
    vector<vector<string>> operators = {{"*"}, {"+", "-"}};
    auto operation = [&](const string &op, mint a, mint b) -> mint {
        if (op == "+") return a + b;
        else if (op == "-") return a - b;
        else if (op == "*") return a * b;
        else return 0;
    };
    int id = 0;
    auto get_leaf = [&](const string &S, int &p) -> mint {
        if (S[p] == 'a') {
            ++p;
            return given[id++];
        } else return 0;
    };
    Parser<mint> ps(operators, operation, get_leaf);
    mint base = ps.eval(S);

    // DP
    vector<mint> dp(N);
    auto rec = [&](auto self, int v, mint w) -> void {
        if (ps.ops[v] == ps.OPERATOR_NUMBER) dp[ps.ids[v]] = w;
        else if (ps.ops[v] == "+") {
            self(self, ps.left[v], w);
            self(self, ps.right[v], w);
        }
        else if (ps.ops[v] == "-") {
            self(self, ps.left[v], w);
            self(self, ps.right[v], -w);
        }
        else if (ps.ops[v] == "*") {
            self(self, ps.left[v], w * ps.vals[ps.right[v]]);
            self(self, ps.right[v], w * ps.vals[ps.left[v]]);
        }
    };
    rec(rec, ps.root, mint(1));

    // 出力
    for (int q = 0; q < Q; ++q) {
        long long id, x;
        cin >> id >> x;
        --id;
        mint res = base + dp[id] * (x - given[id]);
        cout << res << endl;
    }
}


int main() {
    // small_test();
    //AOJ_0109();
    //AOJ_2613();
    AOJ_2401();
    //AOJ_1346();
    //TTPC_2023_F();
    //codeFloyer_E();
}
accuracy: 1
time_ms: 300
memory_kb: 3936
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int INF = 1e9 + 10;
const ll INFL = 4e18;

const int V = 11;
bool v[V];

bool contain(bool a, bool b) {
    if (a && !b) return false;
    return true;
}

bool parse_formula(const string &s, int &i);
bool parse_equation(const string &s) {
    int i = 0;
    bool L = parse_formula(s, i);
    assert(s[i] == '=');
    i++;
    bool R = parse_formula(s, i);
    return L == R;
}

bool parse_formula(const string &s, int &i) {
    if (s[i] == 'T') {
        i++;
        return true;
    } else if (s[i] == 'F') {
        i++;
        return false;
    } else if ('a' <= s[i] && s[i] <= 'k') {
        bool ret = v[s[i] - 'a'];
        i++;
        return ret;
    } else if (s[i] == '-') {
        i++;
        return !parse_formula(s, i);
    } else if (s[i] == '(') {
        i++;
        bool ret = parse_formula(s, i);
        if (s[i] == '+') {
            i++;
            ret |= parse_formula(s, i);
        } else if (s[i] == '*') {
            i++;
            ret &= parse_formula(s, i);
        } else if (s[i] == '-' && s[i + 1] == '>') {
            i += 2;
            bool ret2 = parse_formula(s, i);
            ret = contain(ret, ret2);
        } else {
            exit(1);
        }
        assert(s[i] == ')');
        i++;
        return ret;
    }
    return true;
}

int main() {
    while (true) {
        string S;
        cin >> S;

        if (S == "#") break;

        bool ok = true;
        parse_equation(S);
        for (int i = 0; i < 1 << V; i++) {
            for (int j = 0; j < V; j++) {
                if (i >> j & 1)
                    v[j] = true;
                else
                    v[j] = false;
            }
            ok &= parse_equation(S);
        }

        cout << (ok ? "YES\n" : "NO\n");
    }
}
accuracy: 1
time_ms: 20
memory_kb: 3344
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef string::const_iterator state;
int expression(state &begin);
int term(state &begin);
int term2(state &begin);
int factor(state &begin);
int number(state &begin);

int expression(state &begin) {
    int ret = term(begin);
    for (;;) {
        if (*begin == '+') {
            begin++;
            ret = min(1, ret + term(begin));
        } else {
            break;
        }
    }
    return ret;
}

int term(state &begin) {
    int ret = term2(begin);
    for (;;) {
        if (*begin == '*') {
            begin++;
            ret *= term2(begin);
        } else if (*begin == '/') {
            begin++;
            int b = term2(begin);
            if (ret == 1 && b == 1) {
                ret = 1;
            } else if (ret == 1 && b == 0) {
                ret = 0;
            } else if (ret == 0 && b == 1) {
                ret = 1;
            } else {
                ret = 1;
            }
        } else {
            break;
        }
    }
    return ret;
}

int term2(state &begin) {
    int b = 1;
    if (*begin == '-') {
        begin++;
        return b ^ term2(begin);
    } else {
        return factor(begin);
    }
}

int factor(state &begin) {
    if (*begin == '(') {
        begin++;
        int ret = expression(begin);
        begin++;
        return ret;
    } else {
        int ret = number(begin);
        return ret;
    }
}

int number(state &begin) {
    int ret = 0;
    if (isdigit(*begin)) {
        ret *= 10;
        ret += *begin - '0';
        begin++;
    }
    return ret;
}

int main() {
    while (true) {
        string s;
        cin >> s;
        if (s == "#") {
            break;
        }
        string str;
        for (int i = 0; i < s.size(); i++) {
            if (i < s.size() - 1 && s[i] == '-' && s[i + 1] == '>') {
                str.push_back('/');
                i++;
            } else {
                if (s[i] == 'T') {
                    str.push_back('1');
                } else if (s[i] == 'F') {
                    str.push_back('0');
                } else {
                    str.push_back(s[i]);
                }
            }
        }
        bool flg = true;
        for (int i = 0; i < (1 << 11); i++) {
            bool b[12] = {};
            for (int j = 0; j < 11; j++) {
                if (i & (1 << j)) {
                    b[j] = 1;
                }
            }
            string bufstr;
            for (int j = 0; j < str.size(); j++) {
                if ('a' <= str[j] && str[j] <= 'k') {
                    int num = str[j] - 'a';
                    bufstr.push_back(b[num] + '0');
                } else {
                    bufstr.push_back(str[j]);
                }
            }
            string str1, str2;
            bool flag = false;
            for (int j = 0; j < bufstr.size(); j++) {
                if (bufstr[j] == '=') {
                    flag = true;
                } else if (!flag) {
                    str1.push_back(bufstr[j]);
                } else {
                    str2.push_back(bufstr[j]);
                }
            }
            state begin = str1.begin();
            state begin2 = str2.begin();
            int ans1 = expression(begin);
            int ans2 = expression(begin2);
            if (ans1 != ans2) {
                flg = false;
            }
        }
        if (flg) {
            cout << "YES" << endl;
        } else {
            cout << "NO" << endl;
        }
    }
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3368
final_rank: 4

code_snippet: #include <algorithm>
#include <cctype>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int mask;
struct Parser {
  typedef string::const_iterator State;
  bool solve(const string &S) {
    State begin = S.begin();
    return equation(begin);
  }
  bool equation(State &begin) {
    bool left = formula(begin);
    begin++;
    bool right = formula(begin);
    return left == right;
  }
  bool formula(State &begin) {
    if (*begin == '(') {
      begin++;
      bool left = formula(begin);
      char op = *begin;
      begin++;
      if (op == '-')
        begin++;
      bool right = formula(begin);
      begin++;
      bool ret = deduce(left, op, right);
      return ret;
    } else if (*begin == '-') {
      begin++;
      return !formula(begin);
    } else {
      return boolean(begin);
    }
  }
  bool deduce(bool x, char op, bool y) {
    if (op == '*') {
      return x & y;
    } else if (op == '+') {
      return x | y;
    } else {
      return !x | y;
    }
  }
  bool boolean(State &begin) {
    bool ret;
    if (*begin == 'T')
      ret = 1;
    else if (*begin == 'F')
      ret = 0;
    else
      ret = (mask >> (*begin - 'a')) & 1;
    begin++;
    return ret;
  }
};
void solve(string S) {
  Parser ps;
  for (mask = 0; mask < (1 << 11); mask++) {
    if (!ps.solve(S)) {
      cout << "NO" << endl;
      return;
    }
  }
  cout << "YES" << endl;
}
int main() {
  string S;
  while (cin >> S && S != "#") {
    solve(S);
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3416
final_rank: 2

code_snippet: #include <algorithm>
#include <cctype>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int mask;
template <class T> struct Parser {
  typedef string::const_iterator State;
  T solve(const string &S) {
    State begin = S.begin();
    return equation(begin);
  }
  T equation(State &begin) {
    T left = formula(begin);
    ++begin;
    T right = formula(begin);
    return left == right;
  }
  T formula(State &begin) {
    if (*begin == '(') {
      ++begin;
      T left = formula(begin);
      char op = *begin;
      ++begin;
      if (op == '-')
        ++begin;
      T right = formula(begin);
      ++begin;
      T ret = deduce(left, op, right);
      return ret;
    } else if (*begin == '-') {
      ++begin;
      return !formula(begin);
    } else {
      return boolean(begin);
    }
  }
  T deduce(T x, char op, T y) {
    if (op == '*') {
      return x and y;
    } else if (op == '+') {
      return x or y;
    } else {
      return !x or y;
    }
  }
  T boolean(State &begin) {
    T ret;
    if (*begin == 'T')
      ret = 1;
    else if (*begin == 'F')
      ret = 0;
    else
      ret = (mask >> (*begin - 'a')) & 1;
    ++begin;
    return ret;
  }
};
void solve(string S) {
  Parser<bool> ps;
  for (mask = 0; mask < (1 << 11); mask++) {
    if (!ps.solve(S)) {
      cout << "NO" << endl;
      return;
    }
  }
  cout << "YES" << endl;
}
int main() {
  string S;
  while (cin >> S && S != "#") {
    solve(S);
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3492
final_rank: 9

code_snippet: #include <algorithm>
#include <cctype>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int mask;
template <class T> struct Parser {
  typedef string::const_iterator State;
  T solve(const string &S) {
    State begin = S.begin();
    return equation(begin);
  }
  T equation(State &begin) {
    T left = formula(begin);
    begin++;
    T right = formula(begin);
    return left == right;
  }
  T formula(State &begin) {
    if (*begin == '(') {
      begin++;
      T left = formula(begin);
      char op = *begin;
      begin++;
      if (op == '-')
        begin++;
      T right = formula(begin);
      begin++;
      return deduce(left, op, right);
    } else if (*begin == '-') {
      begin++;
      T ret = !formula(begin);
      return ret;
    } else {
      return boolean(begin);
    }
  }
  T deduce(T x, char op, T y) {
    if (op == '*') {
      return x and y;
    } else if (op == '+') {
      return x or y;
    } else {
      return !x or y;
    }
  }
  T boolean(State &begin) {
    T ret;
    if (*begin == 'T')
      ret = 1;
    else if (*begin == 'F')
      ret = 0;
    else
      ret = (mask >> (*begin - 'a')) & 1;
    begin++;
    return ret;
  }
};

void solve(string S) {
  Parser<bool> ps;
  #pragma omp parallel for
  for (mask = 0; mask < (1 << 11); mask++) {
    if (!ps.solve(S)) {
      cout << "NO" << endl;
      return;
    }
  }
  cout << "YES" << endl;
}

int main() {
  string S;
  while (cin >> S && S != "#") {
    solve(S);
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3496
final_rank: 11