After learning about objects, arrays, and loops this week on the Full-Stack Engineer Career Path, I decided to practice what I had learned so far. So, I set out to code a Playfair Cipher. It wound up not using objects, but was definitely some good practice for the other two.
Those unfamiliar with the Playfair Cipher can find more information on that here: Playfair cipher - Wikipedia
I was thinking this project may take me all day, and possibly even some on the weekend, but I was very happy to have it working in about 2.5 hours this morning! It’s still essentially the very first version of this (I have made a few tweaks throughout the afternoon, so I’ve labeled it version 0.1.1).
As laid out in the readme, I still have some things I would like to add to this script to develop it, but I would love to hear from the community about this first version as well. Are there any ways this code could be refined to be simpler or more efficient? Any concepts I’ve not yet learned that could make this more powerful etc? Am I exhibiting any bad habits in this code that I need to stop?
This is the first project I’ve come up with and made myself outside of any lessons. I was very pleased to not have to cheat and look up how to accomplish any of the core logic, but I will admit I found the removeDuplicateCharacters
function on Stack Overflow. I wanted to focus on figuring out the actual loop logic and array structures, and not spend too much time on string manipulation, but I am going to spend some time researching all of the “ingredients” of that function so that I can still learn from it.
My code is below, and I will also link to the readme on GitHub:
/*Playfair Cipher using a 6x6 grid to support numbers*/
//Get input and passkey
let input = 'secret message to encode';
let passkey = 'old tavern';
let output = '';
const gridChars = 'abcdefghijklmnopqrstuvwxyz0123465789';
//Removes duplicate characters from string. Will need this function later.
const removeDuplicateCharacters = (string) => {
return string
.split('')
.filter(function(item, pos, self) {
return self.indexOf(item) == pos;
})
.join('');
}
// Clean input
input = input.toLowerCase();
input = input.replace(/[^a-zA-Z0-9]/g, '');
if (input.length%2 != 0) {
input += 'z';
};
//Group characters into pairs for encoding
let inputArray = [];
for (let i = 0; i < input.length; i += 2) {
let subArray = [input[i], input[i+1]];
inputArray.push(subArray);
};
//Clean passkey (needs no spaces, special characters, or duplicate characters)
passkey = passkey.toLowerCase();
passkey = passkey.replace(/[^a-z0-9]/g,'');
passkey = passkey += gridChars;
passkey = removeDuplicateCharacters(passkey);
//Generates playfair grid
let playfairArray = [];
for (let i = 0; i < passkey.length; i += 6) {
let subArray = [passkey[i], passkey[i+1], passkey[i+2], passkey[i+3], passkey[i+4], passkey[i+5]];
playfairArray.push(subArray);
}
// need to find playfair coordinates of input character pairs stored in each input subarray, stay in same playfair subarray and switch indexes
for (i = 0; i < inputArray.length; i++) {
let char1 = inputArray[i][0];
let char2 = inputArray[i][1];
let pos1;
let pos2;
let row1;
let row2;
for (y = 0; y < playfairArray.length; y++) {
for (x = 0; x < playfairArray[y].length; x++) {
if (char1 === char2 && char1 === playfairArray[y][x]) {
pos1 = x;
pos2 = x;
row1 = y;
row2 = y;
} else if (char1 === playfairArray[y][x]) {
pos2 = x;
row1 = y;
} else if (char2 === playfairArray[y][x]) {
pos1 = x;
row2 = y;
}
}
}
output += playfairArray[row1][pos1] + playfairArray[row2][pos2];
}
console.log(output);