Uczymy się pisać szyfr Cezara, czyli taki szyfr, który ma odpowiednie przesunięcie i litery w nim zawarte są po prostu o tyle przesunięte (A to D dla przesunięcia 3).

Ok, najpierw wypiszmy sobie znaki ASCII. Wiemy, że wielkie zaczynają się od 65 (to powinniśmy pamiętać) oraz że jest 26 liter:

for(let i = 65; i < 65+26; i++){
    console.log(`${String.fromCharCode(i)}: ${i}`);
}

//A: 65
//B: 66
//C: 67
//D: 68
//E: 69
//F: 70
//G: 71
//H: 72
//I: 73
//J: 74
//K: 75
//L: 76
//M: 77
//N: 78
//O: 79
//P: 80
//Q: 81
//R: 82
//S: 83
//T: 84
//U: 85
//V: 86
//W: 87
//X: 88
//Y: 89
//Z: 90

No dobra, jak zamienić A na D?

Tak:

function caesar(letter, shift){
    let code = letter.charCodeAt(0);
    return String.fromCharCode(code+shift);
}

console.log(caesar("A", 3)); //D
console.log(caesar("Z", 3)); //]
console.log(caesar("A", 26)); //[

Ok, w przypadku A to działa, bo A ma 65, zaś 68 to D. W przypadku Z to z ma 90 zaś C 67, a pod 93 to jest znak „]”, którego absolutnie nie chcemy. W przypadku przesunięcia o 26 zaś to my powinniśmy dostać tekst niezmieniony, A znowu równa się A.

Musimy mieć patent, że jak kolejność w alfabecie + przesunięcie jest mniejsza niż 26, to to przesunięcie jest dobre (nie przesunie nam poza zakres). A jak jest kolejność + przesunięcie równe 26 to nie przesuwamy w ogóle. A jak większe, mają się zapętlać.

Jeszcze pamiętać musimy, że w ASCII zaczynamy liczyć litery alfabetu od 65 zaś my je liczymy od 1 (A jest 1, przesunięcie 3, 4 mniejsze od 26, można przesuwać. Z to 26, przesunięcie 3, 30 > 26, nie można przesuwać)

Ok, cała funkcja wygląda tak:

function caesar(string, shift){

    string = string.toUpperCase();
    let result = "";

    for(let i = 0; i < string.length; i++){

        let char = string[i];
        let code = string.charCodeAt(i);

        if(code >= 65 && code <= 90){
            char = String.fromCharCode(((code - 65 + shift) % 26) + 65);
        }
        
        result += char;
        
    }

    return result;
}

console.log(caesar("A", 3)); //D
console.log(caesar("Z", 3)); //C
console.log(caesar("HELLO WORLD", 3)); //KHOOR ZRUOG

Zrobiłem naprawdę wszystko, aby temat wprowadzić powoli i bez zamętu, ale to się w głowie musi ułożyć. Proponuję skoczyć z JS do Pythona i tam, nieco czytelniej, rozłożyć ten algorytm na czynniki pierwsze i zobaczyć czy działa i jak działa:

print(ord("A")); #65
print(ord("D")); #68

print( ( (65 - 65 + 3 ) % 26) + 65) #68

print(ord("Z")) #90
print(ord("C")) #67

print( ( (90 - 65 + 3 ) % 26) + 65) #67

(Z) 90 – 65? 25.

25 + 3? 29.

29 mod 26? 3.

3 + 65? 67 (C)