【每日一题20220414】罗马数字

:mage:‍ 给定一个罗马数字符号,请编写一个函数,将它翻译成十进制数字。

I:1
V :5
X:10
L:50
C:100
D:500
M:1,000
注意:IV表示4,因为I表示1,V表示5,左侧1比右侧5小,所以最终是5-1=4

【示例】
输入:XXI
输出:21
解释:因为罗马数字X表示10,罗马数字I表示1,因此XXI是21。

题目难度:困难
题目来源:CodeWars-Roman Numerals Decoder

def solution(roman: str)-> int:
    # your code here

assert solution(XXI) == 21
assert solution(IV) == 4
assert solution(MMVIII) == 2008
assert solution(MDCLXVI) == 1666
def solution(roman: str) -> int:
    # your code here
    rule_dict = {"I": 1, "V": 5, "X": 10, "L": 50, "C": 100, "D": 500, "M": 1000}
    count = rule_dict.get(roman[-1])
    if len(roman) == 0:
        return count
    else:
        for i in range(len(roman)-1):
            if rule_dict.get(roman[i]) >= rule_dict.get(roman[i+1]):
                count += rule_dict.get(roman[i])
            elif rule_dict.get(roman[i]) < rule_dict.get(roman[i+1]):
                count -= rule_dict.get(roman[i])
    print(count)
    return count


assert solution("XXI") == 21
assert solution("IV") == 4
assert solution("MMVIII") == 2008
assert solution("MDCLXVI") == 1666

def solution(roman: str) -> int:
    roman_numerals = {
        "I": 1,
        "V": 5,
        "X": 10,
        "L": 50,
        "C": 100,
        "D": 500,
        "M": 1000
    }
    num = 0
    pre_num = roman_numerals.get(roman[0])
    for i, k in enumerate(roman[1:]):
        value = roman_numerals.get(k)
        if value > pre_num:
            num -= pre_num
        else:
            num += pre_num
        pre_num = value
    num += pre_num
    return num

思路:遍历罗马字符换算成阿拉伯数字,若当前值小于下一位则变负数,最后求和

rome_dict ={"I": 1, "V": 5, "X": 10, "L": 50, "C": 100, "D": 500, "M": 1000, "O": 0}

def solution(roman: str) -> int:
    roman = roman + "O"
    rome_num_list = [rome_dict[roman[num_idx]] if rome_dict[roman[num_idx]] >= rome_dict[roman[num_idx + 1]] else -rome_dict[roman[num_idx]] for num_idx in range(len(roman)-1)]
    return sum(rome_num_list)
def solution(roman: str)-> int:
    m = 0
    # 创建映射
    roman2num = {'I':1,
              'V':5,
              'X':10,
              'L':50,
              'C':100,
              'D':500,
              'M':1000
              }

    # 判断罗马数字中最后一个元素和倒数第二个元素的大小
    if roman2num[roman[len(roman)-1]] > roman2num[roman[len(roman)-2]]:
        for i in range(len(roman)-1):
            m += roman2num[roman[i]]  # 除开最后一个元素之和
            m = roman2num[roman[len(roman)-1]] - m
        return m
    else:
        for i in range(len(roman)):
            m += roman2num[roman[i]]
        return m


assert solution("XXI") == 21
assert solution("IV") == 4
assert solution("MMVIII") == 2008
assert solution("MDCLXVI") == 1666
assert solution("VI") == 6
assert solution("IX") == 9
assert solution("X") == 10

题目给的 case 让你误解了?并不是只有最后两位需要处理噢,你代码执行下面的测试会报错

assert solution("MCMXCIV") == 1994
def solution(roman: str)-> int:
    dict_luoma={'I':1,'V' :5,'X':10,'L':50,'C':100,'D':500,'M':1000}
    a=[y for y in roman]
    n=dict_luoma[a[-1]]
    for i in range(len(a)-1):
        if dict_luoma[a[i+1]]>dict_luoma[a[i]]:
            n=n-dict_luoma[a[i]]
        elif dict_luoma[a[i+1]]<=dict_luoma[a[i]]:
            n=n+dict_luoma[a[i]]
    return n
