How to carry with result on recursive operation - javascript

If I can't pass an integer by reference how I can carry with the result on this function:
function operation(k, n, result) {
if (k == 0) {
console.log(n);
result += n;
return result;
} else {
//the result variable its back to the old value when the recursions goes back
for (var i = 1; i <= n; i++) {
operation(k - 1, i, result);
}
}
}
console.log('resultado = ', operation(2, 3, 0));
I need to accumulate n value on result when k=0,but result goes back to older values.I'm not sure about how to make it

In JavaScript arguments are passed by value: the result parameter is a separate variable in your recursive function's execution context.
As #Pointy remarked in comments you need to assign the return value back to result. The idea is to return the new value.
That would look like this:
function operation(k, n, result) {
if (k == 0) {
result += n;
} else {
for (var i = 1; i <= n; i++) {
result = operation(k - 1, i, result);
}
}
return result;
}
console.log('resultado = ', operation(2, 3, 0));
Although this works, the more natural way to implement recursion, is to let the recursive call produce a result that is independent from the larger context it is running in: it should not have to know the "result so far". Instead it should return the result as if it was executing the top-level call. It is up to the caller to accumulate the result further.
So with that pattern, you would not pass a result as argument at all:
function operation(k, n) {
if (k == 0) return n;
let result = 0; // we start from scratch
for (var i = 1; i <= n; i++) {
result += operation(k - 1, i); // note the addition here!
}
return result;
}
console.log('resultado = ', operation(2, 3));

Related

Calculate and push fibonacci numbers in an array

let result = [];
function recurseFivonaci(n){
if(n < 2){
return n;
}
return recurseFivonaci(n - 2) + recurseFivonaci(n - 1);
}
console.log(recurseFivonaci(10).map(r => result.push(r)))
TypeError: recurseFivonaci(...).map is not a function
at <anonymous>:16:33
at dn (<anonymous>:16:5449)
How can I push in the result of fibonacci function into an array?
I expect this to work but doesn't:
result = [0,1,1,2,...];
Here's a possible solution
let result=[];
function fibonacci_series(n)
{
if(n === 0){
return [0];
}
if (n===1)
{
return [0, 1];
}
else
{
result = fibonacci_series(n - 1);
result.push(result[result.length - 1] + result[result.length - 2]);
return result;
}
};
console.log(fibonacci_series(10))
Map() is a function available on an Array type in JavaScript and since you're returning a number from your function, it is throwing this error. What you need instead is something like:
let result=[];
function recurseFibonaci (n) {
if(n < 2){
return n;
}
return recurseFibonaci(n-2) + recurseFibonaci(n-1);
}
result.push(recurseFibonaci(10));
console.log(result)
There may be some neato means to achieve it but a basic iteration seems fine?
const arr = [0,1]
for (let i = 0; i < 10; i++) {
arr.push(arr[i] + arr[i + 1]);
}
console.log(arr);

two for loops in js. cannot work on nested for loop

I'm working on a problem below, but not sure why my second for loop does console.log anything. I currently get a result, [], and when I work on loops I sometimes confused because the output returns empty result. So why my second for loop is not executed and why I'm not able to push the result to result array?
Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target.You may assume that each input would have exactly one solution, and you may not use the same element twice.You can return the answer in any order.
Example 1:
Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Output: Because nums[0] + nums[1] == 9, we return [0, 1].
function a(nums, target) {
let result = [];
for (let i = 0; i < nums.length -1; i++){
let firstNum = nums[i];
console.log(i)
for (let j = i + 1; j < nums.length -1; j++){
console.log(j)
let secondNum = nums[j];
let sum = firstNum + secondNum;
if (sum === target) {
return result.push(i, j);
}
}
}
return result;
};
a([2,7,11,15], 9)
Push return only the length of the array, try like below,
function a(nums, target) {
let result = [];
for (let i = 0; i < nums.length; i++){
let firstNum = nums[i];
console.log("i", i)
for (let j = i + 1; j < nums.length; j++){
console.log("j", j)
let secondNum = nums[j];
let sum = firstNum + secondNum;
if (sum === target) {
result.push(i, j);
return result;
}
}
}
return result;
};
let result = a([2,7,11,15], 9);
console.log(result);
Your code is actually correct except for the fact that you are returning the result of result.push(i, j) which returns the length of the array.
Use result.push(i, j); and then return result;
Instead of just return result.push(i, j);
Consider breaking the problem down into smaller parts -
t generates unique combinations of numbers
a steps thru the generator searching for the first valid solution
function* t(n, i = 0, p = [])
{ if (p.length >= 2)
yield p
else if (i >= n.length)
return
else
( yield* t(n, i + 1, [...p, n[i]])
, yield* t(n, i + 1, p)
)
}
function a(n, q)
{ for (const [a, b] of t(n)) // <- step thru t
if (a + b == q) // <- simple condition
return [a, b] // <- solution
}
const result =
a([2,7,11,15], 9)
console.log(result)
Output -
[2, 7]
a will return undefined if the answer cannot be reached

