-1

I need to convert a roman numeral string into an integer. I have NO clue how to even start, only that I need to use the regex.

import re

def romanNumeralToInt(romanNum):
    romanNum = romanNum.upper()
    totalValue = 0

I do have a series of tests that it should past:

def test():
    print("Tests started.")
    x = "III"
    "" if romanNumeralToInt(x) == 3 else print(x + " - " + str(romanNumeralToInt(x)))
    x = "IV"
    "" if romanNumeralToInt(x) == 4 else print(x + " - " + str(romanNumeralToInt(x)))
    x = "IX"
    "" if romanNumeralToInt(x) == 9 else print(x + " - " + str(romanNumeralToInt(x)))
    x = "C"
    "" if romanNumeralToInt(x) == 100 else print(x + " - " + str(romanNumeralToInt(x)))
    x = "CC"
    "" if romanNumeralToInt(x) == 200 else print(x + " - " + str(romanNumeralToInt(x)))
    x = "CCC"
    "" if romanNumeralToInt(x) == 300 else print(x + " - " + str(romanNumeralToInt(x)))
    x = "CD"
    "" if romanNumeralToInt(x) == 400 else print(x + " - " + str(romanNumeralToInt(x)))
    x = "D"
    "" if romanNumeralToInt(x) == 500 else print(x + " - " + str(romanNumeralToInt(x)))
    x = "DC"
    "" if romanNumeralToInt(x) == 600 else print(x + " - " + str(romanNumeralToInt(x)))
    x = "DCC"
    "" if romanNumeralToInt(x) == 700 else print(x + " - " + str(romanNumeralToInt(x)))
    x = "DCCC"
    "" if romanNumeralToInt(x) == 800 else print(x + " - " + str(romanNumeralToInt(x)))
    x = "M"
    "" if romanNumeralToInt(x) == 1000 else print(x + " - " + str(romanNumeralToInt(x)))
    x = "LXI"
    "" if romanNumeralToInt(x) == 61 else print(x + " - " + str(romanNumeralToInt(x)))
    x = "IC"
    "" if romanNumeralToInt(x) == 99 else print(x + " - " + str(romanNumeralToInt(x)))
    x = "MMCI"
    "" if romanNumeralToInt(x) == 2101 else print(x + " - " + str(romanNumeralToInt(x)))
    print("Tests ended.")
Kryptos
  • 542
  • 2
  • 8
  • 18
  • What do you have so far? A good place to start would be to look on wikipedia to see how to convert these by hand, then try to code up what you're doing. If you're just looking for code that does this, google search, it's all over. – U2EF1 May 17 '14 at 04:02
  • @U2EF1 I did try that, I could not find any examples that use a regex – Kryptos May 17 '14 at 04:03
  • 1
    Do you "need" to use regexes because you think that's the best way (I disagree) or because it's part of the assignment? – jwodder May 17 '14 at 04:03
  • @Kryptos Do you know how to use a regex? Maybe you could look at the documentation. – U2EF1 May 17 '14 at 04:04
  • I know "how" to use the regex in general, but I cannot figure it out for specific numbers, and yes, I need to use a regex – Kryptos May 17 '14 at 04:07
  • Make a dictionary of Roman Numerals to decimal. Look at each character in the string, use the dictionary and the rules for roman numerals. – wwii May 17 '14 at 04:08
  • @wwii can you post an example? – Kryptos May 17 '14 at 04:09
  • I would do it without using ```re```. – wwii May 17 '14 at 04:12
  • @wwii I am required to use a re – Kryptos May 17 '14 at 04:13

2 Answers2

0

You can use regex to split a string like CCMMI into three parts: The string of largest value ("MM"), whatever's left of it to be subtracted, and whatever's right of it to be added.

You then have the trivial problem of finding the value of a string of a single value (MM), and the two smaller problems of finding the value of two roman numerals that don't include "M" (CC and I). You can divide and conquer like this until the base case of an empty string, which is 0.

Here's a suboptimal implementation of this, which does a lot more matching than necessary and has no input validation (wouldn't want to ruin all the fun):

import re

values = [ ("M", 1000), ("D", 500), ("C", 100),
    ("L", 50), ("X", 10), ("V", 5), ("I", 1) ]

def romanNumeralToInt(romanNum):
    for (c, v) in values:
        match = re.match("(.*?)(" + c + "+)(.*)", romanNum)   
        if match:                                          
            return len(match.group(2)) * v \
                - romanNumeralToInt(match.group(1)) \
                + romanNumeralToInt(match.group(3))
    return 0
that other guy
  • 116,971
  • 11
  • 170
  • 194
0

With a regex:

import re
roman = {'I' : 1, 'V' : 5, 'X' : 10, 'L' : 50,
         'C' : 100, 'D' : 500, 'M' : 1000,
         'IV' : 4, 'IX' :9, 'XL' : 40, 'XC' : 90,
         'CD': 400, 'CM' : 900}

def convert(numerals):
    total = 0
    specials = re.compile('IV|IX|XL|XC|CD|CM')
    for special in specials.findall(numerals): 
        total += roman[special]
        numerals = numerals.replace(special, '', 1)
    return total + sum(roman[n] for n in numerals)

Without regex:

def convert(numerals):
    total = 0
    for special in ('IV', 'IX', 'XL', 'XC', 'CD', 'CM'):
        if numerals.count(special):
            total += roman[special] * numerals.count(special)
            numerals = numerals.replace(special, '')
    return total + sum(roman[n] for n in numerals)
wwii
  • 23,232
  • 7
  • 37
  • 77