Skip to content

Instantly share code, notes, and snippets.

@nikolat
Forked from fumokmm/roman_arabic.groovy
Created August 24, 2011 14:53
Show Gist options
  • Save nikolat/1168248 to your computer and use it in GitHub Desktop.
Save nikolat/1168248 to your computer and use it in GitHub Desktop.
// http://d.hatena.ne.jp/fumokmm/20110822/1314013182
// ローマ数字定義
def romans = [
I :1 ,
IV:4 , V:5 , IX:9 , X:10 ,
XL:40 , L:50 , XC:90 , C:100 ,
CD:400, D:500, CM:900, M:1000
]
// シンボル化能力を追加
String.metaClass.getSymbol = { delegate.intern() }
Integer.metaClass.getSymbol = { delegate.toString().intern() }
// 文字列自体に変換能力を追加
romans.each { r, a ->
r.symbol.metaClass.toArabic = { a }
a.symbol.metaClass.toRoman = { r }
}
// アラビア数字 -> ローマ数字
def arabicToRoman = { int arabic ->
('1'*arabic).findAll(
~/${romans.values().sort{-it}.collect{ "1{$it}" }.join('|')}/
)*.size()*.symbol*.toRoman().join()
}
// ローマ数字 -> アラビア数字
def romanToArabic = { String roman ->
roman.findAll(
~/(${romans.keySet().sort{-it.size()}.join('|')})/
)*.symbol*.toArabic().sum()
}
// テスト
assert arabicToRoman(11) == 'XI'
assert romanToArabic('XI') == 11
assert arabicToRoman(12) == 'XII'
assert romanToArabic('XII') == 12
assert arabicToRoman(14) == 'XIV'
assert romanToArabic('XIV') == 14
assert arabicToRoman(18) == 'XVIII'
assert romanToArabic('XVIII') == 18
assert arabicToRoman(24) == 'XXIV'
assert romanToArabic('XXIV') == 24
assert arabicToRoman(43) == 'XLIII'
assert romanToArabic('XLIII') == 43
assert arabicToRoman(99) == 'XCIX'
assert romanToArabic('XCIX') == 99
assert arabicToRoman(495) == 'CDXCV'
assert romanToArabic('CDXCV') == 495
assert arabicToRoman(1888) == 'MDCCCLXXXVIII'
assert romanToArabic('MDCCCLXXXVIII') == 1888
assert arabicToRoman(1945) == 'MCMXLV'
assert romanToArabic('MCMXLV') == 1945
assert arabicToRoman(3999) == 'MMMCMXCIX'
assert romanToArabic('MMMCMXCIX') == 3999
import re
def getArabicRomanTable():
t = {
1: 'I',
5: 'V',
10: 'X',
50: 'L',
100: 'C',
500: 'D',
1000: 'M',
}
for k in [x for x in t.keys() if x > 1]:
if str(k)[0] == '1':
t[9*k/10] = t[k/10] + t[k]
else:
t[8*k/10] = t[k/5] + t[k]
return t
def arabicToRoman(n):
if not (isinstance(n, int) and 0 < n < 4000):
raise
t = getArabicRomanTable()
r = ''
for k in sorted(t.keys(), reverse=True):
r += t[k] * (n / k)
n = n % k
return r
def romanToArabic(s):
if not (isinstance(s, str) and re.compile('^[IVXLCDMivxlcdm]+$').match(s)):
raise
s = s.upper()
t = {}
r = 0
for k, v in getArabicRomanTable().items():
t[v] = k
for k in [x for x in t.keys() if len(x) > 1]:
r += t[k] * s.count(k)
s = s.replace(k, '')
for k in [x for x in t.keys() if len(x) == 1]:
r += t[k] * s.count(k)
return r
if __name__ == '__main__':
assert arabicToRoman(11) == 'XI'
assert arabicToRoman(12) == 'XII'
assert arabicToRoman(14) == 'XIV'
assert arabicToRoman(18) == 'XVIII'
assert arabicToRoman(24) == 'XXIV'
assert arabicToRoman(43) == 'XLIII'
assert arabicToRoman(99) == 'XCIX'
assert arabicToRoman(495) == 'CDXCV'
assert arabicToRoman(1888) == 'MDCCCLXXXVIII'
assert arabicToRoman(1945) == 'MCMXLV'
assert arabicToRoman(3999) == 'MMMCMXCIX'
assert romanToArabic('XI') == 11
assert romanToArabic('XII') == 12
assert romanToArabic('XIV') == 14
assert romanToArabic('XVIII') == 18
assert romanToArabic('XXIV') == 24
assert romanToArabic('XLIII') == 43
assert romanToArabic('XCIX') == 99
assert romanToArabic('CDXCV') == 495
assert romanToArabic('MDCCCLXXXVIII') == 1888
assert romanToArabic('MCMXLV') == 1945
assert romanToArabic('MMMCMXCIX') == 3999
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment