Problem p00950 (C++) — buggy submission, verdict: Runtime Error

#include <algorithm>
#include <cctype>
#include <cstdint>
#include <iostream>
#include <map>
#include <numeric>
#include <stdexcept>
#include <string>
#include <utility>

using Num = std::int64_t;

class Solver {
public:
  std::string s;
  Num solve() {
    std::map<char, int> char_idx;
    std::string symbols = "=+-*01()";
    Num num = 0;
    for (auto c : s) {
      if (std::isalpha(c) and char_idx.count(c) == 0) {
        int x = char_idx.size();
        char_idx[c] = x;
      }
    }
    if (char_idx.size() > 8)
      return 0;
    s_ = s;
    s_.push_back('\\0');
    std::sort(symbols.begin(), symbols.end());
    do {
      for (std::size_t i = 0; i < s_.size(); ++i) {
        s_[i] = (isalpha(s[i]) ? symbols[char_idx[s[i]]] : s[i]);
      }
      if (eval_q())
        ++num;
      std::reverse(symbols.begin() + char_idx.size(), symbols.end());
    } while (std::next_permutation(symbols.begin(), symbols.end()));
    return num;
  }

private:
  std::string s_;
  bool eval_q() {
    // std::cerr << "TRY: " << s_ << std::endl;
    try {
      std::size_t i = 0;
      Num left, right;
      left = eval_e(i);
      if (s_[i] != '=')
        throw std::runtime_error("left");
      ++i;
      right = eval_e(i);
      if (i < s.size())
        throw std::runtime_error("right");
      // std::cerr << left << (left == right? " == ": " != ") << right <<
      // std::endl;
      return left == right;
    } catch (std::runtime_error &e) {
      // std::cerr << "FAIL: " << e.what() << std::endl;
      return false;
    }
  }
  Num eval_e(std::size_t &i) {
    Num n = eval_t(i);
    while (i < s.size()) {
      if (s_[i] == '+') {
        ++i;
        n += eval_t(i);
      } else if (s_[i] == '-') {
        ++i;
        n -= eval_t(i);
      } else {
        break;
      }
    }
    return n;
  }
  Num eval_t(std::size_t &i) {
    Num n = eval_f(i);
    while (s_[i] == '*') {
      ++i;
      n *= eval_f(i);
    }
    return n;
  }
  Num eval_f(std::size_t &i) {
    Num n;
    if (s_[i] == '-') {
      ++i;
      n = -eval_f(i);
    } else if (s_[i] == '(') {
      ++i;
      n = eval_e(i);
      if (s_[i] != ')')
        throw std::runtime_error(")");
      ++i;
    } else {
      n = eval_n(i);
    }
    return n;
  }
  Num eval_n(std::size_t &i) {
    if (s_[i] == '0' or s_[i] == '1') {
      Num n = s_[i] - '0';
      ++i;
      if (n == 0 and (s_[i] == '0' or s_[i] == '1'))
        throw std::runtime_error("leading zero");
      while (true) {
        if (s_[i] == '0' or s_[i] == '1') {
          n = 2 * n + s_[i] - '0';
          ++i;
        } else {
          break;
        }
      }
      return n;
    } else {
      throw std::runtime_error("N");
    }
  }
};

int main() {
  Solver s;
  std::cin >> s.s;
  std::cout << s.solve() << std::endl;
  return 0;
}

Error: 0
0 != 1
1 != 0


Fixed submission:

#include <algorithm>
#include <cctype>
#include <cstdint>
#include <iostream>
#include <map>
#include <numeric>
#include <stdexcept>
#include <string>
#include <utility>

using Num = std::int64_t;

class Solver {
public:
  std::string s;
  Num solve() {
    std::map<char, int> char_idx;
    std::string symbols = "=+-*01()";
    Num num = 0;
    for (auto c : s) {
      if (std::isalpha(c) and char_idx.count(c) == 0) {
        int x = char_idx.size();
        char_idx[c] = x;
      }
    }
    if (char_idx.size() > 8)
      return 0;
    s_ = s;
    std::sort(symbols.begin(), symbols.end());
    do {
      for (std::size_t i = 0; i < s_.size(); ++i) {
        s_[i] = (isalpha(s[i]) ? symbols[char_idx[s[i]]] : s[i]);
      }
      if (eval_q())
        ++num;
      std::reverse(symbols.begin() + char_idx.size(), symbols.end());
    } while (std::next_permutation(symbols.begin(), symbols.end()));
    return num;
  }

private:
  std::string s_;
  bool eval_q() {
    // std::cerr << "TRY: " << s_ << std::endl;
    try {
      std::size_t i = 0;
      Num left, right;
      left = eval_e(i);
      if (s_[i] != '=')
        throw std::runtime_error("left");
      ++i;
      right = eval_e(i);
      if (i < s_.size())
        throw std::runtime_error("right");
      std::cerr << left << (left == right ? " == " : " != ") << right
                << std::endl;
      return left == right;
    } catch (std::runtime_error &e) {
      // std::cerr << "FAIL: " << e.what() << std::endl;
      return false;
    }
  }
  Num eval_e(std::size_t &i) {
    Num n = eval_t(i);
    while (i < s_.size()) {
      if (s_[i] == '+') {
        ++i;
        n += eval_t(i);
      } else if (s_[i] == '-') {
        ++i;
        n -= eval_t(i);
      } else {
        break;
      }
    }
    return n;
  }
  Num eval_t(std::size_t &i) {
    Num n = eval_f(i);
    while (s_[i] == '*') {
      ++i;
      n *= eval_f(i);
    }
    return n;
  }
  Num eval_f(std::size_t &i) {
    Num n;
    if (s_[i] == '-') {
      ++i;
      n = -eval_f(i);
    } else if (s_[i] == '(') {
      ++i;
      n = eval_e(i);
      if (s_[i] != ')')
        throw std::runtime_error(")");
      ++i;
    } else {
      n = eval_n(i);
    }
    return n;
  }
  Num eval_n(std::size_t &i) {
    if (s_[i] == '0' or s_[i] == '1') {
      Num n = s_[i] - '0';
      ++i;
      if (n == 0 and (s_[i] == '0' or s_[i] == '1'))
        throw std::runtime_error("leading zero");
      while (true) {
        if (s_[i] == '0' or s_[i] == '1') {
          n = 2 * n + s_[i] - '0';
          ++i;
        } else {
          break;
        }
      }
      return n;
    } else {
      throw std::runtime_error("N");
    }
  }
};

int main() {
  Solver s;
  std::cin >> s.s;
  std::cout << s.solve() << std::endl;
  return 0;
}