用 python 对皇家国王名字进行排序

Sort Royal King names with python

您好,我正在尝试解决这个问题,但我无法解决这些错误
我想如何解决这个问题的想法是首先将名称拆分为名称和罗马数字,然后将罗马数字转换为阿拉伯数字,然后像整数一样排序,然后将阿拉伯数字反向转换为罗马数字

def from_roman(num):
    roman_numerals = {'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000}
    result = 0
    for i,c in enumerate(num):
        if (i+1) == len(num) or roman_numerals[c] >= roman_numerals[num[i+1]]:
            result += roman_numerals[c]
        else:
            result -= roman_numerals[c]
    return result

# convert from arabic to roman
def to_roman(num):
    roman_numerals = {1:'I', 5:'V', 10:'X', 50:'L', 100:'C', 500:'D', 1000:'M'}
    result=''
    for i,c in enumerate(num):
        if (i+1) == len(num) or roman_numerals[c] >= roman_numerals[num[i+1]]:
            result += roman_numerals[c]
        else:
            result -= roman_numerals[c]
    return result

def SortPrintKingsNames(kings):
    
    romanList=[]
    arabicList=[]
    #sort kings name first
    kings.sort()
    #sort roman numbers by converting them to arabic and sorting them
    for king in kings:
        romanList.append(from_roman(king.split()[-1]))
    romanList.sort()
    #convert to roman again      
    for roman in romanList:
        arabicList=to_roman(roman)
    
    for k in kings:
        # print names with roman number 
        print(k,arabicList[k])

错误如下:

Traceback (most recent call last):
  File "Solution.py", line 58, in <module>
    SortPrintKingsNames(kingsNames)
  File "Solution.py", line 48, in SortPrintKingsNames
    arabicList=to_roman(roman)
  File "Solution.py", line 29, in to_roman
    for i,c in enumerate(num):
TypeError: 'int' object is not iterable

出现此错误是因为您正在尝试枚举阿拉伯(整数)值。

更新 to_roman 功能以解决问题。

试试这个代码:

def from_roman(num):  # IV > 4
    roman_numerals = {'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000}
    result = 0
    for i,c in enumerate(num):
        if (i+1) == len(num) or roman_numerals[c] >= roman_numerals[num[i+1]]:
            result += roman_numerals[c]
        else:
            result -= roman_numerals[c]
    return result

# convert from arabic to roman
def to_roman(num):   #  4 > IV
    roman_numerals = {1:'I', 5:'V', 10:'X', 50:'L', 100:'C', 500:'D', 1000:'M'}
    result=''
    for k in list(roman_numerals.keys())[::-1]:
       while num >= k:
          result+=roman_numerals[k]
          num -= k
    # do replacements based on 'max 3' rule
    rt = [('DCCCC','CM'), ('CCCC','CD'), ('LXXXX','XC'), ('XXXX','XL'), ('VIIII','IX'), ('IIII','IV')]
    for r in rt:
        result = result.replace(*r) # convert tuple to args
#    for i,c in enumerate(num):
#        if (i+1) == len(num) or roman_numerals[c] >= roman_numerals[num[i+1]]:
#            result += roman_numerals[c]
#        else:
#            result -= roman_numerals[c]
    return result

def SortPrintKingsNames(kings):
    print(kings)
    romanList=[]
    arabicList=[]
    #sort kings name first
    #kings.sort()
    #sort roman numbers by converting them to arabic and sorting them
    #romanlist = from_roman(kings)
    for king in kings:
        romanList.append(from_roman(king.split()[-1]))
    print(romanList)
    romanList.sort()
    print(romanList)
    #convert to roman again      
    for roman in romanList:
        arabicList.append(to_roman(roman))
    
    print(arabicList)
#    for k in kings:
        # print names with roman number 
#        print(k,arabicList[k])

k = SortPrintKingsNames(['VI','I','IC','XX'])

输出

['VI', 'I', 'IC', 'XX']
[6, 1, 99, 20]
[1, 6, 20, 99]
['I', 'VI', 'XX', 'XCIX']

请注意,IC (99) 不是有效的罗马数字,因此将其转换为 XCIX。

替换是根据 'max 3' 规则完成的。任何数字只需要 6 个替换,因此列出替换比使用复杂的循环更清晰。

罗马数字规则(注意规则#4):

https://classace.io/learn/math/3rdgrade/roman-numerals-ivxlcdm

附带说明一下,如果这用于注册号码,则您需要的最大号码是 72 (LXXII)。

https://en.wikipedia.org/wiki/Heinrich_LXXII,_Prince_Reuss_of_Lobenstein_and_Ebersdorf

def roman_to_int(s:str):
    rom_to_int_map = {"I": 1, "V": 5, "X": 10, "L": 50, "C": 100, "D": 500, "M": 1000}
    sub_map = {'IV': 4, 'IX':9, 'XL': 40, 'XC': 90, 'CD':400, 'CM': 900}
    summation = 0
    idx = 0

    while idx < len(s):
        if s[idx:idx+2] in sub_map:
            summation += sub_map.get(s[idx:idx+2])
            idx += 2
        else:
            summation += rom_to_int_map.get(s[idx])
            idx += 1
    return summation
    
def sort_roman(names):
    name_array = []
    for name in names:
        n, num = name.split()
        num = roman_to_int(num)
        name_array.append((n, num, name))
    name_array.sort(key=lambda x: [x[0], x[1]])
    return list(map(lambda x:x[2], name_array))

sort_roman["Louis IV", "Louis I"]

// Result: ["Louis I", "Louis IV"]