2007-08-15 14:27:29 -03:00
|
|
|
"""Convert to and from Roman numerals"""
|
|
|
|
|
|
|
|
__author__ = "Mark Pilgrim (f8dy@diveintopython.org)"
|
|
|
|
__version__ = "1.4"
|
|
|
|
__date__ = "8 August 2001"
|
|
|
|
__copyright__ = """Copyright (c) 2001 Mark Pilgrim
|
|
|
|
|
|
|
|
This program is part of "Dive Into Python", a free Python tutorial for
|
|
|
|
experienced programmers. Visit http://diveintopython.org/ for the
|
|
|
|
latest version.
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the Python 2.1.1 license, available at
|
|
|
|
http://www.python.org/2.1.1/license.html
|
|
|
|
"""
|
|
|
|
|
|
|
|
import re
|
|
|
|
|
|
|
|
#Define exceptions
|
|
|
|
class RomanError(Exception): pass
|
|
|
|
class OutOfRangeError(RomanError): pass
|
|
|
|
class NotIntegerError(RomanError): pass
|
|
|
|
class InvalidRomanNumeralError(RomanError): pass
|
|
|
|
|
|
|
|
#Define digit mapping
|
|
|
|
romanNumeralMap = (('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))
|
|
|
|
|
|
|
|
def toRoman(n):
|
|
|
|
"""convert integer to Roman numeral"""
|
|
|
|
if not (0 < n < 5000):
|
Merged revisions 72558,72745,72750,72876,73042,73045-73048,73069,73089,73163,73186,73213,73215,73217,73257-73258,73260 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r72558 | benjamin.peterson | 2009-05-11 01:52:09 +0200 (Mo, 11 Mai 2009) | 1 line
sys.setdefaultencoding() strikes me as a bad example
........
r72745 | benjamin.peterson | 2009-05-17 16:16:29 +0200 (So, 17 Mai 2009) | 1 line
ignore .rst files in sphinx its self
........
r72750 | benjamin.peterson | 2009-05-17 18:59:27 +0200 (So, 17 Mai 2009) | 1 line
chop off slash
........
r72876 | benjamin.peterson | 2009-05-23 22:59:09 +0200 (Sa, 23 Mai 2009) | 1 line
remove mention of old ctypes version
........
r73042 | benjamin.peterson | 2009-05-30 05:10:52 +0200 (Sa, 30 Mai 2009) | 1 line
no fdatasync on macos
........
r73045 | georg.brandl | 2009-05-30 09:26:04 +0200 (Sa, 30 Mai 2009) | 1 line
#6146: fix markup bug.
........
r73046 | georg.brandl | 2009-05-30 09:31:25 +0200 (Sa, 30 Mai 2009) | 1 line
Use preferred form of raising exceptions.
........
r73047 | georg.brandl | 2009-05-30 12:33:23 +0200 (Sa, 30 Mai 2009) | 1 line
Fix some more small markup problems.
........
r73048 | georg.brandl | 2009-05-30 12:34:25 +0200 (Sa, 30 Mai 2009) | 1 line
Fix markup problem.
........
r73069 | benjamin.peterson | 2009-05-31 02:42:42 +0200 (So, 31 Mai 2009) | 1 line
fix signature
........
r73089 | andrew.kuchling | 2009-06-01 02:14:19 +0200 (Mo, 01 Jun 2009) | 1 line
The class for regexes isn't called RegexObject any more; correct the text
........
r73163 | georg.brandl | 2009-06-03 09:25:35 +0200 (Mi, 03 Jun 2009) | 1 line
Use the preferred form of raise statements in the docs.
........
r73186 | georg.brandl | 2009-06-03 23:21:09 +0200 (Mi, 03 Jun 2009) | 1 line
#6174: fix indentation in code example.
........
r73213 | georg.brandl | 2009-06-04 12:15:57 +0200 (Do, 04 Jun 2009) | 1 line
#5967: note that the C slicing APIs do not support negative indices.
........
r73215 | georg.brandl | 2009-06-04 12:22:31 +0200 (Do, 04 Jun 2009) | 1 line
#6176: fix man page section for flock(2).
........
r73217 | georg.brandl | 2009-06-04 12:27:21 +0200 (Do, 04 Jun 2009) | 1 line
#6175: document that inet_aton supports alternate input formats with less than three dots.
........
r73257 | georg.brandl | 2009-06-06 19:50:05 +0200 (Sa, 06 Jun 2009) | 1 line
#6211: elaborate a bit on ways to call the function.
........
r73258 | georg.brandl | 2009-06-06 19:51:31 +0200 (Sa, 06 Jun 2009) | 1 line
#6204: use a real reference instead of "see later".
........
r73260 | georg.brandl | 2009-06-06 20:21:58 +0200 (Sa, 06 Jun 2009) | 1 line
#6224: s/JPython/Jython/, and remove one link to a module nine years old.
........
2009-10-27 11:19:50 -03:00
|
|
|
raise OutOfRangeError("number out of range (must be 1..4999)")
|
|
|
|
if int(n) != n:
|
|
|
|
raise NotIntegerError("decimals can not be converted")
|
2007-08-15 14:27:29 -03:00
|
|
|
|
|
|
|
result = ""
|
|
|
|
for numeral, integer in romanNumeralMap:
|
|
|
|
while n >= integer:
|
|
|
|
result += numeral
|
|
|
|
n -= integer
|
|
|
|
return result
|
|
|
|
|
|
|
|
#Define pattern to detect valid Roman numerals
|
|
|
|
romanNumeralPattern = re.compile("""
|
|
|
|
^ # beginning of string
|
|
|
|
M{0,4} # thousands - 0 to 4 M's
|
|
|
|
(CM|CD|D?C{0,3}) # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
|
|
|
|
# or 500-800 (D, followed by 0 to 3 C's)
|
|
|
|
(XC|XL|L?X{0,3}) # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
|
|
|
|
# or 50-80 (L, followed by 0 to 3 X's)
|
|
|
|
(IX|IV|V?I{0,3}) # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
|
|
|
|
# or 5-8 (V, followed by 0 to 3 I's)
|
|
|
|
$ # end of string
|
|
|
|
""" ,re.VERBOSE)
|
|
|
|
|
|
|
|
def fromRoman(s):
|
|
|
|
"""convert Roman numeral to integer"""
|
|
|
|
if not s:
|
Merged revisions 72558,72745,72750,72876,73042,73045-73048,73069,73089,73163,73186,73213,73215,73217,73257-73258,73260 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r72558 | benjamin.peterson | 2009-05-11 01:52:09 +0200 (Mo, 11 Mai 2009) | 1 line
sys.setdefaultencoding() strikes me as a bad example
........
r72745 | benjamin.peterson | 2009-05-17 16:16:29 +0200 (So, 17 Mai 2009) | 1 line
ignore .rst files in sphinx its self
........
r72750 | benjamin.peterson | 2009-05-17 18:59:27 +0200 (So, 17 Mai 2009) | 1 line
chop off slash
........
r72876 | benjamin.peterson | 2009-05-23 22:59:09 +0200 (Sa, 23 Mai 2009) | 1 line
remove mention of old ctypes version
........
r73042 | benjamin.peterson | 2009-05-30 05:10:52 +0200 (Sa, 30 Mai 2009) | 1 line
no fdatasync on macos
........
r73045 | georg.brandl | 2009-05-30 09:26:04 +0200 (Sa, 30 Mai 2009) | 1 line
#6146: fix markup bug.
........
r73046 | georg.brandl | 2009-05-30 09:31:25 +0200 (Sa, 30 Mai 2009) | 1 line
Use preferred form of raising exceptions.
........
r73047 | georg.brandl | 2009-05-30 12:33:23 +0200 (Sa, 30 Mai 2009) | 1 line
Fix some more small markup problems.
........
r73048 | georg.brandl | 2009-05-30 12:34:25 +0200 (Sa, 30 Mai 2009) | 1 line
Fix markup problem.
........
r73069 | benjamin.peterson | 2009-05-31 02:42:42 +0200 (So, 31 Mai 2009) | 1 line
fix signature
........
r73089 | andrew.kuchling | 2009-06-01 02:14:19 +0200 (Mo, 01 Jun 2009) | 1 line
The class for regexes isn't called RegexObject any more; correct the text
........
r73163 | georg.brandl | 2009-06-03 09:25:35 +0200 (Mi, 03 Jun 2009) | 1 line
Use the preferred form of raise statements in the docs.
........
r73186 | georg.brandl | 2009-06-03 23:21:09 +0200 (Mi, 03 Jun 2009) | 1 line
#6174: fix indentation in code example.
........
r73213 | georg.brandl | 2009-06-04 12:15:57 +0200 (Do, 04 Jun 2009) | 1 line
#5967: note that the C slicing APIs do not support negative indices.
........
r73215 | georg.brandl | 2009-06-04 12:22:31 +0200 (Do, 04 Jun 2009) | 1 line
#6176: fix man page section for flock(2).
........
r73217 | georg.brandl | 2009-06-04 12:27:21 +0200 (Do, 04 Jun 2009) | 1 line
#6175: document that inet_aton supports alternate input formats with less than three dots.
........
r73257 | georg.brandl | 2009-06-06 19:50:05 +0200 (Sa, 06 Jun 2009) | 1 line
#6211: elaborate a bit on ways to call the function.
........
r73258 | georg.brandl | 2009-06-06 19:51:31 +0200 (Sa, 06 Jun 2009) | 1 line
#6204: use a real reference instead of "see later".
........
r73260 | georg.brandl | 2009-06-06 20:21:58 +0200 (Sa, 06 Jun 2009) | 1 line
#6224: s/JPython/Jython/, and remove one link to a module nine years old.
........
2009-10-27 11:19:50 -03:00
|
|
|
raise InvalidRomanNumeralError('Input can not be blank')
|
2007-08-15 14:27:29 -03:00
|
|
|
if not romanNumeralPattern.search(s):
|
Merged revisions 72558,72745,72750,72876,73042,73045-73048,73069,73089,73163,73186,73213,73215,73217,73257-73258,73260 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r72558 | benjamin.peterson | 2009-05-11 01:52:09 +0200 (Mo, 11 Mai 2009) | 1 line
sys.setdefaultencoding() strikes me as a bad example
........
r72745 | benjamin.peterson | 2009-05-17 16:16:29 +0200 (So, 17 Mai 2009) | 1 line
ignore .rst files in sphinx its self
........
r72750 | benjamin.peterson | 2009-05-17 18:59:27 +0200 (So, 17 Mai 2009) | 1 line
chop off slash
........
r72876 | benjamin.peterson | 2009-05-23 22:59:09 +0200 (Sa, 23 Mai 2009) | 1 line
remove mention of old ctypes version
........
r73042 | benjamin.peterson | 2009-05-30 05:10:52 +0200 (Sa, 30 Mai 2009) | 1 line
no fdatasync on macos
........
r73045 | georg.brandl | 2009-05-30 09:26:04 +0200 (Sa, 30 Mai 2009) | 1 line
#6146: fix markup bug.
........
r73046 | georg.brandl | 2009-05-30 09:31:25 +0200 (Sa, 30 Mai 2009) | 1 line
Use preferred form of raising exceptions.
........
r73047 | georg.brandl | 2009-05-30 12:33:23 +0200 (Sa, 30 Mai 2009) | 1 line
Fix some more small markup problems.
........
r73048 | georg.brandl | 2009-05-30 12:34:25 +0200 (Sa, 30 Mai 2009) | 1 line
Fix markup problem.
........
r73069 | benjamin.peterson | 2009-05-31 02:42:42 +0200 (So, 31 Mai 2009) | 1 line
fix signature
........
r73089 | andrew.kuchling | 2009-06-01 02:14:19 +0200 (Mo, 01 Jun 2009) | 1 line
The class for regexes isn't called RegexObject any more; correct the text
........
r73163 | georg.brandl | 2009-06-03 09:25:35 +0200 (Mi, 03 Jun 2009) | 1 line
Use the preferred form of raise statements in the docs.
........
r73186 | georg.brandl | 2009-06-03 23:21:09 +0200 (Mi, 03 Jun 2009) | 1 line
#6174: fix indentation in code example.
........
r73213 | georg.brandl | 2009-06-04 12:15:57 +0200 (Do, 04 Jun 2009) | 1 line
#5967: note that the C slicing APIs do not support negative indices.
........
r73215 | georg.brandl | 2009-06-04 12:22:31 +0200 (Do, 04 Jun 2009) | 1 line
#6176: fix man page section for flock(2).
........
r73217 | georg.brandl | 2009-06-04 12:27:21 +0200 (Do, 04 Jun 2009) | 1 line
#6175: document that inet_aton supports alternate input formats with less than three dots.
........
r73257 | georg.brandl | 2009-06-06 19:50:05 +0200 (Sa, 06 Jun 2009) | 1 line
#6211: elaborate a bit on ways to call the function.
........
r73258 | georg.brandl | 2009-06-06 19:51:31 +0200 (Sa, 06 Jun 2009) | 1 line
#6204: use a real reference instead of "see later".
........
r73260 | georg.brandl | 2009-06-06 20:21:58 +0200 (Sa, 06 Jun 2009) | 1 line
#6224: s/JPython/Jython/, and remove one link to a module nine years old.
........
2009-10-27 11:19:50 -03:00
|
|
|
raise InvalidRomanNumeralError('Invalid Roman numeral: %s' % s)
|
2007-08-15 14:27:29 -03:00
|
|
|
|
|
|
|
result = 0
|
|
|
|
index = 0
|
|
|
|
for numeral, integer in romanNumeralMap:
|
|
|
|
while s[index:index+len(numeral)] == numeral:
|
|
|
|
result += integer
|
|
|
|
index += len(numeral)
|
|
|
|
return result
|