Roman Numeral Converter
I started with a bunch of if
and else if
statements, using an object for the roman numerals:
const convertToRoman = num => {
const romanNumerals = {
1: "I",
4: "IV",
5: "V",
9: "IX",
10: "X",
40: "XL",
50: "L",
90: "XC",
100: "C",
400: "CD",
500: "D",
900: "CM",
1000: "M"
};
let result = "";
if (num > 1 && num < 4) {
result += romanNumerals[1] + convertToRoman(num - 1);
}
else if (num > 5 && num < 9) {
result += romanNumerals[5] + convertToRoman(num - 5);
}
else if (num > 10 && num < 40) {
result += romanNumerals[10] + convertToRoman(num - 10);
}
else if (num > 40 && num < 50) {
result += romanNumerals[40] + convertToRoman(num - 40);
}
else if (num > 50 && num < 90) {
result += romanNumerals[50] + convertToRoman(num - 50);
}
else if (num > 90 && num < 100) {
result += romanNumerals[90] + convertToRoman(num - 90);
}
else if (num > 100 && num < 400) {
result += romanNumerals[100] + convertToRoman(num - 100);
}
else if (num > 400 && num < 500) {
result += romanNumerals[400] + convertToRoman(num - 400);
}
else if (num > 500 && num < 900) {
result += romanNumerals[500] + convertToRoman(num - 500);
}
else if (num > 900 && num < 1000) {
result += romanNumerals[900] + convertToRoman(num - 900);
}
else if (num > 1000) {
result += romanNumerals[1000] + convertToRoman(num - 1000);
}
else {
result = romanNumerals[num];
}
return result;
}
Even though that works, I noticed there was a lot of repeating code. However, I wanted to finish the other projects before refactoring. Once I finished the projects, I revisited this code and refactored into the following:
const convertToRoman = num => {
const romanNumerals = {
1: "I",
4: "IV",
5: "V",
9: "IX",
10: "X",
40: "XL",
50: "L",
90: "XC",
100: "C",
400: "CD",
500: "D",
900: "CM",
1000: "M"
};
let dif = 0;
if (num <= 0) return;
if (romanNumerals[num] !== undefined) {
return romanNumerals[num];
}
else {
while (romanNumerals[num] === undefined) {
num--;
dif++;
}
}
return romanNumerals[num] + convertToRoman(dif);
}
This is better, but I’m sure there are better ways to solve this. In looking at the fCC Guide for Roman Numeral Converter, the basic solution shows a simpler, more straightforward way to solve this (updated with ES6 syntax):
const convertToRoman = num => {
const decimalValue = [ 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 ];
const romanNumeral = [ 'M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I' ];
let romanized = '';
romanNumeral.map((numeral, index) => {
while (decimalValue[index] <= num) {
romanized += romanNumeral[index];
num -= decimalValue[index];
}
});
return romanized;
}
The other two solutions in the guide seem more complicated than they have to be. However, maybe there are performance gains from using those methods, I don’t know.
There are some interesting ways to solve this problem on the Convert a number into a Roman Numeral in javaScript Stack Overflow question. I found the following solution listed on that page to be interesting because it uses recursion:
function convertToRoman(num) {
const decimals = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
const roman = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I'];
for (let i = 0; i < decimals.length; i++) {
if(num < 1)
return "";
if(num >= decimals[i]) {
return roman[i] + convertToRoman(num - decimals[i]);
}
}
}
I’m not sure if this solution is efficient or if it uses best practices, but it works.
The following solution from felixvolny.com also uses recursion, but uses the JavaScript Map Object instead of an object or arrays:
const map = new Map();
map.set('M', 1000);
map.set('CM', 900);
map.set('D', 500);
map.set('CD', 400);
map.set('C', 100);
map.set('XC', 90);
map.set('L', 50);
map.set('XL', 40);
map.set('X', 10);
map.set('IX', 9);
map.set('V', 5);
map.set('IV', 4);
map.set('I', 1);
const convertToRoman = (number) => {
if (number === 0) {
return '';
}
for (const [roman, integer] of map.entries()) {
if (number >= integer) {
return roman + convertToRoman(number - integer);
}
}
};
Read through the post at felixvolny.com for a great explanation of the code. Felix has some interesting solutions for other fCC algorithms as well.
I found a solution on selftaughtjs.com. It uses a little math, but the num%decimal[i] < num
can be exchanged for decimalValue[index] <= num
, which makes it identical to the basic solution in the fCC Guide. I like the detailed explanation. It describes what Roman Numerals are, how the solution was created, and how it works.
There’s also an exaplanation of how to convert from Roman Numerals to Arabic Numerals on the selftaughtjs.com page.
Maria Campbell has a great write up of the problem and solution as well, if one wants another explanation.
As mentoined on the selftaughtjs.com page, this Roman Number converter by Bert McLees on jsfiddle.net goes far deeper than the fCC requirements. It’s well-documented in case one’s curious how to do something like this.
Thoughts and criticisms welcome.