Algorithm to find all possible arrays of max size L that sum up to N or less

I want to find all possible arrays -of non-negative numbers- that sum up to -at most- N in JavaScript:
function findArrays(maxSize, maxSum){}
Example input: findArrays(3, 10)
Some acceptable outputs: (not writing all as it would be too long)
[[0], [0,0,0], [10,0,0], [1,9], [1,2,3] /*, ... */]
What I tried so far:
I know it looks like homework but it's not :) I can think of a solution that simply generates all (size*maxSum) possible arrays of acceptable sizes and then iterate through them to check if sum is greater than maxSum. However, I think this solution is very bad in terms of performance as maxSum gets bigger. I'm looking for a more efficient implementation but I just don't know where to start.
My "bad" solution
function getNextArray(r,maxVal){
for(var i=r.length-1;i>=0;i--){
if(r[i]<maxVal){
r[i]++;
if(i<r.length-1){
r[i+1]=0;
}
break;
}
}
return r;
}
function getAllArraysOfSize(size, maxVal){
var arrays=[],r=[],i;
for(i=0;i<size;i++){
r[i]=0;
}
while(r.reduce((a, b) => a + b, 0) < (maxVal*size)){
r = getNextArray(r.slice(),maxVal);
arrays.push(r);
}
return arrays;
};
function findArrays(maxSize, maxSum){
var allArrays=[],arraysOfFixedSize=[],acceptableArrays=[],i,j;
for(i=1; i<=maxSize; i++){
arraysOfFixedSize=getAllArraysOfSize(i,maxSum);
for(j=0; j<arraysOfFixedSize.length; j++){
allArrays.push(arraysOfFixedSize[j]);
}
}
for(i=0; i<allArrays.length; i++){
if(allArrays[i].reduce((a, b) => a + b, 0) <= maxSum){
acceptableArrays.push(allArrays[i]);
}
}
return acceptableArrays;
};
You can use recursion and a generator. The number of outputs grows quickly for higher valued arguments, so I keep them low here:
function * findArrays(maxSize, maxSum) {
let arr = [];
function * recur(maxSum) {
let k = arr.length;
yield [...arr]; // or: if (k) yield [...arr]
if (k === maxSize) return;
for (let i = 0; i <= maxSum; i++) {
arr[k] = i;
yield * recur(maxSum - i);
}
arr.length = k;
}
yield * recur(maxSum);
}
// demo
for (let arr of findArrays(2, 4))
console.log(JSON.stringify(arr));
NB: this also produces the empty array, which makes sense. If you want to avoid this, then just check that you don't yield an empty array.
If you prefer working with plain functions instead of generators, then translate the innermost yield expression to a push unto a result array, as follows:
function findArrays(maxSize, maxSum) {
let arr = [];
let result = []; // <--- will collect all the subarrays
function recur(maxSum) {
let k = arr.length;
result.push([...arr]);
if (k === maxSize) return;
for (let i = 0; i <= maxSum; i++) {
arr[k] = i;
recur(maxSum - i);
}
arr.length = k;
}
recur(maxSum);
return result;
}
// demo
for (let arr of findArrays(2, 4))
console.log(JSON.stringify(arr));
i hope this is helpful
const data = [[0],[0,0,0],[10,0,0],[1,9],[1,2,3]];
function findArrays(maxSize, maxSum){
return data.reduce(
(acc, value) => {
if (value.length <= maxSize) {
const tempValue = value;
const sum = tempValue.reduce((acc, val) => val >= 0 ? acc + val : 0, 0);
if (sum <= maxSum && sum > 0) acc.push(value);
}
return acc
}, []
)
}
console.log(findArrays(3, 10));

Sum all numbers in array function not returning the sum

