Converting Roman Numerals to integers in python

前端 未结 17 1587
挽巷
挽巷 2020-12-03 03:56

This is now my current code after what user2486 said.

def romanMap():
    map=((\"M\",  1000),(\"CM\", 900),(\"D\",  500),(\"CD\", 400),(\"C\",  100),(\"XC\"         


        
相关标签:
17条回答
  • 2020-12-03 04:24

    There is a very detailed description of the development of the Roman numeral converters in the Dive Into Python 3 by Mark Pilgrim. See the 5.3. Case Study: Roman Numerals that introduces the problem and details.

    But that is not all. See the Chapter 9. Unit Testing where the analysis and the implementation of Roman numeral converters continues, including interesting optimization and exception throwing -- the (unit) test driven development.

    It is directly related to the enginefree's reference to the code in the first comment below the question (the code was written by Mark Pilgrim).

    0 讨论(0)
  • 2020-12-03 04:27

    I know this is an old post, but I would like to add 3 solutions to convert roman numerals to numbers.

    Solution 1: (Approx Runtime = 52ms)

    def romanToInt(self, s: str) -> int:
    
         roman = {'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000 }    
         num = 0
    
         for i in range(len(s)):
    
            if i!= len(s)-1 and roman[s[i]] < roman[s[i+1]]:
                 num += roman[s[i]]*-1
            else:
                 num += roman[s[i]]
    
          return num
    

    Solution 2: (Approx Runtime = 60ms)

    def romanToInt(self, s: str) -> int:
    
         roman = {'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000 }    
         num = 0
    
         s = s.replace("IV", "IIII").replace("IX", "VIIII")
         s = s.replace("XL", "XXXX").replace("XC", "LXXXX")
         s = s.replace("CD", "CCCC").replace("CM", "DCCCC")
    
         for x in s:
            num += roman[x]
    
         return num
    

    Solution 3: (Approx Runtime = 48ms)

    def romanToInt(self, s: str) -> int:
    
         roman = {'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000 }    
         num = 0
    
         for i in range(len(s)-1):
            if roman[s[i]] < roman[s[i+1]]:
                num += roman[s[i]]*-1
                continue
    
             num += roman[s[i]]
    
          num +=roman[s[-1]]
    
          return num
    

    The simplest solution appears to be the best at times :)

    0 讨论(0)
  • 2020-12-03 04:28

    Here is my solution:

    numerals = [
            {'letter': 'M', 'value': 1000},
            {'letter': 'D', 'value': 500},
            {'letter': 'C', 'value': 100},
            {'letter': 'L', 'value': 50},
            {'letter': 'X', 'value': 10},
            {'letter': 'V', 'value': 5},
            {'letter': 'I', 'value': 1},
        ]
    
    def arabic_to_roman(number):
        remainder = number
        result = ''
        for numeral_index in xrange(len(numerals)):
            numeral = numerals[numeral_index]
            next_numeral = numerals[numeral_index + 1] if numeral_index + 1 < len(numerals) else None
    
            factor = remainder / numeral['value']
            remainder -= factor * numeral['value']
    
            if next_numeral:
                numeral_difference = numeral['value'] - next_numeral['value']
                if (remainder - numeral_difference >= 0) and (numeral_difference > next_numeral['value']):
                    result += next_numeral['letter'] + numeral['letter']
                    remainder -= numeral_difference
    
            if factor > 0:
                result += numeral['letter'] * factor
    
        return result
    
    
    def roman_to_arabic(number):
        index_by_letter = {}
        for index in xrange(len(numerals)):
            index_by_letter[numerals[index]['letter']] = index
    
        result = 0
        previous_value = None
        for letter in reversed(number):
            index = index_by_letter[letter]
            value = numerals[index]['value']
            if (previous_value is None) or (previous_value <= value):
                result += value
            else:
                result -= value
            previous_value = value
    
        return result
    
    0 讨论(0)
  • 2020-12-03 04:28

    A nice compact version with no external libraries:

    def rn_to_int(s):
      d = {'m': 1000, 'd': 500, 'c': 100, 'l': 50, 'x': 10, 'v': 5, 'i': 1}
      n = [d[i] for i in s.lower() if i in d]
      return sum([i if i>=n[min(j+1, len(n)-1)] else -i for j,i in enumerate(n)])
    
    
    for numeral, expected in [['CLXIV', 164], ['MDCCLXXXIII', 1783], ['xiv', 14]]:
      assert rn_to_int(numeral) == expected
    
    0 讨论(0)
  • 2020-12-03 04:28

    Work from right to left of the roman numeral to add or subtract values. Easy.

    def rome(roman_num):
         d = {'I':1,'V':5,'X':10,'L':50,'C':100,'D':500,'M':1000}
         nl = list(roman_num)
         sum = d[nl[len(nl)-1]]
         for i in range(len(nl)-1,0,-1):
                 if d[nl[i]]>d[nl[i-1]]:
                         sum -= d[nl[i-1]]
                 else:
                         sum += d[nl[i-1]]       
         return sum
    
    0 讨论(0)
提交回复
热议问题