Si solo está tratando de contar cuántas veces se reduce y no le importa la recursión específicamente ... simplemente puede eliminarla. El siguiente código permanece fiel a la publicación original, ya que no cuenta num <= 9
como una necesidad de reducción. Por lo tanto, singleDigit(8)
tendrá count = 0
y singleDigit(39)
tendrá count = 3
, al igual que el OP y la respuesta aceptada demuestran:
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;
}
No es necesario procesar los números 9 o menos (es decir num <= 9
). Lamentablemente, el código OP se procesará num <= 9
aunque no lo cuente. El código anterior no procesará ni contaránum <= 9
en absoluto. Simplemente lo pasa a través.
Elijo no usarlo .reduce
porque hacer las matemáticas reales fue mucho más rápido de ejecutar. Y, para mí, más fácil de entender.
Más pensamiento sobre la velocidad
Siento que un buen código también es rápido. Si está utilizando este tipo de reducción (que se usa mucho en numerología), es posible que necesite usarlo en una gran cantidad de datos. En este caso, la velocidad se convertirá en la más importante.
Usar ambos .map(Number)
y console.log
(en cada paso de reducción) son muy largos de ejecutar e innecesarios. Simplemente eliminar .map(Number)
del OP lo aceleró en aproximadamente 4.38x. La eliminación lo console.log
aceleró tanto que era casi imposible probarlo adecuadamente (no quería esperar).
Entonces, de manera similar a la respuesta de customcommander , no usar .map(Number)
ni console.log
empujar los resultados a una matriz y usar .length
for count
es mucho más rápido. Desafortunadamente para la respuesta de customcommander , el uso de una función de generador es realmente muy lento (esa respuesta es aproximadamente 2.68 veces más lenta que el OP sin .map(Number)
y console.log
)
Además, en lugar de usar .reduce
, solo utilicé las matemáticas reales. Este solo cambio aceleró mi versión de la función en un factor de 3.59x.
Finalmente, la recursividad es más lenta, ocupa espacio en la pila, usa más memoria y tiene un límite de cuántas veces puede "repetirse". O, en este caso, cuántos pasos de reducción puede usar para finalizar la reducción completa. El despliegue de su recursión a bucles iterativos lo mantiene todo en el mismo lugar en la pila y no tiene un límite teórico sobre cuántos pasos de reducción puede usar para terminar. Por lo tanto, estas funciones aquí pueden "reducir" casi cualquier número entero de cualquier tamaño, solo limitado por el tiempo de ejecución y el tiempo que puede durar una matriz.
Todo esto en mente ...
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 función anterior se ejecuta extremadamente rápido. Es aproximadamente 3.13 veces más rápido que el OP (sin .map(Number)
y console.log
) y aproximadamente 8.4 veces más rápido que la respuesta de customcommander . Tenga en cuenta que eliminar console.log
del OP evita que produzca un número en cada paso de reducción. Por lo tanto, la necesidad aquí de llevar estos resultados a una matriz.
PT
.map(Number)
es redundante ya que el*
operador obliga a los valores a numerar de todos modos. ;-)