+# Functions to convert between integers and Roman numerals. Doctest examples included.
+# by Paul Winkler
+# http://code.activestate.com/recipes/81611-roman-numerals/
+# PSFL (GPL compatible)
+
+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