I've been reading a lot about recursive functions recently though I wasn't able to figure this one out until today. I think I now understand recursion better. Hopefully I can help someone else who is still struggeling with it:
function count(n) {
if (n === 1) {
return [1];
} else {
var numbers = count(n - 1);
numbers.push(n);
return numbers;
}
}
console.log(count(3));
The result of count(3) will be: [1, 2, 3]
We pass in 3 into count(n). Since n is not equal to 1 we go straight to the else statement. numbers = count(3 - n) or numbers = count(2) if we pass in n. What happens next is recursion:
Since we don't know what exactly count(2) is we have to run it to figure out. So we run count(2). n is not equal to 1 so we go to the else statement again. numbers = count(1). Recursion again. We put in 1 for n and this time the function returns [1].
Now since we know that count(1) = [1] we are able to solve count(2). count(2) is numbers = count(1) or numbers = [1]. This time we go ahead in our code and push in n numbers.push(n) which is 2. So count(2) returns [1, 2]. Now since we know the result for count(2) let's solve count(3). count(3) is numbers = count(2) or numbers = [1, 2] putting in our result. Now push gets activated and voila, our result for count(3) is [1, 2, 3].
Related
https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/basic-javascript/use-recursion-to-create-a-countdown
We have defined a function called countdown with one parameter (n). The function should use recursion to return an array containing the integers n through 1 based on the n parameter. If the function is called with a number less than 1, the function should return an empty array. For example, calling this function with n = 5 should return the array [5, 4, 3, 2, 1]. Your function must use recursion by calling itself and must not use loops of any kind.
// Only change code below this line
function countdown(n){
if (n<1)
return [];
else{
const numbArray = countdown(n-1);
numbArray.push(n)
return numbArray;
}
}
console.log(countdown(5))
// Only change code above this line
comes out like [1 2 3 4 5] instead of [5 4 3 2 1]
I've been breaking my mind forever then I have completed it with the unshift method but felt like it wanted to me use push even though that sends data to the end of the stack
function countdown(max, currentN) {
if (currentN > max)
return [];
else if (currentN <= max) {
const numbArray = countdown(max, currentN + 1);
numbArray.push(currentN)
return numbArray;
}
}
console.log(countdown(5, 1))
// Only change code above this line
basically it just counts up to the end value given at start
else {
const arr = []
arr.push(n)
return arr.concat(countdown(n-1))
}
you can use this code replace, y question reason is y not understand recursion, try to break the point and watch the function execution step by step in the browser or vscode
function countup(n) {
if (n < 1) {
return [];
} else {
const countArray = countup(n - 1);
countArray.push(n);
return countArray;
}
}
console.log(countup(5));
After running the above code it returns an array: [1, 2, 3, 4, 5], but push() adds new values at the end of an array so when value of n was 5 it should push 5 to the end of the array and when value of n got 4 it should push 4 at the end of the array like [5,4].
So why not it is returning [5,4,3,2,1] ? It is hard to understand what is happening in this code probably because of this recursion. Isn’t unshift() (which add new values to start of the array) should return [1,2,3,4,5] and push() [5,4,3,2,1] why opposite is happening?
As #Joseph stated in a comment the second to last function call would get pushed to the array first, then it would return that array, where it immediately adds the next number up the call stack.
Here are the steps being taken.
Initial call enters itself recursively n times, where the bottom call returns [] and then [1], [1, 2] ... [1, 2, ..., n] all the way up the call stack where upon the first function call ends and the program does something else.
To get [n, ..., 2, 1] you need to use the Array.prototype.unshift() method, which takes any javascript primitive type, ie String, Number, Boolean, and Symbols, in a comma separated format, like countArray.unshift(4, 5) or countArray.unshift(...anotherArray), and adds them to the beginning of the array.
ie
let someArr = [3, 2, 1];
someArr.unshift(5, 4);
console.log(JSON.stringify(someArr));
// outputs [5, 4, 3, 2, 1]
or
let someArr = [1, 2, 3];
let anotherArr = [5, 4]
someArr.unshift(...anotherArr);
console.log(someArr);
// outputs [5, 4, 1, 2, 3]
Where the output of
function countup(n) {
if (n < 1) {
return [];
} else {
const countArray = countup(n - 1);
countArray.unshift(n);
return countArray;
}
}
console.log(countup(5));
will be [5, 4, 3, 2, 1] tested with node in Vscode.
One useful way to think about this is to start by imagining you already had a function that does what you want for lower values, and then see how you would write one that works for higher values. That imaginary function should be a black box. All we should know is that it does what we want in the case of lower values. We don't care about its implementation details.
So lets say we had a function imaginaryBlackBox, and we knew that it returned the correct countUp values that we want. So, for instance, we know that imaginaryBlackBox (4) returns [1, 2, 3, 4].
Now, knowing that, how might we write a function that works for an input of 5 as well? How about something like this:
function countup(n) {
if (n < 1) {
return [];
} else {
const countArray = imaginaryBlackBox(n - 1);
countArray.push(n);
return countArray;
}
}
Again, we don't know how imaginaryBlackBox works. We just know that it returns the correct result for lower values of n. Our base case remains obvious. For another case, some n greater than 0, we call imaginaryBlackBox(n - 1), and by our basic assumption, we know that will return [1, 2, 3, ..., (n - 1)], which we store in countArray. Then we push n onto that array, to end up with [1, 2, 3, ..., (n - 1), n]. We return that value and we're done.
Now here's the trick. We know an implementation of imaginaryBlackBox -- it's the function we're writing! So we can simply replace it with countUp and know it will work.
function countup(n) {
if (n < 1) {
return [];
} else {
const countArray = countUp(n - 1);
countArray.push(n);
return countArray;
}
}
This required a few assumptions, and they are important to all recursive functions:
There is at least one base case whose value we can calculate without any recursive call. Here, when n is < 1, we simply return [].
For other cases, we can break down our problem into one or more recursive cases, where the input is in some clear and measurable way closer to a base case, so that subsequent steps will hit a base case in a finite number of calls. Here we reduce n by 1 on every step, so eventually it will be below 1.
Our function is effectively pure: its outputs depend only on its inputs. That means we can't count on changing a global variable or reading from one that might be changed elsewhere. Note that I use the qualifier "effectively" here; it doesn't matter if this function has observable side-effects such as logging to the console, so long as its output is dependent only on its input.
Anytime you have those conditions, you have the makings of a good recursive function.
I was doing a coding algorithm to find the nth number which is the sum of the (n-1)th and (n-2)th numbers.
Here was the solution
function getNthFib(n, hashTable = {1: 0, 2: 1}) {
if (n in hashTable) {
return hashTable[n]
} else {
hashTable[n] = getNthFib(n - 1, hashTable) + getNthFib(n - 2, hashTable)
return hashTable[n]
}
}
can anyone explain to me in the else block of what is actually happening? i am confused with this recursive concept
Recursive Fibonacci works beacse the next number is the last two numbers combined. Eg 3 + 5 = 8 and then 5 + 8 = 13. The recursive solution finds the value of the 2 numbers to add to the next, and then finds the numbers before, etc. The hashtable, which is a plain object, maps precomputed values so it does not have to compute them again, as recursive Fibonacci has a O(n!) time complexity without a table or cache.
I'm a newbie and would like to create a function that takes in an array and returns only the values that have an odd index. For example, given an array [1, 2, 3, 4], I would like to return 2, 4.
My code currently doesn't return any values and I can't figure out why. Below is my code...any help you can provide would be greatly appreciated.
Thanks!
var odder = function(array) {
var only_odds = []
for (var i = 1; i < array.length; i += 2) {
only_odds.push(array[i])
}
return only_odds
}
//Below I test the code on my console; it returns 'undefined.'
console.log(odder[5, 3, 2, 4, 6])
var odder = function(array) {
var only_odds = array.filter(function(value, index){
//value is the current selected value, while index refers to the current index.
//value will not be used in this function, since we only want to test the index.
return index % 2; // only the odd values will be returned.
});
return only_odds;
}
//encapsuled in parentheses to execute the function. Result will be [3, 4]
console.log(odder([5, 3, 2, 4, 6]));
This updated function is a bit optimized. It uses modulo (%). It tests if the index is odd or even. If odd the modulo operator will return true. array.filter then returns the values with an odd index.
I used Array.prototype.filter here.
Modulo: Returns the remainder of a division. So 5 modulo 2 will give a remainder of 1. Since 2 times 2 = 4 + 1 = 5. The 1 will evaluate as truthy (true) in JavaScript. So odd module 2 will evaluate true while even modulo 2 evaluates false.
I'm going through the interview cake algorithms. This is basically self-assigned homework. I've given it a few goes, and my solution is fairly ugly, but I don't understand why it's not giving me the correct output. Only one loop executes in the algorithm, and I've tried switching the order, as well as other versions along this line.
I'm a little stuck here, and have two questions relating to this algorithm, which I'm trying to complete in straight-up Javascript.
Here's the problem:
You have an array of integers, and for each index you want to find the product of every integer except the integer at that index. Write a function get_products_of_all_ints_except_at_index() that takes an array of integers and returns an array of the products. Do not use division.
The array [1, 7, 3, 4]
Would return:
[84, 12, 28, 21]
By calculating:
[7*3*4, 1*3*4, 1*7*4, 1*7*3]
My overwrought attempt is below:
var l = [84, 12, 28, 21],
products_before_curr_index = 1,
products_after_curr_index = 1,
backwards_index=1,
forwards_index,
product_array = [];
for(var factor=0; factor<l.length; factor++){
forwards_index=factor+1;
while(forwards_index<l.length){
products_after_curr_index*=l[forwards_index];
forwards_index+=1;
}
if(factor>0){
products_before_curr_index *= l[factor-backwards_index];
backwards_index+=1;
}
product_array.push(products_after_curr_index*products_before_curr_index);
backwards_index=1;
products_after_curr_index = 1;
products_before_curr_index=1;
}
This returns [84, 12, 28, 3]
My questions:
Why doesn't this work? Where am I going wrong?
There must be a more elegant way to do this using slice or map. I'm stumped. Can someone give me a hint here?
This one uses map and reduce methods of Array object.
function get_products_of_all_ints_except_at_index(inList) {
var product = function (x, y) { return x * y; };
var lists = inList.map(function (v, i, a) {
return a.slice(0, i).concat(a.slice(i + 1, a.length));
});
return lists.map(function (v, i, a) { return v.reduce(product); });
}
// test case
console.log(get_products_of_all_ints_except_at_index([1, 7, 3, 4]));
Yeah it looks like you have overcomplicated it a bit. The problem description gives you a bit of a hint on how to solve the problem. For each integer in the array, you want to find the product of all the other integers. In other words, you can loop over each item in the array, then loop over each item in the array again (aka, a nested loop) and add up all the products except for the current index of the first array.
For example:
var a = [1, 7, 3, 4];
var b = [];
a.forEach(function( value_1 ) {
var product = 1;
a.forEach(function( value_2 ) {
if ( value_1 != value_2 )
product *= value_2;
});
b.push( product );
});
console.log( b ); // [84, 12, 28, 21]
Your original solution doesn't work because you only ever go back once. You use a while loop to go forward through the entire array to calculate the product of all the elements after, but you only use one single calculation to go backwards:
products_before_curr_index *= l[factor-backwards_index];
So you're only ever getting the product of the value immediately before the current index. You never go back further. If you're wondering, you only happen to get the third value (28) right because the first number is 1 (aka, multiplying by 1 wouldn't have done anything anyway). Try changing that first number to anything that isn't 1 and you'll see that the third calculation also fails.
I didn't particularly liked the solution given by Interview Cake, I felt it was complicated. I may not have the most optimized solution, and I used Numpy which is not clear if we can (but it doesn't say we can't, so...)
It worked for all test cases and I feel it's way more simple/easy to grasp:
` import numpy as np
def get_products_of_all_ints_except_at_index(int_list):
if len(int_list) < 2:
raise IndexError("you need two numbers at least")
products = []
for i in range(len(int_list)):
temp_list = int_list.copy()
del temp_list[i]
prod = np.prod(temp_list)
products.append(prod)
return products