Wenn Sie nur versuchen zu zählen, wie oft es reduziert wird, und sich nicht speziell um die Rekursion kümmern , können Sie die Rekursion einfach entfernen. Der folgende Code bleibt dem Originalbeitrag treu, da er nicht num <= 9als reduktionsbedürftig gilt. Daher singleDigit(8)wird count = 0und singleDigit(39)wird count = 3, genau wie das OP und die akzeptierte Antwort zeigen:
const singleDigit = (num) => {
let count = 0, ret, x;
while (num > 9) {
ret = 1;
while (num > 9) {
x = num % 10;
num = (num - x) / 10;
ret *= x;
}
num *= ret;
count++;
console.log(num);
}
console.log("Answer = " + num + ", count = " + count);
return num;
}
Es ist nicht erforderlich, die Nummern 9 oder weniger (dh num <= 9) zu verarbeiten. Leider wird der OP-Code verarbeitet, num <= 9obwohl er nicht gezählt wird. Der obige Code wird weder verarbeitet noch gezähltnum <= 9 . Es geht einfach durch.
Ich entscheide mich, es nicht zu verwenden, .reduceda die Ausführung der eigentlichen Mathematik viel schneller war. Und für mich leichter zu verstehen.
Weiteres Denken über Geschwindigkeit
Ich fühle mich gut Code ist auch schnell. Wenn Sie diese Art der Reduzierung verwenden (die in der Numerologie häufig verwendet wird), müssen Sie sie möglicherweise für eine große Datenmenge verwenden. In diesem Fall wird die Geschwindigkeit von größter Bedeutung sein.
Die Verwendung von beiden .map(Number)und console.log(bei jedem Reduktionsschritt) ist sehr, sehr langwierig und unnötig. .map(Number)Durch einfaches Löschen aus dem OP wurde die Geschwindigkeit um das 4,38-fache erhöht. Das Löschen console.logbeschleunigte es so sehr, dass es fast unmöglich war, es richtig zu testen (ich wollte nicht darauf warten).
Ähnlich wie bei der Antwort von customcommander ist es viel schneller , .map(Number)nor nicht zu verwenden console.logund die Ergebnisse in ein Array zu verschieben und .lengthfor zu verwenden count. Unglücklicherweise für die Antwort von customcommander ist die Verwendung einer Generatorfunktion sehr, sehr langsam (diese Antwort ist ungefähr 2,68x langsamer als die OP ohne .map(Number)und console.log).
Anstatt zu verwenden, habe .reduceich auch nur die eigentliche Mathematik verwendet. Allein diese einzelne Änderung hat meine Version der Funktion um den Faktor 3,59 beschleunigt.
Schließlich ist die Rekursion langsamer, beansprucht Stapelspeicher, verbraucht mehr Speicher und kann nur begrenzt "wiederkehren". Oder in diesem Fall, wie viele Reduktionsschritte verwendet werden können, um die vollständige Reduktion abzuschließen. Wenn Sie Ihre Rekursion in iterative Schleifen ausrollen, bleibt alles an derselben Stelle auf dem Stapel und es gibt keine theoretische Begrenzung für die Anzahl der Reduktionsschritte, die zum Beenden verwendet werden können. Somit können diese Funktionen hier nahezu jede beliebige Größe "reduzieren", die nur durch die Ausführungszeit und die Länge eines Arrays begrenzt ist.
All dies im Hinterkopf ...
const singleDigit2 = (num) => {
let red, x, arr = [];
do {
red = 1;
while (num > 9) {
x = num % 10;
num = (num - x) / 10;
red *= x;
}
num *= red;
arr.push(num);
} while (num > 9);
return arr;
}
let ans = singleDigit2(39);
console.log("singleDigit2(39) = [" + ans + "], count = " + ans.length );
// Output: singleDigit2(39) = [27,14,4], count = 3
Die obige Funktion läuft extrem schnell. Es ist ungefähr 3,13x schneller als das OP (ohne .map(Number)und console.log) und ungefähr 8,4x schneller als die Antwort von customcommander . Beachten Sie, dass das Löschen console.logaus dem OP verhindert, dass bei jedem Schritt der Reduzierung eine Zahl erzeugt wird. Daher besteht hier die Notwendigkeit, diese Ergebnisse in ein Array zu verschieben.
PT
.map(Number)ist redundant, da der*Operator die Werte ohnehin zur Nummerierung zwingt. ;-)