Created
June 20, 2024 15:36
-
-
Save djtriptych/85106efeaa86c8680200d9d45c78ae36 to your computer and use it in GitHub Desktop.
roman
This file contains 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
// Converting to/from roman numerals (1-4999) | |
const map = { | |
1: 'I', | |
5: 'V', | |
10: 'X', | |
50: 'L', | |
100: 'C', | |
500: 'D', | |
1000: 'M', | |
} | |
const imap = { | |
I: 1, | |
V: 5, | |
X: 10, | |
L: 50, | |
C: 100, | |
D: 500, | |
M: 1000, | |
} | |
const subs = { | |
5: 1, | |
10: 1, | |
50: 10, | |
100: 10, | |
1000: 100, | |
}; | |
const sortNumeric = (a, b) => a - b; | |
const amounts = Object.keys(map).map(Number).sort(sortNumeric); | |
const dec2roman = n => { | |
// Zero. | |
if (n === 0) | |
return '' | |
// Exact match | |
if (n in map) | |
return map[n] | |
// Larger than largest amount, so just prepend that symbol. | |
if (n > 1000) { | |
return 'M' + dec2roman(n - 1000); | |
} | |
// Find next highest symbol | |
let index; | |
for (var i = 0; i < amounts.length; i++) { | |
if (amounts[i] > n) { | |
index = i; | |
break; | |
} | |
} | |
const highDec = amounts[index]; | |
const highRoman = map[highDec]; | |
const lowDec = amounts[index - 1]; | |
const lowRoman = map[lowDec]; | |
// Return a 2 character decremented roman symbol like 'IV' or 'CM' | |
if (highDec in subs) { | |
const sub = subs[highDec]; | |
if (n >= highDec - sub) { | |
return map[sub] + highRoman + dec2roman(n - (highDec - sub)); | |
} | |
} | |
// Prepend the next lowest symbol e.g. 'V' if n = 6. Then recurse with the | |
// remainder. | |
return lowRoman + dec2roman(n - lowDec); | |
} | |
const roman2dec = s => { | |
const digits = s.split('') | |
if (digits.length === 0) | |
return 0; | |
if (digits.length === 1) | |
return imap[digits.pop()] | |
const first = digits.pop(); | |
const second = digits.pop(); | |
if (imap[second] < imap[first]) { | |
const delta = imap[first] - imap[second] | |
return delta + roman2dec(digits.join('')) | |
} | |
digits.push(second); | |
return imap[first] + roman2dec(digits.join('')) | |
} | |
for (var i = 0; i <= 100; i++) { | |
const roman = dec2roman(i) | |
console.log(i, roman, roman2dec(roman)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment