ホーム > libalgo

ローマ数字とアラビア数字の変換

概要

0 から 3999 まで対応

実装

int from_roman(const std::string &s) {
    static const std::map<char, int> m = {{'I', 1},   {'V', 5},   {'X', 10},  {'L', 50},
                                          {'C', 100}, {'D', 500}, {'M', 1000}};
    static const auto get = [&](char c) {
        assert(m.find(c) != m.end());
        return m.find(c)->second;
    };
    int n = 0;
    for (int i = 0; i < (int)s.size(); ++i) {
        if (i + 1 == (int)s.size() || get(s[i]) >= get(s[i + 1]))
            n += get(s[i]);
        else
            n -= get(s[i]);
    }
    return n;
}

std::string to_roman(int n) {
    static const std::map<int, std::string> m = {{1, "I"},   {5, "V"},   {10, "X"},  {50, "L"},
                                                 {100, "C"}, {500, "D"}, {1000, "M"}};
    static const auto get = [&](int c) {
        assert(m.find(c) != m.end());
        return m.find(c)->second;
    };
    std::string res;
    int p = 1;
    while (n) {
        int d = n % 10;
        int f = d % 5;
        std::string s = "";
        if (f == 0) {
        } else if (f <= 3) {
            for (int i = 0; i < f; ++i) s += get(p);
        } else if (f == 4) {
            s += get(p);
        }
        if (f <= 3) {
            if (d >= 5) s = get(p * 5) + s;
        } else {
            if (d >= 5)
                s += get(p * 10);
            else
                s += get(p * 5);
        }
        res = s + res;
        p *= 10;
        n /= 10;
    }
    return res;
}

検証

AOJ0039 http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=2189361

using namespace std;
int main(){
    for(int i = 0;; ++i){
        cout << i << endl;
        assert(from_roman(to_roman(i)) == i);
    }
}