Skip to content

Instantly share code, notes, and snippets.

@djtriptych
Created June 20, 2024 15:36
Show Gist options
  • Save djtriptych/85106efeaa86c8680200d9d45c78ae36 to your computer and use it in GitHub Desktop.
Save djtriptych/85106efeaa86c8680200d9d45c78ae36 to your computer and use it in GitHub Desktop.
roman
// 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