Сортировка имен королевских королей с помощью python

#python-3.x #string #list #sorting #roman-numerals

#python-3.x #строка #Список #сортировка #римские цифры

Вопрос:

Привет, я пытаюсь решить эту проблему, но я не могу решить эти ошибки
Идея того, как я хотел решить проблему, заключается в том, чтобы сначала разделить имена на имена и римские числа, а затем преобразовать римские числа в арабские, после этого отсортировать как целые числа и выполнить обратное преобразование с арабского на римский

 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
  

Ответ №1:

Ошибка возникает, потому что вы пытаетесь перечислить арабские (целочисленные) значения.

Обновите 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.

Замены выполняются на основе правила «максимум 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

Комментарии:

1. да, но у него есть проблема с числом 9, потому что оно преобразуется как VIIII, а не как IX

Ответ №2:

 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"]