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

Hey folks,

Congrats on finishing the second project of the bootcamp! :tada:

Let’s share our code! Here’s mine:

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);
  converter.processNumeral("M", 1000);
  converter.processNumeral("CM", 900);
  converter.processNumeral("D", 500);
  converter.processNumeral("CD", 400);
  converter.processNumeral("C", 100);
  converter.processNumeral("XC", 90);
  converter.processNumeral("L", 50);
  converter.processNumeral("XL", 40);
  converter.processNumeral("X", 10);
  converter.processNumeral("IX", 9);
  converter.processNumeral("V", 5);
  converter.processNumeral("IV", 4);
  converter.processNumeral("I", 1);
  return converter.result;
}

// Should be MDCCLXXVI
console.log(convertToRoman(2022));
6 Likes

Here my solution for the Roman Numeral Converter

function convertToRoman(num) {
  let result = ""
  const romanArabic = [
    ['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]
  ]
  while (romanArabic.length > 0) {
    if (num >= romanArabic[0][1]) {
      num -= romanArabic[0][1]
      result += romanArabic[0][0]
    }
    else romanArabic.splice(0, 1)
  }
  return result
}

5 Likes

This is Mine

function convertToRoman(num) {
   const numbers = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
  const roman = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I'];
  let result = "";
  for(let i = 0; i < roman.length; i++ ){
    while(num >= numbers[i]){
      result += roman[i];
      num -= numbers[i];
    }
  }
 return result;

}

console.log(convertToRoman(36));

This is what I learnt from Ramon and through which I figured out that how much I should revise class and constructor again as I was having trouble remaking it . Interested in seeing other’s solutions so I can go woah it can be done like that too.

class convrt{
  constructor(number){
    this.number = number;
    this.result = '';
  };
  rconvrt(symval,sym){
    while(this.number >= symval ){
      this.result += sym;
      this.number -= symval;
    }
  };

}
function convertToRoman(num) {
   const numbers = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
  const roman = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I'];
  let lol = new convrt(num);
  for(let i = 0 ; i < numbers.length ; i++ ){
    lol.rconvrt(numbers[i],roman[i]);
  }
  return lol.result;

}

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

I like your solution. It’s quite simple and straight forward.:+1:t5:

2 Likes

Here is my shortest solution:

function 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}, timi = "",i;
  for (i in lookupTable) {
    while (num >= lookupTable[i]) {
      timi += i;
      num -= lookupTable[i];
    }
  }
  return timi;
}
console.log(convertToRoman(3999));
5 Likes

Great job, Yash! I have one small feedback point, if I may:

Conventionally, class names are camel case that start with a capital letter. In your case, this would be better as Convrt.

Otherwise, fabulous work!

3 Likes

I did mine before class and went the absolute longest route haha :sweat_smile: I’ll have to try it properly with a loop later.

function convertToRoman(num) {
  let digits = num.toString().split("");
  
  function convertThousands(thou) {
    switch (thou) {
      case '1': return 'M';
      case '2': return 'MM';
      case '3': return 'MMM';
      case '4': return 'MMMM';
    }
}
    

  function convertHundreds(hund) {
    switch (hund) {
      case '0': return '';
      case '1': return 'C';
      case '2': return 'CC';
      case '3': return 'CCC';
      case '4': return 'CD';
      case '5': return 'D';
      case '6': return 'DC';
      case '7': return 'DCC';
      case '8': return 'DCCC';
      case '9': return 'CM';
      }
    }


  function convertTens(tens) {
    switch (tens) {
      case '0': return '';
      case '1': return 'X';
      case '2': return 'XX';
      case '3': return 'XXX';
      case '4': return 'XL';
      case '5': return 'L';
      case '6': return 'LX';
      case '7': return 'LXX';
      case '8': return 'LXXX';
      case '9': return 'XC';
      }
    }


  function convertOnes(ones) {
    switch (ones) {
      case '0': return '';
      case '1': return 'I';
      case '2': return 'II';
      case '3': return 'III';
      case '4': return 'IV';
      case '5': return 'V';
      case '6': return 'VI';
      case '7': return 'VII';
      case '8': return 'VIII';
      case '9': return 'IX';
    }
  }
  
  
    if (num > 999) {
      num = convertThousands(digits[0]) + convertHundreds(digits[1]) + convertTens(digits[2]) + convertOnes(digits[3])
    } else if (num > 99) {
      num = convertHundreds(digits[0]) + convertTens(digits[1]) + convertOnes(digits[2])
    } else if (num > 9) {
      num = convertTens(digits[0]) + convertOnes(digits[1])
    } else {
      num = convertOnes(digits[0]);
    }
    
 return num;
}

