Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 24 additions & 27 deletions Ciphers/CaesarsCipher.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,32 @@
/**
* Caesar's Cipher - also known as the ROT13 Cipher is when
* a letter is replaced by the one that is 13 spaces away
* from it in the alphabet. If the letter is in the first half
* of the alphabet we add 13, if it's in the latter half we
* subtract 13 from the character code value.
* @function caesarsCipher
* @description - In cryptography, a Caesar cipher, also known as Caesar's cipher, the shift cipher, Caesar's code or Caesar shift, is one of the simplest and most widely known encryption techniques. It is a type of substitution cipher in which each letter in the plaintext is replaced by a letter some fixed number of positions down the alphabet. For example, with a left shift of 3, D would be replaced by A, E would become B, and so on. The method is named after Julius Caesar, who used it in his private correspondence.
* @see - [wiki](https://en.wikipedia.org/wiki/Caesar_cipher)
* @param {string} str - string to be encrypted
* @param {number} rotation - the number of rotation, expect real number ( > 0)
* @return {string} - decrypted string
*/
const caesarsCipher = (str, rotation) => {
if (typeof str !== 'string' || !Number.isInteger(rotation) || rotation < 0) {
throw new TypeError('Arguments are invalid')
}

/**
* Decrypt a ROT13 cipher
* @param {String} str - string to be decrypted
* @return {String} decrypted string
*/
function rot13 (str) {
const response = []
const strLength = str.length
const alphabets = new Array(26)
.fill()
.map((_, index) => String.fromCharCode(97 + index)) // generate all lower alphabets array a-z

for (let i = 0; i < strLength; i++) {
const char = str.charCodeAt(i)
const cipherMap = alphabets.reduce(
(map, char, index) => map.set(char, alphabets[(rotation + index) % 26]),
new Map()
)

if (char < 65 || (char > 90 && char < 97) || char > 122) {
response.push(str.charAt(i))
} else if ((char > 77 && char <= 90) || (char > 109 && char <= 122)) {
response.push(String.fromCharCode(str.charCodeAt(i) - 13))
} else {
response.push(String.fromCharCode(str.charCodeAt(i) + 13))
return str.replace(/[a-z]/gi, (char) => {
if (/[A-Z]/.test(char)) {
return cipherMap.get(char.toLowerCase()).toUpperCase()
}
}
return response.join('')
}

export { rot13 }
return cipherMap.get(char)
})
}

// > rot13('Uryyb Jbeyq')
// 'Hello World'
export default caesarsCipher
16 changes: 16 additions & 0 deletions Ciphers/test/CaesarsCipher.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import caesarsCipher from '../CaesarsCipher'

describe('Testing the caesarsCipher function', () => {
it('Test - 1, Testing for invalid types', () => {
expect(() => caesarsCipher(false, 3)).toThrow()
expect(() => caesarsCipher('false', -1)).toThrow()
expect(() => caesarsCipher('true', null)).toThrow()
})

it('Test - 2, Testing for valid string and rotation', () => {
expect(caesarsCipher('middle-Outz', 2)).toBe('okffng-Qwvb')
expect(caesarsCipher('abcdefghijklmnopqrstuvwxyz', 3)).toBe('defghijklmnopqrstuvwxyzabc')
expect(caesarsCipher('Always-Look-on-the-Bright-Side-of-Life', 5)).toBe('Fqbfdx-Qttp-ts-ymj-Gwnlmy-Xnij-tk-Qnkj')
expect(caesarsCipher('THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG', 23)).toBe('QEB NRFZH YOLTK CLU GRJMP LSBO QEB IXWV ALD')
})
})