Romand to Numeral

by dannye

HTML

We are so used to reading from Left to Right, we forgot about the Right-to-Left alternatives...
<hr>
<script>
  const romanToArabic = (input) => [...input].reduceRight((
    acc,
    letter,
    idx,
    arr,
    value = { m: 1000, d: 500, c: 100,   l: 50, x: 10, v: 5, i: 1 } [letter.toLowerCase()],
    sameLetter = letter == arr[idx + 1] // ignore IIX notation
  ) => {
    if (value < acc.high && !sameLetter) {
      acc.Arabic += -value;
    } else {
      acc.Arabic += acc.high = value;
    }
    console.log(idx, letter, acc, 'value:', value, acc.high, arr[idx + 1]);
    return acc;
  }, { high: 0,Arabic: 0 }).Arabic; // return Arabic value
// TESTS
  Object.entries({
    "cxxiv": 124,
    "ix": 9,
    "iix": 10,
    "xL": 40,
    "MMMDXLIX": 3549,
    "MMMMCMXCIX": 4999,
    "MDCLXVI": 1666,
    "MIII": 1003
  }).map(([roman, value, converted = romanToArabic(roman)]) => {
    document.body.append(roman, "=", converted, document.createElement("HR"));
    console.assert(converted == value, "wrong conversion,", roman, "must be", value)
  })
</script>

JavaScript

/* let input = 999;
Object.entries({
  "M": 1000,
  "D": 500,
  "c": 100,
  "l": 50,
  "x": 10,
  "v": 5,
  "i": 1
}).reduce((acc,[letter, value],idx,arr) => {
  console.log(idx,input,acc);
  let letterRepeat = ~~(input/value);
  input -= letterRepeat * value;
  acc += letter.repeat(letterRepeat);
  console.log(letter,input) //999
  return acc;
},"");
 */