Can I add numbers using JavaScript Closures? - javascript

How can I create a closure function, that sums all passed arguments, like this?
Add(2)(2) //4
Add(2)(2)(3) // 7
Add(3)(2)(3)(0) // 8
function Add(number){
return function(number1){
return function(number2){
return number+number1+number2;
}
}
}
alert(Add(2)(2)(2));
I wanted a generalized way to achieve this.

There are duplicates here, probably with better examples, but I can't find one right now. You need to create a closure to keep track of the sum, then return the add function. Give it valueOf and toString methods so it works in other operations:
var add = (function() {
var sum = 0;
function add(n) {
sum += +n || 0;
return add;
}
add.valueOf = function(){
return sum;
}
add.toString = valueOf;
return add;
}());
document.write(add(1)(2)(3)(-2)); // 4
document.write('<br>' + add(2)(1) * 2); // 14
document.write('<br>' + add( -add())); // 0

Related

Only allowing a function to run n times with wrapper function

I need to make a wrapper function to invoke a function multiply with a given number num of times to allow the multiply to execute. nTimes(num,2) Then assign to runTwice -- runTwice can be any function that invoke the nTimes function which given a different num input--
In my case, for simplicity, I am only allowing it to run 2 times num=2
If we run the runTwice function the first time and the second time it will return the result of multiply function calculated with the inputs for multiply. Any invocation after the second time will not run the multiply function but will return the latest result of the multiply function.
Here is my implementation using an object to keep track of how many times we have execute the function, the max number allowed to execute and the latest result of multiply
'use strict'
//use a counter object to keep track of counts, max number allowed to run and latest result rendered
let counter = {
count:0,
max: 0,
lastResult: 0
};
let multiply = function(a,b){
if(this.count<this.max){
this.count++;
this.lastResult = a*b;
return a*b;
}else{
return this.lastResult;
}
}
// bind the multiply function to the counter object
multiply = multiply.bind(counter);
let nTimes=function(num,fn){
this.max = num;
return fn;
};
// here the nTimes is only executed ONE time, we will also bind it with the counter object
let runTwice = nTimes.call(counter,3,multiply);
console.log(runTwice(1,3)); // 3
console.log(runTwice(2,3)); // 6
console.log(runTwice(3,3)); // 6
console.log(runTwice(4,3)); // 6
Note that I have altered the simple multiply quite a bit and bind it the counterobject to make it work. Also using call on nTimes to bind counter object.
What can I do to implement the same result with a wrapper function but less alteration to the simple multiply function?
Let's say the multiply function is very simple:
let multiply = function(a,b){ return a*b };
You could use a closure over the count and the last value and check count and decrement and store the last result.
const
multiply = (a, b) => a * b,
maxCall = (fn, max, last) => (...args) => max && max-- ? last = fn(...args) : last,
mult3times = maxCall(multiply, 3);
console.log(mult3times(2, 3));
console.log(mult3times(3, 4));
console.log(mult3times(4, 5));
console.log(mult3times(5, 6));
console.log(mult3times(6, 7));
Nina's answer is great. Here's an alternative, with code that might look slightly easier to read:
function multiply(a, b) {
return a * b;
}
function executeMaxTimes(max, fn) {
let counter = 0, lastResult;
return (...args) => counter++ < max
? lastResult = fn(...args)
: lastResult;
}
const multiplyMaxTwice = executeMaxTimes(2, multiply);
console.log(multiplyMaxTwice(1, 3)); // 3
console.log(multiplyMaxTwice(2, 3)); // 6
console.log(multiplyMaxTwice(3, 3)); // 6
console.log(multiplyMaxTwice(4, 3)); // 6
Seeing how both Nina and Jeto have answered your question, here is a simple and similar way to do it that also keeps a history of all the results in case you want to get them at a later time.
function multiply(a, b) {
return a * b;
}
function runMaxNTimes(num, callBack) {
var results = new Array(num);
var callTimes = 0;
return function(...params) {
return results.length > callTimes ?
results[callTimes++] = callBack(...params) :
results[callTimes - 1];
};
}
var runTwice = runMaxNTimes(2, multiply);
console.log(runTwice(1, 3)); // 3
console.log(runTwice(2, 3)); // 6
console.log(runTwice(3, 3)); // 6
console.log(runTwice(4, 3)); // 6

Javascript: Use reduce() method to find the LCM in an array

I am trying to find the LCM(least common multiples) among several numbers in an array. To get a LCM between each two numbers in the array, I use the reduce() method which is not working.Please tell me what's wrong? Thanks.
function gcd(a,b){
//gcd: greatest common divisor
//use euclidean algorithm
var temp = 0;
while(a !== 0){
temp = a;
a = b % a;
b = temp;
}
return b;
}
function lcm(a,b){
//least common multiple between two numbers
return (a * b / gcd(a,b));
}
function smallestCommons(arr) {
//this function is not working, why?
arr.reduce(function(a, b){
return lcm(a, b);
});
}
smallestCommons([1,2,3,4,5]);
//------>undefined
Your smallestCommons function is missing a return. undefined is the default return value for all functions that don't have an explicit return.
function smallestCommons(arr) {
return arr.reduce(lcm);
}

