Inhalt
Die Fakten:
Plattform: | codewars.com |
Name: | Simple Fun #23: Square Digits Sequence |
Level: | 6 kyu |
Sprache: | TypeScript |
Beschreibung:
Task
Consider a sequence of numbers a0, a1, ..., an, in which an element is equal to the sum of squared digits of the previous element. The sequence ends once an element that has already been in the sequence appears again.
Given the first element a0
, find the length of the sequence.
Example
For a0 = 16, the output should be 9
Here's how elements of the sequence are constructed:
a0 = 16
a1 = 12 + 62 = 37
a2 = 32 + 72 = 58
a3 = 52 + 82 = 89
a4 = 82 + 92 = 145
a5 = 12 + 42 + 52 = 42
a6 = 42 + 22 = 20
a7 = 22 + 02 = 4
a8 = 42 = 16, which has already occurred before (a0)
Thus, there are 9 elements in the sequence.
For a0 = 103, the output should be 4
The sequence goes as follows: 103 -> 10 -> 1 -> 1, 4 elements altogether.
Input/Output
-
[input]
integera0
First element of a sequence, positive integer.
Constraints: 1 ≤ a0 ≤ 650.
-
[output]
an integer
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 können wir uns 2 Hilfsfunktionen basteln, eine, die Zahlen in ihre Ziffern zerlegt und eine, die diese Ziffern aufsummiert.
Schritt 2
Dann können wir uns um die Hauptfunktion kümmern.
Schritt 3
Dort können wir zuerst ein Ergebnis-Array anlegen und schon mal die Input-Zahl rein tun.
Schritt 4
Dann wird geloopt bis der Arzt kommt oder wir auf eine Summe stoßen, die bereits im Ergebnis-Array enthalten ist.
Schritt 5
Wenn das so ist, geben wir die Länge des Ergebnis-Arrays + 1 zurück.
Schritt 6
Ansonsten fügen wir die aktuelle quadrierte Ziffernsumme zum Ergebnis-Array hinzu.
Code
Geil. Übersetzen wir unseren Pseudo-Code in TypeScript:
Lösungsschritte
Die erste Zeile meines Verzifferungs-Helferleins:
function digitize(num: number): number[] {
Was kommt jetzt? Ah, die Logik! Logisch oder?!:
return [...num.toString()].map(Number);
}
Hier wird einfach die Input-Zahl erst in einen String und dann in ein Array umgewandelt. Mit .map(Number) werden dann die String-Zahlen wieder in Zahlen umgewandelt.
Dann die Hilfsfunktion zum Aufsummieren der Ziffern.
Die erste Zeile der Hilfsfunktion zum Aufsummieren der Ziffern:
function sumUpSquaredDigits(num: number): number {
Hier die Logik:
return digitize(num).reduce((sum, digit) => sum + digit ** 2, 0);
}
Hier können wir unsere erste Hilfsfunktion anwenden um die Input-Zahl in ein Array aus Ziffern zu verwandeln. Dann können wir mit .reduce()
jede Ziffer quadrieren und zur Summe addieren, die wir dann zurückgeben. Die 0
am Ende heißt, dass wir bei 0
anfangen.
Dann kann es endlich losgehen mit der Hauptfunktion:
Die erste Zeile meiner Hauptfunktion (ich habe a
in num
umbenannt):
export function squareDigitsSequence(num: number): number {
Als Erstes erstelle ich mir mein Ergebnis-Array und packe direkt num
als erstes Element rein:
const results = [num];
Dann der Loop:
while (true) {
Dieser Loop ist unendlich. Wir müssen also dran denken, ihn irgendwann zu beenden.
Für jeden Durchlauf erstelle ich mir 2 Variablen:
const curr = results[0];
const squaredDigitsSum = sumUpSquaredDigits(curr);
Als aktuelles Element wähle ich hier das erste. Du kannst hier gerne auch immer das letzte nehmen.
Wir loopen solange, bis wir auf eine Zahl stoßen, die bereits im Ergebnis-Array vorhanden ist:
if (results.includes(squaredDigitsSum)) return results.length + 1;
Wenn das der Fall ist, beenden wir Loop und Funktion mit return
. Wir geben die aktuelle Länge des Arrays plus dem einen Element mit der aktuellen Summe zurück.
Wenn nicht, hängen wir die aktuelle Summe an das Ergebnis-Array dran:
results.unshift(squaredDigitsSum);
}
}
Da wir oben das erste Element als unser aktuelles gewählt haben, hängen wir es hier VORNE an. Wenn du das letzte genommen hast, musst du es HINTEN anfügen.
Voilá! 💪
Komplettlösung
export function squareDigitsSequence(num: number): number {
const results = [num];
while (true) {
const curr = results[0];
const squaredDigitsSum = sumUpSquaredDigits(curr);
if (results.includes(squaredDigitsSum)) return results.length + 1;
results.unshift(squaredDigitsSum);
}
}
function digitize(num: number): number[] {
return [...num.toString()].map(Number);
}
function sumUpSquaredDigits(num: number): number {
return digitize(num).reduce((sum, digit) => sum + digit ** 2, 0);
}