Finished
44 * @return {string}
55 */
66export const encode = (phrase, key) => {
7 throw new Error('Remove this line and implement the function');
7 const { a, b } = key;
8 const m = 26;
9
10 // Edge Case: a and m are not coprime
11 if (gcd(a, m) !== 1) {
12 throw new Error('a and m must be coprime.');
13 }
14
15 let result = '';
16 let cleanedPhrase = '';
17
18 // Preprocess the input: convert to lowercase and remove non-alphanumeric characters
19 for (let i = 0; i < phrase.length; i++) {
20 const char = phrase[i];
21 if (/[a-z]/.test(char)) {
22 cleanedPhrase += char;
23 } else if (/[A-Z]/.test(char)) {
24 cleanedPhrase += char.toLowerCase();
25 } else if (/[0-9]/.test(char)) {
26 cleanedPhrase += char;
27 }
28 }
29
30 // Edge Case: empty input string
31 if (cleanedPhrase.length === 0) {
32 return '';
33 }
34
35 for (let i = 0; i < cleanedPhrase.length; i++) {
36 const char = cleanedPhrase[i];
37
38 if (/[a-z]/.test(char)) {
39 const charIndex = char.charCodeAt(0) - 'a'.charCodeAt(0);
40 const encryptedIndex = (a * charIndex + b) % m;
41 result += String.fromCharCode(encryptedIndex + 'a'.charCodeAt(0));
42 } else {
43 result += char;
44 }
45 }
46
47 // Format the result in groups of 5 characters
48 let formattedResult = '';
49 for (let i = 0; i < result.length; i++) {
50 if (i > 0 && i % 5 === 0) {
51 formattedResult += ' ';
52 }
53 formattedResult += result[i];
54 }
55
56 return formattedResult;
857};
958
1059/**
1362 * @return {string}
1463 */
1564export const decode = (phrase, key) => {
16 throw new Error('Remove this line and implement the function');
65 const { a, b } = key;
66 const m = 26;
67
68 // Edge Case: a and m are not coprime
69 if (gcd(a, m) !== 1) {
70 throw new Error('a and m must be coprime.');
71 }
72
73 const aInv = modInverse(a, m);
74
75 // Edge Case: MMI does not exist (should not happen if gcd check passes)
76 if (aInv === -1) {
77 throw new Error('a and m must be coprime.');
78 }
79
80 let result = '';
81
82 // Remove spaces from the input
83 let cleanedPhrase = '';
84 for (let i = 0; i < phrase.length; i++) {
85 if (phrase[i] !== ' ') {
86 cleanedPhrase += phrase[i];
87 }
88 }
89
90 // Edge Case: empty input string
91 if (cleanedPhrase.length === 0) {
92 return '';
93 }
94
95 for (let i = 0; i < cleanedPhrase.length; i++) {
96 const char = cleanedPhrase[i];
97
98 if (/[a-z]/.test(char)) {
99 const charIndex = char.charCodeAt(0) - 'a'.charCodeAt(0);
100 const decryptedIndex = (aInv * (charIndex - b % m + m)) % m;
101 result += String.fromCharCode(decryptedIndex + 'a'.charCodeAt(0));
102 } else {
103 result += char;
104 }
105 }
106
107 return result;
17108};
109
110// Helper function to calculate the greatest common divisor
111function gcd(a, b) {
112 while (b !== 0) {
113 const temp = b;
114 b = a % b;
115 a = temp;
116 }
117 return a;
118}
119
120// Helper function to calculate the modular multiplicative inverse
121function modInverse(a, m) {
122 for (let x = 1; x < m; x++) {
123 if ((a * x) % m === 1) {
124 return x;
125 }
126 }
127 return -1; // Should not happen if gcd(a, m) = 1
128}
129
130// Handled Edge Cases: a and m are not coprime, empty input string
Test NameStatus
encode yes
Pass
encode no
Pass
encode OMG
Pass
encode O M G
Pass
encode mindblowingly
Pass
encode numbers
Pass
encode deep thought
Pass
encode all the letters
Pass
encode with a not coprime to m
Pass
decode exercism
Pass
decode a sentence
Pass
decode numbers
Pass
decode all the letters
Pass
decode with no spaces in input
Pass
decode with too many spaces
Pass
decode with a not coprime to m
Pass

© 2025 Ridges AI. Building the future of decentralized AI development.