Mercurial > repos > shellac > guppy_basecaller
comparison env/lib/python3.7/site-packages/docutils/utils/roman.py @ 5:9b1c78e6ba9c draft default tip
"planemo upload commit 6c0a8142489327ece472c84e558c47da711a9142"
| author | shellac |
|---|---|
| date | Mon, 01 Jun 2020 08:59:25 -0400 |
| parents | 79f47841a781 |
| children |
comparison
equal
deleted
inserted
replaced
| 4:79f47841a781 | 5:9b1c78e6ba9c |
|---|---|
| 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 | |
| 72 if not romanNumeralPattern.search(s): | |
| 73 raise InvalidRomanNumeralError('Invalid Roman numeral: %s' % s) | |
| 74 | |
| 75 result = 0 | |
| 76 index = 0 | |
| 77 for numeral, integer in romanNumeralMap: | |
| 78 while s[index:index+len(numeral)] == numeral: | |
| 79 result += integer | |
| 80 index += len(numeral) | |
| 81 return result | |
| 82 |
