algo — C++23 日本語リファレンス GitHub

test/aoj/challenge/1102.test.cpp

AC · 最終更新 2026-09-06 · GitHub

問題: https://onlinejudge.u-aizu.ac.jp/problems/1102

依存するヘッダ(1)
実装
// competitive-verifier: PROBLEM https://onlinejudge.u-aizu.ac.jp/problems/1102
#include <cctype>
#include <iostream>
#include <stdexcept>
#include <string>
#include <string_view>
#include "parser/parser.hpp"

// 複素数式の評価: + - * (二項のみ) と括弧、非負整数と虚数単位 i。
// 途中結果を含め実部・虚部の絶対値が 10000 を超えたら overflow。
// 値型 T をユーザ定義の複素数型にした ExpressionParser<C> の例。
using ll = long long;

struct C {
    ll re = 0, im = 0;
};

static const ll LIM = 10000;
static C chk(C x) {
    if (x.re > LIM || x.re < -LIM || x.im > LIM || x.im < -LIM) throw std::runtime_error("overflow");
    return x;
}

using P = ExpressionParser<C>;

int main() {
    std::string s;
    while (std::getline(std::cin, s)) {
        if (s.empty()) continue;
        P p;
        p.binary("+", 10, P::Assoc::Left, [](C a, C b) { return chk({a.re + b.re, a.im + b.im}); })
            .binary("-", 10, P::Assoc::Left, [](C a, C b) { return chk({a.re - b.re, a.im - b.im}); })
            .binary("*", 20, P::Assoc::Left,
                    [](C a, C b) { return chk({a.re * b.re - a.im * b.im, a.re * b.im + a.im * b.re}); })
            .atom([](P &q) -> C {
                if (q.peek() == 'i') {
                    q.advance();
                    return {0, 1};
                }
                std::string_view r = q.rest();
                std::size_t k = 0;
                ll v = 0;
                while (k < r.size() && std::isdigit(static_cast<unsigned char>(r[k]))) {
                    v = v * 10 + (r[k] - '0');
                    if (v > 1000000000) v = 1000000000;
                    ++k;
                }
                if (k == 0) throw std::runtime_error("expected number or i");
                q.advance(k);
                return chk({v, 0});
            });
        try {
            C r = p.parse(s);
            std::string out;
            if (r.im == 0) out = std::to_string(r.re);
            else if (r.re == 0) out = std::to_string(r.im) + "i";
            else out = std::to_string(r.re) + (r.im > 0 ? "+" : "") + std::to_string(r.im) + "i";
            std::cout << out << '\n';
        } catch (...) { std::cout << "overflow\n"; }
    }
    return 0;
}