devdropper87 devdropper87 - 1 month ago 14
Javascript Question

Roman Numeral Translator Using JavaScript

I got this to work without using underscore, but as an extra challenge I'm trying to convert Roman Numerals to Arabic numbers using underscore. Below is my attempt. It works, except for in the case of the "next" number being greater than the "current" one. I'm really not sure why, but when I check for if(next>= num), that if block is not even being executed?

var DIGIT_VALUES = {
I: 1,
V: 5,
X: 10,
L: 50,
C: 100,
D: 500,
M: 1000
};

var translateRomanNumeral = function(roman) {
// if it's not in the digit values object, return null
for (var i = 0; i < roman.length; i++) {

if (!(roman[i] in DIGIT_VALUES)) {
return null;
}

}
//with underscore:
var romanTranslated = reduce(roman, function(memo, letter, i) {
var prev = DIGIT_VALUES[roman[i - 1]];
var num = DIGIT_VALUES[letter];
var next = DIGIT_VALUES[roman[i + 1]];
if (next === undefined || next <= num) {
return memo + num;
}





This is not being executed for some reason:

if (next >= num) {
var diff = num - prev;
console.log(diff);
return memo + (diff - prev);
}
}, 0);
// grab the first one

//1
// console.log(num);
return romanTranslated;


};

console.log(translateRomanNumeral("LXIV")); //returns 66 ---> should return 64
console.log(translateRomanNumeral("CI")); //working --> returns 101
console.log(translateRomanNumeral("MMMMCCL")); // working ---> returns 4250.
//works!

Answer

The main source of my error was that the way I had defined reduce did not allow me access to the index while iterating. I updated my reduce function, then it worked after a little debugging:

var DIGIT_VALUES = {
  I: 1,
  V: 5,
  X: 10,
  L: 50,
  C: 100,
  D: 500,
  M: 1000
};
var each = function(collection, iterator) {
  if (Array.isArray(collection)) {
    for (var i = 0; i < collection.length; i++) {
      iterator(collection[i], i, collection);
    }

  } else {
    for (var key in collection) {
      iterator(collection[key], key, collection);
    }
  }

};

var reduce = function(collection, iterator, total) {
  if (total == undefined) {
    total = collection.shift();
  }


  each(collection, function(val, i) {
    total = iterator(total, val, i);
  })
  return total;
};

var translateRomanNumeral = function(roman) {
  if (typeof(roman) !== 'string') {
    return null;
  }
  if (!roman) {
    return 0;
  }
  // if it's not in the digit values object, return null
  for (var i = 0; i < roman.length; i++) {

    if (!(roman[i] in DIGIT_VALUES)) {
      return null;
    }

  }
  //with underscore:

  return reduce(roman, function(memo, letter, i) {
    var num = DIGIT_VALUES[letter];
     //console.log(i);
    //how do you acess the next item in a collection in reduce?
    var next = DIGIT_VALUES[roman[Number(i) + 1]];
    // console.log(Number(i) + 1);
    // console.log(next);

      if ( next === undefined || next <= num) {
        return memo + num;
        //console.log(memo);
      }

      else {
        // var diff = num - prev;
        // console.log(diff);
        return memo - num;
        // memo = memo + (next - num);
      }


    // return memo;
  }, 0);

};

console.log(translateRomanNumeral("LXIV")); //returns 66 ---> should return 64
console.log(translateRomanNumeral("IX")) // should return 9
console.log(translateRomanNumeral("IV")) /// should return 4

console.log(translateRomanNumeral("CI")); 
//working --> returns 101
console.log(translateRomanNumeral("MMMMCCL")); 
// working ---> returns 4250.
//works!
Comments