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

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.

Related

Leetcode 104 Maximum Depth of Binary Tree

I am reviewing the solution to this leetcode problem. The solution is the following:
var maxDepth = function(root) {
let maxNode = (node, sum) => {
if (node === null) {
return sum;
}
return Math.max(maxNode(node.left, sum + 1), maxNode(node.right, sum + 1));
}
return maxNode(root, 0);
};
I was wondering why return maxNode(root, 0); must include a return. Is it required to 'activate' the inner function? If so, why doesn't just maxNode(root, 0) just 'activate' it?
The solution includes "recursion", which means the maxNode function is called multiple times from within itself. This requires the maxNode function to return a value to it's calling "instance".
The maxDepth function has a return statement to return the calculated maxNode value.
This function maxDepth will determine the maximum depth of a binary tree.
You would use it like this:
let depth = maxDepth(treeRoot);
Without the return, the function will determine the depth but you will not get the result when you call the function.
It is a another construction of a recursive function by taking a sum as parameter for a recursion.
It could be easily rewritten to the below function where the adding of one is outside of the function call.
var maxDepth = function(node) {
if (!node) return 0;
return 1 + Math.max(maxNode(node.left), maxNode(node.right));
};

How to get the underscore function _.first to work on the arguments objects?

As part of the precourse for a coding bootcamp, we have to create a simpler version of the underscore JS library. I am struggling with creating the _.first function, which:
Returns an array with the first n elements of an array.
If n is not provided it returns an array with just the first element.
This is what I've got so far:
_.first = function(array, n) {
if (!Array.isArray(array)) return [];
if (typeof n != "number" || n <= 0) return [].slice.call(array, 0, 1);
return n >= array.length ? array : [].slice.call(array, 0, n);
};
It passes all test except one: "It must work on an arguments object"
I know the arguments object passes an array with all the arguments passed and it has a length property but Im struggling to work with it.
Any help would be much appreciated.
The arguments object is just that, a variable defined implicitly on each function scope that acts like an array. Has a length property and you can access the elements by using number properties like a normal array:
var _ = {};
_.first = function() {
if (arguments.length == 0) { // If there's no arguments
return [];
} else { // When there's 1 or more arguments
var array = arguments[0];
var n = arguments.length > 1 ? arguments[1] : 1; // If there's only the "array" argument ("n" is not provided), set "n" to 1
// And now your code, which has nice checks just in case the values are invalid
if (!Array.isArray(array)) {
return [];
}
if (typeof n != "number" || n <= 0) {
n = 1;
}
return [].slice.call(array, 0, n); // Don't worry if slice is bigger than the array length. It will just work, and also always return a copy of the array instead of the array itself.
}
};
console.log( _.first() );
console.log( _.first([0,1,2]) );
console.log( _.first([0,1,2], 2) );
console.log( _.first([0,1,2], 10) );
I would add something to the first answer. The arguments object is something that is normally created implicitly by JavaScript and made available inside the function body. In order to write a unit test for "It must work on an arguments object", they must explicitly define an arguments object and pass it in. This is a bad unit test because it is testing the internal working of your function. You should be free to write the function any way you like, and a unit test should test the external behaviour of the function (return value and/or side effects, based on the arguments passed).
So imo your original solution is good and the test is designed to force you to use a certain syntax for the sake of learning, but this is misleading.

Javascript Nested Function Evaluation

Hi I am confused with this Javascript function:
var currying = function(a) {
return function(b){
return function(c){
return function(d){
return a + b /c * d;
};
};
};
};
var a = currying(4)(8);
var b = a(2)(6);
console.log(b);
It outputs 28 but I am not sure how did Javascript evaluated the function. I also have learned that a = 4, b = 8, c = 2 and lastly d = 6. Thank you for somebody that will be able to explain the function.
When you use currying you are writing a function that takes one argument, that will return a function taking the next argument until all arguments are supplied.
In this case you need to call the returned function 4 times until you get to the last function and evaluate all the arguments.
This is good because you can pass in arguments at different times during the execution of your code and you can create new functions with arguments already set within the closure of the final functions. eg.
const fourPlusTwo = currying(4)(2)
now you can use the new function fourPlusTwo anywhere in your code and you will have those arguments baked in the closure of the remaining two functions.
The code you have is a non standard example but maybe if you needed to calculate tax throughout your app you could do something like.
const inclusiveTax = rate => amount => {
return '$' + (amount * (rate / (100 + rate))).toFixed(2)
}
const norwayIncomeTax = inclusiveTax(60.2)
const strayaIncomeTax = inclusiveTax(32.5)
const muricaIncomeTax = inclusiveTax(31.5)
console.log(
norwayIncomeTax(50000),
strayaIncomeTax(50000),
muricaIncomeTax(50000)
)
Using just one function you have curried the tax rate for 3 separate countries and returned functions waiting for the amount.
You should know the difference between function object and function call.
like: var a = function(v){return v + 1;} a is a function object. Then a(2) invokes function a.
Try to understand the procedure step by step.
currying is a function which return another function.
so currying(4) returns a function(a is given value 4):
function(b){
return function(c){
return function(d){
return 4 + b /c * d;
};
};
};
};
then currying(4)(8) also is 'var a' returns another function:
function(c){
return function(d){
return 4 + 8 /c * d;
};
};
};
invoking a(2) returns a function object:
function(d){
return 4 + 8 / 2 * d;
};
};
finally a(2)(6) returns 4 + 8 / 2 * 6 which is 28.
This is kind of lexical scoping called Closures
Basically: A closure is a function within function that has access to all parent's variables and parameters. As every parameter in javascript is by default passed by reference, it can even modify parent's variables so you can later execute parent function to see the changes. The great example is jquery's ready function that wraps all other functions within.
You can read more about this here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
This is a very convoluted example of currying - hence the name of the main function.
Currying originates in the field of functional programming and to fully understand it I would suggest that you do some reading, especially as it is implemented in javascript.
To give you some pointers:
In the line:
var a = currying(4)(8);
the first function is called with a parameter of 4; the result of that function call is another function which is then called immediately with a parameter of 8.
Ultimately, all that happens is that the line:
return a + b / c * d;
is executed with the values 4, 8, 2 and 6 for each of the respective variables.
Normal arithmetic rules are applied to give you an answer of 28 (divide first, then multiply and finally add).

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));

