Post your Roman Numeral Converter solutions here! (Fall 2022)

Here is my attempt using the switch case statement and a double array.

function convertToRoman(num) {
  if (num >= 4000 || num <= 0) { 
    return 'Converter is limited to numbers below 4000';
  } else if (/\D/.test(num)) {
    return 'Input includes non digit characters'
  }

  const romanSymbol = [['I','IV','V','IX'],['X','XL','L','XC'],['C','CD','D','CM'],['M']];

  const arrNum = num.toString().match(/\d/g).reverse();
  console.log(arrNum);
  const arrRoman = []; // Declare array to build Roman Number
  for(let i=0; i<arrNum.length; i++){
    switch (arrNum[i]){
      case '0':
        break;
      case '9':
        arrRoman.unshift(romanSymbol[i][3]);
        break;
      case '8':
        arrRoman.unshift(romanSymbol[i][0]);
      case '7':
        arrRoman.unshift(romanSymbol[i][0]);
      case '6':
        arrRoman.unshift(romanSymbol[i][0]);
      case '5':
        arrRoman.unshift(romanSymbol[i][2]);
        break;
      case '4':
        arrRoman.unshift(romanSymbol[i][1]);
        break;
      case '3':
        arrRoman.unshift(romanSymbol[i][0]);
      case '2':
        arrRoman.unshift(romanSymbol[i][0]);
      case '1':
        arrRoman.unshift(romanSymbol[i][0]);
      break;
    }
  }
  return num = arrRoman.join('');
}

console.log(convertToRoman(3948 ))
3 Likes

Here is a shorter version using class, and lookup.

const lookup = {'M': 1000, 'CM': 900, 'D': 500, 'CD':400, 'C': 100, 'XC': 90, 'L': 50, 'XL': 40, 'X': 10, 'IX': 9, 'V': 5, 'IV': 4, 'I': 1}

class NumeralConverter {
  constructor(number){
    this.number = number;
    this.result = '';
  }
  processNumeral(symbol, symbolValue) {
    while (this.number >= symbolValue) {
      this.result += symbol;
      this.number -= symbolValue;
    }
  }
}


function convertToRoman(num) {
  let converter = new NumeralConverter(num);
  for (const roman in lookup) {
    converter.processNumeral(roman, lookup[roman]);
  }
  return converter.result;
}


console.log(convertToRoman(2893));
3 Likes

Here is my solution. Comments are highly welcome.
const convertToRoman = num => {
let lookUpTable= {
M: 1000,
CM: 900,
D: 500,
CD: 400,
C: 100,
XC: 90,
L: 50,
XL: 40,
X: 10,
IX: 9,
V: 5,
IV: 4,
I: 1
};
let result = ‘’;
for (const[romanNumeral,arabicNumeral] of Object.entries(lookUpTable)){
while (num >= arabicNumeral){
result += romanNumeral;
num -= arabicNumeral;
}
}
return result;
};

console.log(convertToRoman(83)); // should log LXXXIII

3 Likes

Wooow, there are so many ways to Rom…an Numerals!
This is my solution without having watched the video.

function convertToRoman(num) {
  let romanNum = [];

  while (num != 0) {
    if (num >= 1000) {
      romanNum.push("M");
      num -= 1000;
    } else if (num >= 900){
      romanNum.push("CM");
      num -= 900;
    } else if (num >= 500){
      romanNum.push("D");
      num -= 500;
    } else if (num >= 400){
      romanNum.push("CD");
      num -= 400;
    } else if (num >= 100){
      romanNum.push("C");
      num -= 100;
    } else if (num >= 90){
      romanNum.push("XC");
      num -= 90;
    } else if (num >= 50){
      romanNum.push("L");
      num -= 50;
    } else if (num >= 40){
      romanNum.push("XL");
      num -= 40;
    } else if (num >= 10){
      romanNum.push("X");
      num -= 10;
    } else if (num >= 9){
      romanNum.push("IX");
      num -= 9;
    } else if (num >= 5){
      romanNum.push("V");
      num -= 5;
    } else if (num >= 4){
      romanNum.push("IV");
      num -= 4;
    } else if (num >= 1){
      romanNum.push("I");
      num -= 1;
    } 
  }
  
  romanNum = romanNum.join("");
 return romanNum;
}

convertToRoman(36);
3 Likes

Here is my solution. It’s not the smartest one and not even the shortest but works.

