Reputation: 87
I'm building a Caesar Cipher in javascript. It uses a randomly set variable called currentkey
as the cipher's key. it can be a number from -25 to +25, skipping 0.
I can't figure out why the function returns undefined in the beginning of the string, or why it translates the same letter for as long as the string goes, or even why that letter doesn't get translated at all.
var currentkey = 5 //for example
function convertKey(str) {
var o_text = str;
var o_letters = o_text.split("");
var alphabet = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','x','y','w','z']
var c_text, _x = "";
for (x in o_letters) {
if (currentkey > 0) {
_x = alphabet[alphabet.indexOf(x) + currentkey]
} else {
_x = alphabet[alphabet.indexOf(x) + (26 - currentkey)]
}
c_text = c_text + _x;
}
return c_text;
}
For example, running convertKey("example")
returns undefinedeeeeeee
(undefined + 7 times the first letter in "example").
Upvotes: 1
Views: 4658
Reputation: 31
function rot13(str) {
const alphabet1 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXY';
const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
return str
.split('')
.map(function(char) {
const pos = alphabet.indexOf(char);
return pos >=0? alphabet1[pos+13] : char;
})
.join('');
}
rot13("SERR PBQR PNZC");
Upvotes: 0
Reputation: 629
Here's a more simple answer:
var rot = {
'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',
' ': ' ',
'.': '.',
'!': '!',
'?': '?'
};
// Change the inputs below to test
rot13("SERR CVMMN!");
// FREE CODE CAMP
function rot13(str) {
var index = [];
for (var key in str) {
for (var property in rot) {
if (str[key] === property) {
index.push(rot[property]);
}
}
}
return index.join('');
}
Upvotes: 0
Reputation: 175
Implementation the Caesar Cipher algorithm in JavaScript is very interesting due to the fact that JavaScripts lacks true modulo operator. The % is just the reminder of division. Read this article for more explanations.
However, you can easily define the modulo as a custom function and then proceed to the implementation of the Caesar Cipher - which is a very simple form of encryption, in which each letter in the original message is shifted to the left or right by a certain number of positions.
To decrypt the message we simply shift back the letters the same number of positions.
Example:
If after shifting a letter goes outside the range of letters, then the letter is wrapped around in alphabet. Example: Letter Z becomes C if is shifted by 3 positions.
This “wrap-around” effect means use of modulo. In mathematical terms, the above can be expressed as this:
En(x) = (x + n) mod 26
Dn(x) = (x – n) mod 26
Trying to implement this algorithm in JavaScript without the use of a proper modulo operator will produce either incorrect results or a very cryptic and difficult to understand code.
By using a custom modulo function, the code expresses the mathematical equation identically:
// Function will implement Caesar Cipher to
// encrypt / decrypt the msg by shifting the letters
// of the message acording to the key
function encrypt(msg, key)
{
var encMsg = "";
for(var i = 0; i < msg.length; i++)
{
var code = msg.charCodeAt(i);
// Encrypt only letters in 'A' ... 'Z' interval
if (code >= 65 && code <= 65 + 26 - 1)
{
code -= 65;
code = mod(code + key, 26);
code += 65;
}
encMsg += String.fromCharCode(code);
}
return encMsg;
}
// Implement modulo by replacing the negative operand
// with an equivalent positive operand that has the same wrap-around effect
function mod(n, p)
{
if ( n < 0 )
n = p - Math.abs(n) % p;
return n % p;
}
Have fun!
Encrypt a few messages to try out the code. Remember: If you encrypt with a positive key, use the complementary negative key to decrypt it. You can also use this code to decode those ROT13 messages that appears everywhere on the web and newsgroups.
If you want to find out other ways of implementing modulo in JavaScript, please consult the article mentioned at the beginning of this post.
Upvotes: 3
Reputation: 93
// working at https://www.freecodecamp.org/challenges/caesars-cipher
function rot13(str){
var res = [];
var currentPosition;
var shiftedPosition;
for (var i = 0; i<str.length; i++){
currentPosition = str.charCodeAt(i);
if (currentPosition<65 || currentPosition>90){
res.push(String.fromCharCode(currentPosition));
}
shiftedPosition = str.charCodeAt(i) - 13;
if (currentPosition>=65 && shiftedPosition <65){
res.push(String.fromCharCode(91-(13-(currentPosition-65))));
}
if (currentPosition>=78 && currentPosition<=90){
res.push(String.fromCharCode(shiftedPosition));
}
}
return res.join('');`enter code here`
}
// Change the inputs below to test
rot13("GUR DHVPX OEBJA QBT WHZCRQ BIRE GUR YNML SBK.");
Upvotes: 1
Reputation: 1509
The undefined
is a result of not initializing c_text
before you try concatenate it with _x
.
The code only works on one letter because alphabet.indexOf(x)
returns -1
(not found). When using o_text = "abc"
, x
equals 0, 1, and 2. Thus, the index of 0, 1, or 2 in alphabet
is nonexistent (indicated by the -1
result). You need to relate those numbers back to o_text
by changing indexOf(x)
to indexOf(o_text[x])
. Also, to prevent going outside the bounds of your array, you need a modulus operation to wrap values greater than 26 (I've used alphabet.length
to allow this code to work with other alphabets) back around into a valid region. Thus, the correct code would be as follows (note: I've moved 'w' in your array into its proper location alphabetically, as I assumed its location in your example was an error and not intentional):
var currentkey = 5 //for example
function convertKey(str) {
var o_text = str;
var o_letters = o_text.split("");
var alphabet = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
var c_text="", _x = "";
for (x in o_letters) {
if (currentkey > 0) {
_x = alphabet[(alphabet.indexOf(o_letters[x]) + currentkey) % alphabet.length]
} else {
_x = alphabet[(alphabet.indexOf(o_letters[x]) + (26 - currentkey)) % alphabet.length]
}
c_text = c_text + _x;
}
return c_text;
}
alert(convertKey('abcdefghijklmnopqrstuvwxyz'));
This alert's fghijklmnopqrstuvwxyzabcde
Upvotes: 2
Reputation: 83293
(1) You are not iterating through your array o_letters
properly.
(2) You are going out-of-bounds for your array.
for (var i = 0; i < o_letters.length; i++) {
_x = alphabet[(alphabet.indexOf(o_letters[i]) + currentkey + 26) % 26]
c_text = c_text + _x;
}
Also, in your code, you don't need .split("")
at all.
I would just do this:
var currentkey = 5 //for example
function convertKey(str) {
var ret = '';
for (var i = 0; i < str.length; i++) {
ret += String.fromCharCode((str.charCodeAt(i) + currentKey + 26) % 26);
}
return ret;
}
Or more succinctly (but less efficiently):
function convertKey(str) {
return str.split('').map(function(c) {
return String.fromCharCode((c.charCodeAt(0) + currentKey + 26) % 26);
}).join('');
}
Upvotes: 2