Javascript: Compose a function with argument placement instructions for each composition

I'm looking for a javascript function that can:
Condition (I)
compose another function when it does not have recursion in its definition, kind of like in maths when the function is given a power, but with multiple arguments possible in the first input - e.g. with a (math) function f:
f(x) := x+2
f5(x) = f(f(f(f(f(x))))) = x+10
Condition (II)
Or maybe even input custom arguments into each step of composition:
(52)2)2=
Math.pow(Math.pow(Math.pow(5,2),2),2) = Math.pow.pow([5,2],2,["r",2]])
//first arg set, how times the next, 2nd arg set - "r" stands for recursion -
//that argument will be occupied by the same function
//Using new solution:
_.supercompose(Math.pow,[[5,2],[_,2],[_,2]]) //-> 390625
2((52)3)=
Math.pow(2,Math.pow(Math.pow(5,2),3)) = Math.pow.pow([5,2],["r",2],["r",3],[2,"r"])
//Using new solution:
_.supercompose(Math.pow,[[5,2],[_,2],[_,3]]) //-> 244140625
_.supercompose(Math.pow,[[5,2],[_,2],[_,3],[2,_]]) //-> Infinity (bigger than the max. number)
Note: The above are just templates, the resulting function doesn't have to have the exact arguments, but the more close to this (or creative, for example, a possibility of branching off like this ->[2,4,"r",4,2,"r"], which would also be complicated) the better.
I've been attempting to do at least (I) with Function.prototype, I came up with this:
Object.defineProperty(Function.prototype,"pow",{writable:true});
//Just so the function not enumerable using a for-in loop (my habit)
function forceSlice(context,argsArr)
{returnArray.prototype.slice.apply(context,argsArr)}
Function.prototype.pow = function(power)
{
var args=power<2?forceSlice(arguments,[1]):
[this.pow.apply(this,[power-1].concat(forceSlice(arguments,[1])))];
return this.apply(0,args);
}
//Usage:
function square(a){return a*a;}
square.pow(4,2) //65536
function addThree(a,b){return a+(b||3); }
// gives a+b when b exists and isn't 0, else gives a+3
addThree.pow(3,5,4) //15 (((5+4)+3)+3)
Worst case, I might just go with eval, which I haven't figured out yet too. :/
Edit: Underscore.js, when played around with a bit, can fulfill both conditions.
I came up with this, which is close to done, but I can't get it to work:
_.partialApply = function(func,argList){_.partial.apply(_,[func].concat(argList))}
_.supercompose = function(func,instructions)
{
_.reduce(_.rest(instructions),function(memo,value)
{
return _.partialApply(_.partialApply(func, value),memo)();
},_.first(instructions))
}
//Usage:
_.supercompose(Math.pow,[[3,2],[_,2]]) //should be 81, instead throws "undefined is not a function"
Edit: jluckin's cleareance of terms (recursion-> function composition)
Edit: made example function return number instead of array
The term you are looking for is called function composition, not necessarily recursion. You can apply function composition in javascript easily since you can pass a function as an argument.
I created a small function called compose, which takes a function, an initial value, and the number of times to compose the function.
function compose(myFunction, initialValue, numberOfCompositions) {
if (numberOfCompositions === 1) {
return myFunction(initialValue);
}
else {
return compose(myFunction, myFunction(initialValue), --numberOfCompositions);
}
}
When this function is evaluated, you pass in some function f(x), some initial x0, and the repeat count. For example, numberOfCompositions = 3 gives f(f(f(x)));
If there is one composition, then f(x) is returned. If there are two compositions, compose returns f(x) with f(x) replacing x as the argument, with 1 passed in as the composition so it will evaluate f(f(x)).
This pattern holds for any number of compositions.
Since functions are treated as objects and can be passed as arguments of functions, this method basically wraps your "non-recursive" functions as recursive functions to allow composition.
Success(simplicity wins):
_.supercompose = function (func,instructions,context)
{
var val;
for(var i = 0; i < instructions.length; i++)
{
val = _.partial.apply(_,[func].concat(instructions[i])).apply(context||this,val?[val]:[]);
}
return val;
}
//Usage (with a function constructor for operations):
_.op = function(o){return Function.apply(this,"abcdefghijklmnopqrstuvwxyz".split("").concat(["return " + o]))}
_.op("a+b")(3,5) //-> 8
_.op("a*b")(3,5) //-> 15
_.supercompose(_.op("(a+b)*c*(d||1)"),[[1,2,3],[-5,_,1],[1,2,_,3]])
//-> (1+2)*((-5+((1+2)*3))*1)*3 -> 36

Categories

Resources