Resolví kata en codewars. De hecho, hice esto por accidente y no entiendo por qué funciona este código. ¿Puedes explicarlo?
Cata:
Escribe una función, persistencia, que tome un parámetro positivo num y devuelva su persistencia multiplicativa, que es el número de veces que debes multiplicar los dígitos en num hasta llegar a un solo dígito.
39 --> 3 (porque 3 9 = 27, 2 7 = 14, 1*4 = 4 y 4 tiene un solo dígito)
Mi solución:
function persistence(num) { let count = 0; const arr = [...num.toString()]; const sumArr = arr.reduce((res, val) => (res *= val)); if (arr.length > 1) { **// Why? How this line works? // Why it doesn't crashes? // Why it returns correct counter value and calls the function?** count += 1 + persistence(sumArr) } return count; } persistence(39); //3Por que si me gusta esto, el contador no guarda el resultado:
if (arr.length > 1) { count += 1 persistence(sumArr) }Básicamente, la función de persistence(sumArr) actúa como una función recursiva y devuelve el recuento de 0 para una condición base que es cuando el número es de un solo dígito.
Para 39, el conteo es 1+persistence(27)
Para 27, el conteo es 1+persistence(14)
y para 14, 1+ persistence (4) que no es más que 1+0 y recursivamente suma 3
count es una variable local, solo accesible dentro del alcance de persistence() , por lo que cuando hace un bucle recursivo, crea una nueva variable llamada count pero está en un nuevo alcance, el método que llamó, simplemente tiene el mismo nombre que persistence() .
Sería totalmente diferente si count fuera una variable global, fuera del alcance del método.
let count = 0; function persistence(num) { ... } Llamar a persistence() nuevamente dentro de persistence() usaría la misma variable, no una nueva.
¡Esto es recursión!
Cada vez que la persona que llama llama a una función, esa función (también conocida como destinatario) se inserta en la pila de llamadas. Todos los argumentos, las variables locales necesarias para esa función están presentes allí. Esto también se conoce como marco de pila. El destinatario de la llamada se saca de la pila cuando vuelve a la persona que llama.
En su caso, tanto la persona que llama como la persona que llama tienen la misma función. Esto se llama recursividad. Durante la recursividad, las variables locales de esa función no se comparten. Se configura un nuevo marco de pila para cada destinatario.
if (arr.length > 1) { count += 1 persistence(sumArr) }Aquí, el conteo que está devolviendo el destinatario de la llamada no se suma con el conteo de la persona que llama.
Si visualizamos lo que está pasando entonces:
persistence(37) = 1 + persistence(27) = 1 + 1 + 1 + 0 // [putting value returned from persistence(27)] persistence(27) = 1 + persistence(14) = 1 + 1 + 0 // [putting value returned from persistence(14)] persistence(14) = 1 + persistence(4) = 1 + 0 // [putting value returned from persistence(4)] persistence(4) = 0