def int_to_roman(input):
"""
Convert an integer to Roman numerals.
Examples:
>>> int_to_roman(0)
Traceback (most recent call last):
ValueError: Argument must be between 1 and 3999
>>> int_to_roman(-1)
Traceback (most recent call last):
ValueError: Argument must be between 1 and 3999
>>> int_to_roman(1.5)
Traceback (most recent call last):
TypeError: expected integer, got <type 'float'>
>>> for i in range(1, 21): print int_to_roman(i)
...
I
II
III
IV
V
VI
VII
VIII
IX
X
XI
XII
XIII
XIV
XV
XVI
XVII
XVIII
XIX
XX
>>> print int_to_roman(2000)
MM
>>> print int_to_roman(1999)
MCMXCIX
"""
if type(input) != type(1):
raise TypeError, "expected integer, got %s" % type(input)
if not 0 < input < 4000:
raise ValueError, "Argument must be between 1 and 3999"
ints = (1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1)
nums = ('M', 'CM', 'D', 'CD','C', 'XC','L','XL','X','IX','V','IV','I')
result = ""
for i in range(len(ints)):
count = int(input / ints[i])
result += nums[i] * count
input -= ints[i] * count
return result
def roman_to_int(input):
"""
Convert a roman numeral to an integer.
>>> r = range(1, 4000)
>>> nums = [int_to_roman(i) for i in r]
>>> ints = [roman_to_int(n) for n in nums]
>>> print r == ints
1
>>> roman_to_int('VVVIV')
Traceback (most recent call last):
...
ValueError: input is not a valid roman numeral: VVVIV
>>> roman_to_int(1)
Traceback (most recent call last):
...
TypeError: expected string, got <type 'int'>
>>> roman_to_int('a')
Traceback (most recent call last):
...
ValueError: input is not a valid roman numeral: A
>>> roman_to_int('IL')
Traceback (most recent call last):
...
ValueError: input is not a valid roman numeral: IL
"""
if type(input) != type(""):
raise TypeError, "expected string, got %s" % type(input)
input = input.upper()
nums = ['M', 'D', 'C', 'L', 'X', 'V', 'I']
ints = [1000, 500, 100, 50, 10, 5, 1]
places = []
for c in input:
if not c in nums:
raise ValueError, "input is not a valid roman numeral: %s" % input
for i in range(len(input)):
c = input[i]
value = ints[nums.index(c)]
# If the next place holds a larger number, this value is negative.
try:
nextvalue = ints[nums.index(input[i +1])]
if nextvalue > value:
value *= -1
except IndexError:
# there is no next place.
pass
places.append(value)
sum = 0
for n in places: sum += n
# Easiest test for validity...
if int_to_roman(sum) == input:
return sum
else:
raise ValueError, 'input is not a valid roman numeral: %s' % input
ZGVmIGludF90b19yb21hbihpbnB1dCk6CiAgICIiIgogICBDb252ZXJ0IGFuIGludGVnZXIgdG8gUm9tYW4gbnVtZXJhbHMuCgogICBFeGFtcGxlczoKICAgPj4+IGludF90b19yb21hbigwKQogICBUcmFjZWJhY2sgKG1vc3QgcmVjZW50IGNhbGwgbGFzdCk6CiAgIFZhbHVlRXJyb3I6IEFyZ3VtZW50IG11c3QgYmUgYmV0d2VlbiAxIGFuZCAzOTk5CgogICA+Pj4gaW50X3RvX3JvbWFuKC0xKQogICBUcmFjZWJhY2sgKG1vc3QgcmVjZW50IGNhbGwgbGFzdCk6CiAgIFZhbHVlRXJyb3I6IEFyZ3VtZW50IG11c3QgYmUgYmV0d2VlbiAxIGFuZCAzOTk5CgogICA+Pj4gaW50X3RvX3JvbWFuKDEuNSkKICAgVHJhY2ViYWNrIChtb3N0IHJlY2VudCBjYWxsIGxhc3QpOgogICBUeXBlRXJyb3I6IGV4cGVjdGVkIGludGVnZXIsIGdvdCA8dHlwZSAnZmxvYXQnPgoKICAgPj4+IGZvciBpIGluIHJhbmdlKDEsIDIxKTogcHJpbnQgaW50X3RvX3JvbWFuKGkpCiAgIC4uLgogICBJCiAgIElJCiAgIElJSQogICBJVgogICBWCiAgIFZJCiAgIFZJSQogICBWSUlJCiAgIElYCiAgIFgKICAgWEkKICAgWElJCiAgIFhJSUkKICAgWElWCiAgIFhWCiAgIFhWSQogICBYVklJCiAgIFhWSUlJCiAgIFhJWAogICBYWAogICA+Pj4gcHJpbnQgaW50X3RvX3JvbWFuKDIwMDApCiAgIE1NCiAgID4+PiBwcmludCBpbnRfdG9fcm9tYW4oMTk5OSkKICAgTUNNWENJWAogICAiIiIKICAgaWYgdHlwZShpbnB1dCkgIT0gdHlwZSgxKToKICAgICAgcmFpc2UgVHlwZUVycm9yLCAiZXhwZWN0ZWQgaW50ZWdlciwgZ290ICVzIiAlIHR5cGUoaW5wdXQpCiAgIGlmIG5vdCAwIDwgaW5wdXQgPCA0MDAwOgogICAgICByYWlzZSBWYWx1ZUVycm9yLCAiQXJndW1lbnQgbXVzdCBiZSBiZXR3ZWVuIDEgYW5kIDM5OTkiICAgCiAgIGludHMgPSAoMTAwMCwgOTAwLCAgNTAwLCA0MDAsIDEwMCwgIDkwLCA1MCwgIDQwLCAxMCwgIDksICAgNSwgIDQsICAgMSkKICAgbnVtcyA9ICgnTScsICAnQ00nLCAnRCcsICdDRCcsJ0MnLCAnWEMnLCdMJywnWEwnLCdYJywnSVgnLCdWJywnSVYnLCdJJykKICAgcmVzdWx0ID0gIiIKICAgZm9yIGkgaW4gcmFuZ2UobGVuKGludHMpKToKICAgICAgY291bnQgPSBpbnQoaW5wdXQgLyBpbnRzW2ldKQogICAgICByZXN1bHQgKz0gbnVtc1tpXSAqIGNvdW50CiAgICAgIGlucHV0IC09IGludHNbaV0gKiBjb3VudAogICByZXR1cm4gcmVzdWx0CgoKCmRlZiByb21hbl90b19pbnQoaW5wdXQpOgogICAiIiIKICAgQ29udmVydCBhIHJvbWFuIG51bWVyYWwgdG8gYW4gaW50ZWdlci4KICAgCiAgID4+PiByID0gcmFuZ2UoMSwgNDAwMCkKICAgPj4+IG51bXMgPSBbaW50X3RvX3JvbWFuKGkpIGZvciBpIGluIHJdCiAgID4+PiBpbnRzID0gW3JvbWFuX3RvX2ludChuKSBmb3IgbiBpbiBudW1zXQogICA+Pj4gcHJpbnQgciA9PSBpbnRzCiAgIDEKCiAgID4+PiByb21hbl90b19pbnQoJ1ZWVklWJykKICAgVHJhY2ViYWNrIChtb3N0IHJlY2VudCBjYWxsIGxhc3QpOgogICAgLi4uCiAgIFZhbHVlRXJyb3I6IGlucHV0IGlzIG5vdCBhIHZhbGlkIHJvbWFuIG51bWVyYWw6IFZWVklWCiAgID4+PiByb21hbl90b19pbnQoMSkKICAgVHJhY2ViYWNrIChtb3N0IHJlY2VudCBjYWxsIGxhc3QpOgogICAgLi4uCiAgIFR5cGVFcnJvcjogZXhwZWN0ZWQgc3RyaW5nLCBnb3QgPHR5cGUgJ2ludCc+CiAgID4+PiByb21hbl90b19pbnQoJ2EnKQogICBUcmFjZWJhY2sgKG1vc3QgcmVjZW50IGNhbGwgbGFzdCk6CiAgICAuLi4KICAgVmFsdWVFcnJvcjogaW5wdXQgaXMgbm90IGEgdmFsaWQgcm9tYW4gbnVtZXJhbDogQQogICA+Pj4gcm9tYW5fdG9faW50KCdJTCcpCiAgIFRyYWNlYmFjayAobW9zdCByZWNlbnQgY2FsbCBsYXN0KToKICAgIC4uLgogICBWYWx1ZUVycm9yOiBpbnB1dCBpcyBub3QgYSB2YWxpZCByb21hbiBudW1lcmFsOiBJTAogICAiIiIKICAgaWYgdHlwZShpbnB1dCkgIT0gdHlwZSgiIik6CiAgICAgIHJhaXNlIFR5cGVFcnJvciwgImV4cGVjdGVkIHN0cmluZywgZ290ICVzIiAlIHR5cGUoaW5wdXQpCiAgIGlucHV0ID0gaW5wdXQudXBwZXIoKQogICBudW1zID0gWydNJywgJ0QnLCAnQycsICdMJywgJ1gnLCAnVicsICdJJ10KICAgaW50cyA9IFsxMDAwLCA1MDAsIDEwMCwgNTAsICAxMCwgIDUsICAgMV0KICAgcGxhY2VzID0gW10KICAgZm9yIGMgaW4gaW5wdXQ6CiAgICAgIGlmIG5vdCBjIGluIG51bXM6CiAgICAgICAgIHJhaXNlIFZhbHVlRXJyb3IsICJpbnB1dCBpcyBub3QgYSB2YWxpZCByb21hbiBudW1lcmFsOiAlcyIgJSBpbnB1dAogICBmb3IgaSBpbiByYW5nZShsZW4oaW5wdXQpKToKICAgICAgYyA9IGlucHV0W2ldCiAgICAgIHZhbHVlID0gaW50c1tudW1zLmluZGV4KGMpXQogICAgICAjIElmIHRoZSBuZXh0IHBsYWNlIGhvbGRzIGEgbGFyZ2VyIG51bWJlciwgdGhpcyB2YWx1ZSBpcyBuZWdhdGl2ZS4KICAgICAgdHJ5OgogICAgICAgICBuZXh0dmFsdWUgPSBpbnRzW251bXMuaW5kZXgoaW5wdXRbaSArMV0pXQogICAgICAgICBpZiBuZXh0dmFsdWUgPiB2YWx1ZToKICAgICAgICAgICAgdmFsdWUgKj0gLTEKICAgICAgZXhjZXB0IEluZGV4RXJyb3I6CiAgICAgICAgICMgdGhlcmUgaXMgbm8gbmV4dCBwbGFjZS4KICAgICAgICAgcGFzcwogICAgICBwbGFjZXMuYXBwZW5kKHZhbHVlKQogICBzdW0gPSAwCiAgIGZvciBuIGluIHBsYWNlczogc3VtICs9IG4KICAgIyBFYXNpZXN0IHRlc3QgZm9yIHZhbGlkaXR5Li4uCiAgIGlmIGludF90b19yb21hbihzdW0pID09IGlucHV0OgogICAgICByZXR1cm4gc3VtCiAgIGVsc2U6CiAgICAgIHJhaXNlIFZhbHVlRXJyb3IsICdpbnB1dCBpcyBub3QgYSB2YWxpZCByb21hbiBudW1lcmFsOiAlcycgJSBpbnB1dA==