Pseudo planning.. am I in left field? Is it dumb to use a case switch in a while loop?

//Rookie Code may cause the infinite loop, decrements not set, still planning
I am planning my code for the Roman Numeral Converter at FreeCodeCamp… I watched the highest ranked tutorials last year, what I don’t remember directly or find in the hints… I’m trying to improvise in my own style (which obviously is a work in progress) I guess my main question is if I’m off base to be trying to use a case switch inside of a while loop? Is this a logical course to pursue? Or is there some obvious rookie mistake like the infinite loop I’m about to embark upon the wrong tree?
also, I’ve only seen case switches used with variables, not really conditions… should I be wrapping them in parenthesises?

//Rookie Code may cause an infinite loop, decrements not set, still planning
function convertToRoman(num) {

while (num > 1){

switch (num) {
  case num > 1000:
    console.log('M');
    break;
  case num > 500:
    console.log('D');
    break;    
  case num > 100:
    console.log('C');
    break;
  case num > 50:
    console.log('L');
    break;    
  case num > 10:
    console.log('X');
    break;
  case num > 5:
    console.log('V');
    break;    
  case num > 1:
    console.log('I');
    break;
  default:
    console.log(num);
}//end of switch
//decrement num!!
}//end of while..


return num;
}

convertToRoman(36);

//  1       I  
//  5       V  
//  10      X  
//  50      L  
//  100     C  
//  500     D  
//  1000    M 

From what I’m seeing at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch I don’t think that the switch statement supports using expressions as cases.

By the way, if it helps I did a series on using test-driven development techniques for roman numerals using Jest for testing, and saving regularly to github on successful tests.

1 Like

yes, Can I get a link to that? oh, never mind… I see that is a link

1 Like

What I did there was inspired by the amazing techiques that Corey Haines uses in the following video:

1 Like

You can if you use switch (true). It’s a debated technique with strong proponents and opponents, but it works :slight_smile:

Personally, I wouldnt use a loop at all for what you’re doing.
Take the number as a string. Invert the string.
Take the substring of 3 til the end of the string. Invert it, restore it to an integer. That is the number of M’s to write out.
Take the third character. If it is greater than or equal to 5, write out a D and subtract 5; then write out the number number of C’s.
Repeat for the second character, except with L and X.
Repeat for the first character, except with V and I.

Why doesnt this work? Consider your output for the number 9. By this logic, your output is VIIII. The correct numeraliztion for 9 is IX.

Roman numerals have a secondary condition: You never write the same symbol 4 times in a row (Roman numerals kind of fall apart once you get to 4000, though there were some methods to represent it, I’m not aware of a standardized one). 90 is not LXXXX, it’s XC.

Essentially there’s a hidden extra condition to the above logic. If the digit is a 9 in steps 3-5, write out the proper form of a 9 (CM,XC,IX) and move on. Otherwise [remainder of the logic for that step]

and 4’s, because i’m silly and forget things at 6 AM. Same pattern, except (CD,XL,IV)

Alternatively, if you insist on doing it with a switch in a loop, here’s a possibility:

switch(num.toString().length+","+(num.toString().split("")[0]))

Ugly as sin, but it constructs a string such that it uniquely identifies the current working character. The cases become ridiculous too: for example, here’s the cases for just the Hundreds:

case "3,1":
case "3,2":
case "3,3":
  console.log("C");
 num -= 100;
break;
case "3,4":
 console.log("CD");
 num -= 400;
break;
case "3,5":
case "3,6":
case "3,7":
case "3,8":
 console.log("D");
 num -= 500;
break;
case "3,9":
 console.log("CM");
num -= 900;
break;

EDIT: no, bad me. You’d never end up with a “,0” case because thats not how integer strings work.

So my mild “code-challenge puzzle” OCD kicked in and I started looking at the problem in more generalized terms.

The OP is currently planning out their approach to the problem, so I won’t put my full code blocks in the thread, but I’ve attached a few files for those that might be interested (or the OP once they come up with their own solution and might want additional insights):

rn.js: My original attempt at a non-looping solution. 48 lines.
rn3.js: The “Mega-Switch” switch-inside-a-loop solution. 83 lines.
rn2.js: My revised generalized while-loop-only solution. 14 lines.

My constraints for the code minimization:

  • I am solving for any numeral less than 4000.
  • I may not execute the same string manipulation operation more than once. Type conversion of the same input is ok; but if not it simply adds 1 line to the rn2 and rn3 file.

rn.js (1.2 KB)
rn3.js (1.3 KB)
rn2.js (494 Bytes)

1 Like

searching for switch (true), could you link an example or two of how to structure that? I found this one at least. https://powerpivotpro.com/2015/03/the-diabolical-genius-of-switch-true/

Well, exactly what you had, except use switch (true) instead of switch (num)

1 Like

