Codewars Lösung | Cryptanalysis Word Patterns


coden
Codewars. Achieve mastery through challenge.
Daniel Kaser|10. Dezember 2023
3 min.

Inhalt

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

Die Fakten:

Plattform:codewars.com
Name:Cryptanalysis Word Patterns
Level:7 kyu
Sprache:TypeScript

Beschreibung:

In cryptanalysis, words patterns can be a useful tool in cracking simple ciphers.

A word pattern is a description of the patterns of letters occurring in a word, where each letter is given an integer code in order of appearance. So the first letter is given the code 0, and second is then assigned 1 if it is different to the first letter or 0 otherwise, and so on.

As an example, the word "hello" would become "0.1.2.2.3". For this task case-sensitivity is ignored, so "hello", "helLo" and "heLlo" will all return the same word pattern.

Your task is to return the word pattern for a given word. All words provided will be non-empty strings of alphabetic characters only, i.e. matching the regex "[a-zA-Z]+".

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

Wir brauchen einen Loop!

Schritt 2

Zuerst wandeln wir jeden Buchstaben in einen Kleinbuchstaben um.

Schritt 3

Bereits gefundene Buchstaben können wir in einem String oder Array speichern.

Schritt 4

Wenn der aktuelle Buchstabe noch nicht im Gefunden-Array enthalten ist, ergänzen wir ihn.

Schritt 5

Dann speichern wir seinen Index im Gefunden-Array in einem neuen Array.

Schritt 6

Zum Schluss geben wir das neue Array mit den Indices als punkt-getrennten String zurück.

Code

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

Lösungsschritte
Meine erste Zeile:
export function wordPattern(word: string): string {
Dann unser Gefunden-Array initialisieren:
const foundChars: string[] = [];
Jetzt der Loop:
  word
    .split("")
    .map((char) => {

Erst wandeln wir den String mit .split("") in ein Array um. Dann können wir durch das Array loopen.

Weil wir genauso viele Elemente ändern/zurückgeben wollen wie drin sind, bietet sich hier .map() an.

Dann den aktuellen Buchstaben in einen Kleinbuchstaben umwandeln:
char = char.toLowerCase();
Jetzt prüfen wir, ob der aktuelle Buchstabe bereits im Gefunden-Array enthalten ist. Wenn nicht, ergänzen wir ihn:
if (!foundChars.includes(char)) foundChars.push(char);

Alternative:

Wir könnten hier den jeweiligen Buchstaben auch in einem String speichern. Das sähe dann so aus:

if (!foundChars.includes(char)) foundChars += char;

Dazu müssten wir oben statt des Arrays einen leeren String initialisieren.

Dann geben wir dem Array den Index im Gefunden-Array zurück:
      return foundChars.indexOf(char);
    })
Dann nur noch die Elemente des Arrays mit einem Punkt zu einem String verbinden:
    .join(".");
}
Zum Schluss noch das return-Keyword. Unser kompletter method-gechainter Loop sieht dann so aus:
return word
  .split("")
  .map((char) => {
    char = char.toLowerCase();
    if (!foundChars.includes(char)) foundChars.push(char);
    return foundChars.indexOf(char);
  })
  .join(".");
Voilá! 💪

Fragen?

Komplettlösung
export function wordPattern(word: string): string {
  const foundChars: string[] = [];

  return word
    .split("")
    .map((char) => {
      char = char.toLowerCase();
      if (!foundChars.includes(char)) foundChars.push(char);
      return foundChars.indexOf(char);
    })
    .join(".");
}

Feedback

Schreib mir!