Skip to content

Instantly share code, notes, and snippets.

@rfprod
Last active April 22, 2017 15:54
Show Gist options
  • Save rfprod/61534a42408b42845c49 to your computer and use it in GitHub Desktop.
Save rfprod/61534a42408b42845c49 to your computer and use it in GitHub Desktop.
Caesar's Cipher
function rot13(encodedStr) {
var codeArr = encodedStr.split("");
var decodedArr = [];
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 codeIndex;
var decodedIndex;
for (var i=0;i<codeArr.length;i++){
codeIndex = isAlphabetSymbol(codeArr[i]);
if (codeIndex !== undefined){
if (codeIndex >= 13){
decodedIndex = codeIndex - 13;
}else{
decodedIndex = alphabet.length - (13 - codeIndex);
}
decodedArr.push(alphabet[decodedIndex]);
}else{
decodedArr.push(codeArr[i]);
}
}
function isAlphabetSymbol(symbol){
var z;
for (var j=0;j<alphabet.length;j++){
if (symbol == alphabet[j]){
z = j;
break;
}
}
return z;
}
return decodedArr.join("");
}
// TEST
rot13("SERR PBQR PNZC");
/*
* universal encoder / decoder
*/
function CaesarCryptoCoder(text, shift) {
//console.log(text, shift);
const onlySpaces = new RegExp(/^(\s){1,}$/).test(text);
if (text && !onlySpaces) {
const inputArr = text.split('');
let codedArr = [];
const 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', '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'];
function isAlphabetSymbol(symbol) {
let z;
for (let j = 0, jMax = alphabet.length; j < jMax; j++) {
if (symbol == alphabet[j]){
z = j;
break;
}
}
return z;
}
let codeIndex;
let decodedIndex;
for (let i = 0, max = inputArr.length; i < max; i++) {
codeIndex = isAlphabetSymbol(inputArr[i]);
if (codeIndex !== undefined) {
//console.log('codeIndex', codeIndex);
decodedIndex = codeIndex + shift;
//console.log('decodedIndex', decodedIndex);
if (decodedIndex > alphabet.length) { decodedIndex -= alphabet.length * Math.floor(decodedIndex / alphabet.length); }
else if (decodedIndex < 0) { decodedIndex = decodedIndex - alphabet.length * Math.floor(decodedIndex / alphabet.length); }
//console.log('decodedIndex', decodedIndex);
codedArr.push(alphabet[decodedIndex]);
} else { codedArr.push(inputArr[i]); }
}
return codedArr.join('');
}
return '';
}
// TEST
CaesarCryptoCoder("Et tu, Brute?", 3) // returns "Hw wx, Euxwh?"
/*
* coder class
*/
function CaesarCipher(shift) {
this.coder = (text, shiftIndex) => {
//console.log(text, shiftIndex);
const onlySpaces = new RegExp(/^(\s){1,}$/).test(text);
if (text && !onlySpaces) {
const inputArr = text.split('');
let codedArr = [];
const 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', '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'];
function isAlphabetSymbol(symbol) {
let z;
for (let j = 0, jMax = alphabet.length; j < jMax; j++) {
if (symbol == alphabet[j]){
z = j;
break;
}
}
return z;
}
let codeIndex;
let decodedIndex;
for (let i = 0, max = inputArr.length; i < max; i++) {
codeIndex = isAlphabetSymbol(inputArr[i]);
if (codeIndex !== undefined) {
//console.log('codeIndex', codeIndex);
decodedIndex = codeIndex + shiftIndex;
//console.log('decodedIndex', decodedIndex);
if (decodedIndex >= alphabet.length) { decodedIndex -= alphabet.length * Math.floor(decodedIndex / alphabet.length); }
else if (decodedIndex < 0) { decodedIndex = decodedIndex - alphabet.length * Math.floor(decodedIndex / alphabet.length); }
//console.log('alphabet[decodedIndex]', alphabet[decodedIndex]);
codedArr.push(alphabet[decodedIndex]);
} else { codedArr.push(inputArr[i]); }
}
return codedArr.join('');
}
return '';
}
this.encode = (str) => {
const sh = (shift < 0) ? 0 - shift : shift;
//console.log('encode called on', str, 'with shift', sh);
return this.coder(str, sh).toUpperCase();
}
this.decode = (str) => {
const sh = (shift > 0) ? 0 - shift : shift;
//console.log('decode called on', str, 'with shift', sh);
return this.coder(str, sh).toUpperCase();
}
};
// TEST
let coder = new CaesarCipher(5);
const encoded = coder.encode('Codewars'); // 'HTIJBFWX'
const decoded = coder.decode('BFKKQJX'); // 'WAFFLES'
/*
* first variation on ROTn
*/
function movingShift(s, shift) {
const onlySpaces = new RegExp(/^(\s){1,}$/).test(s);
if (s && !onlySpaces) {
const inputArr = s.split('');
let codedArr = [];
const 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', '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'];
function isAlphabetSymbol(symbol) {
let z;
for (let j = 0, jMax = alphabet.length; j < jMax; j++) {
if (symbol === alphabet[j]){
z = j;
break;
}
}
return z;
}
let codeIndex;
let decodedIndex;
for (let i = 0, max = inputArr.length; i < max; i++) {
codeIndex = isAlphabetSymbol(inputArr[i]);
if (codeIndex !== undefined) {
decodedIndex = codeIndex + shift;
if (decodedIndex >= alphabet.length) { decodedIndex -= alphabet.length * Math.floor(decodedIndex / alphabet.length); }
else if (decodedIndex < 0) { decodedIndex = decodedIndex - alphabet.length * Math.floor(decodedIndex / alphabet.length); }
codedArr.push(alphabet[decodedIndex]);
} else { codedArr.push(inputArr[i]); }
// fix case
codedArr[codedArr.length - 1] = (inputArr[i].toLowerCase() === inputArr[i]) ? codedArr[codedArr.length - 1].toLowerCase() : codedArr[codedArr.length - 1].toUpperCase();
shift++;
}
let undistributed = codedArr.join('');
const ul = undistributed.length;
let partLength = (ul % 5 === 0) ? ul / 5 : Math.floor(ul / 4);
codedArr = [];
while (codedArr.length < 4) {
const part = (ul % 4 === 0) ? undistributed.substring(0, partLength) : undistributed.substring(0, partLength + 1);
undistributed = (ul % 4 === 0) ? undistributed.slice(partLength) : undistributed.slice(partLength + 1);
codedArr.push(part);
}
codedArr.push(undistributed);
undistributed = '';
while (codedArr[0].length - 1 >= codedArr[4].length + 4) {
partLength--;
for (let i = 0, max = codedArr.length; i < max; i++) {
codedArr[i] = (undistributed) ? undistributed + codedArr[i] : codedArr[i];
undistributed = codedArr[i].slice(partLength + 1);
if (i === max - 1) {
codedArr[i] = undistributed + codedArr[i];
undistributed = '';
} else {
codedArr[i] = codedArr[i].substring(0, partLength + 1);
}
}
}
return codedArr;
}
return codedArr;
}
function demovingShift(arr, shift) {
const s = arr.reduce((a, b) => a.concat(b), []).join('');
const onlySpaces = new RegExp(/^(\s){1,}$/).test(s);
if (s && !onlySpaces) {
const inputArr = s.split('');
let codedArr = [];
const 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', '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'];
function isAlphabetSymbol(symbol) {
let z;
for (let j = 0, jMax = alphabet.length; j < jMax; j++) {
if (symbol === alphabet[j]){
z = j;
break;
}
}
return z;
}
let codeIndex;
let decodedIndex;
for (let i = 0, max = inputArr.length; i < max; i++) {
codeIndex = isAlphabetSymbol(inputArr[i]);
if (codeIndex !== undefined) {
decodedIndex = codeIndex - shift;
if (decodedIndex >= alphabet.length) { decodedIndex -= alphabet.length * Math.floor(decodedIndex / alphabet.length); }
else if (decodedIndex < 0) { decodedIndex = decodedIndex - alphabet.length * Math.floor(decodedIndex / alphabet.length); }
codedArr.push(alphabet[decodedIndex]);
} else { codedArr.push(inputArr[i]); }
// fix case
codedArr[codedArr.length - 1] = (inputArr[i].toLowerCase() === inputArr[i]) ? codedArr[codedArr.length - 1].toLowerCase() : codedArr[codedArr.length - 1].toUpperCase();
shift++;
}
return codedArr.join('');
}
return '';
}
// TEST
const u = 'I should have known that you would have a perfect answer for me!!!';
const v = ['J vltasl rlhr ', 'zdfog odxr ypw', ' atasl rlhr p ', 'gwkzzyq zntyhv', ' lvz wp!!!'];
movingShift(u, 1); // returns v
demovingShift(v, 1); // return u

