He estado tratando de resolver el siguiente problema en codewars usando recursividad:
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. Por ejemplo (Entrada --> Salida):
39 --> 3 (because 3*9 = 27, 2*7 = 14, 1*4 = 4 and 4 has only one digit) 999 --> 4 (because 9*9*9 = 729, 7*2*9 = 126, 1*2*6 = 12, and finally 1*2 = 2) 4 --> 0 (because 4 is already a one-digit number)Esto es lo que he intentado:
var numOfIterations = 0; function persistence(num) { //code me var i; var digits=[]; var result = 1; if (num.toString().length==1) { return numOfIterations; } else { numOfIterations++; digits = Array.from(String(num), Number); for (i=0;i<digits.size;i++) { result=result*digits[i]; } persistence(result); } }Pero por alguna razón, en lugar de devolver el número de iteraciones, devuelve indefinido. Me han dicho que no estoy usando la recursividad correctamente, pero simplemente no puedo encontrar el problema.
Otras respuestas han explicado lo que está mal con su código. Solo quiero señalar una implementación más simple:
const multiplyDigits = (n) => n < 10 ? n : (n % 10) * multiplyDigits (n / 10 | 0); const persistence = (n) => n < 10 ? 0 : 1 + persistence (multiplyDigits (n)); [39, 999, 4] .forEach (t => console .log (`${t}:\t${persistence (t)}`)); multiplyDigits hace exactamente lo que dice, multiplica recursivamente el dígito final por el número que queda cuando quitas ese último dígito (piensa en | 0 como Math .floor), y se detiene cuando n es un solo dígito.
persistence verifica si ya somos un solo dígito, y si es así, devuelve cero. Si no, sumamos uno al valor que obtenemos cuando recurrimos al múltiplo de los dígitos.
Como @David escribió en su respuesta, te faltaba el retorno de la llamada recursiva a sí mismo.
Además, estaba usando digits.size en lugar de digits.length .
De todos modos, considere que un solo dígito siendo cero colapsará el juego porque eso es suficiente para establecer el resultado en cero a pesar de cuántos dígitos está formado por el número.
Para lidiar con el restablecimiento de numOfIterations , al principio intenté usar function.caller para discriminar entre llamadas recursivas y llamadas directas y establecer la variable en consecuencia. Dado que ese método está en desuso como se muestra aquí:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/caller
Opté por la iteration de argumento opcional que se establece en cero de forma predeterminada, para realizar un seguimiento de ese valor mientras baja la pila de llamadas. Esta solución aún cumple con el hecho de que la persona que llama no necesita conocer una nueva interfaz para que la función funcione.
//var numOfIterations = 0; function persistence(num, iteration=0) { /* Commented strategy using the function.caller working but deprecated so I can't recommend anymore used optional argument iteration instead //gets the name of the caller scope let callerName = persistence.caller?.name; //if it's different from the name of this function if (callerName !== 'persistence') //reset the numOfIterations numOfIterations = 0; */ var digits=[]; if (num.toString().length==1){ return iteration; } else { var result = 1; digits = Array.from(String(num), Number); for (let i=0;i<digits.length;i++) { result = result * digits[i]; } return persistence(result, iteration+1); } } console.log( persistence(39) ); //-> 3 console.log( persistence(999 ) ); //-> 4 console.log( persistence(4) ); //-> 0Me han dicho que no estoy usando la recursividad correctamente
Está recurriendo, pero no está devolviendo el resultado de esa recursión. Imagine por un momento solo esta estructura:
function someFunc() { if (someCondition) { return 1; } else { anotherFunc(); } } Si someCondition es false , ¿qué someFunc() ? Nada. Entonces su resultado es undefined .
Independientemente de cualquier recursión, en su forma más simple, si desea devolver un resultado de una función, debe return :
function persistence(num) { //... if (num.toString().length==1) { //... } else { //... return persistence(result); // <--- here } }