Codewars Lösung | Letter triangles


coden
Codewars. Achieve mastery through challenge.
Daniel Kaser|11. September 2024
4 min.

Inhalt

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

Die Fakten:

Plattform:codewars.com
Name:Letter triangles
Level:6 kyu
Sprache:TypeScript

Beschreibung:

Letter triangles

Similar to Coloured triangles.

But this one sums indexes of letters in alphabet.

Examples

c o d e w a r s
c is 3
o is 15
15+3=18
18. letter in the alphabet is r
then append r
next is o d
sum is 19
append s
do this until you iterate through whole string
now, string is rsibxsk
repeat whole cycle until you reach 1 character
then return the char
output is l
codewars -> l
triangle -> d
C O D E W A R S
 R S I B X S K
  K B K Z Q D
   M M K Q U
    Z X B L
     X Z N
      X N
       L
A B C D
 C E G
  H L
   T

More examples

youhavechosentotranslatethiskata -> a
cod -> k
yes -> b
hours -> y
circlecipher -> z
lettertriangles -> o
cod -> rs -> k
abcd -> ceg -> hl -> t
codewars -> rsibxsk -> kbkzqd -> mmkqu -> zxbl -> xzn -> xn -> l

Note, if the sum is bigger than 26, then start over

Input will always be lowercase letters. Random tests contains strings up to 30 letters.

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

Als Erstes brauchen wir eine Variable für das Alphabet.

Schritt 2

Außerdem können wir uns noch eine Variable für die jeweils nächste Reihe erstellen.

Schritt 3

Dann brauchen wir einen Loop! Durch die Reihen...

Schritt 4

Wir loopen solange, bis nur noch 1 Buchstabe übrigt ist.

Schritt 5

Dann brauchen wir einen weiteren Loop, durch die Buchstaben in der Reihe.

Schritt 6

In jedem Durchlauf ermitteln wir den jeweils aktuellen und den nächsten Buchstaben.

Schritt 7

Dann können wir für beide Buchstaben den Index im Alphabet ermitteln.

Schritt 8

Und beide Indizes zusammen addieren.

Schritt 9

Um einen "Off-by-One-Error" zu vermeiden müssen wir die Summe gegebenenfalls korrigieren.

Schritt 10

Wir werden auch den Modulo-Operator brauchen, falls die Summe über 26 (bzw. 25) ist.

Schritt 11

Dann den neuen Buchstaben im Alphabet ermitteln und an die nächste Zeile anhängen.

Schritt 12

Zum Schluss das Ergebnis zurückgeben.

Code

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

Lösungsschritte
Meine erste Zeile (ich habe row in str umbenannt):
export function triangle(str: string): string {
Als Erstes das Alphabet und die Variable für die nächste Reihe definieren:
const alphabet = "abcdefghijklmnopqrstuvwxyz";
let nextRow = str;
Dann der äußere Loop, solange wie unsere nächste Reihe länger als 1 ist:
  while (nextRow.length > 1) {

Ich hab mich hier für einen while-Loop entschieden.

Dann der innere Loop durch die einzelnen Buchstaben:
    nextRow = nextRow
      .split("")
      .reduce((acc, currChar, i) => {

Hier habe ich mich für Method-Chaining und .reduce() entschieden. Du kannst auch gerne z.B. einen for...of-Loop verwenden. 😉

Dann müssen wir prüfen, ob der aktuelle Buchstabe der letzte in der Reihe ist:
const isLastChar = i === nextRow.length - 1;

Der Lesbarkeit halber speichere ich mir das Ergebnis in einer Variablen ab (optional), die ich dann im nächsten Schritt verwurste.

Wenn ja, geben wir für diesen Buchstaben das Ergebnis-Array (den Akkumulator) unverändert zurück:
if (isLastChar) return acc;

Ansonsten können wir fortfahren.

Ich erstelle mir eine Variable für den nächsten Buchstaben (optional):
const nextChar = nextRow[i + 1];
Dann suchen wir uns die Indizes des jeweils aktuellen und des nächsten Buchstabens raus und addieren sie:
const currCharIndex = alphabet.indexOf(currChar);
const nextCharIndex = alphabet.indexOf(nextChar);

const newCharIndex = (currCharIndex + nextCharIndex + 1) % 26;

Um einen “Off-by-One-Error” zu vermeiden, addieren wir die 1 noch oben drauf. Mit Modulo 26 schneiden wir alles ab, was über 26 ist.

Jetzt noch den neuen Buchstaben ans Ergebnis-Array anhängen:
        return [...acc, alphabet[newCharIndex]];
      }, [] as string[])

Fertig ist der .reduce()-Loop!

Dann das Ergebnis-Array in einen String umwandeln:
      .join("");
  }
Und zum Schluss das Ergebnis zurückgeben:
  return nextRow;
}
Voilá! 💪

Fragen?

Komplettlösung
export function triangle(str: string): string {
  const alphabet = "abcdefghijklmnopqrstuvwxyz";

  let nextRow = str;

  while (nextRow.length > 1) {
    nextRow = nextRow
      .split("")
      .reduce((acc, currChar, i) => {
        const isLastChar = i === nextRow.length - 1;

        if (isLastChar) return acc;

        const nextChar = nextRow[i + 1];
        const currCharIndex = alphabet.indexOf(currChar);
        const nextCharIndex = alphabet.indexOf(nextChar);

        const newCharIndex = (currCharIndex + nextCharIndex + 1) % 26;

        return [...acc, alphabet[newCharIndex]];
      }, [] as string[])
      .join("");
  }

  return nextRow;
}

Feedback

Schreib mir!