Reputation: 131
There is an object with "value" or/and "children" as properties. The problem is to add all the values and return the sum. This is working. I have used recursion. I am using a global variable to store the sum.
Please refer - https://jsfiddle.net/ws6ty78b/1/
function sumup(node) {
sum+=node.value;
if (node.children && node.children.length > 0) {
for (var i =0; i < node.children.length; i++) {
sumup(node.children[i]);
}
}
return sum
}
The problem - While invoking the same function again, I am not getting same result. The sum is doubling. I DO KNOW why it is happening, that is since I am using a global variable.
Question - For the above problem, is there a way I get the same result for any number of invocations.
Please note the restrictions -
1) Do not change the function signature and declaration.
2) Use the 'sum' variable inside the 'sumup' function.
3) Do not use any extra variable.
4) Only make changes within the sumup function.
Upvotes: 2
Views: 1270
Reputation: 370929
You could call
sumup while recursing and assign/test against a custom this
:
var obj = {
"value": 4,
"children": [{
"value": 2,
"children": [{
"value": 1
}]
},
{
"value": 9
}
]
};
var sum = 0;
function sumup(node) {
//Only make change within this function body
if (!this || !this.recurse) sum = 0;
sum += node.value;
if (node.children && node.children.length > 0) {
for (var i = 0; i < node.children.length; i++) {
sumup.call({ recurse: true }, node.children[i]);
}
}
return sum
}
console.log(sumup(obj));
console.log(sumup(obj));
Alternatively, you could do away with the global variable entirely and use a recursive reduce
over the children instead:
var obj = {
"value": 4,
"children": [{
"value": 2,
"children": [{
"value": 1
}]
},
{
"value": 9
}
]
};
const sumup = (node) => (
node.value + (node.children
? node.children.reduce((a, child) => a + sumup(child), 0)
: 0
)
);
console.log(sumup(obj));
console.log(sumup(obj));
Upvotes: 0
Reputation: 4866
In order to accomplish your goal the function sumup()
will be invoked N times. We don't know how much this N is, since it depends on the number of recursions for the children nodes. Also, thanks to the restrictions, we can't edit the function signature and cannot write code elsewhere to do pretty anything, not even manually set sum to 0.
Therefore we need a way to distinguish one bunch of invocations from the NEXT bunch, and reset it.
My idea is we set a threshold, use a closure. From the first invocation, in the example, you have 5 seconds of time to keep calling and afterwards it will start anew. This is really all we can do unless another way to distinguish the invocations is provided.
EDIT: What I was trying here is keep all the recursions as a base case and not altering the object. Since OP has accepted that solution, I am adding a node resetter property. If any node has resetter not defined or null or zero or undefined, this will reset the sum. We must assume it is not defined in the started object. As I said this is kind of a weak assumption. By defining it when recursing, current sum is carried over. I will also keep the original time threshold idea for eventual interest.
var obj = {
"value": 4,
"children": [
{
"value": 2,
"children": [
{
"value": 1
}
]
},
{
"value": 9
}
]
}
const sumup = (function(){
var lastTime = 0;
var newTime = 0;
var sum = 0;
const timeThreshold = 5000; // 5 seconds
return function(node) {
newTime = new Date().getTime();
if(!node["resetter"] || (newTime-lastTime >= timeThreshold)){
sum=0;
lastTime = newTime;
}
sum+=node.value;
if (node.children && node.children.length > 0) {
for (var i =0; i < node.children.length; i++) {
sumup(Object.assign({"resetter":true},node.children[i]));
}
}
return sum;
}
})();
console.log(sumup(obj)); //16
console.log(sumup(obj)); //32! should print 16 everytime
Upvotes: 0
Reputation: 21
You could simply sum the values of each child to the value of the current node:
function sumup(node) {
sum=node.value;
if (node.children && node.children.length > 0) {
for (var i =0; i < node.children.length; i++) {
sum+=sumup(node.children[i]);
}
}
return sum
}
Upvotes: 2