"""Convert to and from Roman numerals This program is part of "Dive Into Python 3", a free Python book for experienced programmers. Visit http://diveintopython3.org/ for the latest version. """ class OutOfRangeError(ValueError): pass class NotIntegerError(ValueError): pass class InvalidRomanNumeralError(ValueError): pass roman_numeral_map = (('M', 1000), ('CM', 900), ('D', 500), ('CD', 400), ('C', 100), ('XC', 90), ('L', 50), ('XL', 40), ('X', 10), ('IX', 9), ('V', 5), ('IV', 4), ('I', 1)) to_roman_table = [ None ] from_roman_table = {} def to_roman(n): """convert integer to Roman numeral""" if not (0 < n < 5000): raise OutOfRangeError("number out of range (must be 1..4999)") if int(n) != n: raise NotIntegerError("non-integers can not be converted") return to_roman_table[n] def from_roman(s): """convert Roman numeral to integer""" if not isinstance(s, str): raise InvalidRomanNumeralError("Input must be a string") if not s: raise InvalidRomanNumeralError("Input can not be blank") if s not in from_roman_table: raise InvalidRomanNumeralError("Invalid Roman numeral: {0}".format(s)) return from_roman_table[s] def build_lookup_tables(): def to_roman(n): result = "" for numeral, integer in roman_numeral_map: if n >= integer: result = numeral n -= integer break if n > 0: result += to_roman_table[n] return result for integer in range(1, 5000): roman_numeral = to_roman(integer) to_roman_table.append(roman_numeral) from_roman_table[roman_numeral] = integer build_lookup_tables() # Copyright (c) 2009, Mark Pilgrim, All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE.