《余録》Python3.1 セミナー課題 #4b: ローマ数字

Smalltalk-80, JPython1.1 で作成した例題を、Python3.1 で再構成しました。

■ Python3.1 セミナー課題 #4b: ローマ数字

《付記》K&R には、整数から文字列へと変換する関数 itoa() が、事例として紹介されています。これを参考に、整数からローマ数字へと変換する itor を作成する課題(Smalltalk 版)を作成したものです。そこで今回は、ローマ数字から整数へと変換する rtoi を作成する課題(Python 版)を提示します。

《課題》ローマ数字から整数(1..3999)へと変換する rtoi を作成してください。
  • Smalltalk 3分クッキング《問4》ローマ数字, 1988.
class Rtoi:
    """
    >>> # ローマ数字 Roman numerals
    >>> #           ローマ数字 -> 整数
    >>> rtoi = Rtoi()
    >>> s = ",I,IV,V,VI,IX,X,XI,XL,L,LX,XC,C,CX,CD,D,DC,CM,M,MC,MMMCMXCIX"
    >>> s = s.split(",")
    >>> for e in s: "%4d: %s"%(rtoi(e), e)
    '   0: '
    '   1: I'
    '   4: IV'
    '   5: V'
    '   6: VI'
    '   9: IX'
    '  10: X'
    '  11: XI'
    '  40: XL'
    '  50: L'
    '  60: LX'
    '  90: XC'
    ' 100: C'
    ' 110: CX'
    ' 400: CD'
    ' 500: D'
    ' 600: DC'
    ' 900: CM'
    '1000: M'
    '1100: MC'
    '3999: MMMCMXCIX'
    """
    mapping = {}
    
    def __init__(self):
        class_ = self.__class__
        if not class_.mapping:
            m = {"@": 0}
            m.update(self.romanNumerals())
            class_.mapping = m

    def __call__(self, s):
        return self._value(s)
        
    def romanNumerals(self):
        s1,s2 = "IXCM","VLD"
        m1 = {e:  10**s1.index(e) for e in s1}
        m2 = {e:5*10**s2.index(e) for e in s2}
        m1.update(m2)
        return m1

    def _value(self, s):
        acc = 0
        c = "@"
        for e in s:
            acc += self._value1(c, e)
            c = e
        return acc

    def _value1(self, c1, c2):
        n1 = self.mapping[c1]
        n2 = self.mapping[c2]
        return (n2, n2-n1*2)[n1 < n2]

《付記》残念ながら、Python の組み込み機能は脆弱なので、Smalltalk なら3分クッキングで済むところを、30分以上は掛かりそうです。「名探偵コナン」でも見ながら、しばらくお待ちくださいませ。(_o_)

》こちらに移動中です《
TOP


関連記事

Last updated♪2010/01/24