Converting Integers to Roman Numerals

Converting integers to their roman numeral equivalents

To minimize confusion, I suggest making two function instead of one:

private static final String[] ROMAN_LETTERS = {"I", "IV", "V", "IX", "X", "XL", "L", "XC", "C", "CD", "D", "CM",  "M" };
private static final int[] ROMAN_NUMBERS = { 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000 };

public static String romanizer(int num) {
StringBuilder result = new StringBuilder();
for (int h = ROMAN_NUMBERS.length - 1; h >= 0; h--) {
result.append(ROMAN_LETTERS[h].repeat(num / ROMAN_NUMBERS[h]));
num = num % ROMAN_NUMBERS[h];
}
return result.toString();
}

public static List<String> romanizer(List<Integer> numbers) {
List<String> result = new ArrayList<>();
for (int num : numbers)
result.add(romanizer(num));
return result;
}

Basic program to convert integer to Roman numerals?

One of the best ways to deal with this is using the divmod function. You check if the given number matches any Roman numeral from the highest to the lowest. At every match, you should return the respective character.

Some numbers will have remainders when you use the modulo function, so you also apply the same logic to the remainder. Obviously, I'm hinting at recursion.

See my answer below. I use an OrderedDict to make sure that I can iterate "downwards" the list, then I use a recursion of divmod to generate matches. Finally, I join all generated answers to produce a string.

from collections import OrderedDict

def write_roman(num):

roman = OrderedDict()
roman[1000] = "M"
roman[900] = "CM"
roman[500] = "D"
roman[400] = "CD"
roman[100] = "C"
roman[90] = "XC"
roman[50] = "L"
roman[40] = "XL"
roman[10] = "X"
roman[9] = "IX"
roman[5] = "V"
roman[4] = "IV"
roman[1] = "I"

def roman_num(num):
for r in roman.keys():
x, y = divmod(num, r)
yield roman[r] * x
num -= (r * x)
if num <= 0:
break

return "".join([a for a in roman_num(num)])

Taking it for a spin:

num = 35
print write_roman(num)
# XXXV

num = 994
print write_roman(num)
# CMXCIV

num = 1995
print write_roman(num)
# MCMXCV

num = 2015
print write_roman(num)
# MMXV

Converting integers into words and roman numerals

Take a look at cl-format, it can return "twenty one", I used that for project euler.

http://clojuredocs.org/clojure_core/1.2.0/clojure.pprint/cl-format

and Roman too:

~@R prints arg as a Roman numeral: IV; and ~:@R prints arg as an old Roman numeral: IIII.

Conversion of integers to Roman numerals (python)

The two lists, ints and nums are the same length. The loop iterates over the length of ints, which means that the variable i can access the same position of either list, matching one to the other.

If we step through the loop, count is assigned the integer value of the input divided by the first number in ints, which is 1000. If the input variable is, say, 10, then 10/1000 will result in a number <1, and using int() on the result will cause it to assign 0 to count. When 0 is multiplied by the matching string from nums, the assigned result is basically nothing. Then the same amount is subtracted from input, which in this case leaves it unchanged.

Eventually, the loop will reach a point when the result of the division is a number >=1, so the following steps will do something.

Let's say the result of int(input / ints[i]) is 3. "X" * 3 results in "XXX", which is added to result, and the input is reduced by the appropriate amount, in this case 30. So on, until the loop ends.

How to convert Python Integer to Roman Numeral and vice-versa?

Here's my take on an OOP approach to this.

We have a class Number which can be constructed in one of 3 ways. Either with a plain int, a string representation of an int or a Roman numeral.

The internal representation of the value is converted to a plain int.

Users can use the class's asInteger() and asRoman() functions to retrieve the class's value as an int or as a Roman numeral. These methods are impervious to the way the class was constructed.

Users can perform addition or subtraction using plain int or other instances of the Number class.

Examples of use follow the code:

class Number:
control = [
(1000, 'M', 1),
(900, 'CM', 2),
(500, 'D', 1),
(400, 'CD', 2),
(100, 'C', 1),
(90, 'XC', 2),
(50, 'L', 1),
(40, 'XL', 2),
(10, 'X', 1),
(9, 'IX', 2),
(5, 'V', 1),
(4, 'IV', 2),
(1, 'I', 1)]

def __init__(self, value):
if isinstance(value, int):
self.value = value
elif value.isdigit():
self.value = int(value)
else:
self.value = self._toInteger(value)
if value != self.toRoman(self.value):
raise ValueError('Not a valid Roman numeral')

def asInteger(self):
return self.value

def asRoman(self):
return self.toRoman(self.value)

def toRoman(self, num):
if num == 0:
return ''
for v, c, _ in Number.control:
if num >= v:
return c + self.toRoman(num-v)

def _toInteger(self, num):
result, offset = 0, 0
for c, r, l in Number.control:
while num[offset:].startswith(r):
result += c
offset += l
return result

def __add__(self, o):
if isinstance(o, Number):
self.value += o.value
elif isinstance(o, int):
self.value += o
else:
raise ValueError
return self

def __sub__(self, o):
if isinstance(o, Number):
self.value -= o.value
elif isinstance(o, int):
self.value -= o
else:
raise ValueError
return self

n = Number('MCMI')
m = Number(5)
print(n.asRoman())
n += m
print(n.asRoman())
m = 4
n -= m
print(n.asRoman())

Output:

MCMI
MCMVI
MCMII


Related Topics



Leave a reply



Submit