Javascript, factorial , too difficult - javascript

var fact = (function(){
var cache = {'0': 1};
var func = function(n){
var result = 0;
if(typeof(cache[n]) === 'number'){
result = cache[n];
}
else{
result = cache[n] = n * func(n-1);
}
return result;
}
return func;
})();
console.log(fact(5)); //120
The code is this.
I can't understand this code, wholly.
It's look like add cache, and add cache
but how does this work?
Don't we need for loop to add cache?
also, return func; <- what's is this?
please explain wholly

The code is more complex than is needed. The cache array isn't being used as cache; it's being used as a means of hardcoding the fact that the factorial of 0 is 1. The recursion loop doesn't need to add to the cache, but if the extra line to do so were added, then the array would really function as a cache, and it would provide performance improvements on subsequent calls to the function.

Related

I'm trying to rewrite memoize in javascript (for underscore), can someone explain this?

I know that the purpose of memoize is to cache values so code can be run faster by not having to re-calculate the same answer everytime. My issue stems from returning a function (i think). The google chrome debugger isn't that useful for me here because everytime I try to run this memoize function, it just goes from the argus variable (on line 4 i believe) all the way down to the semi-colon. Furthermore, result always returns an empty object instead of storing a value in result.
I start by defining a function:
function add(a,b){
return a+b;
}
This is my attempt at the memoize function:
_.memoize = function(func) {
var result = {};
var flag = 0;
var argus = Array.prototype.slice.call(arguments)
return function() {
if(result[key] === arguments){
flag = 1
}
else if(flag = 0){
result[argus] = func.apply(this, argus);
}
return result[argus];
};
};
I'd call memoize by doing _.memoize(add(2,5)) but the result doesn't get stored in the result object.
Am I even close to getting this memoize function working properly? Any guidance you guys can give here would be appreciated.
The biggest point you're missing is that _.memoize is called on the function first, and it returns a new function. You are calling it on the result of a function call (which is the number 7 in this case).
In order to get it to work, you need to rearrange a few things.
Also note that it's not wise to try to use an array itself as the index to an object. One approach to get around that would be to convert the arguments array to JSON and use that as the index on the results object:
function add(a, b) {
console.log('Called add(' + a + ', ' + b + ')');
return a + b;
}
var _ = {};
_.memoize = function(func) {
var results = {};
return function() {
var args = Array.prototype.slice.call(arguments);
var key = JSON.stringify(args);
if (!(key in results)) {
results[key] = func.apply(this, args);
}
return results[key];
};
};
var madd = _.memoize(add);
console.log(madd(2, 4));
console.log(madd(9, 7));
console.log(madd(2, 4));

JS: Can a recursive function be decorated with cache?

We're going to make a decorator, caching computed results of deterministic functions (for simplisity let's assume one-argument functions).
In common case is could be done this way:
function makeCacheable(origFunc){
let registry = {};
return function (a){
if (a in registry){
return registry[a];
}
let res = origFunc(a);
registry[a] = res;
return res;
}
}
A problem appears when origFunc is recursive: only top-level calls go through the wrapping cache, but the rest of recursive call stack doesn't meet the cache. No need to explain why this happens. I wonder is there a natural way to make a recursive function cacheable in the same manner?
function fibonacciF(n) {
if (n <= 2) return 1;
let a = 1, b = 1;
for (let i = 2; i < n; ++i){
[a, b] = [b, a+b];
}
return b;
}
function fibonacciR(n) {
return n <= 2 ? 1 : (fibonacciR(n-1) + fibonacciR(n-2));
}
let fiboF = makeCacheable(fibonacciF); // OK
let fiboR = makeCacheable(fibonacciR); // actually is not what expected
The function calls a function named fibonacciR. If you want to make this call go through the cache, you have to overwrite fibonacciR:
fibonacciR = makeCacheable(fibonacciR);
Is there a natural way to make a recursive function cacheable in the same manner?
No. In general, a function implementation cannot be inspected, and it doesn't make a difference whether it's implemented recursively or with a loop or something else. Using pure functional programming, we can only use the whole function as a building block for the cached version (fiboR), but we cannot alter its behaviour or take only parts of the function unless the implementation is cooperative (e.g. by using some kind of recursion operator that can be user-supplied).
In the above solution, we break these rules by overwriting a variable that is used inside the function, but this is not always possible even in JavaScript.
You could make it work, if you would use the same (function) variable for storing the decorated version of it. To allow for returning back to the original, you could add a property original to the function object:
function makeCacheable(origFunc){
let registry = {};
let f = function (a){
if (a in registry){
console.log(`retrieving value from registry[${a}]`);
return registry[a];
}
let res = origFunc(a);
registry[a] = res;
return res;
}
// Add property for exposing the original function:
f.original = origFunc;
return f;
}
function fibonacciR(n) {
console.log(`Called fibonnacci(${n})`);
return n <= 2 ? 1 : (fibonacciR(n-1) + fibonacciR(n-2));
}
// Demo illustrating the registry is being used:
console.log('Call fibonnacciR(5) with cache turned on:');
var fibonacciR = makeCacheable(fibonacciR);
var f5 = fibonacciR(5);
console.log(`Result: fibonnaciR(5) = ${f5}`);
// Demo illustrating the function can be restored:
console.log('Call fibonnacciR(5) with cache removed:');
fibonacciR = fibonacciR.original;
f5 = fibonacciR(5);
console.log(`Result: fibonnaciR(5) = ${f5}`);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Higher Order Internal Memoization In JavaScript does not Work

Context.
Memoization is a functional technique operating over recursive functions with overlapping invocations aiming to optimize time performance by using an internal cache that remembers previous results with already used parameters. A typical use case is the fibonacci function. Below, it is shown a non memoized and memoized version of that function and an assisting function for timing purposes:
function time (fn) {
return function () {
var before = Date.now();
var result = fn.apply(this, arguments);
var after = Date.now();
return {
value : result,
time : after - before
};
};
}
var fib = function (n) {
if (n < 2) return n;
else return fib(n-1) + fib(n-2);
};
var mfib = function (n) {
var cache = {};
var memoizefib = function (n) {
if (n < 2) return n;
else {
var k1 = JSON.stringify(n-1);
var k2 = JSON.stringify(n-2);
var v1 = k1 in cache ? cache[k1] : (cache[k1] = memoizefib(n-1));
var v2 = k2 in cache ? cache[k2] : (cache[k2] = memoizefib(n-2));
return v1 + v2;
}
};
return memoizefib (n);
};
If now we test our functions we realize that memoization dramatically reduces execution time:
(function test (n) {
var tfib = time(fib);
var tmfib = time(mfib);
console.log(tfib(n)); // -> { value: 433494437, time: 5780 }
console.log(tmfib(n)); // -> { value: 433494437, time: 1 }
})(43);
Problem.
As it frequently happens in functional programming, memoization becomes a useful tool when applied at the higher order to allow defining a memoize function that can transform over a generic function fn. Typical solutions similar to the next one can be found on the Web [1][2][3]:
function memoize (fn) {
var cache = {};
return function () {
var args = [].slice.call (arguments);
var key = JSON.stringify(args);
return key in cache ?
cache[key] :
cache[key] = fn.apply(this, args); (1)
};
}
fn.js - http://eliperelman.com/fn.js
underscore - http://underscorejs.org
Addy Osmani on Memoization - http://addyosmani.com/blog/faster-javascript-memoization
Question.
Nevertheless, surprisingly none of these solutions works!!! After revolving around the code. I think that the problem is in (1) because the recursion it is not applied over the memoized version of fn but over primitive fn and hence memoization is only applied once. Here are my results:
(function test (n) {
var tfib = time(fib);
var tmfib = time(memoize(fib));
console.log (tfib(n)); // -> { value: 433494437, time: 5768 }
console.log (tmfib(n)); // -> { value: 433494437, time: 5723 } :(
})(43);
It seems that in Javascript it is not possible to apply this technique at higher order. Am I right? Does anybody have any solution or alternative code to get a higher order memoization function?
Interesting problem. Why not just memoize the function onto itself?
function factorial(n) { return n ? n * factorial(n-1) : 1; }
// simple memoization with one argument and console reporting
function memoize(fn) {
var cache = {};
return function(x) {
if (x in cache) { console.log('retrieved value from cache for', x); }
return x in cache ? cache[x] : cache[x] = fn.apply(this, arguments);
};
}
// redefine factorial to be its memoized version
factorial = memoize(factorial);
Once you do this, factorial will now be calling its memoized version.
> factorial(6)
720
> factorial(7)
retrieved value from cache for 6
5040
Applying this to your case (no need for mfib):
(function test (n) {
var tfib = time(fib);
console.log(tfib(n));
fib = memoize(fib); // <-- memoize on top of itself
var tmfib = time(fib);
console.log(tmfib(n));
})(30);
Results:
Object {value: 832040, time: 714}
Object {value: 832040, time: 22}
Note that this solution very much applies to "internal memoization" used within a single recursive computation, not just additional external calls to the function as in the factorial case above. By redefining the function with its memoized version, the internal recursive calls are now made to the memoized function. That accounts for the dramatic time improvement from 714 to 22.
If you are looking for "internal" memoization within a single recursive computation, the factorial function (which is given in the currently accepted answer - which BTW I also think is wrong) is a bad candidate and can't be used to showcase it. This is because, there's a single chain of recursion, so once you compute, e.g. the value for 5! you are not going to need it again within the same computation. To showcase what you are asking for, you would indeed need to use an example like the Fibonnaci sequence (which you are yourself using in the question).
The higher-order memoize function you wrote will not work internally within the same computation as it is calling the non-memoized version of it. The currently accepted answer suggests "redefining" the function to be its memoized version. However I think this is wrong. The memoize function closes over the function it was provided with as an argument (functions are values). Changing the variable that used to point to that function value to some other function value (the memoized version) accomplishes nothing.
So, I don't think it is possible to generalize it. That is, I don't believe it is possible to implement a memoize function that externally memoizes a function and makes it work also for a single recursive computation.
Here's what would work for Fibonnaci (like I said, not generalizable):
var fib = (function() {
function fib(n) {
if ((n===1) || (n==2))
return 1;
else
return memoizedFibonacci(n-1)+memoizedFibonacci(n-2);
}
var cache = {};
function memoizedFibonacci(n) {
if (n in cache) { console.log('retrieved value from cache for', n); }
return n in cache ? cache[n] : cache[n] = fib(n);
};
return fib;
})();
console.log(fib(10));
console.log(fib(10));
The above code produces on the output:
retrieved value from cache for 2
retrieved value from cache for 3
retrieved value from cache for 4
retrieved value from cache for 5
retrieved value from cache for 6
retrieved value from cache for 7
retrieved value from cache for 8
55
retrieved value from cache for 9
retrieved value from cache for 8
55
... which is consistent with the expectation for "internal memoization" for the first recursive computation. That the value for 10 is not cached is insignificant for this example and could be trivially fixed but it would add very little (basically you would need to access the cache from the fib function as well).

sandwich pattern in javascript code

Apologize if the title of the question is misleading. Actually I am looking for the javascript equivalent of the following python code:
## python code
def call_with_context(fn, *args):
## code to create context, e.g. profiling, db.connect, or drawing context store stack
fn(*args)
## code to close context
This implements the similiar functionality as the "with statement" in python, which implements the aspect-oriented paradigm.
So my question is what is the javascript way of doing such things? I have seen some code using Array.prototype.slice(arguments, 1) to do so, but I don't know if this is a common pattern in javascript, or there are better patterns supported in javascript (e.g. by closure) so ppl don't really do that. Pls also correct me if I am using the wrong keywords, because I really dont know how to refer to my problem with a better name than sandwich.
EDT 1: And I appreciate if someone can explain how to return the result of fn(*args) from inside the wrapper call_with_context. thanks!
I think a more typical JS way of doing this might be to decorate the function. So if you wanted to wrap your function in something that logged timing, you might create a function like this (off the top of my head):
var createTimer = function(fn) {
return function() {
var start = new Date();
var result = fn.apply(this, arguments);
console.log("Took " + (new Date() - start) + " ms.");
return result;
}
};
var test = function(a, b, c) {
return a * b + c;
}
test = createTimer(test);
console.log(test(3, 4, 5));
// Took 0 ms.
// 17
The main point is that you might not call something like this:
runTimerAround(test, 3, 4, 5);
although that could also be done in JS, it is, I believe less common than overwriting the functions directly.
It sounds like you want to call a method with specific context.
In js, you would typically do...
function someFunction( fn, context ) {
fn.call( context );
}
var Button = {
isClicked: false
};
someFunction(function () {
// this === Button
this.isClicked = true;
}, Button );
now the this keyword inside of fn will represent the context passed into the method someFunction. This sort of pattern is done quite often. Especially with the callbacks.
Here is my solution after some search. Hope it is helpful to others.
function call_with_context(fn) {
// some beginning code
console.log('begin');
r = fn.apply(null, Array.prototype.slice.call(arguments, 1));
// some ending code
console.log('end');
return r;
}
Something like this
// javascript code
function call_with_context(fn) {
// code to create context, e.g. profiling, db.connect, or drawing context store stack
var r = fn.call(Array.prototype.slice.call( arguments, 1)); // remove first arg - fn
//code to close context
return r;
}
so you will be able to do this:
call_with_context(myfun,1,2,3);
that will end up in call
myfun(1,2,3);
After having carefully read through every post/comment, I think the OP is
looking for [javascript] and [method-modification]. And answering right
away the OP's question about terminology, altering closed functionality in
JavaScript has nothing to do with Aspect-oriented Programming unless an
implementation that claims to be AO provides abstraction and code-reuse
levels for at least Aspect, Advice and Pointcut.
As it already has been commented
by Scott Sauyet, everything
else can be done by just (manually) wrapping functionality into one another. Here
again, I wouldn't go that far and calling it function-composition. In order to
qualify for that, there should be at least some tool-sets for it, as they already
exist with various implementations of compose and/or curry methods/patterns.
For what the OP is going to achieve there are a whole bunch of before, after
around / wrap solutions, mostly unfortunately mentioning AO(P), and in too
many cases not taking care of the context or target which is essential and
also has been ask for by the OP.
The example I do provide uses a prototypal implementation of Function.around.
Because JavaScript already features a standardized bind, I'm firmly convinced
that Function.prototype is the right place as well for some other method-modifiers
like before,
after,
around,
afterThrowing
and afterFinally.
code base that will support the afterwards following example:
(function (Function) {
var
isFunction = function (type) {
return (
(typeof type == "function")
&& (typeof type.call == "function")
&& (typeof type.apply == "function")
);
},
getSanitizedTarget = function (target) {
return ((target != null) && target) || null;
}
;
Function.prototype.around = function (handler, target) { // [around]
target = getSanitizedTarget(target);
var proceed = this;
return (isFunction(handler) && isFunction(proceed) && function () {
return handler.call(target, proceed, handler, arguments);
}) || proceed;
};
}(Function));
example code, altering a given closed function by additionally provided behavior before and after it and also providing it's context.
var loggingDelegate = function () { // closed code that can not be changed for any reason.
this.log.apply(this, arguments);
};
loggingDelegate.call(console, "log", "some", "arguments");
var interceptedLoggingDelegate = loggingDelegate.around(function (proceed, interceptor, args) {
// everything that needs to be done before proceeding with the intercepted functionality.
// [this] in this example refers to [console], the second argument of the [around] modifier.
this.log("proceed:", proceed); // the original functionality - here [loggingDelegate].
this.log("interceptor:", interceptor); // the modifying functionality - [around]s 1st argument.
this.log("args:", args); // the arguments that get passed around.
proceed.apply(this, args);
// or:
//return proceed.apply(this, args);
// or:
//var result = proceed.apply(this, args);
// everything that still needs to be done after invoking the intercepted functionality.
// if necessary:
//return result;
}, console); // [console] has to be provided as target to the modified [loggingDelegate].
interceptedLoggingDelegate("intercept", "and", "log", "some", "arguments");

JavaScript - shorten math function

function randomize() {
var ra = Math.floor(Math.random()*ar.length=4);
document.getElementById('es').innerHTML = ar[ra];
}
Is there a way to short this code even more than it is? The reason why is because I'm going to be using this code a lot in other projects and objects and I cannot just call it inside like this: randomize(); because I have diffrent arrays.
function randomize() {document.getElementById('es').innerHTML = ar[Math.floor(Math.random()*ar.length)];}
But you wanted to use it more without a function call:
function $(id) {
return document.getElementById(id);
}
function randomize() {
$('es').innerHTML = ar[Math.floor(Math.random()*ar.length)];
}
And instead of Math.floor, you can use ~~ for a microscopical faster diffrence.
This saves some space and time if you are going to use it more. But if only one time, use the first example.
Without knowing what, precisely, you're doing, I'd suggest passing the relevant arguments into the function as parameters:
function randomize(el, array){
if (!el || !array){
return false;
}
else {
var ra = Math.floor(Math.random() * array.length=4);
// please note that I don't understand what's happening in the above line
// and suspect, quite strongly, that the '=4' was a typo. Correct as necessary
el.innerHTML = ar[ra];
}
}
// call:
randomize(document.getElementById('es'), ['1','2']);
/* or:
var el = document.getElementById('es'),
array = ['one','two'];
randomize(el,array);

Categories