I was reading too fast and was baffled until I saw SWITCH([MyMeasure], was replaced with SWITCH(TRUE(), and then the light bulb went on!

found this in the comments & it makes a bit more sence to me that he is passing in a function… I’m assuming it’s a typo that he missed the lass parenthesis, but I’m going to play with this in the original structure and see what outputs I get

…my bad, that’s for something called DAX… I guess it’s an excel thing. This Stack Overflow has a sample that makes sense to me.

Ironically my version of the switch statement ended up at 48 lines too…
but I’m content with it for now, as it is proof of concept. I can proceed on this course. I just need to push what the console is logging into a joined array
As far as where to put it in front or back, I may just add cases for those, like at 700, 400 etc… I’m trying to take the literal explanation of how to convert Roman numerals as my premise… somehow it feels like an abacus of sorts. Mainly I like how it’s still in a tight column off to the left edge.

function convertToRoman(num) {

while (num > 0){

switch (true) {
  case (num > 1000):
    console.log('M');
    num = num -1000;
    break;
  case (num > 500):
    console.log('D');
    num = num -500;
    break;    
  case (num > 100):
    console.log('C');
    num = num -100;
    break;
  case (num > 50):
    console.log('L');
    num = num -50;
    break;    
  case (num > 10):
    console.log('X');
    num = num -10;
    break;
  case (num > 5):
    console.log('V');
    num = num -5;
    break;    
  case (num > 0):
    console.log('I');
    num = num -1;
    break;
  default:
    console.log(num);
  }//end of switch
  }//end of while..
return num;
}
convertToRoman(36);
//  1       I  
//  5       V  
//  10      X  
//  50      L  
//  100     C  
//  500     D  
//  1000    M 

Roman Numeral Switch(True)

Except the literal explanation says to take the column and replace it. If you were doing it that way, you would have a case for every number between 1-9, for the 1’s, 1-9 for the 10’s, 1-9 for the 100’s, etc.

So you’re already shorthanding it (and missing cases - every 4X* and 9X* is a fail.)

Run the number 49 through your code. It should come out XLIX.

As a proof of concept for a switch statement, sure, it works. For a proof of concept for a Roman Numeral converter? No.

I’m sure there are exceptions that won’t pass, I’ll try 49 as you’ve suggested. But for the record, I came back to post this… because I just got it to go pass the requirements at FCC. It’s an automated pass fail… but this apparently works.

function convertToRoman(num) {
let romanString = '';
while (num > 0){
switch (true) {
  // triple digits
  case (num > 999):
    romanString = romanString.concat('M');
    num = num -1000;
    break;
  case (num > 899):
    romanString = romanString.concat('CM');
    num = num -900;
    break;    
  case (num > 499):
    romanString = romanString.concat('D');
    num = num -500;
    break;    
  case (num > 499):
    romanString = romanString.concat('D');
    num = num -500;
    break;    
  case (num > 399):
    romanString = romanString.concat('CD');
    num = num -400;
    break;
  case (num > 99):
    romanString = romanString.concat('C');
    num = num -100;
    break;    
// double digits    
  case (num > 90):
    romanString = romanString.concat('XC');
    console.log(romanString);    
    num = num -90;
    break;
  case (num > 80):
    romanString = romanString.concat('LXXX');    
    num = num -80;
    break; 
  case (num > 50):
    romanString = romanString.concat('L');    
    num = num -50;
    break;
  case (num > 39):
    romanString = romanString.concat('XL');    
    num = num -40;
    break;
  case (num > 30):
    romanString = romanString.concat('XXX');    
    num = num -30;
    break;    
//single digits    
  case (num > 9):
    romanString = romanString.concat('X');
    console.log(romanString);    
    num = num -10;
    break;
  case (num > 8):
    romanString = romanString.concat('IX');    
    num = num -9;
    break;     
  case (num > 4):
    romanString = romanString.concat('V');    
    num = num -5;
    break;
  case (num > 3):
    romanString = romanString.concat('IV');    
    num = num -5;
    break;
  case (num > 0):
    romanString = romanString.concat('I');
    num = num -1;
    break;
  default:
    console.log(num);
  }//end of switch
  }//end of while..
  console.log(romanString);
  return romanString;
}//end of function convertToRoman(num)
//  convertToRoman(3);
//  convertToRoman(4);
//  convertToRoman(5);
//  convertToRoman(6);
//  convertToRoman(7);
//  convertToRoman(8);
//  convertToRoman(9);
//  convertToRoman(10);
//  convertToRoman(11);
//  convertToRoman(12);
//  convertToRoman(13);
//  convertToRoman(14);
//  convertToRoman(15);
//  convertToRoman(16);
//  convertToRoman(17);
//  convertToRoman(18);
//  convertToRoman(19);
//  convertToRoman(20);
//  convertToRoman(21);
//  convertToRoman(22);
//  convertToRoman(23);
//  convertToRoman(36);
//  convertToRoman(39); // should return "XXXIX".
//  convertToRoman(42); // should return "XLII".
//  convertToRoman(40); //  should return "XL"
//  convertToRoman(44); // should return "XLIV".
//  convertToRoman(45); //  should return "XLV"
//  convertToRoman(68); //  should return "LXVIII"
//  convertToRoman(96); //  should return "XCVI"
//  convertToRoman(97); //  should return "XCVII"
//  convertToRoman(98); //  should return "XCVIII"
//  convertToRoman(99); //  should return "XCIX"
//  convertToRoman(100); //  should return "C"
//  convertToRoman(333); //  should return "CCCXXXIII"
//  convertToRoman(400); //  should return "CD"
//  convertToRoman(500); //  should return "D"
//  convertToRoman(666); //  should return "DCLXVI"
//  convertToRoman(999); //  should return "CMXCIX"
//  convertToRoman(1000);
//  convertToRoman(649); //  should return "DCXLIX"
//  convertToRoman(798); //  should return "DCCXCVIII"
//  convertToRoman(891); //  should return "DCCCXCI"
//  convertToRoman(3999); //  should return "MMMCMXCIX"

I’m sure there are much more elegant ways to do it & I’ll eventually study them for comparison… but right now I’m pretty proud of how it brute force carves a string out of an interger

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.