what does the code bellow does in javascript explanation? - javascript

function power(a,b){
return b--?a*power(a,b):1;
}
I don't understand that line of code b--?a*power(a,b):1
a function that returns the power of a number without using any math function like power(a,b) of a ** b

It'll be clearer if you move the b-- to its own line. Assuming that b is a positive integer, the code is equivalent to:
function power(a,b){
const bBeforeDecrement = b;
b--;
return bBeforeDecrement !== 0
? a * power(a,b)
: 1;
}
power recursively calls itself, multiplying the ultimate return value by a each iteration, decrementing b and recursively calling itself until b reaches 0.
At the end, the return value is a multiplied by itself b times.
Like the comment notes, the reassignment of b makes things more confusing than it needs to be - it would make more sense to subtract 1 from b in the recursive call instead:
function power(a,b){
return b > 0
? a * power(a, b - 1)
: 1;
}

Related

Simple JavaScript Function that returns the parameter of greater value

I'm learning how to build functions and my task is to create a function declaration that will return the parameter of greater value. So far, I've only learned how to sums and products -- in other words, I don't know how to get JavaScript to "decide" which parameter is greater.
The extact task description is as follows: Build a function declaration called maxOf2 that takes in two numbers and returns the greater value. Be careful to think about the possibility of equality as well and return one of the numbers.
I've read about Math.max(), but as the course hasn't covered that, I'm not supposed to use it.
Here is what I have so far, which is not much:
function maxOf2(a, b) {
var a = 12;
var b = 4;
return ...;
}
Very basic example:
function maxOf(a, b){
if(a > b){
return a;
} else {
return b;
}
}
You can use that Math.max() function like so:
Math.max(a, b);
And another example that uses ternary operator:
function maxOf(a, b){
return a > b ? a : b;
}
Another answer because there are only 3 answers:
const maxOf = (a,b) => (a > b ? a : b);

Calling function name inside function

There are some concept I still cannot figure out in Javascript. Like this one for example. I came across this code while searching for a function to return the greatest common divisor of two integers. I tested it but I can't understand how this returns the gcd. Please can explain anyone who understand explain what does return gcd(b, a % b); do here?
var gcd = function(a, b) {
if ( ! b) {
return a;
}
return gcd(b, a % b);
};
You are using a recusion, which is a pattern of calling the same function again with different paramters until an exit condition is found and then the recursion stops.
// exit condition
if (!b) {
return a;
}
In this case the function is called again with moved parameter b as a and a new parameter of b with a modulo b.
// call function again with different parameters
return gcd(b, a % b);

Where does this function gets its values?

This is an example from a book. The function returns TRUE if even and FALSE if not. I don't understand how it works. This is what I understand:
42 binds to n
Creating "even" function
x binds to n which = 42
x != 0
initiating "else"
creating "odd" function
odd(42 - 1)
Initiating "!even(41)".
What does JS do with "even(41)"? where TRUE comes from? The way I understand it should return TRUE only when x === 0
document.write(
((n) => {
const even = (x) => {
if (x === 0) return true;
else {
const odd = (y) => !even(y);
return odd(x - 1);
}
}
return even(n)
})(42)
)
It's intentionally confusing. Follow the logic.
If n is not 0, we create a new function called odd which calls even and reverses the boolean value of even.
We then call that function with n-1.
So essentially, it's like a while loop where you keep subtracting 1 from the number and reversing its truthiness or falsiness on each step deeper, until you have a 0. If the function is called an even number of times, it's even. If it's called an odd number of times, it's odd.
The following code performs the same logic as the book example, including use of recursion, but prevents an infinite loop if isEven is called with a non integral or negative value.
const isEven = (n) =>
{
const even = (x) => x ? !even(x-1) : true;
return even( Math.abs(Math.floor(n)));
}
isEven( 42)
Now the bench logic test is fairly straight forward:
even( 0) returns true;
even( 1) returns !even( 1-1), which is !even(0), which is false;
even( 2) returns !even( 2-1), which is !even(1), which is true;
and so on for higher numbers. Each increment of the parameter value executes an additional, recursive call to even, which complements the "even-ness" of the number below it, until reaching zero which is hard coded as being even.
The end result is that if even is called an odd number of times (for an even number) isEven returns true; and if even is called an an even number of times (for an odd number) isEven returns false.