def solution(roman: str)-> int:
    r = list(roman)
    value = {
        "I": 1,
        "V": 5,
        "X": 10,
        "L": 50,
        "C": 100,
        "D": 500,
        "M": 1000,
    }
    num = value.get(r[-1])
    for i in range(len(r) - 1):
        if value.get(r[i]) < value.get(r[i+1]):
            num = num - value.get(r[i])
        else:
            num = num + value.get(r[i])
    print(num)
    return num

assert solution("XXI") == 21
assert solution("IV") == 4
assert solution("MMVIII") == 2008
assert solution("MDCLXVI") == 1666
assert solution("VD") == 495
assert solution("DC") == 600
def test_solution(roman:str)-> int:

    rome_dict={"I":1,
               "V":5,
               "X":10,
               "L":50,
               "C":100,
               "D":500,
               "M":1000}
    result=rome_dict[roman[-1]]
    for i,n in enumerate(roman):
        if i<len(roman)-1 and  rome_dict[n]>=rome_dict[roman[i+1]] :
            result+=rome_dict[n]
        elif i<len(roman)-1 and rome_dict[n]<rome_dict[roman[i+1]] :
            result-=rome_dict[n]
    return result
assert solution(XXI) == 21
assert solution(IV) == 4
assert solution(MMVIII) == 2008
assert solution(MDCLXVI) == 1666
def solution(roman: str) -> int:
    data = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}
    l = len(roman)
    result = data[roman[0]]
    for i in range(l - 1):
        if data[roman[i]] >= data[roman[i + 1]]:
            result += data[roman[i + 1]]
        else:
            result = data[roman[i + 1]] - result
    return result


assert solution('XXI') == 21
assert solution('IV') == 4
assert solution('MMVIII') == 2008
assert solution('MDCLXVI') == 1666
def solution(roman: str)-> int:
    # your code here
    dict1 = {'I': 1,
            'V': 5, 
            'X': 10,
            'L': 50,
            'C': 100,
            'D': 500,
            'M': 1000
            }
    roman = roman[::-1]
    roman_num = []
    for  i in range(len(roman) - 1):
        if dict1[roman[i]] > dict1[roman[i + 1]]:
            roman_num.extend([f"{dict1[roman[i]]}", '-'])
        else:
            roman_num.extend([f"{dict1[roman[i]]}", '+'])
    roman_num.append(f"{dict1[roman[-1]]}")
    return eval(''.join(roman_num))



assert solution('XXI') == 21
assert solution('IV') == 4
assert solution('MMVIII') == 2008
assert solution('MDCLXVI') == 1666
def solution(roman: str)-> int:
    # your code here
    dict1 = {'I': 1,
            'V': 5, 
            'X': 10,
            'L': 50,
            'C': 100,
            'D': 500,
            'M': 1000
            }
    roman_num = [f"+{dict1[roman[-1]]}"]
    for  i in range(len(roman) - 1):
        if dict1[roman[i]] >= dict1[roman[i + 1]]:
            roman_num.extend([f"+{dict1[roman[i]]}"])
        else:
            roman_num.extend([f"-{dict1[roman[i]]}"])
    return eval(''.join(roman_num))


assert solution('XXI') == 21
assert solution('XIV') == 14
assert solution('MMVIII') == 2008
assert solution('MDCLXVI') == 1666
print(solution('MCMXCIV'))
def solution(roman: str)-> int:
    dict_luoma={'I':1,'V' :5,'X':10,'L':50,'C':100,'D':500,'M':1000}
    a = [y for y in roman]
    n=0
    for i in range(len(roman)-1):
        if i==len(roman) - 2 and dict_luoma[a[i]]<dict_luoma[a[i+1]]:
            n+=dict_luoma[a[i+1]]-dict_luoma[a[i]]
        elif  dict_luoma[a[i]]<dict_luoma[a[i+1]]:
            n-=dict_luoma[a[i]]
        elif i <len(roman) - 2 and dict_luoma[a[i]]>=dict_luoma[a[i+1]]:
            n +=dict_luoma[a[i]]
        elif i ==len(roman) - 2 and dict_luoma[a[i]]>=dict_luoma[a[i+1]]:
            n+=dict_luoma[a[-1]]+dict_luoma[a[i]]
    return n
