Question about these type of exercices (Roman Numeral Converter & Caesars Cipher)

Question about these type of exercices (Roman Numeral Converter & Caesars Cipher)
0

#1

Links:
https://beta.freecodecamp.org/en/challenges/intermediate-algorithm-scripting/roman-numeral-converter
https://beta.freecodecamp.org/en/challenges/intermediate-algorithm-scripting/caesars-cipher

Hello, i just did these exercices today but after watching for official responses, i find a bit “ashamed”, like i cheated or some thing. I used what first came to my mind and what i find the easiest way to achieve it and understand it.
It’s like i transformed an intermediate exercice into a newbi tutorial…

The officials responses:
https://forum.freecodecamp.org/t/freecodecamp-algorithm-challenge-guide-roman-numeral-converter/16044
https://forum.freecodecamp.org/t/freecodecamp-algorithm-challenge-guide-caesars-cipher/16003

The first (roman converter):

/*
Link: https://beta.freecodecamp.org/en/challenges/intermediate-algorithm-scripting/roman-numeral-converter
https://forum.freecodecamp.org/t/freecodecamp-algorithm-challenge-guide-roman-numeral-converter/16044
*/

function convertToRoman( num ) {
	let n = num.toString().length;
	
	let array = [  [0, ""],[1,"I"],[2,"II"],[3,"III"],[4,"IV"],[5,"V"],[6,"VI"],[7,"VII"],[8,"VIII"],[9,"IX"],[10, "X"],[20,"XX"],[30,"XXX"],
				   [40,"XL"],[50,"L"],[60,"LX"],[70,"LXX"],[80,"LXXX"],[90,"XC"],[100,"C"],[200,"CC"],[300,"CCC"],[400,"CD"],[500,"D"],
				   [600,"DC"],[700,"DCC"],[800,"DCCC"],[900,"CM"],[1000,"M"],[2000,"MM"],[3000,"MMM"],[4000,"MMMM"],[5000,"MMMMM"],
				   [6000,"MMMMMM"],[7000,"MMMMMMM"],[8000,"MMMMMMMM"],[9000,"MMMMMMMMM"]
				];
	
	if( num > 9999 ) {
		return "Too big";
	
	}else if ( num < 0 ){
		return "Too little";
	}
	
	if( n == 4 ) {
		let milleString = num.toString()[0]+"000";
		let centaineString = num.toString()[1]+"00";
		let dizaineString = num.toString()[2]+"0";
		let uniteString = num.toString()[3];

		let milleInt = parseInt( milleString );
		let centaineInt = parseInt( centaineString );
		let dizaineInt = parseInt( dizaineString );
		let uniteInt = parseInt( uniteString );
		
		for( let k = 0; k < array.length; k++ ) {
			if( milleInt == array[k][0] ) {
				milleInt = array[k][1];
			
			}
			if( centaineInt == array[k][0] ) {
				centaineInt = array[k][1];
			
			}
			if( dizaineInt == array[k][0] ) {
				dizaineInt = array[k][1];
			
			}
			if( uniteInt == array[k][0] ) {
				uniteInt = array[k][1];
			}
		}
		
		return milleInt+centaineInt+dizaineInt+uniteInt;
	
	}else if( n == 3 ) {
		let centaineString = num.toString()[0]+"00";
		let dizaineString = num.toString()[1]+"0";
		let uniteString = num.toString()[2];

		let centaineInt = parseInt( centaineString );
		let dizaineInt = parseInt( dizaineString );
		let uniteInt = parseInt( uniteString );

		for( let k = 0; k < array.length; k++ ) {
			if( centaineInt == array[k][0] ) {
				centaineInt = array[k][1];
			
			}
			if( dizaineInt == array[k][0] ) {
				dizaineInt = array[k][1];

			}
			if( uniteInt == array[k][0] ) {
				uniteInt = array[k][1];
			}
		}
	
		return centaineInt+dizaineInt+uniteInt;
		
	}else if( n == 2 ) {
		let dizaineString = num.toString()[0]+"0";
		let uniteString = num.toString()[1];

		let dizaineInt = parseInt( dizaineString );
		let uniteInt = parseInt( uniteString );
		
		for( let k = 0; k < 19; k++ ) {
			if( dizaineInt == array[k][0] ) {
				dizaineInt = array[k][1];
			
			}
			if( uniteInt == array[k][0] ) {
				uniteInt = array[k][1];
			}
		}
	
		return dizaineInt+uniteInt;
	
	}else if( n == 1 ) {
		let uniteString = num.toString()[0];
		
		let uniteInt = parseInt( uniteString );
		
		for( let k = 0; k < 10; k++ ) {
			if( uniteInt == array[k][0] ) {
				uniteInt = array[k][1];
			}
		}
		
		return uniteInt;
		
	}
};

console.log( convertToRoman( 2 ) );
console.log( convertToRoman( 3 ) );
console.log( convertToRoman( 4 ) );
console.log( convertToRoman( 5 ) );
console.log( convertToRoman( 9 ) );
console.log( convertToRoman( 12 ) );
console.log( convertToRoman( 16 ) );
console.log( convertToRoman( 29 ) );
console.log( convertToRoman( 44 ) );
console.log( convertToRoman( 48 ) );
console.log( convertToRoman( 68 ) );
console.log( convertToRoman( 83 ) );
console.log( convertToRoman( 97 ) );
console.log( convertToRoman( 99 ) );
console.log( convertToRoman( 400 ) );
console.log( convertToRoman( 500 ) );
console.log( convertToRoman( 501 ) );
console.log( convertToRoman( 649 ) );
console.log( convertToRoman( 798 ) );
console.log( convertToRoman( 891 ) );
console.log( convertToRoman( 999 ) );
console.log( convertToRoman( 1000 ) );
console.log( convertToRoman( 1004 ) );
console.log( convertToRoman( 1006 ) );
console.log( convertToRoman( 1023 ) );
console.log( convertToRoman( 2014 ) );
console.log( convertToRoman( 3999 ) );
console.log( convertToRoman( 9999 ) );

console.log( convertToRoman( 10000 ) );
console.log( convertToRoman( -1 ) );
console.log( convertToRoman( 0 ) );

.
The second (Caesars Cipher):

/*
Link: https://beta.freecodecamp.org/en/challenges/intermediate-algorithm-scripting/caesars-cipher
https://forum.freecodecamp.org/t/freecodecamp-algorithm-challenge-guide-caesars-cipher/16003
*/

function rot13( str ) {
	let array = [ ['A', 'N'],['B','O'],['C','P'],['D','Q'],['E','R'],['F','S'],['G','T'],['H','U'],['I','V'],['J','W'], 
				  ['K','X'],['L','Y'],['M','Z'],['N','A'],['O','B'],['P','C'],['Q','D'],['R','E'],['S','F'],['T','G'],
				  ['U','H'],['V','I'],['W','J'],['X','K'],['Y','L'],['Z','M'],['!','!'],['?','?'],['.','.'],[' ',' ']
				];
	let arrL = array.length;
	let strL = str.length;
	let newStr = "";
	
	for( let k = 0; k < strL; k++ ) {
		for( let x = 0; x < arrL; x++ ) {
			if( str[k] == array[x][0] ) {
				newStr += array[x][1];
			}
		}
	}
	
	return newStr;
};

console.log( rot13( "SERR PBQR PNZC" ) );
console.log( rot13( "SERR CVMMN!" ) );
console.log( rot13( "SERR YBIR?" ) );
console.log( rot13( "GUR DHVPX OEBJA SBK WHZCF BIRE GUR YNML QBT." ) );

.
Some of you will say “Well, you achieved it, it’s ok. But look at the more ‘officials’ responses and if you understand them and can reproduce them, it’s ok”.
The thing is, i don’t completly understand them :confused:

I have trouble using reduce/map/filter function so if i can avoid them, i do. I know it’s not good to avoid difficulties. It’s better to take time and try to learn from them so you can reuse this skill later and gain time.

I think i have to force me to use these methods even if i know a way to not do it. Would be better in the long run and will train my mind in wider/complex problem.

I feel a bit like talking to myself and doing a self therapy. You can enter the discussion:)

Have a nice day.


#2

What specifically is your question?


#3

Hello, is it that bad to use array like i did to achieve conversion type like exercices ?
Is it bad to “rush” an exercice the simpliest way you can think at the moment and depending on your skill if you can take much (much much) more time to think and figure it out an other way that is more productive for your skill in a more long/professional run.
Like i said, i feel ashamed i have finished exercices like this.


#4

I don’t see any issue with the array variable. I do see a lot of repetitive code, with an example being:

			if( uniteInt == array[k][0] ) {
				uniteInt = array[k][1];
			}

