Quiero usar la recursividad para encontrar el rango de un entero dado por un paso específico.
given number --> -20 step --> 4 returns --> [ -20, -16, -12, -8, -4, -2, 0, 2, 4 ]Hasta ahora, pude crear una función recursiva para devolver los resultados correspondientes:
function range(num,step,res=[]) { const s = num < step ? step : -step; if (num === step + s) return res; return num === step ? [...res,num] : range(num+s,step,[...res,num]); } console.log(range(5,1)); // [ 5, 4, 3, 2, 1 ] console.log(range(-8,2)); // [ -8, -6, -4, -2, 0, 2 ] console.log(range(-20,4)); // [ -20, -16, -12, -8, -4, -2, 0, 2, 4 ]Sin embargo, las siguientes invocaciones devuelven stackoverflow
console.log(range(-7,2)); // stackoverflow! console.log(range(11,5)); // stackoverflow!Sé que algo está mal con el código, pero simplemente no pude averiguar qué es. ¿Puede alguien amablemente indicarme la dirección correcta o mostrarme qué estoy haciendo mal? Millones de gracias de antemano :)
ACTUALIZAR:
Gracias al flujo de control de TazHinkle pude resolver el problema de la siguiente manera:
function range(num,step,res=[]) { const s = num < step ? step : -step; if (num > step && num < step) return res; if (num < step && num + s > step) return [...res,num]; return num === step ? [...res,num] : range(num+s,step,[...res,num]); } console.log(range(5,1)); // [ 5, 4, 3, 2, 1 ] console.log(range(-8,2)); // [ -8, -6, -4, -2, 0, 2 ] console.log(range(-20,4)); // [ -20, -16, -12, -8, -4, 0, 4 ] console.log(range(11,5)); // [ 11, 6, 1 ] console.log(range(-7,2)); // [ -7, -3, -5, -1, 1 ] console.log(range(-9,4)); // [ -9, -5, -1, 3 ]El rango de casos (-7,2) no puede resolverse en la versión actual porque se moverá infinitamente entre 1 y 3 (porque está avanzando en 2 e intentando llegar a 2, pero nunca lo hará). Puedes hacer que se rinda cuando pasa con algo como esto:
function range(num,step,res=[]) { const s = num < step ? step : -step; const forward = num < step ? true : false; if (num === step + s) return res; if(forward) { if(num + s > step) { return [...res,num] } return num === step ? [...res,num] : range(num+s,step,[...res,num]); }else { if(num + s < step) { return [...res,num] } return num === step ? [...res,num] : range(num+s,step,[...res,num]); } }Esto es bajo el supuesto de que su objetivo es comenzar en el primer parámetro y luego bajar hasta que el último número sea 0, 1 o -1 (básicamente lo más cerca posible de cero).
Primero, en lugar de invertir el step hacia/desde neg/pos, convierta neg a pos y establezca una bandera para los pasos neg:
if (num < 0) { n = Math.abs(num); neg = true; } else n = num;Elimine este paso adicional que no dejaba forma de que los parámetros impares se detuvieran:
if (num === step + s) return res;
La única diferencia en esta línea es < en lugar de === . Eso acercará los números impares a 0 y los números pares a cero:
let result = n < step ? [n, ...res] : rangeToZero(n -step, step, [n, ...res]); Finalmente, si neg == true hacemos que cada número sea negativo (se siente como hacer trampa):
if (neg) { return result.map(N => -Math.abs(N)); } function rangeToZero(num, step, res=[]) { let n, neg = false; if (num < 0) { n = Math.abs(num); neg = true; } else n = num; let result = n < step ? [n, ...res] : rangeToZero(n -step, step, [n, ...res]); if (neg) { return result.map(N => -Math.abs(N)); } return result; } console.log(rangeToZero(5,1)); // [ 5, 4, 3, 2, 1, 0 ] console.log(rangeToZero(-8,2)); // [ -8, -6, -4, -2, 0 ] console.log(rangeToZero(-20,4)); // [ -20, -16, -12, -8, -4, 0 ] console.log(rangeToZero(10, 3)); // [ 10, 7, 4, 1 ] console.log(rangeToZero(-7,2)); // [ -7, -3, -5, -1 ] console.log(rangeToZero(11,5)); // [ 11, 6, 1 ]