function convertToRoman(num) {

  let thousandsProto;
  let hundredsProto;
  let tensProto;
  let cipherProto;

  let thousands = "";
  let hundreds = "";
  let tens = "";
  let cipher = "";
  let numeralNumber;


  thousandsProto = Math.floor(num / 1000);

  for (let i = 0; i < thousandsProto; i++) {
    thousands += "M";
  }

  // console.log(thousandsProto);
  // console.log(thousands);

  
  hundredsProto = Math.floor((num % 1000) / 100);
  // console.log(hundredsProto);

  switch(hundredsProto) {
    case 1:
      hundreds = "C";
      break;
    case 2:
      hundreds = "CC";
      break;
    case 3:
      hundreds = "CCC";
      break;
    case 4:
      hundreds = "CD";
      break;
    case 5:
      hundreds = "D";
      break;
    case 6:
      hundreds = "DC";
      break;
    case 7:
      hundreds = "DCC";
      break;
    case 8:
      hundreds = "DCCC";
      break;
    case 9:
      hundreds = "CM";
      break;

  }

  // console.log(hundreds);


  tensProto = Math.floor((num % 100) / 10);
  // console.log(tensProto);

  switch(tensProto) {
    case 1:
      tens = "X";
      break;
    case 2:
      tens = "XX";
      break;
    case 3:
      tens = "XXX";
      break;
    case 4:
      tens = "XL";
      break;
    case 5:
      tens = "L";
      break;
    case 6:
      tens = "LX";
      break;
    case 7:
      tens = "LXX";
      break;
    case 8:
      tens = "LXXX";
      break;
    case 9:
      tens = "XC";
      break;

  }

  // console.log(tens);


  cipherProto = Math.floor(num % 10);
  // console.log(cipherProto);

  switch(cipherProto) {
      case 1:
        cipher = "I";
        break;
      case 2:
        cipher = "II";
        break;
      case 3:
        cipher = "III";
        break;
      case 4:
        cipher = "IV";
        break;
      case 5:
        cipher = "V";
        break;
      case 6:
        cipher = "VI";
        break;
      case 7:
        cipher = "VII";
        break;
      case 8:
        cipher = "VIII";
        break;
      case 9:
        cipher = "IX";
        break;

    }

    // console.log(cipher);

    numeralNumber = thousands + hundreds + tens + cipher;
    // console.log(numeralNumber);


  return numeralNumber;

}

console.log(convertToRoman(36));
console.log(convertToRoman(3457));
2 Likes

Here’s my solution. I can now see that many of the other, more efficient solutions are essentially doing the same thing as I’m doing, except instead of the copy-paste of each block in the if-else, the equivalent to the concatenation is implemented once, and objects are created to map the Roman numerals onto their specific values.

In that case, my question is: how does one gain the intuition to simplify the process in these ways? Is it just a matter of time/doing exercises/reading other people’s solutions and learning from them?

function convertToRoman(num) {
 let countDown = num;
 let romanStr = "";
 while (countDown > 0){
   if (countDown >= 1000) {
     romanStr += "M";
     countDown -= 1000;
     continue;
   } else if (countDown >= 900) {
     romanStr += ("CM");
     countDown -= 900;
     continue;
   } else if (countDown >= 500) {
     romanStr += ("D");
     countDown -= 500;
   } else if (countDown >= 400) {
     romanStr += ("CD");
     countDown -= 400;
   } else if (countDown >= 100) {
     romanStr += ("C");
     countDown -= 100;
   } else if (countDown >= 90) {
     romanStr += ("XC");
     countDown -= 90;
   } else if (countDown >= 50) {
     romanStr += ("L");
     countDown -= 50;
   } else if (countDown >= 40) {
     romanStr += ("XL");
     countDown -= 40;
   } else if (countDown >= 10) {
     romanStr += ("X");
     countDown -= 10;
   } else if (countDown >= 9) {
     romanStr += ("IX");
     countDown -= 9;
   } else if (countDown >= 5) {
     romanStr += ("V");
     countDown -= 5;
   } else if (countDown >= 4) {
     romanStr += ("IV");
     countDown -= 4;
   } else if (countDown >= 1) {
     romanStr += ("I");
     countDown -= 1;
   
   }
 }
 
 return romanStr;
}

console.log(convertToRoman(36));
1 Like

After reviewing some of the other solutions, I’ve gone ahead and refactored:

