Skip to content

Instantly share code, notes, and snippets.

@colingourlay
Created April 18, 2012 22:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save colingourlay/2417038 to your computer and use it in GitHub Desktop.
Save colingourlay/2417038 to your computer and use it in GitHub Desktop.
Roman numerals generator
(function () {
function romanify(value) {
var numbers, numerals, result, i, len;
numbers = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 ];
numerals = ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"];
result = "";
for (i = 0, len = numbers.length; i < len; i++) {
while (value >= numbers[i]) {
value -= numbers[i];
result += numerals[i];
}
}
return result;
}
function shouldEqual(a, b) {
var result;
result = a == b;
if (!result) {
console.log(["shouldEqual: expected ", b, " but got ", a].join(""));
}
return result;
}
function testAll() {
console.log("romanify: 1 -> I", shouldEqual(romanify(1), "I"));
console.log("romanify: 5 -> V", shouldEqual(romanify(5), "V"));
console.log("romanify: 10 -> X", shouldEqual(romanify(10), "X"));
console.log("romanify: 4 -> IV", shouldEqual(romanify(4), "IV"));
console.log("romanify: 6 -> VI", shouldEqual(romanify(6), "VI"));
console.log("romanify: 87 -> LXXXVII", shouldEqual(romanify(87), "LXXXVII"));
console.log("romanify: 147 -> CXLVII", shouldEqual(romanify(147), "CXLVII"));
console.log("romanify: 2487 -> MMCDLXXXVII", shouldEqual(romanify(2487), "MMCDLXXXVII"));
}
testAll();
})();
@chrisjpowers
Copy link

Nice, that's a good approach! The recursion certainly DRYs the code up.

Only one problem -- in JavaScript (and Ruby, not sure about Python), you are not guaranteed to get your object keys back in the order that you put them in. In other words, when you do for (numeral in numerals) you are not guaranteed to get "M" first, "CM" second, etc. How can you change the code to ensure that you will always loop through these values in the right order, no matter what browser/JS environment you're in?

@colingourlay
Copy link
Author

Ah, that is a great consideration! I bundled the numbers and numerals together as an objects keys/values because I thought it improved readability.

So I could fix this in a few ways. The one I've implemented (and updated the gist with) is to use two arrays, one for numbers and one for corresponding numerals. This means my for-in loop changes to a for loop, I just output corresponding numerals using the same array index.

Other considerations were mainly around the structure of the numbers/numerals (a single array containing objects with a single key/value, or a single array containing arrays with two indexes), but I think I picked the most efficient one.

@chrisjpowers
Copy link

Cool, that does the trick! I hear what you're saying re: legibility of the object -- one other approach is to zip the two arrays together to make an array of tuples, ie var tuples = [["M", 1000], ["CM", 900]...] and then iterate over these tuples. As to which is more legible, that's debatable :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment