Inhalt
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á! 💪
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;
}