function convertToRoman(num) {
 const conversions = [
  [1000, "M"],
  [900, "CM"],
  [500, "D"],
  [400, "CD"],
  [100, "C"],
  [90, "XC"],
  [50, "L"],
  [40, "XL"],
  [10, "X"],
  [9, "IX"],
  [5, "V"],
  [4, "IV"],
  [1, "I"]
]

 let countDown = num;
 let romanStr = "";
 for (let i = 0; i < conversions.length; i++) {
   while (countDown >= conversions[i][0]) {
     romanStr += conversions[i][1];
     countDown -= conversions[i][0];
   }
 }
 
 return romanStr;
}

console.log(convertToRoman(36));
3 Likes

All the things you mentioned are important. If you only do exercises but don’t look at other people’s solutions, you get better with the tools you already know. But you won’t know the limits of your knowledge.
When you finished an exercise, go and look at other peoples solutions - try to understand what they did and then try to use that way on a similar problem yourself.

Trust me, if you constantly see people using some way you don’t know, you really want to figure out how to do it that way yourself :laughing:

2 Likes

Hi everyone!

I was trying to come with a different solution but… :sweat_smile: :rofl: Too late. :upside_down_face:

I have sent this solution (similar to others I have saw here I am afraid, nothing new under the stars :face_with_monocle:):

function convertToRoman(num) {

  const romansArabics = {
    "M": 1000,
    "CM": 900,
    "D": 500,
    "CD": 400,
    "C": 100,
    "XC": 90,
    "L": 50,
    "XL": 40,
    "X": 10,
    "IX": 9,
    "V": 5,
    "IV": 4,
    "I": 1
  };
  let romans = "";
  let arabic = 0;
  // console.log({num, romans, arabic});

  // Loop throw all romans (properties) in romansArabics object
  for (const roman in romansArabics) {

    // Assign the value of the property (roman) to the arabic variable
    arabic = romansArabics[roman];
    // console.log(`Arabic: ${romansArabics[roman]} | Roman ${roman}`);

    // Loops while number minus arabic value is bigger or equal to 0
    while (num - arabic >= 0) {
      // Concat the roman property to romans variable
      romans += roman;
      // Subtract the arabic value to the number, before the new iteration
      num -= arabic;
      // console.log({num, romans, arabic, roman});
    }

  }

  return romans;
}
console.log(convertToRoman(2022));

Great job everyone. You all rocks!!!

2 Likes

Just revisiting some solutions and I do not see anyone mentioning the little optimization you applied by removing the ‘processed’ inner array once handled. Nice! I do like this solution.

2 Likes

This is a very nice approach to solving this solution. I like how you applied recursion and presented the code so compact that it remains easily readable. Nice!

1 Like

My belated solution - I would not have known to use “while” without doing the course or reviewing other people’s answers. I’m not sure of the thought processes people use to decide whether to use switch case, for loops or while - is this something that will just come naturally to me, the more I practice?

Also, when I started doing this solution, I was doing it back to front and wondering why, e.g. (24) would always return “IV”. I also initially missed out many of the + signs before the = in the second lines of the while statements, which gave some interesting results.

function convertToRoman(num) {

let newStr = "";

while (num >= 1000) {
  newStr += "M";
  num -= 1000;
}
while (num >= 900) {
  newStr += "C" + "M";
  num -= 900;
}
while (num >= 600) {
  newStr += "D" + "C";
  num -= 600;
}
while (num >= 500) {
  newStr += "D";
  num -= 500;
}
while (num >= 400) {
  newStr += "C" + "D";
  num -= 400;
}
while (num >= 100) {
  newStr += "C";
  num -= 100;
}
while (num >= 90) {
  newStr += "X" + "C";
  num -= 90;
}
while (num >= 50) {
  newStr += "L";
  num -= 50;
}
while (num >= 40) {
  newStr += "X" + "L";
  num -= 40;
}
while (num >= 39) {
  newStr += "I" + "X" + "L";
  num -= 39;
}
while (num >= 10) {
  newStr += "X";
  num -= 10;
}
while (num >= 9) {
  newStr += "I" + "X";
  num -= 9
}
while (num >= 5) {
  newStr += "V";
  num -= 5;
}
while (num >= 4) {
  newStr += "I" + "V";
  num -= 4;
}
while (num >= 1) {
  newStr += "I";
  num -= 1;
}
return newStr;
}
console.log(convertToRoman(999));
4 Likes