I am trying to create a function that sum all numbers in an array! I am new to JavaScript and in need of someone pointing me in the right direction!
function sum(arr) {
var i = 0;
for (var index = 0; index < arr.length; index++) {
return index += arr[i];
}
}
sum([1, 2, 3]); //6
Lots of basic issues with the code.
You need a separate variable to accumulate the result in. Your code is writing into the index variable of a for loop. This is wrong for a number of reasons.
You also return after the first iteration of the loop.
Assuming you want to use a for loop (which is not the least amount of code),
function sum(arr) {
var sum = 0;
for (var index = 0; index < arr.length; index++) {
sum += arr[index];
}
return sum;
}
Use Array.reduce() for that:
function getSum(ary){
return ary.reduce(function(sum, value) {
return sum + value;
}, 0);
}
console.log(getSum([0, 1, 2, 3]));
to illustrate where your code is wrong
function sum(arr) {
var i = 0;
for (var index = 0; index < arr.length; index++) {
return index += arr[i]; // this will return from your function in the first iteration
}
}
as the comment says, return will exit your function in the first iteration
also, you're adding to index, which is supposed to be the index into the array, you want to add to i, and then return i after the loop
so, the code should be
function sum(arr) {
var i = 0;
for (var index = 0; index < arr.length; index++) {
i += arr[index];
}
return i;
}
As another answer pointed out, a probably better alternative is to use array reduce function - however the code in that answer is not the "best" usage of reduce
function getSum(ary){
return ary.reduce(function(sum, value) {
return sum + value;
}, 0);
}
can actually be written
function getSum(ary){
return ary.reduce(function(sum, value) {
return sum + value;
});
}
This uses one less iteration, because there is no "initial value", and the first iteration adds index 0 and 1 together
Sure, it's not going to make a performance difference, but why not use built-in functions properly :p
function Sum(arr) {
var sum = 0;
for (var index = 0; index < arr.length; index++) {
sum += arr[index];
}
return index;
}
Sum([1, 2, 3]); //6
Return immediately exits a function. Your code will never sum values. What is 'i' in your code!?! And what index do!?
Here's how you get your function to work:
function sum(arr) {
// this is the variable we're going to add our numbers onto
var acc = 0;
for (var index = 0; index < arr.length; index++) {
// don't return here, return is used to return from a function
acc += arr[index];
}
// after adding all numbers, return the sum
return acc
}
sum([1, 2, 3]); //6
But there are built in ways to do this, like Array.reduce() like Scott Marcus mentioned.

Counting number of occurrences recursively

Why is this recursive countOccurence function not working? this has a subroutine. is there a way to do it without a subroutine? it seems in javascript you have to have a closure (subroutine function) for the counter variable, otherwise it gets rewritten every time!
function numOccurencesRecursive(arr, val) {
//base case. check it if it only has a length of 1
var count = 0;
function doCount(arr, val) {
if (arr[0] === val) {
count++;
} else {
count += doCount(arr.slice(1), val)
}
return count;
}
return doCount(arr, val);
}
console.log(numOccurencesRecursive([2, 7, 4, 4, 1, 4], 4)); // should return 3 but returns 1
I think the problem is that you were thinking iteratively but used a recursive approach.
The iterative approach has a global variable which may be updated at each step:
function numOccurencesIterative(arr, val) {
var count = 0;
for(var i=0; i<arr.length; ++i) if(arr[i] === val) ++count;
return count;
}
However, when using recursive approaches, better avoid global variables.
function numOccurencesRecursive(arr, val) {
if(!arr.length) return 0;
return (arr[0] === val) + numOccurencesRecursive(arr.slice(1), val);
}
This should definitely do with all the nests with recursion:
function countItems(arr, item) {
var count = 0;
for (var i=0; i<arr.length; i++){
if (typeof(arr[i]) == typeof([])){
count += countItems(arr[i], item);
}
else{
if(typeof(arr[i]) != typeof([])){
if (arr[i] === item){
++count;
}
}
}
}
return count;
}
doCount stops recursing once it finds a match; hence, it will never find more than 1 match to count.
So, what you are doing is that you are incrementing the count only when you find the value, and when you do find it, your recursive function ends, but its the other way around, which means you have to count for unfound elements in the array and if you find something, increment it and then if the array is empty, return the count.
Code:
function numOccurencesRecursive(arr, val) {
//base case. check it if it only has a length of 1
var count = 0;
function doCount(arr, val) {
if (arr[0] === val) {
count++;
} else if (!arr.length) {
return count;
}
return doCount(arr.slice(1), val);
}
return doCount(arr, val);
}
console.log(numOccurencesRecursive([2, 7, 4, 4, 1, 4], 4)); // should return 3 but returns 1

Categories