Как починить конвертер из римских в арабские числа?
Проблема лежит в прохождении по циклу (он начинается заново), вместо XC(90), находит X, a C вообще почему-то не ищет
rom2num = {'M': 1000, 'CM': 900, 'D': 500, 'CD': 400, 'C': 100,
'XC': 90, 'XL': 40, 'X': 10, 'IX': 9, 'V': 5,
'IV': 4, 'I': 1}
def tonum(str):
num = 0
while not str.find(""):
for letter,value in rom2num.items():
if letter in str:
num+= value
str = str.replace(letter,"",1)
return num
print(tonum("MCMXCIV"))
Ответы (2 шт):
Зачем вы записали такое странное условие цикла not str.find("")? Вне зависимости от того, что у вас в строке, find всегда будет возвращать 0, даже если она пустая, поэтому у вас бесконечный цикл. Достаточно было проверить строчку на пустоту, например так: s == "".
А ещё код нерабочий по причине того, что в словаре сочетания из двух цифр идут за теми, которые состоят из одной цифры. Из-за этого, на примере CM ответ будет 1100, т.к. он сначала извлечёт M, потом C. Поэтому все двузначные цифры в словаре должны стоять впереди:
rom2num = {'CM': 900, 'CD': 400, 'XC': 90, 'XL': 40, 'IX': 9, 'IV': 4, 'M': 1000, 'D': 500, 'C': 100, 'L': 50, 'X': 10, 'V': 5, 'I': 1}
def tonum(s):
num = 0
while s != "":
for letter,value in rom2num.items():
if letter in s:
num+= value
s = s.replace(letter,"",1)
return num
print(tonum("MCMXCIV"))
Стоит сказать, что необязательно всегда items идут в том же порядке, что вы задали при инициализации словаря. В данном случае это порядок сохраняется, но не думайте, что он будет сохраняться и в других случаях.
while not str.find(""): - это видимо проверка строки на пустоту. Обычно пишут так: while str:. Это в точности означает "пока строка не пустая".
После правки в программе останется ошибка: 'CD' отобразится в 600. А должно быть 400. Проблема в том что сперва найдётся строка 'D' (500), а потом 'C' (100). В сумме 600. До строки 'CD' очередь не дойдет.
Последняя ошибка - 'L' пропущено в словаре.
Чтобы устранить ошибку "CD->600" нужно искать подстроку начиная с фиксированного места. Программа ниже разбирает строку слева направо, примеряя фрагменты из "словаря" к текущей позиции. Если фрагмент совпал, сумма увеличивается, текущая позиция двигается:
items = (
('M' , 1000),
('CM', 900), ('D' , 500), ('CD', 400), ('C' , 100),
('XC', 90), ('L', 50), ('XL', 40), ('X' , 10),
('IX', 9), ('V' , 5), ('IV', 4), ('I' , 1)
)
def to_n(roman):
n = 0
i = 0
for t, v in items:
# while t == roman[i:i + len(t)]:
while roman.startswith(t, i):
n += v
i += len(t)
return n
print(to_n(input()))