Reputation: 1088
I am performing a simple recursion and I am noticing that the logic which holds the recursion is being called even with a false parameter at the return
ternary
rule statement.
This little recursion will do the following:
a
is smaller than 100a
is bigger than 100
, call the function with the sliced array
and increase vol
.In this case, the result if I call nSVol(nSm2, 0)
should be 4
.
I have noticed that it works well, until, after the last recursion, the arr
is 70
, arr
length is 1
and vol
is 4. Somehow, at this point of the recursion, even though I state that when the length
equals 1 return vol + 1
, the function is called once more, with the last snapshot of the arr
, which in this case is [55, 70]
and at the very end, vol
is the result of its own value, plus the value of arr
, which result in 73
.
What am I doing wrong?
const nSm2 = [20, 55, 13, 20, 55, 13, 70];
function nSVol(arr, vol) {
return arr.length === 1
? vol + 1
: arr
.sort((a, b) => a - b)
.reduce((a, b, i) =>
a + b < 100 ? a + b : nSVol(arr.slice(i), vol + 1)
);
}
Upvotes: 0
Views: 44
Reputation: 50807
Another fairly clean approach is the following more traditional recursive version:
const nSVol = (arr) => {
const recur = ([x, ...xs], sum, vol) =>
x == undefined
? vol
: sum + x < 100
? recur (xs, sum + x, vol)
: recur (xs, x, vol + 1)
return recur (arr .sort ((a, b) => a - b), 0, 1)
}
const nSm2 = [20, 55, 13, 20, 55, 13, 70];
console .log (nSVol (nSm2)) //=> 4
We can easily convert it to one which collects the lists of numbers summing to below 100 rather than just counting them, with a version like this:
const breakdown = (arr) => {
const recur = ([x, ...xs], sum, current) =>
x == undefined
? current
: sum + x < 100
? recur (xs, sum + x, [...current.slice(0, -1), [...current[current.length - 1], x]])
: recur (xs, x, [...current, [x]])
return recur (arr .sort ((a, b) => a - b), 0, [[]])
}
console .log (breakdown ([20, 55, 13, 20, 55, 13, 70]))
//=> [[13, 13, 20, 20], [55], [55], [70]]
This latter version could be made cleaner by using some simple reusable helper functions:
const init = (xs) => xs .slice (0, -1)
const last = (xs) => xs [xs .length - 1]
//...
: sum + x < 100
? recur (xs, sum + x, [...init (current), [...last (current), x]])
or a dedicated helper function:
const appendToLast = (x, xss) =>
[... xss .slice (0, -1), [...xss [xss.length - 1], x]]
// ...
: sum + x < 100
? recur (xs, sum + x, appendToLast(x, current))
Upvotes: 0
Reputation: 35560
The issue with your code is that the reduce
keeps going after it passes 100, which means that you end up having a lot of repeated calculations that don't need to happen. Instead of using reduce
, just use a loop (yes, recursive functions can still have loops in them) to find when you first pass 100. Also, you don't need to sort every time, so you can just put the recursive part in a helper function:
function nSVolHelper(arr, vol) {
let sum = 0;
for (let i = 0; i < arr.length; i ++) {
if (sum + arr[i] < 100) {
sum += arr[i];
} else {
return nSVolHelper(arr.slice(i), vol + 1);
}
}
return vol + 1;
}
function nSVol(arr) {
return nSVolHelper(arr.sort((a, b) => a - b), 0);
}
Upvotes: 1