Using Recursion for Additive Persistence

I'm trying to solve a Coderbyte challenge, and I'm still trying to fully understand recursion.
Here's the problem: Using the JavaScript language, have the function AdditivePersistence(num) take the num parameter being passed which will always be a positive integer and return its additive persistence which is the number of times you must add the digits in num until you reach a single digit. For example: if num is 2718 then your program should return 2 because 2 + 7 + 1 + 8 = 18 and 1 + 8 = 9 and you stop at 9.
Here's the solution I put into jsfiddle.net to try out:
function AdditivePersistence(num) {
var count=0;
var sum=0;
var x = num.toString().split('');
for(var i=0; i<x.length; i++) {
sum += parseInt(x[i]);
}
if(sum.length == 1) {
return sum;
}
else {
return AdditivePersistence(sum);
}
}
alert(AdditivePersistence(19));
It tells me that there's too much recursion. Is there another "else" I could put that would basically just re-run the function until the sum was one digit?
One of the problems is that your if statement will never evaluate as 'true'. The reason being is that the sum variable is holding a number, and numbers don't have a length function. Also, as 'Barmar' pointed out, you haven't incremented the count variable, and neither are you returning the count variable.
Here's a solution that works using recursion.
function AdditivePersistence(num) {
var result = recursive(String(num).split('').reduce(function(x,y){return parseInt(x) + parseInt(y)}), 1);
function recursive(n, count){
c = count;
if(n < 10)return c;
else{
count += 1
return recursive(String(n).split('').reduce(function(x,y){return parseInt(x) + parseInt(y)}), count)
}
}
return num < 10 ? 0 : result
}
To fix the 'too much recursion problem',
if(sum.toString().length == 1)
However, as the others have said, your implementation does not return the Additive Persistence. Use James Farrell's answer to solve the Coderbyte challenge.

Tail function in javascript [duplicate]

This question already has answers here:
Variadic curried sum function
(19 answers)
Closed 7 years ago.
I want to make a function which adds arguments. Invoking this function should be
functionAdd(2)(3)(4)...(n);
And the result 2+3+4...+n
I'm trying this
function myfunction(num){
var summ =+ num;
if(num !== undefined){
return myfunction(summ);
}
};
But it doesn't works, an error of ovwerflow. And I don't understand where I should out from this function;
You can use the .valueOf to do the trick:
function myfunction(sum){
var accum = function(val) {
sum += val;
return accum;
};
accum.valueOf = function() {
return sum;
};
return accum(0);
};
var total = myfunction(1)(2)(3)(4);
console.log(total); // 10
JSFiddle: http://jsfiddle.net/vdkwhxrL/
How it works:
on every iteration you return a reference to the accumulator function. But when you request for the result - the .valueOf() is invoked, that returns a scalar value instead.
Note that the result is still a function. Most importantly that means it is not copied on assignment:
var copy = total
var trueCopy = +total // explicit conversion to number
console.log(copy) // 10 ; so far so good
console.log(typeof copy) // function
console.log(trueCopy) // 10
console.log(typeof trueCopy) // number
console.log(total(5)) // 15
console.log(copy) // 15 too!
console.log(trueCopy) // 10
If last call can be without arguments:
function add(value) {
var sum = value;
return function add(value) {
if(typeof value === 'number') {
sum += value
return add
} else {
return sum
}
}
}
console.log(add(1)(2)(3)(0)()) // 6

Index of a really big Fibonacci Number

