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