Welcome, guest | Sign In | My Account | Store | Cart

Provides two functions: romanToNumber - Converts a string of Roman Numerals (I,V,X,L,C,D,M) into an integer. (ignores formatting, will return best guess if improperly formatted) numberToRoman - Converts an integer into a string of Roman Numerals

Python, 123 lines
 ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123``` ```#Roman Numeral Converter #Written By Brandon Martin #Digital Sol class IllegalCharacterError(Exception): pass def romanToNumber(numerals): '''Converts a string of Roman Numerals (I,V,X,L,C,D,M) into an integer.''' romanConversionTable = { 'I' : 1, 'V' : 5, 'X' : 10, 'L' : 50, 'C' : 100, 'D' : 500, 'M' : 1000 } ### Build List of Numbers ### numberList = [] for letter in numerals: # Build List of Numbers if letter in romanConversionTable: numberList += [romanConversionTable[letter]] else: raise IllegalCharacterError('{} is not a Roman Numeral'.format(letter)) if len(numberList) == 1: return numberList[0] ### Construct Final Total ### previous = numberList[-1] total = previous for current in range(len(numberList)-2,-1, -1): if numberList[current] < previous: total -= numberList[current] else: total += numberList[current] previous = numberList[current] return total def numberToRoman(integer): '''Converts an integer into a string of Roman Numerals.''' if type(integer) != int: raise TypeError('Input must be an integer.') numberConversionTable = { 1 : 'I', 5 : 'V', 10 : 'X', 50 : 'L', 100 : 'C', 500 : 'D', 1000 : 'M' } quads = ('I','X','C') doubs = ('V','L','D') foundNumeral = '' found = 0 ### Build List of Roman Numerals ### numeralList = [] for value in [1000,500,100,50,10,5,1]: while integer >= value: integer -= value numeralList += [numberConversionTable[value]] if len(numeralList) == 1: #Return result if only one symbol return numeralList.pop() ### Modify List to Proper Formatting ### finalNumeralList = [] repeats = 0 for numeral in numeralList: if len(finalNumeralList) == 0: # ADD FIRST NUMBER finalNumeralList += [numeral] else: if numeral != finalNumeralList[len(finalNumeralList)-1]: # CURRENT NUMERAL IS DIFFERENT FROM THE LAST if 3 > repeats > 0: # ADD IN ALL REPEATS for i in range(repeats): finalNumeralList += [finalNumeralList[-1]] repeats = 0 finalNumeralList += [numeral] else: # CURRENT NUMERAL IS THE SAME AS THE LAST repeats += 1 if repeats == 3 and numeral != 'M': # EXCHANGE THREE ONES NUMERALS FOR ONE FIVES NUMERAL modifiedNumeral = doubs[quads.index(numeral)] if modifiedNumeral == finalNumeralList[len(finalNumeralList)-2]: # NUMERALS IN A THREE DIGIT RANGE ADD TO 9 finalNumeralList.pop(len(finalNumeralList)-2) if numeral != 'C': finalNumeralList += [quads[quads.index(numeral)+1]] else: finalNumeralList += ['M'] else: finalNumeralList += [modifiedNumeral] repeats = 0 elif numeral == 'M': # AUTOMATICALLY ADD M finalNumeralList += ['M'] repeats = 0 if repeats > 0: # ADD IN ANY REMAINING REPEATS for i in range(repeats): finalNumeralList += [finalNumeralList[-1]] finalString = ''.join(finalNumeralList) return finalString ```

The implementation I have coded seems a bit bulky to me, if anyone has a better method for accomplishing a task please let me know.

#### 1 comment

Gary Whitsett 7 years, 1 month ago

Hi Brandon,

Could this be simplified by adding the quads and doubs into the conversion table? In other words, include 4: "IV", 9: "IX", etc in the numberConversionTable. Then the "value in" statement includes all of them, as well ([1000,900,500,400,100,90,50,40,10,9,5,4,1]). This would make the code to find the triples redundant. Would this work or am I missing something?

 Created by Brandon Martin on Mon, 12 Dec 2016 (MIT)

### Required Modules

• (none specified)