I think the above code and other sections like it could be refactored to provide more DRY solution.

When f I take the time to write out the simplest algorithm on paper and test it by going through it manually with all the test cases, I find it easier to write simpler code also. Many people (including myself) when they first learn to code try to jump right into the coding part before understanding the complete algorithm they should be using. Typically, this will tend to cause bloated/bandaged solutions, because they merely try to band-aid their semi-algorithm.

The only advice I can give you is to just keep practicing FCC challenges and other websites’ challenges. We get better at understanding and mapping out algorithms as we learn what does not work and by studying other solutions which are more efficient. When ever you come across a challenge where you don’t like your working solution, just click the “Reset your code” button and start from scratch again. I have done this many times with production code on my own websites which “worked”, but I did not think was “professional”.

Hope my response helps.


#5

I very often will solve something the simplest and most obvious way first. I think that this gives me a better grasp of the problem that I’m working on. Once the solution is running, I can look at it and find ways to improve my solution. In a way, this means I’m getting more bang for my buck per challenge because I am solving it more than once.


#6

Regarding your use of array in the Caesars Cipher, I would say, your solution works for the test cases used by FCC, but there could have been hundreds of special characters used and you would have had to hard-code all of them if they would have shown up in the tests. You did not take advantage of the ASCII codes and mod function as many of the other solutions I have seen, but your solution could be modified using the array variable for just the letters A-Z and then something like the following would have worked. Note the comments I put in for explaining what the code is doing.

function rot13( str ) {
	let array = [ ['A', 'N'],['B','O'],['C','P'],['D','Q'],['E','R'],['F','S'],['G','T'],['H','U'],['I','V'],['J','W'], 
				  ['K','X'],['L','Y'],['M','Z'],['N','A'],['O','B'],['P','C'],['Q','D'],['R','E'],['S','F'],['T','G'],
				  ['U','H'],['V','I'],['W','J'],['X','K'],['Y','L'],['Z','M'] ];
				  
	let arrL = array.length;
	let strL = str.length;
	let newStr = "";
	
	for( let k = 0; k < strL; k++ ) {
	  let newLetter; // used to hold converted letter
	  let foundConversion = false; // used to determine if a conversion was found in array
		for( let x = 0; x < arrL; x++ ) {
			if( str[k] == array[x][0] ) {
			  newLetter = array[x][1];
			  found = true;
			  break; // kicks out of inner loop because letter found already
			}
		}
		newStr += foundConversion ? newLetter : str[k]; // if is letter add it, otherwise add current str character
	}
	
	return newStr;
}

EDIT: If you really wanted to hard-code the letters as you did with the array, a more efficient solution would have used an object instead of a multi-dimensional array.

function rot13( str ) {
	const convertedLetters = { A:'N', B:'O', C:'P', D:'Q', E:'R', F:'S', G: 'T', H:'U', I:'V', J:'W', 
				  K:'X', L:'Y', M:'Z', N:'A', O:'B', P:'C', Q:'D', R:'E', S:'F', T:'G',
				  U:'H', V:'I', W:'J', X:'K',Y:'L',Z:'M' };

	let strL = str.length;
	let newStr = "";
	
	for( let k = 0; k < strL; k++ ) {
	  let letter = convertedLetters[str[k]]; // letter will contained a conversion or undefined if a property called str[k] is not found
	  newStr += letter ? letter : str[k]; // if found is not undefined, then add converted letter, otherwise add the current str character
	}
	return newStr;
}

#7

Thanks you both ! I’m going to read more precisely the code you wrote to me tomorrow !


#8

Hello back !
I really like what you used with the boolean and break then the ternary is sweet :slight_smile:
It really manage the special ponctuations and a gain of time with the break.
Is there performance difference between object and array ?

And thanks you for your feedback about “simple” code. I will try it out !


#9

You can access a property’s value in an object in O(1) time. With the structure you were using with the 2 dimensional array, it could have taken O(m*n), where m is the length of the outer array and n is the length of the inner array. Objects are much better for retrieving items quickly because of they way they are stored in memory. Arrays have to be iterated over to find specific values inside them. The only time an array can be as fast to retrieve a value in O(1) is if you already know the index of the item up front. From a memory stand point, objects do take up more than arrays.


#10

Thanks you very much ! I knew some one good in maths could answere this xD