Caesars Cipher

A common modern use of the simplest and most widely known ciphers, Caesar cipher, is the ROT13 cipher, where the values of the letters are shifted by 13 places. Thus 'A' ↔ 'N', 'B' ↔ 'O' and so on.

The rot13() function takes a ROT13 encoded string as input and returns a decoded string. All letters must be uppercase.

The CaesarCryptoCoder() function takes a string of characters and a shift value. It uses double length alphabet, including all lower case and upper case characters: a-zA-Z.

The CaesarsCipher class should be instantiated with new provided a shift value. The instance can be used to encode/decode strings. Resulting string letters are converted to upper case after encoding/decoding.

The movingShift() and demovingShift() functions perform a variation of the Caesar cipher where the shift increases by 1 for each character (on each iteration). The movingShift() function takes a string and a shift value as parameters, encodes the entire string and then returns an array of strings containing the encoded string divided in 5 parts as follows:

  1. if possible, the message is evenly split in 5 parts;
  2. if not possible, parts 1, 2, 3, 4 will be longer and part 5 shorter;
  3. the 5th part length can be equal to the other ones or less;
  4. if there are multiple possible ways to split the encoded message, provided that the previous conditions are fulfilled, an option where the 5th part has the longest possible length is selected;
  5. if the last part is an empty string, this empty string is included in the resulting array.

The demovingShift() function takes an array with previously encoded message and a shift value as parameters, and decodes the message.

A script by V.

License.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment