Задача:
Семь различных символов представляют римские цифры со следующими значениями:
| Символ | Значение |
|---|---|
| I | 1 |
| V | 5 |
| X | 10 |
| L | 50 |
| C | 100 |
| D | 500 |
| M |
1000 |
Римские цифры формируются путем добавления значений десятичных разрядов от наибольшего к наименьшему. Преобразование значения десятичного разряда в римскую цифру имеет следующие правила:
1. Если значение не начинается с 4 или 9, выберите символ максимального значения, который можно вычесть из введенного числа, добавьте этот символ к результату, вычтите его значение и преобразуйте остаток в римскую цифру.
2. Если значение начинается с 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).
3. Только степени 10 (I, X, C, M) могут добавляться последовательно не более 3 раз для представления кратных 10. Нельзя добавлять 5 (V), 50 (L) или 500 (D) несколько раз. Если необходимо добавить символ 4 раза, используйте вычитаемую форму.
Дано целое число в диапазоне от 1 до 3999, преобразуйте его в римскую цифру.
1 <= num <= 3999
Решение:
Сразу скажу, способов решения данной задачи несколько. Способ, которым я пытался решать был в лоб и не оптимален, плюс мое решение не учитывало цифры "4" и "9" (пропустил этот момент) и на тестах, естественно, мое решение провалилось, поэтому пошел к умному чат-боту за объяснением (все же я по образованию не программист и многих вещей могу не знать, а знать хочется).
Итак, сразу вот решение:
function int_to_roman($num) {
$val = [
1000, 900, 500, 400,
100, 90, 50, 40,
10, 9, 5, 4,
1
]; // массив, который содержит арабские значения, соответствующие римским цифрам
$syms = [
"M", "CM", "D", "CD",
"C", "XC", "L", "XL",
"X", "IX", "V", "IV",
"I"
]; // массив, который содержит римские символы, которые мы будем использовать для формирования результата
$result = "";
for ($i = 0; $i < count($val); $i++) { // цикл проходит по всем элементам из массива значений $val
while ($num >= $val[$i]) {// нутренний цикл while проверяет, больше ли число $num текущего значения из массива $val. Если это так, то:
// - Римский символ (из массива $syms) добавляется к переменной $result.
//- Значение текущего элемента из $val вычитается из числа $num.
// Это происходит до тех пор, пока $num больше или равно текущему значению.
$result .= $syms[$i];
$num -= $val[$i];
}
}
return $result;
}
// Пример использования:
echo int_to_roman(1994); // Вывод: MCMXCIV
Вот такое вышло простое и интересное решение :)