I am trying to simply find recursion factorial
function factorial(num, result) {
console.log('num', num)
if (num === 0) {
console.log('res ', result);
return result;
} else {
result = result * num;
console.log(result)
factorial(--num, result);
}
}
let res = factorial(3, 1)
console.log(res)
It is giving undefined, not sure why, need some help.
plnkr
Bside the missing return statement, some annotations:
Use a default value for the result. This enables to call the function without given a starting value and allows touse only a single parameter.
Take only one early exit of the recursive call, without using else in combination with return. The return statement omits the following else statement. Just go on with the code without an else part.
Return at the end of the function a recursive call to allow to use the compiler to take a TCO (tail call optimization). This wotks without extending the stack, because the last call is replace with the actual recursive call. This optimization may not actually implemented.
Do not use decrement operators, if you need only the reduced value without using the reduced value again.
Move the calculation into the function call.
function factorial(num, result = 1) {
console.log('num', num);
if (num === 0) return result;
return factorial(num - 1, result * num);
}
console.log(factorial(3))
Related
I'm trying to use the factorial function with memoization. I have taken the max value from the object to reduce the number of recursive calls made. But the problem is the first call is I don't know whether this is optimized or not since the first call is pretty expensive. Any insights on this will be great.
let cache = {0: 1};
function factMemoize(key) {
if (!cache[key]) {
let maxVal = Object.keys(cache).reduce(function (a, b) {
return Math.max(a, b);
});
console.log(maxVal);
while (key >= maxVal) {
cache[key] = key * factMemoize(key - 1);
maxVal++;
}
}
return cache[key];
}
You don't buy much from memoizing this since you only use each value once. After you've called the function you do have the cache for a second call, but we often think of memoizing as something that happens in a cache that only exists during the function. For something like that, calculating Fibonacci numbers is a classic example where memoizing is a huge improvement over the naive recursive function.
Having said that, in your function it's not clear why you are using an object for your cache and then searching it. You can just use an array where the indexes will be the number you're looking for calculate. You don't need to search it, just start with the number and recursively call the next lower one. If there's a cache it, it will return. For example:
let cache = [1];
function factMemoize(key) {
if (!cache[key]) {
cache[key] = key * factMemoize(key - 1)
} else { // just to demo cache:
console.log("cache hit:", key)
}
return cache[key]
}
// only hits cache at the end
console.log("6! = ", factMemoize(6))
// second call benefits from cache:
console.log("8! = ", factMemoize(8))
Factorial Memoization using Closure
As #mark-meyer mentioned in this thread, there is no advantage coming from memoizing the results since each value will be calculated only one time during computation. The solution Mark offered is great for reusing the function in a later time by re-calling factorials with same or different values. In that case, you can speed up the process and reduce the time complexity by reusing existing results.
Here is how it can look like in a closure:
function factorialFn() {
const cache = [];
return function _factorial() {
if (n < 2) {
return 1;
}
if (cache[n]) {
return cache[n];
}
return cache[n] = n * _factorial(n - 1);
}
}
Then, you can use it like so:
const factorial = factorialFn();
factorial(5); // 120
factorial(7); // 5040
At the first call, it will calculate `factorial(5)` and save it in cache for future reference.
At the second call, `factorial(7)` will execute `7 * factorial(6)`, which `factorial(6)` is basically `6 * the cached value of factorial(5)`
let cache = {};
function factorial(n) {
if (n < 2) return 1;
if (n in cache) return cache[n];
return cache[n] = n * factorial(n - 1);
}
factorial(5); // it will store values in cache from 2-5
factorial(7); // for this it would not compute till 5(from cache)
I don't have much practice with recursion and I have only some experience with javascript.
How do I refactor the code below to use recursion instead of the for loop?
function add(a, b) {
var sum = 0;
for (var i = a; i <= b; i++) {
sum += i;
}
return sum;
}
console.log(add(3,7)); //25
The for loop makes sense to me; recursion not so much.
EASY WAY:
function recursive(a, b)
{
if(a > b)
{
return 0;
}
return a + recursive(a+1, b);
}
console.log(recursive(3,7));
HARD WAY: (EASY + EXPLANATION)
What is a recursion in a common programming language?
according to Wikipedia: Recursion in computer science is a method where the solution to a problem depends on solutions to smaller instances of the same problem (as opposed to iteration).
translated in everyday language a recursion is when you iterate n-times a function(in this case) and every time that the function call hisself wait for the result of the invoked function's instance.
The invoked functions's intance will invoke himself another time and wait for the result.
When this endless loop will stop?
When an instance will finally return a value, this happens typically with a check before the recursive call(see the easy way).
When a function will return a value all the knots will be loose and the first function that started the cycle will return the final value.
if you want to go deep or just my short explanation was not convincing i reccoment you to read this article: https://www.codecademy.com/en/forum_questions/5060c73fcfadd700020c8e54
You could use another parameter for the sum of the last call, for a later tail call optimisation of the recursive call.
At start, initialize s which keeps the summed result and add a.
The perform an exit check, if the target value is reached, then exith with the sum s.
Otherwise call the function again with reduced start value, given end value and the actual sum of all.
Don't forget to return the value of the call.
function sum(a, b, s) {
s = s || 0;
s += a;
if (a === b) {
return s;
}
return sum(a + 1, b, s);
}
console.log(sum(3, 7));
Without tail optimization, this keeps all intermediate results in stack.
function sum(a, b) {
if (a === b) {
return a;
}
return a + sum(a + 1, b);
}
console.log(sum(3, 7));
I need to find the sum of integers in an array using recursion.
The following code throws an error :
var sum = function(array) {
if(array.length === 0) return 0;
while(array.length) {
sum = array[0] + sum(array.slice(1));
return sum;
}
}
while this works :
var sum = function(array) {
if(array.length === 0) return 0;
while(array.length) {
return array[0] + sum(array.slice(1));
}
}
The difference is the way the sum is returned. Can someone explain?
As mentioned in comments, the while loop never loops - it executes a return statement before testing the loop condition a second time.
Even so, why does the first version work the first time it is called but not the second?
sum = array[0] + sum(array.slice(1));
stores the right hand expression value in sum, after the function call to sum returns. That variable is in scope, so the assignment is valid.
But the assignment doesn't occur until after the call to sum (on the right hand side) returns. Each time sum returns, assignment overwrites the variable sum with the partial, and eventually the final result.
So the first call works successfully, but leaves sum set to the result of the first call. Since you can't call a number, it errors the second time you call it.
I posted a question not too long ago this morning regarding a kata that I was trying to solve. In that question, (found here if interested Kata Question) I needed to add a return statement to my function so that I would avoid the following error Value is not what was expected.
Now I have my second iteration of my kata solution to try out and here it is:
function isMerge(s, part1, part2) {
var pointer = 0
splitString = s.split('');
splitString.forEach(function(character) {
if (part1.includes(character) || part2.includes(character)) {
pointer++;
return true;
} else {
return false;
}
});
}
isMerge('codewars','cdw','oears')
I am still getting Value is not what was expected errors when I try to execute the code and this time I'm confused as to why in particular this happens.
For starters, taken from the MDN guide
The return statement ends function execution and specifies a value to be returned to the function caller.
expression
The expression to return. If omitted, undefined is returned instead.
Look at my if/else logic I am specifying a return true and return false condition in my forEach loop to see if all the chars from part1 and part2 are in the string. I am returning something so why is it that I have a Value is not what was expected?.
Second of all, by definition of the return statement, the function is supposed to stop when it reaches that keyword. However, when I place a console.log(character) in the logic, I can see on my console that all of the characters are being outputted so the function is not breaking at all when return true is executed. Why is that?
Third, I am confused as to when to use the return keyword in general. Consider these examples from the MDN docs for ForEach.
Example 1:
function logArrayElements(element, index, array) {
console.log('a[' + index + '] = ' + element);
}
// Notice that index 2 is skipped since there is no item at
// that position in the array.
[2, 5, , 9].forEach(logArrayElements);
// logs:
// a[0] = 2
// a[1] = 5
// a[3] = 9
Example 2:
function Counter() {
this.sum = 0;
this.count = 0;
}
Counter.prototype.add = function(array) {
array.forEach(function(entry) {
this.sum += entry;
++this.count;
}, this);
// ^---- Note
};
var obj = new Counter();
obj.add([2, 5, 9]);
obj.count
// 3
obj.sum
// 16
Not a single return statement to in these examples.
Now look at this .every example.
function isBigEnough(element, index, array) {
return element >= 10;
}
[12, 5, 8, 130, 44].every(isBigEnough);
And finally, from my previous question, I need to add a second return statement like this to avoid the value error.
function isBigEnough(element, index, array) {
return element >= 10;
}
function whenToUseReturn(array) {
return array.every(isBigEnough);
}
whenToUseReturn([12, 5, 8, 130, 44]);
So....... in conclusion, for my original function that started this how am I supposed to exit the loop when I reach false and return it and likewise when all the characters are in the string, how do I return a 'cumulative' true and avoid a Value error. I hope this makes sense and I can clarify with edits to better illustrate my point.
I am returning something so why is it that I have a Value is not what was expected?.
The return statement returns from the callback you pass to forEach, not from isMerge. return statements don't cross function boundaries. isMerge doesn't contain a return statement, hence it returns undefined. If we rewrite the function slightly it might become clearer:
function doSomething(part1, part2) {
return function(character) {
if (part1.includes(character) || part2.includes(character)) {
return true;
} else {
return false;
}
}
}
function isMerge(s, part1, part2) {
splitString = s.split('');
splitString.forEach(doSomething(part1, part2));
}
isMerge('codewars','cdw','oears')
This is equivalent to your code. As you can see, there is no return statement in isMerge.
Not a single return statement to in these examples.
There are no return statements in the forEach examples because forEach doesn't do anything with the return value of the callback, so there is no point in returning anything.
forEach is just a different way to iterate over an array, but it doesn't produce a value like reduce or every.
how am I supposed to exit the loop when I reach false and return it and likewise when all the characters are in the string, how do I return a 'cumulative' true and avoid a Value error.
You cannot exit a forEach "loop". If you have to stop the iteration early, you need to use a normal for (for/in, for/of) loop.
To return and produce a value, you can use your original solution that uses every.
My friend, since you decided to go the "callback way" using .each and the like, you should consider using callbacks, since you cannot return anything in this case. If you do not wish to go the callback way, just use standard javascript, such as:
splitString.forEach(function(character) {
Replace with
for(var i = 0 ; i < splitString.length; i++){
And now you can return. Using "each" to loop an array is just plain unnecessary and prevents you to return.
I am trying to learn recursive functions in JS but for some reason the result is undefined I want to alert (4,3,2,1,0) respectively.
function someFun(number) {
if (number < 0) {
return 1;
}
else {
alert(number = someFun(number - 1))
}
}
someFun(4)
Your function only has one return statement in it. When the else path of the if statement is taken, nothing is returned.
That said, you really don't need a return value because you just want the sequence of numbers printed (in descending order):
function someFun(number) {
if (number >= 0) {
alert(number);
someFun(number - 1);
}
}
someFun(4);
If you want the numbers printed in ascending order, you'd just reverse the order of the alert() and the recursive call.