convertToRoman(2);
console.log(convertToRoman(4983))
3 Likes
function loadTable(romanTable) {
    /*
    Setting all the roman numeric equivalents in an array
    Numeric order deliberate from highest to lowest to work with my code logic
    Each item set as an object with named fields to make the code more readable
    i.e. romanTable[0].decimal much more readable than romanTable[0][0]
     */
    romanTable.push({
        decimal: 1000,
        roman: 'M'
    });
    romanTable.push({
        decimal: 900,
        roman: 'CM'
    });
    romanTable.push({
        decimal: 500,
        roman: 'D'}
    );
    romanTable.push({
        decimal: 400,
        roman: 'CD'
    });
    romanTable.push({
        decimal: 100,
        roman: 'C'
    });
    romanTable.push({
        decimal: 90,
        roman: 'XC'
    });
    romanTable.push({
        decimal: 50,
        roman: 'L'
    });
    romanTable.push({
        decimal: 40,
        roman: 'XL'
    });
    romanTable.push({
        decimal: 10,
        roman: 'X'
    });
    romanTable.push({
        decimal: 9,
        roman: 'IX'
    });
    romanTable.push({
        decimal: 5,
        roman: 'V'
    });
    romanTable.push({
        decimal: 4,
        roman: 'IV'
    });
    romanTable.push({
        decimal: 1,
        roman: 'I'
    });
}

function convertToRoman(num) {
    let workingNum = num;
    let romanNumber = '';

    /*
    Process loop, runs until the number >= 1, the lowest value with a Roman equivalent
    Assumes initial number parameter is a positive, integer value
    For each iteration, read through the Roman table array until first
     item where the number is less than/equal to current number value
    Append the associated Roman digit value to the roman number string
     and subtract the table number value from current number value.
    There will always eventually be a table value which is equal to the
     current number value so once this Roman value is appended and
     the subtraction done, current number value will = zero and loop will stop.
     */
    while (workingNum >= 1) {
        for (let i = 0; i < romanTable.length; i++) {
            if (romanTable[i].decimal <= workingNum) {
                // append Roman number for this table entry to the roman number string
                romanNumber += romanTable[i].roman;
                // subtract number value of this table entry from the current number
                workingNum -= romanTable[i].decimal;
                console.log(`num = ${num}, working num = ${workingNum}, roman num = ${romanNumber}`);
                // exit for loop
                break;
            }
        }
    }
    return romanNumber;
}

// to pass FreeCodeCamp project tests these 2 lines loading the roman value array
// need to be in the convertToRoman function
// but much more efficient to have them here and just execute once per program run.
const romanTable = [];
loadTable(romanTable);

// test calls
console.log(convertToRoman(3)); //should return the string III.
console.log(convertToRoman(4)); //should return the string IV.
console.log(convertToRoman(5)); //should return the string V
console.log(convertToRoman(9)); //should return the string IX.
console.log(convertToRoman(12)); //should return the string XII.
console.log(convertToRoman(16)); //should return the string XVI.
console.log(convertToRoman(29)); //should return the string XXIX.
console.log(convertToRoman(44)); //should return the string XLIV.
console.log(convertToRoman(45)); //should return the string XLV.
console.log(convertToRoman(68)); //should return the string LXVIII
console.log(convertToRoman(83)); //should return the string LXXXIII
console.log(convertToRoman(97)); //should return the string XCVII
console.log(convertToRoman(99)); //should return the string XCIX
console.log(convertToRoman(400)); //should return the string CD
console.log(convertToRoman(500)); //should return the string D
console.log(convertToRoman(501)); //should return the string DI
console.log(convertToRoman(649)); //should return the string DCXLIX
console.log(convertToRoman(798)); //should return the string DCCXCVIII
console.log(convertToRoman(891)); //should return the string DCCCXCI
console.log(convertToRoman(1000)); //should return the string M
console.log(convertToRoman(1004)); //should return the string MIV
console.log(convertToRoman(1006)); //should return the string MVI
console.log(convertToRoman(1023)); //should return the string MXXIII
console.log(convertToRoman(2014)); //should return the string MMXIV
console.log(convertToRoman(3999)); //should return the string MMMCMXCIX
4 Likes

