Inhalt
Die Fakten:
Plattform: | codewars.com |
Name: | Moves in squared strings (III) |
Level: | 6 kyu |
Sprache: | TypeScript |
Beschreibung:
You are given a string of n
lines, each substring being n
characters long: For example:
s = "abcd\nefgh\nijkl\nmnop"
We will study some transformations of this square of strings.
Let's now transform this string!
- Symmetry with respect to the main diagonal: diag_1_sym (or diag1Sym or diag-1-sym)
diag_1_sym(s) => "aeim\nbfjn\ncgko\ndhlp"
- Clockwise rotation 90 degrees: rot_90_clock (or rot90Clock or rot-90-clock)
rot_90_clock(s) => "miea\nnjfb\nokgc\nplhd"
- selfie_and_diag1(s) (or selfieAndDiag1 or selfie-and-diag1) It is initial string + string obtained by symmetry with respect to the main diagonal.
s = "abcd\nefgh\nijkl\nmnop" -->
"abcd|aeim\nefgh|bfjn\nijkl|cgko\nmnop|dhlp"
or printed for the last:
selfie_and_diag1
abcd|aeim
efgh|bfjn
ijkl|cgko
mnop|dhlp
Task:
- Write these functions
diag_1_sym
,rot_90_clock
,selfie_and_diag1
and
-
high-order function
oper(fct, s)
where -
fct is the function of one variable f to apply to the string
s
(fct will be one ofdiag_1_sym
,rot_90_clock
,selfie_and_diag1
)
Examples:
s = "abcd\nefgh\nijkl\nmnop"
oper(diag_1_sym, s) => "aeim\nbfjn\ncgko\ndhlp"
oper(rot_90_clock, s) => "miea\nnjfb\nokgc\nplhd"
oper(selfie_and_diag1, s) => "abcd|aeim\nefgh|bfjn\nijkl|cgko\nmnop|dhlp"
Notes:
-
The form of the parameter
fct
in oper changes according to the language. You can see each form according to the language in "Your test cases". -
It could be easier to take these katas from number (I) to number (IV)
-
Bash Note: The output strings should be separated by \r instead of \n. See "Sample Tests".
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
Für die Diagonal-Version erstelle ich mir zuerst ein Ergebnis-Array, das genauso lang ist, wie die "Wörter" im Input und fülle es mit leeren Strings.
Schritt 2
Dann loope ich durch die "Wörter".
Schritt 3
Und dann noch mal durch jedes "Wort".
Schritt 4
Jedes Zeichen hänge ich an den String mit dem gleichen Index im Ergebnis-Array.
Schritt 5
Für die Rotierte-Version erstelle ich erst die Diagonal-Version.
Schritt 6
Dann drehe ich jedes "Wort" einfach um.
Schritt 7
Für die Selfie-und-Diagonal-Version erstelle ich auch wieder erst die Diagonal-Version.
Schritt 8
Dann gebe ich einfach das Original-Wort, gefolgt von Pipe und Diagonal-Wort zurück.
Schritt 9
In der Oper-Funktion gebe ich einfach die Input-Funtion mit dem Input-String als Argument zurück.
Code
Na denn... übersetzen wir unseren Pseudo-Code in TypeScript:
Lösungsschritte
Die erste Zeile meiner Diagonal-Funktion (ich habe in jeder Funktion strng
zu str
umbenannt):
export function diag1Sym(str: string): string {
Dann erstellen wir das Ergebnis-Array mit der Länge bzw. Anzahl der "Wörter" im Input-String:
const words = str.split("\n");
const result: string[] = Array(words.length).fill("");
Jetzt der Loop durch die "Wörter":
words.forEach((word) =>
Dann der Loop durch die Zeichen jedes einzelnen Wortes:
word.split("").forEach((char, i) => (result[i] += char))
);
Jedes Zeichen hängen wir an den korrespondierenden String im Ergebnis-Array. Dafür nutzen wir den Index i
.
Zum Schluss noch das Ergebnis-Array als String zurückgeben:
return result.join("\n");
}
Als nächstes kümmern wir uns um die Rotations-Version.
Hier die erste Zeile meiner Rotations-Funktion:
export function rot90Clock(str: string): string {
Das kriegen wir mit Method-Chaining hin:
return diag1Sym(str)
.split("\n")
.map((word) => word.split("").reverse().join(""))
.join("\n");
}
Erst wenden wir unsere Diagonal-Funktion auf den Input-String an. Dann drehen wir die einzelnen "Wörter" einfach um.
Weiter geht’s mit der Selfie-Diagonal-Funktion:
Hier die erste Zeile der Selfie-Diagonal-Funktion:
export function selfieAndDiag1(str: string): string {
Dann wenden wir wieder unsere Diagonal-Funktion an:
const diagWords = diag1Sym(str).split("\n");
Außerdem splitte ich hier die "Wörter" in ein Array und speichere es in einer Variablen.
Den Rest kriegen wir wieder mit Method-Chaining hin:
return str
.split("\n")
.map((word, i) => `${word}|${diagWords[i]}`)
.join("\n");
}
Hier ersetzen wir jedes "Wort" im Input-String mit dem Original-Wort, einer Pipe und dem entsprechenden Diagonal-Wort.
Zum Schluss nur noch die Oper-Funktion.
Die erste der Oper-Funktion Zeile:
export function oper(fct: (str: string) => string, str: string): string {
Wir geben einfach die Input-Funktion mit dem Input-String als Argument zurück:
return fct(str);
}
Voilá! 💪
Komplettlösung
export function diag1Sym(str: string): string {
const words = str.split("\n");
const result: string[] = Array(words.length).fill("");
words.forEach((word) =>
word.split("").forEach((char, i) => (result[i] += char)),
);
return result.join("\n");
}
export function rot90Clock(str: string): string {
return diag1Sym(str)
.split("\n")
.map((word) => word.split("").reverse().join(""))
.join("\n");
}
export function selfieAndDiag1(str: string): string {
const diagWords = diag1Sym(str).split("\n");
return str
.split("\n")
.map((word, i) => `${word}|${diagWords[i]}`)
.join("\n");
}
export function oper(fct: (str: string) => string, str: string): string {
return fct(str);
}