symbian-qemu-0.9.1-12/python-2.6.1/Doc/tools/roman.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 """Convert to and from Roman numerals"""
       
     2 
       
     3 __author__ = "Mark Pilgrim (f8dy@diveintopython.org)"
       
     4 __version__ = "1.4"
       
     5 __date__ = "8 August 2001"
       
     6 __copyright__ = """Copyright (c) 2001 Mark Pilgrim
       
     7 
       
     8 This program is part of "Dive Into Python", a free Python tutorial for
       
     9 experienced programmers.  Visit http://diveintopython.org/ for the
       
    10 latest version.
       
    11 
       
    12 This program is free software; you can redistribute it and/or modify
       
    13 it under the terms of the Python 2.1.1 license, available at
       
    14 http://www.python.org/2.1.1/license.html
       
    15 """
       
    16 
       
    17 import re
       
    18 
       
    19 #Define exceptions
       
    20 class RomanError(Exception): pass
       
    21 class OutOfRangeError(RomanError): pass
       
    22 class NotIntegerError(RomanError): pass
       
    23 class InvalidRomanNumeralError(RomanError): pass
       
    24 
       
    25 #Define digit mapping
       
    26 romanNumeralMap = (('M',  1000),
       
    27                    ('CM', 900),
       
    28                    ('D',  500),
       
    29                    ('CD', 400),
       
    30                    ('C',  100),
       
    31                    ('XC', 90),
       
    32                    ('L',  50),
       
    33                    ('XL', 40),
       
    34                    ('X',  10),
       
    35                    ('IX', 9),
       
    36                    ('V',  5),
       
    37                    ('IV', 4),
       
    38                    ('I',  1))
       
    39 
       
    40 def toRoman(n):
       
    41     """convert integer to Roman numeral"""
       
    42     if not (0 < n < 5000):
       
    43         raise OutOfRangeError, "number out of range (must be 1..4999)"
       
    44     if int(n) <> n:
       
    45         raise NotIntegerError, "decimals can not be converted"
       
    46 
       
    47     result = ""
       
    48     for numeral, integer in romanNumeralMap:
       
    49         while n >= integer:
       
    50             result += numeral
       
    51             n -= integer
       
    52     return result
       
    53 
       
    54 #Define pattern to detect valid Roman numerals
       
    55 romanNumeralPattern = re.compile("""
       
    56     ^                   # beginning of string
       
    57     M{0,4}              # thousands - 0 to 4 M's
       
    58     (CM|CD|D?C{0,3})    # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
       
    59                         #            or 500-800 (D, followed by 0 to 3 C's)
       
    60     (XC|XL|L?X{0,3})    # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
       
    61                         #        or 50-80 (L, followed by 0 to 3 X's)
       
    62     (IX|IV|V?I{0,3})    # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
       
    63                         #        or 5-8 (V, followed by 0 to 3 I's)
       
    64     $                   # end of string
       
    65     """ ,re.VERBOSE)
       
    66 
       
    67 def fromRoman(s):
       
    68     """convert Roman numeral to integer"""
       
    69     if not s:
       
    70         raise InvalidRomanNumeralError, 'Input can not be blank'
       
    71     if not romanNumeralPattern.search(s):
       
    72         raise InvalidRomanNumeralError, 'Invalid Roman numeral: %s' % s
       
    73 
       
    74     result = 0
       
    75     index = 0
       
    76     for numeral, integer in romanNumeralMap:
       
    77         while s[index:index+len(numeral)] == numeral:
       
    78             result += integer
       
    79             index += len(numeral)
       
    80     return result