Перевод числа в римскую нотацию
Задача:
Семь различных символов представляют римские цифры со следующими значениями:
Числа: | Римсие числа: |
---|---|
I | 1 |
V | 5 |
X | 10 |
L | 50 |
C | 100 |
D | 500 |
M | 1000 |
Римские цифры образуются путем добавления преобразований значений десятичных знаков от самого высокого к самому низкому. Преобразование значения десятичного знака в римское число имеет следующие правила:
Если значение не начинается с 4 или 9, выберите символ максимального значения, которое можно вычесть из входных данных, добавьте этот символ к результату, вычтите его значение и преобразуйте остаток в римскую цифру. Если значение начинается с 4 или 9, используйте субтрактивную форму , представляющую один символ, вычитаемый из следующего символа, например, 4 на 1 ( I) меньше 5 ( V): IV и 9 на 1 ( I) меньше 10 ( X): IX. Используются только следующие субтрактивные формы: 4 ( IV), 9 ( IX), 40 ( XL), 90 ( XC), 400 ( CD) и 900 ( CM). Только степени 10 ( I, X, C, M) могут быть добавлены последовательно не более 3 раз для представления кратных 10. Вы не можете добавить 5 ( V), 50 ( L) или 500 ( D) несколько раз. Если вам нужно добавить символ 4 раза, используйте вычитательную форму . Дано целое число, преобразуйте его в римскую цифру.
Пример 1:
Ввод: число = 3749
Вывод: "MMMDCCXLIX"
Объяснение:
3000 = МММ как 1000 (М) + 1000 (М) + 1000 (М)
700 = DCC как 500 (D) + 100 (C) + 100 (C)
40 = XL как 10 (X) меньше 50 (L)
9 = IX как 1 (I) меньше 10 (X)
Примечание: 49 не на 1 (I) меньше 50 (L), поскольку преобразование основано на десятичных знаках.
Пример 2:
Ввод: число = 58
Вывод: "LVIII"
Объяснение:
50 = L, 8 = VIII
Пример 3:
Ввод: число = 1994
Вывод: "MCMXCIV"
Объяснение:
1000 = М
900 = СМ
90 = ХС
4 = IV
Ограничения:
1 <= num <= 3999
Ссылка:
Ссылка на leetcode
Моё решение:
def intToRoman(num):
result = []
roman_nums = {1: 'I', 5: 'V', 10: 'X',
50: 'L', 100: 'C', 500: 'D',
1000: 'M'}
while num > 0:
for elem in reversed(roman_nums):
if elem <= num:
num -= elem
result.append(roman_nums[elem])
break
return ''.join(result)
Вопрос:
У меня скорее возникает вопрос в постановке задачи, нежели как её решить. будет ли корректно добавлять в словарь такие значения (ключ: значение) как:
{4: 'IV', 9: 'IX'} # И так далее для 40, 90, 400 и 900.
Или стоит решить задачу по-другому? Без использования этих значений (ключ: значение)? Я имею ввиду, что могу попробовать определять какое число наиболее подходит на данный момент, и в случае, если это будет 4 или 9 (или 40, 90, 400, 900), собирать уже такую конструкцию как IV (и тп. для других случаев). Может, в этом и состоит суть задачи?
Ответы (1 шт):
Всё-таки решил попробовать использовать только те значения, что есть в таблице. Вот что получилось:
def int_to_roman(num):
result = []
nums = (1000, 500, 100, 50, 10, 5, 1, None)
roman_nums = ('M', 'D', 'C', 'L', 'X', 'V', 'I')
while not num == 0:
for max_deductible in nums:
# Находим такое наибольшее вычитаемое, которое будет меньше либо равно num
if max_deductible <= num:
# Сохраняем индекс вычитаемого
max_deductible_index = nums.index(max_deductible)
break
# Сохраняем предыдущее число (до max_deductible)
previous_num = nums[max_deductible_index - 1]
flag = len(str(max_deductible)) == len(str(previous_num))
# Выбор вычитаемого из next_num, которое подходит для данного случая
possibly_deductible = (nums[max_deductible_index + 1], max_deductible)[flag]
# Если существует число менее num и более max_deductible (в nums)
if all((possibly_deductible, previous_num)) and previous_num - possibly_deductible <= num:
num -= (previous_num - possibly_deductible)
possibly_deductible_index = nums.index(possibly_deductible)
# В римском вычитании сначала ставится вычитаемое, а потом уменьшаемое
result.append(roman_nums[possibly_deductible_index] +
roman_nums[max_deductible_index - 1])
else: # Если такого числа не существует, вычитаем max_deductible
num -= max_deductible
result.append(roman_nums[max_deductible_index])
return ''.join(result) # Возращаем результат
Хоть это и абсолютно бесполезно, решил поставить себе такую задачу. Стоит понимать, что я занимаюсь программированием менее полугода, поэтому, возможно, ваше решение может быть намного более эффективнее. Я лишь попробовал реализовать свою логику теми знаниями, которые на данный момент у меня есть. Также сделал вариант где возможны такие комбинации как: 49, 55 (и так далее), но, его выложить пока не могу, возможно, позже.