Here’s mine, it feels kind of crooked. Feedback is always welcome…

const equivalences = {
  th: {1:"M"},
  hu: {1:"C", 4:"CD", 5:"D", 9:"CM"},
  te: {1:"X", 4:"XL", 5:"L", 9:"XC"},
  un: {1:"I", 4:"IV", 5:"V", 9:"IX"}
}

function convert(number, arry){
  let output;
  if (number[0] <= 3) output = equivalences[number[1]][1].repeat(number[0])
  else if (number[0] === 4) output = equivalences[number[1]][4]
  else if (number[0] === 5) output = equivalences[number[1]][5]
  else if (number[0] > 5 && number[0] < 9) output = equivalences[number[1]][5] + equivalences[number[1]][1].repeat(number[0] - 5)
  else if (number[0] === 9) output = equivalences[number[1]][9]

  return arry.push(output)
}

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

  //from 4000 onward Roman numeral system changes a little bit
  if(num>3999) return "Not implemented";
  
  // Break down into digits
  let thousands = [Math.trunc(num / 1000 % 10), "th"];
  let hundreds = [Math.trunc(num / 100 % 10), "hu"];
  let tens = [Math.trunc(num / 10 % 10), "te"];
  let units = [Math.trunc(num / 1 % 10), "un"];
  let decimals = [thousands, hundreds, tens, units];

  for (let elements of decimals){
    convert(elements, arry)
  }
  return arry.join("");
}

console.log(convertToRoman(3999));
2 Likes
const LOOKUP = {
  1: 'I',
  4: 'IV',
  5: 'V',
  9: 'IX',
  10: 'X',
  40: 'XL',
  50: 'L',
  90: 'XC',
  100: 'C',
  400: 'CD',
  500: 'D',
  900: 'CM',
  1000: 'M',
};
const HOPS = Object.keys(LOOKUP);
const MAX_HOPS = HOPS.length;

function convertToRoman(num) {
  if (num <= 0) {
    return "";
  }
  for(let n=1; n < MAX_HOPS; n++) {
    if (num < parseInt(HOPS[n])) {
      return LOOKUP[HOPS[n-1]] + convertToRoman(num - parseInt(HOPS[n-1]));
    }
    if (n === MAX_HOPS - 1) {
      return LOOKUP[HOPS[MAX_HOPS-1]] + convertToRoman(num - parseInt(HOPS[MAX_HOPS-1]));
    }
  }
}

convertToRoman(36);


console.log(convertToRoman(3999));
2 Likes

Hello! I am posting my ridiculous thought processes before I start watching the video - I have tried for an hour and a half and am stuck - you can see why I find this so difficult - I was starting with a specific case before (hopefully) going on to make this more general and expanding to the larger Roman numerals (RN), as well as adding the requirement that if the first RN is smaller than the second, it has to be subtracted from the second before the output value can be determined (and then I need to reverse that thought process, ha ha). Anyway, I’m just leaving this here and will return later after viewing the lesson.
ETA: from my handwritten notes - should I use parseInt(num, radix)? use case declarations?

