Executando verificação de segurança...
1

[JS] Problema mátematico

Boa tarde, galera!
Estou fazendo um programa que soma todos os algarismos de um numero até que a soma vire unidade, exemplo:

16 --> 1 + 6 = 7
942 --> 9 + 4 + 2 = 15 --> 1 + 5 = 6
132189 --> 1 + 3 + 2 + 1 + 8 + 9 = 24 --> 2 + 4 = 6
493193 --> 4 + 9 + 3 + 1 + 9 + 3 = 29 --> 2 + 9 = 11 --> 1 + 1 = 2

Porém, meu código esta dando erro e nao sei o por que!

function digitalRoot(n) {
    let sum = 0
    while(n/10 != 0 && n%10 != 10){
        valor = n%10 //resto da divisao por 10
        n = n/10 
        sum = sum + valor //colocando o resto 'valor' em sum
    }
    if( sum / 10 != 0) //verificando se sum é unidade 
        sum = digitalRoot(sum)
    return sum
}
console.log(digitalRoot(16))
Carregando publicação patrocinada...
2

O erro está no trecho abaixo:

while(n/10 != 0 && n%10 != 10){
    valor = n%10 //resto da divisao por 10
    n = n/10 
    sum = sum + valor //colocando o resto 'valor' em sum
}

O problema é que a condição de while está incorreta. Você deve substituir por:

while(n > 0){
    valor = n%10 //resto da divisao por 10
    n = Math.floor(n/10) 
    sum = sum + valor //colocando o resto 'valor' em sum
}
1

Vejo que, quando executo seu código, mostra um erro de Maximum call stack size exceeded, e isso geralmente acontece quando as chamadas recursivas não possuem uma condição de parada clara, o que faz com que a função continue chamando a si mesma infinitamente.

Esse erro ocorreu por conta do trecho onde verifica se o sum é unidade if (sum / 10 != 0), mas só que o sum sempre será diferente de zero, então ficará chamando a função infinitamente, e assim dando o erro de Maximum call stack size exceeded.

1

Bom dia PedroPontes, obrigado por compartilhar seu problema matemático.
Essa é minha primeira interação, primeira resposta no TabNews, espero que lhe seja útil.

O legal de problemas de lógica assim, é que você pode resolver com qualquer linguagem, a lógica é a mesma.
Porém o JS tem uma magia que nos ajuda a resolver o problema de uma forma mais elegante, se posso chamar assim, apesar de menos legível de primeiro momento.

Logo quando vi esse problema, de cara me lembrou os problemas do CodeWars. Se não conhece, sugiro dar uma olhada!

Vou deixar uma solução aqui para o seu problema e vou mostrar o que cada etapa faz! No começo pode parecer BEM CONFUSO, talvez seja mesmo, mas eu acho bem bacana. Vamos lá!!!


function digitalRoot(num){
  return num.toString().split('').map((item) => parseInt(item)).reduce((a,b) => a + b);
}

console.log(digitalRoot(1234)); // 10
console.log(digitalRoot(124354435)); // 31

Passo a passo da function:

  1. num.toString() // transforma o número em string

  2. .split('') // divide a string em substrings procurando pelo padrão passado na chamada do split, nesse caso, '' faz com que separe um por um e adiciona num array.

  3. .map((item) => parseInt(item)) // transforma cada item desse array em número novamente.

  4. .reduce((a, b) => a + b); // simplificando, o reduce faz a mágica de somar cada item do array, considerando o 'a' como acumulador e o 'b' como o valor atual, ele passa por cada item do array e vai somando, até restar somente um item, por esse motivo, o reduce sempre nos retorna um único valor.


Quando olhei seu problema, logo pensei que poderia resolver em poucas linhas, porém eu não tinha certeza EXATAMENTE do que fazer até testar no codepen ali, essa é a magia da tecnologia, poder resolver um problema de muitas formas diferentes, e nessa tentativa de te ajudar, estudei também a utilização desses métodos, obrigado.

Espero que eu possa ter ajudado de alguma forma a ver o problema e espero que tenha compreendida a solução proposta.

Qualquer coisa pode me chamar no Discord quando quiser. Manozzo#6762
Abraços,

Manozzo

1

Opa, show de bola seu programa, eu pensei em fazer algo parecido, eu pensei q se eu passasse o valor para uma string ja de primeira, ele me retornaria um vetor com os algarismos separados, ai dps transformar para inteiro cada indice na hora da soma, porem nao funcionou...
O seu ficou bem otimizado e elegante, obrigado!