Codewars Lösung | ASCII Shift Encryption/Decryption


coden
Codewars. Achieve mastery through challenge.
Daniel Kaser|23. Januar 2024
3 min.

Inhalt

  1. Die Fakten
  2. Beschreibung
  3. Lösung
    1. Pseudo-Code
    2. Code
  4. Feedback

Die Fakten:

Plattform:codewars.com
Name:ASCII Shift Encryption/Decryption
Level:7 kyu
Sprache:TypeScript

Beschreibung:

Ascii Shift Encryption/Decryption

The goal of this kata is to create a very simple ASCII encryption and decryption. The encryption algorithm should shift each character's charcode by the character's current index in the string (0-based).

The input strings will never require to go outside of the ASCII range.

Example:

  p | a | s | s | w | o | r | d # Plaintext
+ 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 # Shift (add)
  p | b | u | v | { | t | x | k # Ciphertext

The decryption should reverse this:

  p | b | u | v | { | t | x | k # Ciphertext
- 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 # Shift (subtract)
  p | a | s | s | w | o | r | d # Plaintext

Quelle: codewars.com

Lösung

Pseudo-Code

Wie immer gibt's reichlich Varianten, hier ist eine meiner.

Erst die Lösungsschritte in Pseudo-Code. Los geht’s:

Lösungsschritte
Schritt 1

Zuerst brauchen wir einen Loop.

Schritt 2

Dann addieren wir den aktuellen Index zu jedem Char-Code hinzu.

Schritt 3

Diesen neuen Char-Code wandeln wir dann wieder in ein Zeichen um.

Schritt 4

Ähnlich für die Entschlüsselungs-Funktion, nur dass wir hier den Index abziehen statt addieren.

Code

Geil. Übersetzen wir unseren Pseudo-Code in TypeScript:

Lösungsschritte
Meine erste Zeile der Verschlüsselungs-Funktion:
export function asciiEncrypt(plainText: string): string {
Jetzt der Loop:
  return [...plaintext]
    .map((char, i) => {

Ich versuch's hier mal mit Method-Chaining. Dazu wandele ich mir den String erst in ein Array um und loope dann mit .map().

Das return können wir schon mal davor schreiben, weil wir sind ja gleich fertig 😉

Dann addieren wir den Index zum Char-Code des aktuellen Zeichens dazu und wandeln den neuen Char-Code wieder in ein Zeichen um:
      const charCode = char.charCodeAt(0);
      return String.fromCharCode(charCode + i);
    })
Zum Schluss das Array wieder in einen String umwandeln:
    .join("");
}

Jetzt die zweite Funktion. Der Verschlüsselungs-Funktion sehr, sehr ähnlich...

Hier die erste Zeile meiner Entschlüsselungs-Funktion:
export function asciiDecrypt(cipherText: string): string {
Loop-Loop:
  return [...ciphertext]
    .map((char, i) => {

Auch hier wieder direkt mit return-Statement.

Hier müssen wir den Index vom Char-Code des aktuellen Zeichens abziehen bevor wir das Ergebnis in das neue Zeichen umwandeln:
      const charCode = char.charCodeAt(0);
      return String.fromCharCode(charCode - i);
    })
Dann noch das Array wieder in einen String umwandeln:
    .join("");
}
Voilá! 💪

Man hätte hier auch eine dritte Funktion schreiben können, die die ganze Logik enthält und als Parameter quasi nur das + bzw. - empfängt.

Hmm... eigentlich eine coole Bonus-Aufgabe... viel Spaß!

Fragen?

Komplettlösung
export function asciiEncrypt(plainText: string): string {
  return [...plaintext]
    .map((char, i) => {
      const charCode = char.charCodeAt(0);
      return String.fromCharCode(charCode + i); // Index addieren
    })
    .join("");
}

export function asciiDecrypt(cipherText: string): string {
  return [...ciphertext]
    .map((char, i) => {
      const charCode = char.charCodeAt(0);
      return String.fromCharCode(charCode - i); // Index abziehen
    })
    .join("");
}

Feedback

Schreib mir!