10「ローマ数字変換器を作ってみよう」の問題と解説

今回はローマ数字を(通常の)アラビア数字に変換するプログラムです。
99名もの方が挑戦してくれました。本当にありがとうございます。

問題文

ローマ数字変換器を作ってみよう!

ローマ数字をアラビア(通常の)数字に変換するプログラムをPythonで作ってみましょう。

■ローマ数字について

ローマ数字はラテン文字の一部を使って、I, II, III, IV, X, XVなどのように数を表す方法です。I, V, X, L, C, D, Mがそれぞれ1, 5, 10, 50, 100, 500, 1000を表します。

通常は大きい数字から左から順に加算していきます。しかし例外的な減算則があり、4や9などはそれより小さい数の文字を左においてIVやIXと書きます。つまり、
IV = - I + V 4 = - 1 + 5
IX = - I + X 9 = - 1 + 10

のように表します。XIVは14となります。
XIV = X + (= I + V) 14 = 10 + (- 1 + 5)

詳しくは下記を参考。
http://ja.wikipedia.org/wiki/%E3%83%AD%E3%83%BC%E3%83%9E%E6%95%B0%E5%AD%97

■プログラムについて

あまり複雑になりすぎない簡単なPythonプログラムにしてください。
使われるローマ文字はI, V, X, L, C, D, Mでこれらの組み合わせとなります。
4, 9, 40, 90 ,400, 900等の減算則に注意してローマ数字からアラビア(通常の)数字へのプログラムを作成してください。
実行関数はmain()として、main('XIV')の結果は以下のようにprintで表示されるようにしてください。
XIV = 14

下記の結果を出力するプログラムを送ってください。
main('XLIX')
main('MDCCCLXXXVIII')
main('MCMXLV')
main('MMMCMXCIX')

構文解析ツールついては適切なフィードバックはできませんので、それを使わずに解答してください。私の回答不要の場合は使ってもOKです(評点は付けます)。

■解答方法
作成したPythonプログラムをテキストファイル(roman.txt)に変換しアップロードしてください。

ローマ数字は簡単な規則でできていると思っていましたが、実際に解答者のやり方を見ると、いろいろなやり方(まとめ方)があるので、びっくりしました。

半分ぐらいがアルファベット文字列を他の文字列に置き換えてしまうという方法でした。まず例外(減算)処理のIV(4)やIX(9)をIIIIやVIIII等に変換し、その後、通常の(加算)処理として他の文字をI(1)やX(10)に置き換えるやり方です。
IV → IIII
IX → VIIII 等

私が考えたのは、文字を逐一変換していく方法です。この方法で重要なのは文字の評価を左からするのではなく、右から評価していくという事です。
通常の評価では隣り合った文字は、後の文字 ≧ 前の文字 となります。例えば、VIではV(5) > I(1) となるのでVの評価値は+5となります。
...XVII... ← 評価方向
一方、例外となる減算処理では、後の文字 < 前の文字 となります。例えば、CXでは X(10) < C(100) となるので、Xの評価値は-10はとなります。
...MXCXX... ← 評価の方向

このやり方では、IIX(8)やXXC(80)等のイレギュラーな文字列は扱えませんが、同じ文字(例えばIII)をひとまとまりとしてグルーピングすれば、そのようなイレギュラーな文字列も扱えます。

解答例

#!/usr/bin/python
#
#                               roman2.py
#

class Parser:

    def __init__(self):

        self.value = {'M':1000, 'D':500, 'C':100, 'L':50, 'X':10, 'V':5, 'I':1, '$':0}

    def compute(self, w):

        num = 0
        prev = '$'
        for x in w[::-1]:
            if self.value[x] >= self.value[prev]:
                factor = +1     # ADDITION
            else:
                factor = -1     # SUBTRACTION
            #print x, '%+d' % (factor * self.value[x])
            num += factor * self.value[x]
            prev = x            # STORE THE PREVIOUS CHARACTER
        return num

def main(s):
    
    p = Parser()
    print s, '=', p.compute(s)

#####
main('XLIX')
main('MDCCCLXXXVIII')
main('MCMXLV')
main('MMMCMXCIX')

どうでしょうか。皆さんはどんなローマ数字変換器ができたでしょうか。

CodeIQで問題作成してますので、他の問題も挑戦してみてください。
https://codeiq.jp/ace/kawagashira_nobuyuki/