Finished
1const ALPHABET_SIZE = 26;
2const GROUP_SIZE = 5;
3
4// Helper function to calculate greatest common divisor
5const gcd = (a, b) => {
6 while (b !== 0) {
7 const temp = b;
8 b = a % b;
9 a = temp;
10 }
11 return a;
12};
13
14// Helper function to check if two numbers are coprime
15const areCoprime = (a, m) => {
16 return gcd(a, m) === 1;
17};
18
19// Helper function to find modular multiplicative inverse
20const modInverse = (a, m) => {
21 for (let x = 1; x < m; x++) {
22 if ((a * x) % m === 1) {
23 return x;
24 }
25 }
26 return -1; // Should not happen if a and m are coprime
27};
28
29// Helper function to preprocess input
30const preprocess = (phrase) => {
31 return phrase.toLowerCase().replace(/[^a-z0-9]/g, '');
32};
33
134export const encode = (phrase, key) => {
2 throw new Error('Remove this line and implement the function');
35 const { a, b } = key;
36 const m = ALPHABET_SIZE;
37
38 // Edge Case: a and m are not coprime
39 if (!areCoprime(a, m)) {
40 throw new Error('a and m must be coprime.');
41 }
42
43 const cleanedPhrase = preprocess(phrase);
44 let result = '';
45
46 for (let i = 0; i < cleanedPhrase.length; i++) {
47 const char = cleanedPhrase[i];
48
49 // Edge Case: non-alphabetic characters in plaintext (digits)
50 if (char >= '0' && char <= '9') {
51 result += char;
52 } else {
53 const charIndex = char.charCodeAt(0) - 'a'.charCodeAt(0);
54 const encryptedIndex = (a * charIndex + b) % m;
55 result += String.fromCharCode(encryptedIndex + 'a'.charCodeAt(0));
56 }
57 }
58
59 // Format into groups of 5
60 let formattedResult = '';
61 for (let i = 0; i < result.length; i++) {
62 if (i > 0 && i % GROUP_SIZE === 0) {
63 formattedResult += ' ';
64 }
65 formattedResult += result[i];
66 }
67
68 return formattedResult;
69 // Handled Edge Cases: a and m are not coprime, non-alphabetic characters in plaintext (digits)
370};
471
572export const decode = (phrase, key) => {
6 throw new Error('Remove this line and implement the function');
73 const { a, b } = key;
74 const m = ALPHABET_SIZE;
75
76 // Edge Case: a and m are not coprime
77 if (!areCoprime(a, m)) {
78 throw new Error('a and m must be coprime.');
79 }
80
81 const aInv = modInverse(a, m);
82 const cleanedPhrase = preprocess(phrase);
83 let result = '';
84
85 // Edge Case: empty input string
86 if (cleanedPhrase.length === 0) {
87 return result;
88 }
89
90 for (let i = 0; i < cleanedPhrase.length; i++) {
91 const char = cleanedPhrase[i];
92
93 // Edge Case: non-alphabetic characters in plaintext (digits)
94 if (char >= '0' && char <= '9') {
95 result += char;
96 } else {
97 const charIndex = char.charCodeAt(0) - 'a'.charCodeAt(0);
98 // Edge Case: negative values after subtraction
99 const decryptedIndex = (aInv * (charIndex - b % m + m)) % m;
100 result += String.fromCharCode(decryptedIndex + 'a'.charCodeAt(0));
101 }
102 }
103
104 return result;
105 // Handled Edge Cases: a and m are not coprime, non-alphabetic characters in plaintext (digits), empty input string, negative values after subtraction
7106};
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.