I need to calculate the index of a Fibonacci number with JavaScript, within the Fibonacci sequence. I need to do this without using recursion, or a loop. I found the following formula in the Math forum:
n=⌊logφ(F⋅5√+12)⌋
and coded it in JavaScript:
function fibIndex(fib)
{
fib = BigNumber(fib);
return logBasePhi(fib.times(Math.sqrt(5)).plus((1/2)));
}
function phi()
{
return (1 + Math.sqrt(5))/ 2;
}
function getBaseLog(x, y) {
return Math.log(y) / Math.log(x);
}
function logBasePhi(x)
{
return getBaseLog(phi(), x);
}
Notice the .times() and .plus() functions that are part of this BigNumber Library that has been extremely useful up to this point. This works fine, until the Fibonacci number I want to find the index for is really big.
The problem:
I need a different way to calculate the logarithm with such a big number. If I have a really big number, such as Fibonacci of 2000, I get Infinity for obvious reasons. The library itself does not have any methods to calculate the log, and I can't write this function either.
I would have never imagined that the logarithm of any number with such a small base (phi) can be bigger than the max for JavaScript integers. Can you guys point me in the right direction? Should I just leave it at obtaining the index for numbers less than Fib(1500) and call it good?
You can use BigInteger. You can see an example of how to use it here: http://reallifejs.com/the-meat/calculators/big-number-calculator/
For anyone else looking for this function, here it is using this BigInteger library:
function fibIndex(fib)
{
fib = BigInteger(fib);
var x = fib.multiply(Math.sqrt(5)).add((1/2));
return Math.round(x.log() / Math.log(phi()));
}
function phi()
{
return (1 + Math.sqrt(5))/ 2;
}
I still use the same equation explained in my question above, and it returns the index of Fibonacci's of any size.
fibIndex("35522938794321715091272953991088875073660950670711879743399900326436254083421380378927750257524675311447286915610820861302904371152466182968261111009824391725637150862745505342130220586979511719255023895335108709522075314248260664483166479670588221585277069887873168196490963561219694518077864879100421788205515385380434545975662001723555342440392621808579760295648531141638822913590607533540054087452041707826153271185259107394199852367649618298517093117009455894918353503525076230125819543123779319167440820789626564459764725339684808290073756385496248142195843240135064507885354877296572024804408624272941753639812538039913142028651903030529871116793317789757893606550341466951324756526825899737667945813833853722262630433262780974915425005732866591818868174705546087022106127052877310847951571707582794820376128579789767721485109492542287764348615868723395725124814856415577763540656765591673162724146048330852788081439178288706881889502843933839383437965572895385440792960391702268984769357859686271266574632871727046024303184663919395401465801528726015901456333025573481247959101652204602988035141532490361245742139050819433077833707742246312835208439293469725777437940254819086871672146128972238328251414589544434435170261367824782155103657578194196270111748570034449297964612564456266891635499257186520205662004190179581465184858273590634696557067719668344569716772604494379268256417559005989196664062339943367426392267549671696091620704483335705235401024668972377058959013548701899237423163317609813480075906438821567501678027453981255872940165896765562906948275888682233026018398591561683968279253311810352982216449990605138841279476258998291555393112171672512247299540528273985304628059093340049555047981741901553118436996372565143437092164040501385121979087826864836002852441013290435451405818936965791830088594057993174801701555239838033825491101182302604693483923297155552732646664230339899386949247469662146601783799159535265663192798622519600080199294778264021930327804674406845390858689361183645138036024622999759181149374409868339056190354930762438018253181839721998646473911299168577029520666199783681191268719288387969624745653240780708319950931159323616116725759084631179863296728766212415593748082930558151101350076376704295363472805637813559350925898715117938481138744212886965977892516525139040863376874438253015614485120277306681922196720541898193702570355885540352668267759850827312025869672621201575016416207760471674541668295376322809412095582968275396449970226064500618788480102243996614437085271546164050332641040829307354667753670012241015315160013952802535500838629086649248253271677865717482331893600871123634025348607623548331397239596180750809096946397974233223417735790158178612741331748855629088340732705900553246041710742016160018303725512211509204034880759596775427996675371964469431717567054234107252511625358715489171574578479304777517899774723598872665991091538945488811618222438651723224465992160327444696552759313881273021480919406887970238509074105071808066821703115066838126027585207922256205186141921352880657758551963602504587265334948468963725795943612659061581738118921217900480358979991209140061985794462152498458564473369295078153567296201818251720281822962062936831573631653751528074225190111823253702351177610664803940345503699699208037095784870495785646943997234474258262569998608041243140247674073513323374199936066218946098722092264140092669753657824017634461763981521997119226219136508584203375683292957948563073632975937642581947768042371117470198355444599517718979158713784804470849343173517943800269775988799065209263727016757620989100649249277790139290067789688270481157537247255077854388424596882337360026236416764073030845206282134294301701605369452555608749844089881840152464688185413471165531348083450071936767808847178828505212544681448346850412422392584457798023562617507156540143036586660455094150665003248778589943633804236061867787254092465761897721097498706848304838082130151573830146281598905862080528755999259386441406295844212093958532689277331339576745477613093048842162872506248493879631984787279577095875465635013803960469019743694441996546910736934590725390122252181310568062868015617422771375425422209106466232597689466636780861666245204430735375550444974466951762888881642801337840709202391876433786768647147807880162471534334272202034098411011768290957484345424507121327462388443014612800575348423810123382495642833743034606424879522789397956839996920113680951463518836156462019057063161795046895734075593501902084338246542048532779483281408634769806186279989881229648075555962086774926497206070780542404761166097604241890965888018873735027199940548827053350115337885438800728312460914286268127990478092896975620706029422142841447344514680046143167682001640750053397540223424322177217456434741847020047763710403144096996427837529811812126999093061373016438435440619803496909856986800826405322182728111872725881192065183612822832173197471616932926246556344247662468294551754101114527143077792003917544284111176961413199426663155326179333146951914261328112918116870606040456416800180399145364936151721824514256765308265696290759951243242140057433018143404698921069198350343599629915865217541917472815612277351716569260985624821969133328022587501");
will return 25,001, which is the index of the above fib.
Instead use this formula:
(Fn) = (Fn-1) + (Fn-2)
n is a subindex, for understanding I say...
So let's code :D
function fibonacci(n) {
var f = new Array();
f[0] = 1;
f[1] = 1;
if(n == 1 && n == 2) {
return 1;
}
for(var i = 2; i < n; i++) {
f[i] = f[i - 1] + f[i - 2];
}
return f[n - 1];
}

Categories