Range using recursion, how to output a new array Javascript

How do you output a new array using recursion without declaring an empty array outside of the function? Another way of doing it will be creating an inner function and then return newFunction(), but it is not allowed as the task is to call the function itself. Here's what I have so far:
var newArr=[];
var range = function(x, y) {
if(x === y-1){
return newArr;
}
if(x < y){
newArr.push(x+1);
newArr = range(x+1,y);
}
else{
newArr.push(x-1);
newArr = range(x-1,y);
}
return newArr;
};
range(2,10) //[3,4,5,6,7,8,9]
So the key to this kind of thinking is understanding that you should be creating a lot of arrays.
Looking at a slightly different example...
A factorial is a number which goes backwards, through positive integers, multiplying each term with the term below it, and is written like 5!.
These are helpful when you find yourself asking questions like:
"How many permutations of ____ are there?"
"Given these 5 things, how many permutations can I arrange them in, from left to right?"
5! // =>
5 x 4 x 3 x 2 x 1 // =>
120
You could see how we could build a loop and set a variable for a counter, and a variable for the total, and multiply the current total by the current value of the counter we're decrementing.
But instead of doing that, we can try to use recursion.
First, think about how we could simplify that 5 x 4 x ... into one repeated step.
Really, 2! is 2 x 1. 3! is 3 x 2 x 1, which happens to be 3 x 2!.
So the general case might be something like: n! == n x (n - 1)!
So I might write a generalized function which does something like this:
// DO NOT RUN THIS FUNCTION!
function factorial (n) {
return n * factorial(n - 1);
}
So if I run factorial(5) and use my imagination, we can see that the program is doing something like:
factorial(5)
=> return 5 * factorial(5-1)
=> return 4 * factorial(4-1)
=> return 3 * factorial(3-1)
=> ...
Can you see any problems with the function as-is?
I said at the beginning that factorials (in this simplified case) are over positive integers.
How does my function know to stop when the integers stop being positive?
It doesn't, currently. Which is why the above implementation attempts to run forever, and will freeze the browser, while it tries to, until it gets thousands or tens of thousands of functions deep, before it says that you've reached the maximum depth of the call stack and explodes.
What we really need is a condition or a set of conditions, which we use to determine when we're done.
This is a base-case.
if (shouldStop(n)) {
return defaultValue;
}
Or in our case:
function factorial (n) {
if (n <= 1) {
return 1;
}
return n * factorial(n - 1);
}
Now, when we run the function, we have:
factorial(5)
=> 5 * factorial(5 - 1)
=> 4 * factorial(4 - 1)
=> 3 * factorial(3 - 1)
=> 2 * factorial(2 - 1)
=> 1
=> 2 * 1
=> 3 * 2
=> 4 * 6
=> 5 * 24
=> 120
This is recursion.
And because of where the call is (returned at the very end of whatever branch you're in) it's a special kind of recursion (tail recursion), which allows some languages to optimize the code, replacing the function call with the contents of the function call, and thus skip adding to the call-stack like the first version (future versions of JS will support this power).
In more modern JS, I might rewrite it to look something like
const factorial = n => n <= 1 ? 1 : factorial(n - 1);
So now, what about other cases?
Well, sometimes, you need to make sure you're passing more things in.
Think about what your problem is, and what kinds of counters or flags or collectors you need, in order to do your job.
Here's one:
function makeNumberString (current, max, initialString) {
var str = initialString || ""; // maybe I don't have one yet
var currentString = str.concat(current.toString());
if (current > max) {
return initialString;
}
return makeNumberString(current + 1, max, currentString);
}
makeNumberString(0, 9); // "0123456789"
There are other ways of filling that function out, to make it do the same thing.
Note that currentString there is always a brand new string, made by joining the string that I was given with the new value I was passed. I'm not actually modifying the original string, but creating a new copy [HINT!!].
I hope that helps you.
you can simply do like this;
var range = (x,y,a=[]) => (++x < y && (a = range(x,y,a.concat(x))),a),
arr = range(2,10);
console.log(arr);
Note that the returned array is a parameter of the function and is passed to successive recursive calls.
There are many ways to skin this cat.
The simple way: create an array with the first value in it, then
concatenate the remaining values to it.
var range = function(x,y){
return x+1 >= y ? [] : [x+1].concat(range(x+1, y));
}
console.log(JSON.stringify(range(1, 10)));
The array is being constructed from right to left. Notice how the
recursive call to range is not the last thing the function does
before it returns: concatenation of the array follows.
We can also rewrite the function to be tail recursive with an accumulator as a parameter.
var range2 = function(x,y,a){
a = a || [];
return x+1 >= y ? a : range2(x+1, y, a.concat(x+1));
}
console.log(JSON.stringify(range2(1, 10)));
Now the call to range2 is the last thing the function does before
it returns. ES6 compliant JS engines are required to
optimise
calls in tail position (in strict mode) by discarding the execution
context from the stack.
Notice how we're now constructing the array from left to right.
You can avoid the extra parameter by using a helper function.
I've used an inner function, but it doesn't have to be.
var range3 = function(x,y){
var r = function(x,y,a){
return x+1 >= y ? a : r(x+1, y, a.concat(x+1));
}
return r(x, y, []);
}
console.log(JSON.stringify(range3(1, 10)));
Tail recursive using continuation passing style.
var range4 = function(x,y){
var r = function(x,y,c){
return x+1 >= y ? c([]) : r(x+1, y, function(a){
return c([x+1].concat(a));
});
}
return r(x, y, function(a){return a;});
}
console.log(JSON.stringify(range4(1, 10)));
Notice the similarity with the original range: the array is
constructed in reverse. This is trickier to get your head around and
may be something you never need, but it doesn't hurt to be aware of
it.
Try this:
function rangeRecursive(start, end) {
if(start === end){
return end;
} else if(start > end){
return [];
} else {
return [start].concat(rangeRecursive(++start, end));
}
}
console.log(rangeRecursive(4, 15));

What's wrong with my implementation of the memoize function? [duplicate]

I'm trying to use memoization to optimize an explicitly self recursive implementation of the Fibonacci function. The implementation which is fairly standard (a simple and rather naïve implementation though to focus on the actual problem) follows.
Function.prototype.memoize = function () {
var originalFunction = this,
slice = Array.prototype.slice;
cache = {};
return function () {
var key = slice.call(arguments);
if (key in cache) {
return cache[key];
} else {
return cache[key] = originalFunction.apply(this, key);
}
};
};
Now, when creating and memoizing a function as follows, this works1. (Scenario 1)
var fibonacci = function (n) {
return n === 0 || n === 1 ? n : fibonacci(n - 1) + fibonacci(n - 2);
}.memoize();
console.log(fibonacci(100));
However, the following does not.2 (Scenario 2)
var fibonacci = function (n) {
return n === 0 || n === 1 ? n : fibonacci(n - 1) + fibonacci(n - 2);
};
console.log(fibonacci.memoize()(100));
And neither does this.2 (Scenario 3)
function fibonacci(n) {
return n === 0 || n === 1 ? n : fibonacci(n - 1) + fibonacci(n - 2);
}
console.log(fibonacci.memoize()(100));
My assumption is that because of the different ways of calling memoize() on the functions, something is changing. Note that the functions are otherwise identical. I suppose that this could be due to the fact that other than in the first instance, only the first call is memoized, not the recursive calls.
Question
If my supposition above is indeed correct, then why is this happening? Can someone explain in detail how the latter two scenarios differ from the first?
1To work in this instance means to return the 100th Fibonacci number since it is only possible to compute it recursively if memoization is used.
2To not work is to crash the browser.
Yes, it's right that only the first call is memoized in the second and third scenarios.
In the first scenario the reference to the original function only exists as a value, then memoize is applied to that and the fibonacci variable contains the reference to the memoized function.
In the second and third scenario fibonacci is a reference to the original function. The value of the expression fibonaci.memoize() that contains the reference to the memoized function only exist as a value before it is called once.
The memoize method doesn't change the original function, instead it returns a new function that wraps the original function. The original function is unchanged, and to use the memoization you have to call the function returned by the memoize method.
In the first scenario when the function makes a recursive call to fibonacci, it's the memoized function that is used. In the second and third scenarios when the recursive call is made, fibonacci is the original function instead.

Categories

Resources