Hi Jane @Jane2963637

No worries, try to solve the problems with your actual knowledge you could back later on and try to solve again.

The most important it is make your code and after you can try to make it more readable, prettier or more efficient. It is normal.

Jane don’t be hard on yourself. Congratulate yourself often after you try or if you succeed, it doesn’t matter. When I’m stuck, after I try I play a song that makes me dance and I start dancing. :joy: :dancer:

You could use Pomodore Technique and play a song after those 25 min of focusing, for example. It is a good technique for learning and working.

Happy coding!! Repeat after me: You rock Jane!! :smile:

P.S. Speaking about rocks… One of my favourites moments… I hope it makes you laugh.

# The Big Bang Theory - Sheldon: “Geology isn’t a real science”

(I am a geologist also :rofl:)

3 Likes

In my revised solution here, I created an array for the Roman numerals and their Arabic counterparts. This way, when I iterated through, I was sure that it would start with the biggest number, and then work its way down to the smallest one, since the array is an ordered structure.

I noticed that some other student solutions used objects instead but iterated through in the same way, such as this one.

I used an array because I thought that the keys would not maintain a strict order in an object, meaning that I couldn’t be sure that it would be testing from largest to smallest value, and that seems to be confirmed in this lesson, which notes: “Objects do not maintain an ordering to stored keys like arrays do; thus a key’s position on an object, or the relative order in which it appears, is irrelevant when referencing or accessing that key.”

So I guess my question is: why is this algorithm working predictably when using objects instead of arrays?

3 Likes

Thank you Carlos! :smiley:

I will be trying the exercises again once I have gone through all the JavaScript exercises again. :slight_smile:

Happy coding to you as well! :grin:

3 Likes

I looked a bit around in the internet and found something here: The Order of Javascript Object Keys - DEV Community 👩‍💻👨‍💻

When iterating an object, the system looks first for Strings that look like integer keys, and iterates those in numeric order, then iterates the remaining String keys, in insertion order, then iterates the Symbols, again in insertion order.

So it works here because all the keys are letters and are inserted in the right order from the biggest to the lowest.
That’s obviously not something you want to rely on if you use the object for more than for storing these numerals :wink:

edit:
Beware of trying to have the same key in your object as a number and as a string:
the key is always stored as a string and that results in having the key only one time with the value of the last insertion.

3 Likes

Thanks for this answer. It’s very helpful. To make sure I understood it, I wrote the following bit of code, and it did work as expected.

const myObj = {
  2: "prints second",
  M: "prints fourth",
  100: "prints third",
  A: "prints fifth",
  1: "prints first"
}

for (let obj in myObj){
  console.log(myObj[obj])
}
prints first
prints second
prints third
prints fourth
prints fifth

It seems to me that, all things being equal, it’s probably good practice to use an array when one wants to preserve order, rather than use an object and then remember and count on this specific functionality.

4 Likes
 function convertToRoman(num) {
  var roman = {
    M: 1000,
    CM: 900,
    D: 500,
    CD: 400,
    C: 100,
    XC: 90,
    L: 50,
    XL: 40,
    X: 10,
    IX: 9,
    V: 5,
    IV: 4,
    I: 1
  };
  var str = '';
  
  for (var i of Object.keys(roman)) {
    var r = Math.floor(num/roman[i]);
    num -= r * roman[i];
    str += i.repeat(r);
  }

  return str;
}
convertToRoman(36);

console.log(convertToRoman(187))
2 Likes

Here’s my code for the roman numeral converter :smile:

/* Converts digit numbers to roman numerals */

function convertToRoman(number) {
    let romanNumerals = 
        {
            M: 1000,
            CM: 900,
            D: 500,
            CD: 400,
            C: 100,
            XC: 90,
            L: 50,
            XL: 40,
            X: 10,
            IX: 9,
            V: 5,
            IV: 4,
            I: 1
        }
    
    let result = "";
    for (let i in romanNumerals) {
        while(number >= romanNumerals[i]) {
            result += i;
            number -= romanNumerals[i];
        }
       }
       return result;
    }
    
    console.log(convertToRoman(2081));
    ```
1 Like

Please don’t close this topic, I have not gotten to these exercises yet and I am hoping some people are still around to help once I do! :sweat_smile: :laughing:

1 Like