function convertToRoman(num) {
  // I thought the best way to do this is to break the integers down by iterative division into their component Roman equivalents, so for 36 we have 
  //36/10 = 30 (=3x10) r 6;    then we go 6/5 = 5 r 1; leaving 1;
  //so need to use division to get the whole number and then the remainder operator, % - is there a way to get both of these at the same time? or does it have to be a stepwise process? It seems this is not possible - therefore the division result must then have the decimal removed and the remainder then treated separately. So return just the whole number part of the answer. looks like .toFixed() does this.
  // the Roman Numeral (RN) equivalents of these being 3xX, V, I.
  // Then need to tell the code to return 30 = 3xX as XXX
  // and 5 === V, then 1 === I;
  // Finally, need to tell the code to add each step together consecutively (concatenating?) to output XXXVI
  // Will try for this example, then try to expand to include cases when lesser value RN before greater value RN means take the first value away from the second before outputting the correct value (or, rather, have to do this thinking in reverse as coming from integer to RN). This is complicated! :)
const quotient1 = num/10;
console.log(quotient1);
//const whole1 = Math.floor(quotient1.toFixed());
// well, adding Math.floor did not work - why not?
// maybe try Math.floor on the output of quotient1 and delete the .toFixed() - i think it is superfluous.
const whole1 = Math.floor(quotient1);
console.log(whole1);
// OK so here it is rounding up, annoyingly, so need to introduce Math.floor somehow. Let's try bracketing it round the whole of quotient1.toFixed()
 // Removing .toFixed() etc. worked. So now you have whole1 to go to next division step. Also need to find remainder1 and set this aside to add to the RN at a later stage.
 const remainder1 = num%10;
 console.log(remainder1);
 // OK, now, as the 3 is the result of dividing 30 by ten, need to convert that into 3 times RN X somehow, and tell the code 3 x X === XXX;
 const firstStageRN = whole1*10;
 console.log(firstStageRN);
 // 
 const secondStageRN = whole1*X;
 console.log(secondStageRN);
 // need to tell it to print string "X" three times somehow
 //
 //
 //

Contents of the console:

3.6
3
6
30
ReferenceError: Can’t find variable: X

3 Likes

Mine with recursion.

function convertToRoman(num) {

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

 return num;
}
3 Likes

Your thought process is absolutely correct.
However,
for 36 = 30 * 10 + 6 * 1
You should code the
secondTStageRN = remainder1 * 1

You get an error becuse whole1 * X , and X is not defined anywhere in your code. And to get 6 you should not use whole1, but remainder1 * 1

Hope this is clear.

4 Likes

Woohoo keep going. with @cpucortexm2924547 's extra hints you may get there. The vid will also definitely help but I love how you dived into this trying to sort out how it works first on your own. Coders are problem solvers in the first place, and you got to understand the problem to be able to solve it (and find edge cases to deal with). You are definitely on the right track! Keep going!

2 Likes

Hello,

I am really stuck on this and I am trying to come up a with a solution I can understand… I am trying to get a loop to iterate though the roman object and print out with roman equivalent of the number (object property). What’s the logic to have this done? This is my code so far and yes, I am really far from having a solution.

function convertToRoman(num) {
 var chart = {
   M: 1000, 
   CM: 900, 
   D: 500, 
   CD: 400, 
   C: 100, 
   XC: 90, 
   L: 50, 
   XL: 40, 
   X: 10, 
 }

let str = "";

for (let i = 1; i <= 1000; i++) {
    if (num ===  Object.values(chart)[i]) {
      str = 
    }
  }
   return str
}
1 Like

Hi Damien,

Thinking through a problem and trying to figure out what needs to be done to solve it is the core of our job as programmer. So this is a good start (any start is better than none!)

Avoid using ‘var’. It is not wrong and you will find it in pre-ES6 code, but you should largely treat it as a thing of the past and declare variables with let/const.

Your code is doing 3 things:

  • defines a roman object called ‘chart’
  • implements a for loop with a random stop value of 1000 for index i (I mean I do not understand why you chose that)
  • compares the input argument num with an return value for the index (if it exists, which is mostly not true)

So let’s have a closer look. Did you try a console log to see what your loop does return for your object value?

function convertToRoman(num) {
 const chart = {
   M: 1000, 
   CM: 900, 
   D: 500, 
   CD: 400, 
   C: 100, 
   XC: 90, 
   L: 50, 
   XL: 40, 
   X: 10, 
 }

  for (let i = 1; i <= 10; i++) {
      console.log(Object.values(chart)[i])
  }

}

As you can see I reduced the index to be smaller or equal to 10 and my output is

900
500
400
100
90
50
40
10
undefined
undefined

That should give you already a clue on why this approach is not working. It loops through your object and simply returns the value for each index, and you have only 9 of them. Then you compare the returned value (for each of these values) with the number passed into the function. What is the chance someone asks for exactly 500 to be converted, rather than 2022? So this approach is not very robust.

So you need to restrict your look up to the length of your object, and you do need to gain access to the the key value (you could swap your key and value, so you can look up the number using the key and retrieve the value). In Rotimi’s answer here (Post your Roman Numeral Converter solutions here! (Fall 2022) - #5 by Timiphil) the loop is through all elements in the object and return the key (the variable is named i, but it is not really an index but rather the key).

Then also you need to think in how to process the problem. Solutions that are posted in this thread show different approaches. You could find the number of thousands, hundreds, etc and try to match your answer there. Or reduce the value with the largest amount (if possible) and balance it out with the matching character in the result.

Does this help in any way to develop an approach?

2 Likes

My Solution, no the best, but i do it.

function roman1to10(num){
    const romanUnity = ["I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X"];
    if (num!=0){
        let romano = romanUnity[num-1];
        return romano;
    } else return "";
}

function roman11to100(num){
    const romanDecena = ["X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC", "C"];
    if (num!=0){
        let romano = romanDecena[num-1];
        return romano;
    } else return "";
}

function roman101to1000(num){
    const romanCentena = ["C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM", "M"];
    if (num!=0){
        let romano = romanCentena[num-1];
        return romano;
    } else return "";
}

function roman1001to3999(num){
    const romanMil = ["M", "MM", "MMM"];
    if (num!=0){
        let romano = romanMil[num-1];
        return romano;
    } else return "";
}

function convertToRoman(num) {  
  let strNum = num.toString();
  const numArray = strNum.split("");
  console.log(numArray)
  let romano = "";
  if (numArray.length == 1){
     romano = roman1to10(numArray[0]);
     return romano;
      
  } else if (numArray.length == 2){
    romano = roman11to100(numArray[0]);
    romano += roman1to10(numArray[1]);
    return romano;
    
    } else if (numArray.length == 3){
    romano = roman101to1000(numArray[0]);
    romano += roman11to100(numArray[1]);
    romano += roman1to10(numArray[2]);
    return romano;
    
    } else if (numArray.length == 4){
    romano = roman1001to3999(numArray[0]);
    romano += roman101to1000(numArray[1]);
    romano += roman11to100(numArray[2]);
    romano += roman1to10(numArray[3]);
    return romano;
    
    }
        
}
3 Likes

Here is my solution to Roman Numeral Converter.
Cheers, T.

const RomanArabicMapping = {
  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,
};


const convertToRoman = number => {
  let strRoman = "";

  // Loop through all the Object Properties
  for (const keyRoman in RomanArabicMapping) {
    // Construct the Roman numeral for the current Key
    while (number >= RomanArabicMapping[keyRoman]) {
      strRoman += keyRoman;
      number -= RomanArabicMapping[keyRoman];
    }
  }

  // Take care of "0" being passed
  return (strRoman === "" ? "Unknown" : strRoman);
}

console.log(convertToRoman(2)); //should return the string II.
console.log(convertToRoman(3)); //should return the string III.
console.log(convertToRoman(4)); //should return the string IV.
console.log(convertToRoman(5)); //should return the string V.
console.log(convertToRoman(9)); //should return the string IX.
console.log(convertToRoman(12)); //should return the string XII.
console.log(convertToRoman(16)); //should return the string XVI.
console.log(convertToRoman(29)); //should return the string XXIX.
console.log(convertToRoman(44)); //should return the string XLIV.
console.log(convertToRoman(45)); //should return the string XLV.
console.log(convertToRoman(68)); //should return the string LXVIII
console.log(convertToRoman(83)); //should return the string LXXXIII
console.log(convertToRoman(97)); //should return the string XCVII
console.log(convertToRoman(99)); //should return the string XCIX
console.log(convertToRoman(400)); //should return the string CD
console.log(convertToRoman(500)); //should return the string D
console.log(convertToRoman(501)); //should return the string DI
console.log(convertToRoman(649)); //should return the string DCXLIX
console.log(convertToRoman(798)); //should return the string DCCXCVIII
console.log(convertToRoman(891)); //should return the string DCCCXCI
console.log(convertToRoman(1000)); //should return the string M
console.log(convertToRoman(1004)); //should return the string MIV
console.log(convertToRoman(1006)); //should return the string MVI
console.log(convertToRoman(1023)); //should return the string MXXIII
console.log(convertToRoman(2014)); //should return the string MMXIV
console.log(convertToRoman(3999)); //should return the string MMMCMXCIX
3 Likes

Started step by step and after many tries this worked:

function convertToRoman(num) {
 var romanNumbers = {
    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 romanized = "";
   for(var key in romanNumbers){
     var numberValue = romanNumbers[key];
     while(numberValue <= num){
       num-=numberValue;
       romanized+=key;
     }
   }
   return romanized;
}
var result=convertToRoman(666);
console.log(result);

But a little unsure when to use Var or Const, in this case it went fine with vars,

3 Likes

Love it!

If I may suggest, using the following:

If the value will be reassigned, use let.
If it won’t, use const.

I don’t use var

2 Likes