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

Here is my slow-poke code, done before class where Ramon showed us how to re-factor the code more efficiently:

function convertToRoman(num) {
if (num <= 0) return ‘error’;

let result = ‘’;
let remaining = num;

if (num >= 1000) {
for (let i = 0; i < Math.floor(num / 1000); i++) {
result += ‘M’;
}
remaining = num % 1000;
}

if (remaining >= 900) {
result += ‘CM’;
remaining -= 900;
}

if (remaining >= 500) {
result += ‘D’;
remaining -= 500;
}

if (remaining >= 400) {
result += ‘CD’;
remaining -= 400;
}

if (remaining >= 100) {
for (let i = 0; i < Math.floor(remaining / 100); i++) {
result += ‘C’;
}
remaining = remaining % 100;
}

if (remaining >= 90) {
result += ‘XC’;
remaining -= 90;
}

if (remaining >= 50) {
result += ‘L’;
remaining -= 50;
}

if (remaining >= 40) {
result += ‘XL’;
remaining -= 40;
}

if (remaining >= 10) {
for (let i = 0; i < Math.floor(remaining / 10); i++) {
result += ‘X’;
}
remaining = remaining % 10;
}

if (remaining >= 9) {
result += ‘IX’;
remaining -= 9;
}

if (remaining >= 5) {
result += ‘V’;
remaining -= 5;
}

if (remaining >= 4) {
result += ‘IV’;
remaining -= 4;
}

if (remaining >= 1) {
for (let i = 0; i < remaining; i++) {
result += ‘I’;
}
remaining = 0;
}

if (remaining != 0) return ‘error’;

return result;
}

convertToRoman(36);

console.log(convertToRoman(1798));

3 Likes

Funny, I think your thought process was similar to mine (also done before class) - only that I literally declared thousands of variables :wink:

function convertToRoman(num) {
  //break into biggest chunks and get remainders after each chunk
  //die thousands etc müssen dann noch umgewandelt werden; Achtung: strings können in javascript aber nicht multipliziert werden
  let thousands = Math.floor(num / 1000);
  let remains = num - thousands*1000;
  thousands = "M".repeat(thousands);
  let nineHundreds = Math.floor(remains / 900);
  remains -= nineHundreds*900;
  nineHundreds = "CM".repeat(nineHundreds);
  let fiveHundreds = Math.floor(remains / 500);
  remains -= fiveHundreds*500;
  fiveHundreds = "D".repeat(fiveHundreds);
  let fourHundreds = Math.floor(remains / 400);
  remains -= fourHundreds*400;
  fourHundreds = "CD".repeat(fourHundreds);
  let hundreds = Math.floor(remains / 100);
  remains -= hundreds*100;
  hundreds = "C".repeat(hundreds);
  let nineties = Math.floor(remains / 90);
  remains -= nineties*90;
  nineties = "XC".repeat(nineties);
  let fifties = Math.floor(remains / 50);
  remains -= fifties*50;
  fifties = "L".repeat(fifties);
  let fourties = Math.floor(remains / 40);
  remains -= fourties*40;
  fourties = "XL".repeat(fourties);
  let tens = Math.floor(remains / 10);
  remains -= tens*10;
  tens = "X".repeat(tens);
  let nines = Math.floor(remains / 9);
  remains -= nines*9;
  nines = "IX".repeat(nines);
  let fives = Math.floor(remains / 5);
  remains -= fives*5;
  fives = "V".repeat(fives);
  let fours = Math.floor(remains / 4);
  remains -= fours*4;
  fours = "IV".repeat(fours);
  let ones = Math.floor(remains / 1);
  ones = "I".repeat(ones);

  //add all of them together
  return (thousands + nineHundreds + fiveHundreds + fourHundreds + hundreds + nineties + fifties + fourties + tens + nines + fives + fours + ones);
}

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

That’s great Sandra! Great minds think alike. Are you also doing the Responsive Web Design boot camp, or did you already complete that one previously?

1 Like

I had the same approach, but made one helping function for all :joy:

function convertSingleToRoman(num, einheit) {
  //einheit: 0-9: 10^0, 10-99: 10^1, 101-999: 10^2 1000-3999: 10^3
    const Numerals = {
      0: "",
      1: "I",
      5: "V",
      10: "X",
      50: "L",
      100: "C",
      500: "D",
      1000: "M"
    }
    switch (num) {
      case '0':
        return Numerals[0];;
      case '1':
        return Numerals[einheit];
      case '2':
        return Numerals[einheit] + Numerals[einheit];
      case '3':
        return Numerals[einheit] + Numerals[einheit] + Numerals[einheit];
      case '4':
        return Numerals[einheit] + Numerals[5 * einheit];
      case '5':
        return Numerals[5 * einheit];
      case '6':
        return Numerals[5 * einheit] + Numerals[einheit];
      case '7':
        return Numerals[5 * einheit] + Numerals[einheit] + Numerals[einheit];
      case '8':
        return Numerals[5 * einheit] + Numerals[einheit] + Numerals[einheit] + Numerals[einheit];
      case '9': 
        return Numerals[einheit] + Numerals[10 * einheit];
      default:
        return false;
    }
  }

function convertToRoman(num) {
  let digitArray = num.toString().split("");
  for (let index in digitArray) {
    digitArray[index] = convertSingleToRoman(digitArray[index], Math.pow(10, digitArray.length - 1 - index));
  }
  return digitArray.join("");
}
3 Likes

Yes, I’m also doing the Web Design bootcamp (although I have already done a little bit of HTML and CSS ages ago (pre-HTML5 ;-))

1 Like

function convertToRoman(num) {
//declare lookup variable with object property key/value pairs
let lookup = {
M: 1000,
CM: 900,
D: 500,
CD: 400,
C: 100,
XC: 90,
L: 50,
XL: 40,
X: 10,
V: 5,
IV: 4,
I: 1
},
//declare for loop and while condition; set increment and decrement
romanNum = “”, x;
for (x in lookup) {
while(num >= lookup){
romanNum += x;
num -= lookup;
}
}
//return roman numeral
return romanNum;
}
console.log(convertToRoman(36));

4 Likes

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