Sharing my Roman Numeral Converter

Hi Everyone,
Just wanted to share my solution to the roman numeral converter problem in Javascript. I like it because it is quick and easily scales up to just about any number (by adding to the roman numeral key). No conversion charts are necessary as the function just takes advantage of the pattern roman numerals follow.

Let me know if you have any suggestions.

The code is below

function convertToRoman(num) {
  let a = performance.now();
  const Key = ["I", "V", "X", "L", "C", "D", "M"];
  

  // reversing our number so that we start with the smallest number, 
//and progress upwards.  This way we know what power to the ten our number is.  i.e. 
//should our 2 represent 2 or 20 or 200 or 20000.  
  let reversedNumArr = num.toString().split("").reverse();
  let reversedNumArrLength = reversedNumArr.length;
  let answerArr = [];
  
 // a for loop that loops through our reversed number.  
 for(let i = 0; i < reversedNumArrLength; i++) {
   if(reversedNumArr[i] <= 3) {
    // if our number is between 1 and 3, we will be selecting the correct roman numeral from our key (we know this because it always follows the same pattern) and repeating it the number of times that our number is equal to.    
    answerArr.unshift(Key[i * 2].repeat(reversedNumArr[i]));
    
    // if our number is 4, then we will be selecting the correct roman numerals from our key, and unshifting it to our array.  This continues for 5, 6, 7, 8, 9.  
   } else if(reversedNumArr[i] === "4") {
     
     answerArr.unshift(Key[i * 2] + Key[(i * 2) + 1])
 
   } else if(5 <= reversedNumArr[i] && reversedNumArr[i] <= 8) {
     
     answerArr.unshift(Key[(i * 2) + 1] + Key[i * 2].repeat(reversedNumArr[i] - 5));
     
   } else if(reversedNumArr[i] === "9") {
     answerArr.unshift(Key[i * 2] + Key[(i * 2) + 2]); 
   }
 }
 
 let answer = answerArr.join("");
 
  let b = performance.now();
  console.log(b-a)
 return answer;
}

convertToRoman(29); 

Unshift is linear algorithm inside for loop. By default such function cannot be called performant :slight_smile: Think if you can make it linear or even faster

Hey there,

great work!

My ideas:

  • think about why unshift is slow (like snigo mentioned); not a dealbreaker, only to think about it

Keep us posted!

Thanks @snigo! I didn’t actually think about that. I read up on it, and it looks like unshift isn’t that fast because there are a lot of steps taking place under the hood, and that slows everything down.

I ended up just adding the values directly to a string, and it goes significantly faster for all values! Thanks so much!

The updated code can be found below

function convertToRoman(num) {
  let a = performance.now();
  const Key = ["I", "V", "X", "L", "C", "D", "M"];
  let string = "";

  // reversing our number so that we start with the smallest number, 
//and progress upwards.  This way we know what power to the ten our number is.  i.e. 
//should our 2 represent 2 or 20 or 200 or 20000.  
  let reversedNumArr = num.toString().split("").reverse();
  let reversedNumArrLength = reversedNumArr.length;

  
 // a for loop that loops through our reversed number.  
 for(let i = 0; i < reversedNumArrLength; i++) {
   if(reversedNumArr[i] <= 3) {
    // if our number is between 1 and 3, we will be   
    //selecting the correct roman numeral from our key 
    // (we know this because it always follows the same
    //pattern) and repeating it the number of times that our number is equal to.    
    string = Key[i * 2].repeat(reversedNumArr[i]) + string;
  
    // if our number is 4, then we will be selecting the correct roman numerals from our key, and unshifting it to our array.  This continues for 5, 6, 7, 8, 9.  
   } else if(reversedNumArr[i] === "4") {
     string = Key[i * 2] + Key[(i * 2) + 1] + string;
    
   } else if(5 <= reversedNumArr[i] && reversedNumArr[i] <= 8) {
     string = Key[(i * 2) + 1] + Key[i * 2].repeat(reversedNumArr[i] - 5) + string;
     
   } else if(reversedNumArr[i] === "9") {
     string = Key[i * 2] + Key[(i * 2) + 2] + string;
      
   }
 }
 
  let b = performance.now();
  console.log(b-a)
 return string;
}

convertToRoman(29);
1 Like

Thanks @miku86! I never thought about how unshift actually requires a lot of steps to take place under the hood, but this helped a lot. I ended up just combining the roman numerals to a string using the + operand.

1 Like