import re

table = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}
i_table = {'I': 1, 'II': 2, 'III': 3, 'IV': 4, 'IX': 9}
x_table = {'X': 10, 'XX': 20, 'XXX': 30, 'XL': 40, 'XC': 90}
c_table = {'C': 100, 'CC': 200, 'CCC': 300, 'CD': 400, 'CM': 900}


def solution(roman: str) -> int:
    res = 0

    match = re.search('I+[VX]?', roman)
    if match:
        res += i_table[match.group()]
    
    match = re.search('(?<!I)V', roman)
    if match:
        res += table['V']
    
    match = re.search('(?<!I)X+[LC]?', roman)
    if match:
        res += x_table[match.group()]

    match = re.search('(?<!X)L', roman)
    if match:
        res += table['L']

    match = re.search('(?<!X)C+[DM]?', roman)
    if match:
        res += c_table[match.group()]

    match = re.search('(?<!C)D', roman)
    if match:
        res += table['D']

    match = re.match('M+', roman)
    if match:
        res += 1000 * (match.end() - match.start())

    return res


assert solution('I') == 1
assert solution('II') == 2
assert solution('III') == 3
assert solution('IV') == 4
assert solution('V') == 5
assert solution('VI') == 6
assert solution('VII') == 7
assert solution('VIII') == 8
assert solution('IX') == 9
assert solution('X') == 10
assert solution('XI') == 11
assert solution('XII') == 12
assert solution('XIII') == 13
assert solution('XIV') == 14
assert solution('XV') == 15
assert solution('XVI') == 16
assert solution('XVII') == 17
assert solution('XVIII') == 18
assert solution('XIX') == 19
assert solution('XX') == 20
assert solution('XXI') == 21
assert solution('XXIX') == 29
assert solution('XXX') == 30
assert solution('XL') == 40
assert solution('XLVIII') == 48
assert solution('XLIX') == 49
assert solution('L') == 50
assert solution('LX') == 60
assert solution('XC') == 90
assert solution('XCVIII') == 98
assert solution('XCIX') == 99
assert solution('C') == 100
assert solution('CI') == 101
assert solution('CC') == 200
assert solution('CD') == 400
assert solution('D') == 500
assert solution('DC') == 600
assert solution('CM') == 900
assert solution('M') == 1000
assert solution('MDCLXVI') == 1666
assert solution('MMVIII') == 2008
assert solution('MMMCMXCIX') == 3999

借鉴了大佬们的思路。

# Daily_20220414
def solution(roman: str) -> int:
    # your code here
    roman_num_dict = {"I": 1, "V": 5, "X": 10, "L": 50, "C": 100, "D": 500, "M": 1000}
    result = 0
    for i in range(len(roman)):
        if i == len(roman) - 1 or roman_num_dict[roman[i]] >= roman_num_dict[roman[i + 1]]:
            result += roman_num_dict[roman[i]]
        else:
            result -= roman_num_dict[roman[i]]
    return result


assert solution('XXI') == 21
assert solution('IV') == 4
assert solution('MMVIII') == 2008
assert solution('MDCLXVI') == 1666
def solution(roman: str)-> int:
    li = [("I","V","X","L","C","D","M"),(1, 5,10,50,100,500,1000)]
    ro_li = list(roman)
    ro_li.reverse()
    sum1 = sum([-li[1][li[0].index(i)] if ro_li.index(i)>0 and li[0].index(i)<li[0].index(ro_li[ro_li.index(i)-1])
                else li[1][li[0].index(i)] for i in ro_li])
    return sum1


assert solution("XXI") == 21
assert solution("IV") == 4
assert solution("MMVIII") == 2008
assert solution("MDCLXVI") == 1666
关闭