11/**
2- * Find and retrieve the encryption key automatically.
2+ * Find and retrieve the Caesar cipher encryption key automatically.
33 * @param {string } str - The input encrypted string.
4- * @returns {number } - The encryption key found, or 0 if not found.
4+ * @returns {number|null } - The encryption key found, or null if not found.
55 */
66function keyFinder ( str ) {
7- // str is used to get the input of encrypted string
87 const wordBank = [
98 'I ' ,
109 'You ' ,
@@ -30,126 +29,62 @@ function keyFinder(str) {
3029 'May ' ,
3130 ' be ' ,
3231 'Be '
33- ]
34- const inStr = str . toString ( ) // convert the input to String
35- let outStr = '' // store the output value
36- let outStrElement = '' // temporary store the word inside the outStr, it is used for comparison
32+ ] ;
33+
34+ const inStr = String ( str ) ;
35+
3736 for ( let k = 0 ; k < 26 ; k ++ ) {
38- // try the number of key shifted, the sum of character from a-z or A-Z is 26
39- outStr = caesarCipherEncodeAndDecodeEngine ( inStr , k ) // use the encryption engine to decrypt the input string
37+ const outStr = caesarCipherEncodeAndDecodeEngine ( inStr , k ) ;
4038
41- // loop through the whole input string
4239 for ( let s = 0 ; s < outStr . length ; s ++ ) {
4340 for ( let i = 0 ; i < wordBank . length ; i ++ ) {
44- // initialize the outStrElement which is a temp output string for comparison,
45- // use a loop to find the next digit of wordBank element and compare with outStr's digit
46- for ( let w = 0 ; w < wordBank [ i ] . length ; w ++ ) {
47- outStrElement += outStr [ s + w ]
48- }
49- // this part need to be optimize with the calculation of the number of occurrence of word's probabilities
50- // linked list will be used in the next stage of development to calculate the number of occurrence of the key
51- if ( wordBank [ i ] === outStrElement ) {
52- return k // return the key number if founded
41+ const word = wordBank [ i ] ;
42+ const segment = outStr . slice ( s , s + word . length ) ;
43+
44+ if ( segment === word ) {
45+ return k ; // Found the key
5346 }
54- outStrElement = '' // reset the temp word
55- } // end for (let i=0; i < wordBank.length; i++)
47+ }
5648 }
5749 }
58- return 0 // return 0 if found nothing
50+
51+ return null ; // Key not found
5952}
6053
6154/**
62- * This sub-function is used to assist the keyFinder in finding the key .
55+ * Caesar cipher encode/decode engine .
6356 * @param {string } inStr - The input string.
64- * @param {number } numShifted - The number of characters to shift in the Caesar cipher .
65- * @returns {string } - The decrypted string.
57+ * @param {number } shiftNum - Number of characters to shift (0-25) .
58+ * @returns {string } - The shifted string.
6659 */
67- function caesarCipherEncodeAndDecodeEngine ( inStr , numShifted ) {
68- const shiftNum = numShifted
69- let charCode = 0
70- let shiftedCharCode = 0
71- let result = 0
72-
60+ function caesarCipherEncodeAndDecodeEngine ( inStr , shiftNum ) {
7361 return inStr
7462 . split ( '' )
7563 . map ( ( char ) => {
76- charCode = char . charCodeAt ( )
77- shiftedCharCode = charCode + shiftNum
78- result = charCode
79-
80- if ( charCode >= 48 && charCode <= 57 ) {
81- if ( shiftedCharCode < 48 ) {
82- let diff = Math . abs ( 48 - 1 - shiftedCharCode ) % 10
83-
84- while ( diff >= 10 ) {
85- diff = diff % 10
86- }
87- document . getElementById ( 'diffID' ) . innerHTML = diff
88-
89- shiftedCharCode = 57 - diff
90-
91- result = shiftedCharCode
92- } else if ( shiftedCharCode >= 48 && shiftedCharCode <= 57 ) {
93- result = shiftedCharCode
94- } else if ( shiftedCharCode > 57 ) {
95- let diff = Math . abs ( 57 + 1 - shiftedCharCode ) % 10
64+ const code = char . charCodeAt ( 0 ) ;
9665
97- while ( diff >= 10 ) {
98- diff = diff % 10
99- }
100- document . getElementById ( 'diffID' ) . innerHTML = diff
101-
102- shiftedCharCode = 48 + diff
103-
104- result = shiftedCharCode
105- }
106- } else if ( charCode >= 65 && charCode <= 90 ) {
107- if ( shiftedCharCode <= 64 ) {
108- let diff = Math . abs ( 65 - 1 - shiftedCharCode ) % 26
109-
110- while ( diff % 26 >= 26 ) {
111- diff = diff % 26
112- }
113- shiftedCharCode = 90 - diff
114- result = shiftedCharCode
115- } else if ( shiftedCharCode >= 65 && shiftedCharCode <= 90 ) {
116- result = shiftedCharCode
117- } else if ( shiftedCharCode > 90 ) {
118- let diff = Math . abs ( shiftedCharCode - 1 - 90 ) % 26
119-
120- while ( diff % 26 >= 26 ) {
121- diff = diff % 26
122- }
123- shiftedCharCode = 65 + diff
124- result = shiftedCharCode
125- }
126- } else if ( charCode >= 97 && charCode <= 122 ) {
127- if ( shiftedCharCode <= 96 ) {
128- let diff = Math . abs ( 97 - 1 - shiftedCharCode ) % 26
66+ // Uppercase A-Z
67+ if ( code >= 65 && code <= 90 ) {
68+ return String . fromCharCode ( ( ( code - 65 + shiftNum ) % 26 ) + 65 ) ;
69+ }
12970
130- while ( diff % 26 >= 26 ) {
131- diff = diff % 26
132- }
133- shiftedCharCode = 122 - diff
134- result = shiftedCharCode
135- } else if ( shiftedCharCode >= 97 && shiftedCharCode <= 122 ) {
136- result = shiftedCharCode
137- } else if ( shiftedCharCode > 122 ) {
138- let diff = Math . abs ( shiftedCharCode - 1 - 122 ) % 26
71+ // Lowercase a-z
72+ if ( code >= 97 && code <= 122 ) {
73+ return String . fromCharCode ( ( ( code - 97 + shiftNum ) % 26 ) + 97 ) ;
74+ }
13975
140- while ( diff % 26 >= 26 ) {
141- diff = diff % 26
142- }
143- shiftedCharCode = 97 + diff
144- result = shiftedCharCode
145- }
76+ // Digits 0-9
77+ if ( code >= 48 && code <= 57 ) {
78+ return String . fromCharCode ( ( ( code - 48 + shiftNum ) % 10 ) + 48 ) ;
14679 }
147- return String . fromCharCode ( parseInt ( result ) )
80+
81+ // Non-alphabetic characters remain unchanged
82+ return char ;
14883 } )
149- . join ( '' )
84+ . join ( '' ) ;
15085}
15186
152- export { keyFinder }
87+ export { keyFinder } ;
15388
154- // > keyFinder('test')
155- // 0
89+ // Example usage:
90+ // console.log(keyFinder("Uifsf jt b tfdsfu nfttbhf")); // Should return 1
0 commit comments