Si vous essayez simplement de compter combien de fois il est réduit et que vous ne vous souciez pas spécifiquement de la récursivité ... vous pouvez simplement supprimer la récursivité. Le code ci-dessous reste fidèle à la poste d'origine car il ne compte pas num <= 9
comme nécessitant une réduction. Par conséquent, singleDigit(8)
aura count = 0
, et singleDigit(39)
aura count = 3
, tout comme le PO et la réponse acceptée démontrent:
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;
}
Il n'est pas nécessaire de traiter les nombres 9 ou moins (c.-à-d. num <= 9
). Malheureusement, le code OP sera traité num <= 9
même s'il ne le compte pas. Le code ci-dessus ne traitera ni ne comptera pas num <= 9
du tout. Il passe juste à travers.
J'ai choisi de ne pas l'utiliser, .reduce
car l'exécution des calculs réels était beaucoup plus rapide à exécuter. Et, pour moi, plus facile à comprendre.
Réflexion sur la vitesse
Je pense que le bon code est également rapide. Si vous utilisez ce type de réduction (qui est beaucoup utilisé en numérologie), vous devrez peut-être l'utiliser sur une énorme quantité de données. Dans ce cas, la vitesse deviendra de la plus haute importance.
L'utilisation des deux .map(Number)
et console.log
(à chaque étape de réduction) est à la fois très très longue à exécuter et inutile. La simple suppression .map(Number)
de l'OP l'a accéléré d'environ 4,38x. La suppression console.log
a tellement accéléré qu'il était presque impossible de tester correctement (je ne voulais pas l'attendre).
Donc, comme pour la réponse de customcommander , ne pas utiliser .map(Number)
ni console.log
et pousser les résultats dans un tableau et utiliser .length
for count
est beaucoup plus rapide. Malheureusement pour la réponse de customcommander , l'utilisation d'une fonction de générateur est vraiment très lente (cette réponse est environ 2.68x plus lente que l'OP sans .map(Number)
et console.log
)
En outre, au lieu d'utiliser, .reduce
je viens d'utiliser les mathématiques réelles. Ce seul changement a accéléré à lui seul ma version de la fonction par un facteur de 3,59x.
Enfin, la récursivité est plus lente, elle prend de la place dans la pile, utilise plus de mémoire et a une limite au nombre de fois qu'elle peut "se reproduire". Ou, dans ce cas, combien d'étapes de réduction il peut utiliser pour terminer la réduction complète. Déployer votre récursivité en boucles itératives le maintient au même endroit sur la pile et n'a aucune limite théorique sur le nombre d'étapes de réduction qu'il peut utiliser pour terminer. Ainsi, ces fonctions peuvent ici "réduire" presque n'importe quel entier de taille, uniquement limité par le temps d'exécution et la longueur d'un tableau.
Tout cela à l'esprit ...
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
La fonction ci-dessus est extrêmement rapide. Il est environ 3,13 fois plus rapide que l'OP (sans .map(Number)
et console.log
) et environ 8,4 fois plus rapide que la réponse de customcommander . Gardez à l'esprit que la suppression console.log
de l'OP l'empêche de produire un nombre à chaque étape de réduction. D'où la nécessité ici de pousser ces résultats dans un tableau.
PT
.map(Number)
est redondant puisque l'*
opérateur contraint les valeurs à numéroter de toute façon. ;-)