| 4 | 4 | // |
| 5 | 5 | |
| 6 | 6 | export class Cipher { |
| 7 | | constructor() { |
| 8 | | throw new Error('Remove this line and implement the function'); |
| 7 | constructor(key) { |
| 8 | // Edge Case: null or undefined key |
| 9 | if (key === undefined) { |
| 10 | this._key = this._generateRandomKey(); |
| 11 | } |
| 12 | // Edge Case: empty key |
| 13 | else if (key === '') { |
| 14 | throw new Error('Key must not be empty'); |
| 15 | } |
| 16 | // Edge Case: key with non-alphabetic characters |
| 17 | else if (!/^[a-z]+$/.test(key)) { |
| 18 | throw new Error('Key must contain only lowercase letters'); |
| 19 | } else { |
| 20 | this._key = key; |
| 21 | } |
| 9 | 22 | } |
| 10 | 23 | |
| 11 | | encode() { |
| 12 | | throw new Error('Remove this line and implement the function'); |
| 24 | _generateRandomKey() { |
| 25 | const letters = 'abcdefghijklmnopqrstuvwxyz'; |
| 26 | let key = ''; |
| 27 | for (let i = 0; i < 100; i++) { |
| 28 | key += letters[Math.floor(Math.random() * letters.length)]; |
| 29 | } |
| 30 | return key; |
| 13 | 31 | } |
| 14 | 32 | |
| 15 | | decode() { |
| 16 | | throw new Error('Remove this line and implement the function'); |
| 33 | encode(plaintext) { |
| 34 | // Edge Case: empty plaintext |
| 35 | if (!plaintext) return ''; |
| 36 | |
| 37 | let result = ''; |
| 38 | for (let i = 0; i < plaintext.length; i++) { |
| 39 | const char = plaintext[i]; |
| 40 | // Edge Case: non-letter characters in plaintext |
| 41 | if (!/[a-z]/.test(char)) { |
| 42 | result += char; |
| 43 | continue; |
| 44 | } |
| 45 | |
| 46 | const keyChar = this._key[i % this._key.length]; |
| 47 | const shift = keyChar.charCodeAt(0) - 97; // 'a' = 0, 'b' = 1, etc. |
| 48 | const charCode = char.charCodeAt(0) - 97; |
| 49 | const newCharCode = (charCode + shift) % 26; |
| 50 | result += String.fromCharCode(newCharCode + 97); |
| 51 | } |
| 52 | |
| 53 | return result; |
| 54 | } |
| 55 | |
| 56 | decode(ciphertext) { |
| 57 | // Edge Case: empty ciphertext |
| 58 | if (!ciphertext) return ''; |
| 59 | |
| 60 | let result = ''; |
| 61 | for (let i = 0; i < ciphertext.length; i++) { |
| 62 | const char = ciphertext[i]; |
| 63 | // Edge Case: non-letter characters in ciphertext |
| 64 | if (!/[a-z]/.test(char)) { |
| 65 | result += char; |
| 66 | continue; |
| 67 | } |
| 68 | |
| 69 | const keyChar = this._key[i % this._key.length]; |
| 70 | const shift = keyChar.charCodeAt(0) - 97; |
| 71 | const charCode = char.charCodeAt(0) - 97; |
| 72 | let newCharCode = (charCode - shift) % 26; |
| 73 | // Edge Case: negative result from modulo |
| 74 | if (newCharCode < 0) { |
| 75 | newCharCode += 26; |
| 76 | } |
| 77 | result += String.fromCharCode(newCharCode + 97); |
| 78 | } |
| 79 | |
| 80 | return result; |
| 17 | 81 | } |
| 18 | 82 | |
| 19 | 83 | get key() { |
| 20 | | throw new Error('Remove this line and implement the function'); |
| 84 | return this._key; |
| 21 | 85 | } |
| 22 | 86 | } |
| 87 | |
| 88 | // Handled Edge Cases: null or undefined key, empty key, key with non-alphabetic characters, empty plaintext, non-letter characters in plaintext, empty ciphertext, non-letter characters in ciphertext, negative result from modulo |