Se você está apenas tentando contar quantas vezes ele é reduzido e não se importa especificamente com a recursão ... basta remover a recursão. O código abaixo permanece fiel à postagem original, pois não conta num <= 9
como necessitando de redução. Portanto, singleDigit(8)
terá count = 0
e singleDigit(39)
terá count = 3
, exatamente como o OP e a resposta aceita estão demonstrando:
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;
}
Não é necessário processar números 9 ou menos (ie. num <= 9
). Infelizmente, o código OP será processado num <= 9
mesmo que não conte. O código acima não será processado nem contado num <= 9
. Apenas passa através.
Eu escolhi não usar .reduce
porque fazer as contas reais era muito mais rápido de executar. E, para mim, mais fácil de entender.
Pensando mais sobre velocidade
Eu sinto que um bom código também é rápido. Se você estiver usando esse tipo de redução (que é muito usado em numerologia), pode estar precisando usá-lo em uma grande quantidade de dados. Nesse caso, a velocidade se tornará da maior importância.
O uso de ambos .map(Number)
e console.log
(em cada etapa de redução) é muito longo para executar e desnecessário. A simples exclusão .map(Number)
do OP acelerou em cerca de 4,38x. A exclusão console.log
acelerava tanto que era quase impossível testar adequadamente (eu não queria esperar).
Portanto, semelhante à resposta do comando personalizado , não usar .map(Number)
nem console.log
pressionar os resultados em uma matriz e usar .length
para count
é muito muito mais rápido. Infelizmente para a resposta do comando personalizado , o uso de uma função de gerador é realmente muito lento (essa resposta é cerca de 2,68x mais lenta que o OP sem .map(Number)
e console.log
)
Além disso, em vez de usar .reduce
, apenas usei a matemática real. Somente essa única mudança acelerou minha versão da função por um fator de 3,59x.
Finalmente, a recursão é mais lenta, ocupa espaço na pilha, usa mais memória e tem um limite de quantas vezes pode "se repetir". Ou, nesse caso, quantas etapas de redução ele pode usar para concluir a redução completa. A distribuição de sua recursão para loops iterativos mantém tudo no mesmo lugar na pilha e não tem limite teórico sobre quantas etapas de redução ele pode usar para concluir. Portanto, essas funções aqui podem "reduzir" praticamente qualquer número inteiro, limitado apenas pelo tempo de execução e por quanto tempo uma matriz pode ser.
Tudo isso em 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
A função acima é extremamente rápida. É cerca de 3,13x mais rápido que o OP (sem .map(Number)
e console.log
) e 8,4x mais rápido que a resposta do comando personalizado . Lembre-se de que a exclusão console.log
do OP impede a produção de um número a cada etapa da redução. Portanto, a necessidade aqui de empurrar esses resultados em uma matriz.
PT
.map(Number)
é redundante, pois o*
operador coage os valores para numerar de qualquer maneira. ;-)