Codewars Lösung | Scramblies


coden
Codewars. Achieve mastery through challenge.
Daniel Kaser|7. August 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:Scramblies
Level:5 kyu
Sprache:TypeScript

Beschreibung:

Complete the function scramble(str1, str2) that returns true if a portion of str1 characters can be rearranged to match str2, otherwise returns false.

Notes:

  • Only lower case letters will be used (a-z). No punctuation or digits will be included.
  • Performance needs to be considered.
* Input strings s1 and s2 are null terminated.

Examples

scramble('rkqodlw', 'world') ==> True
scramble('cedewaraaossoqqyt', 'codewars') ==> True
scramble('katas', 'steak') ==> False

Quelle: codewars.com

Lösung

Pseudo-Code

Es gibt wie immer viele Varianten, hier ist eine meiner.

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

Lösungsschritte
Schritt 1

Hier müssen wir ein bisschen auf die Performance achten. Wenn wir durch das Alphabet loopen, brauchen wir nur 26 Iterationen, das könnte klappen...

Schritt 2

Dafür können wir uns als Erstes eine Hilfsfunktion basteln, die die Anzahl eines Zeichens in einem String zählt

Schritt 3

In der Hauptfunktion brauchen wir als Erstes eine Variable mit dem Alphabet

Schritt 4

Dann der Loop durch das Alphabet

Schritt 5

Wir prüfen für jeden Buchstaben im Alphabet, ob der aktuelle Buchstabe im zweiten String öfter vorkommt als im Ersten

Schritt 6

Wenn ja, geben wir false zurück

Schritt 7

Ansonsten können wir nach dem Loop true zurückgeben

Code

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

Lösungsschritte
Die erste Zeile meiner Hilfsfunktion:
function countCharInStr(char: string, str: string): number {
Zum Zählen können wir z.B. den String am gegebenen Buchstaben bzw. Zeichen splitten und dann die Anzahl der Elemente zählen:
  return str.split(char).length - 1;
}

Vom Ergebnis ziehen wir noch 1 ab. Fertig.

HINWEIS
Die Hilfsfunktion ist hier nicht unbedingt nötig, hilft aber bei der Lesbarkeit.

Weiter geht’s mit der Hauptfunktion.

Die erste Zeile meiner Hauptfunktion:
export function scramble(str1: string, str2: string): boolean {
Das Alphabet definieren:
  const alphabet = "abcdefghijklmnopqrstuvwxyz";
Dann der Loop durchs Alphabet:
  for (let letter of alphabet) {

Da wir kein i o.ä. brauchen können wir einen for...of-Loop verwenden. .forEach() ginge nicht, den können wir bei Bedarf leider nicht vorzeitig beenden.

Der Lesbarkeit halber speichere ich mir die Anzahl des aktuellen Buchstabens in str1 und str2 jeweils in einer Variablen ab:
    const numLetterInStr1 = countCharInStr(letter, str1);
    const numLetterInStr2 = countCharInStr(letter, str2);
Dann der Test ob in str2 mehr des aktuellen Buchstabens als in str1 sind:
    if (numLetterInStr1 < numLetterInStr2) return false;
  }

Wenn ja, können wir direkt false zurückgeben und damit den Loop und die Funktion vorzeitig beenden.

Ansonsten geben wir nach dem Loop true zurück:
  return true;
}
Voilá! 💪

Fragen?

Komplettlösung
export function scramble(str1: string, str2: string): boolean {
  const alphabet = "abcdefghijklmnopqrstuvwxyz";

  for (let letter of alphabet) {
    const numLetterInStr1 = countCharInStr(letter, str1);
    const numLetterInStr2 = countCharInStr(letter, str2);
    if (numLetterInStr1 < numLetterInStr2) return false;
  }

  return true;
}

function countCharInStr(char: string, str: string): number {
  return str.split(char).length - 1;
}

Feedback

Schreib mir!
blub