I want to use recursion to find the range of a given integer by a specified step.
given number --> -20
step --> 4
returns --> [ -20, -16, -12, -8, -4 ]
Thus far, I was able to create a recursive function to return the corresponding results:
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 ]
However, the following invocations returns stackoverflow
console.log(range(-7,2)); // stackoverflow!
console.log(range(11,5)); // stackoverflow!
I know something is wrong with the code, but I just couldn't figure out what it is. Can someone kindly point me in the right direction or show me what I'm doing wrong. Million thanks in advance :)
CodePudding user response:
The case range(-7,2) cannot resolve in the current version because it will infinitely step between 1 and 3 (because it's stepping by 2 and trying to arrive at 2, but it's never going to). You can make it give up when it goes past with something like this:
function range(num,step,res=[]) {
const s = num < step ? step : -step;
const forward = num s < step ? true : false;
if (num === step s) return res;
if(forward) {
return num >= step ? [...res,num] : range(num s,step,[...res,num]);
}else {
return num <= step ? [...res,num] : range(num s,step,[...res,num]);
}
}
CodePudding user response:
This is under the assumption that your goal is to start at the first parameter then step down until the last number is 0, 1, or -1 (basically as close to zero as possible).
First, instead of flip-floping the step
to/from neg/pos, convert neg to pos and set a flag for neg steps:
if (num < 0) {
n = Math.abs(num);
neg = true;
} else n = num;
Remove this extra step which left no way for odd numbered parameters to stop:
if (num === step s) return res;
The only difference in this line is <
instead of ===
. That'll take odd numbers closer to 0 and even numbers to zero:
let result = n < step ? [n, ...res] : rangeToZero(n -step, step, [n, ...res]);
Finally, if the neg == true
we make each number a negative (it feels like cheating):
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 ]