Last active
December 2, 2015 14:38
-
-
Save Craga89/1fbf93052efc5a3348d7 to your computer and use it in GitHub Desktop.
Generic method for generating Roman Numerals for numbers 0 - 1M
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
romanNumeral(5) // "V" | |
romanNumeral(9) // "IX" | |
romanNumeral(46) // "XL" | |
romanNumeral(2015) // "MMXV" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var numeralsMap = { | |
1: 'I', | |
5: 'V', | |
10: 'X', | |
50: 'L', | |
100: 'C', | |
500: 'D', | |
1000: 'M', | |
5000: 'V`', | |
10000: 'X`', | |
50000: 'L`', | |
100000: 'C`', | |
500000: 'D`', | |
1000000: 'M`' | |
}; | |
// Retrieves the most significant number of a given number | |
// i.e. the left-hand most number: 5474 -> 5, 4111 -> 4 etc. | |
function mostSignificantNumber(num) { | |
return Number(String(num).charAt(0)); | |
} | |
// Generates the Roman Numeral for a given one, tens, hundreds | |
// etc. number. padded by zeroes that signify it's column | |
function partialRomanNumeral(num) { | |
var letter = numeralsMap[num]; | |
if (letter) { | |
return letter; | |
} | |
var places = String(num).length; | |
var multiplier = Math.pow(10, places - 1); | |
var low = 1 * multiplier; | |
var mid = (5 - 1) * multiplier; | |
var high = (10 - 1) * multiplier; | |
var repeat; | |
// I -> III | |
if (num < mid) { | |
repeat = mostSignificantNumber(num); | |
return numeralsMap[low].repeat(repeat); | |
} | |
// IV | |
else if (num === mid) { | |
return numeralsMap[low] + numeralsMap[mid + low]; | |
} | |
// V -> VIII | |
else if(num < high) { | |
repeat = mostSignificantNumber(num - (mid + multiplier)); | |
return numeralsMap[mid + low] + numeralsMap[low].repeat(repeat); | |
} | |
// IX | |
else { | |
return numeralsMap[low] + numeralsMap[high + low]; | |
} | |
} | |
// Generates the Roman numeral for any given number by splitting it | |
// into individual ones, tens, hundreds etc. numbers, and combining | |
// each individual columns Roman Numeral right-to-left. | |
// | |
// romanNumeral(51) -> partialRomanNumeral(1) + partialRomanNumeral(50) | |
// | |
function romanNumeral(num) { | |
if (num > 1000000) { | |
throw new Error('Number too large'); | |
} | |
return Array.prototype.reduce.call(String(num), function(memo, n, i) { | |
var power = Math.pow(10, i + 1); | |
var numeral = num % power - num % (power / 10); | |
return partialRomanNumeral(numeral) + memo; | |
}, | |
''); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment