I'm trying to calculate a series with a recursive function and jQuery but I don't know how to log each recursion that the function is making so I could get the series members.
the code is the following:
$(document).ready(function () {
$("#button").click(function () {
var n = $("#number").val();
function series(n) {
if (n == 1) {
return 6;
} else {
return 0.5 * series(n - 1) + 4;
}
}
console.log(series(n));
});
});
The problem is that the function only logs the last series member. For example if n = 4 the series should be 6, 7, 7.5, 7.75.
The function only returns 7.75.
This is the series formula: series(n) = 0.5 * series(n - 1) + 4, if n = 1 then series(n) = 6;
Thank you!
It's not the most beautiful looking example, but if you take your code and then wrap it in another function with a results array. Then call your inner recursive function and store them to that array it can return the results as an array. You can then use a join to make it into a string to display using jQuery or console log it.
Fiddle: http://jsfiddle.net/mcfarljw/hPWuW/
function getSeriesArray(n) {
var results = [];
function series(n) {
if (n === 1) {
results.push(6);
return 6;
} else {
var result = 0.5 * series(n - 1) + 4;
results.push(result);
return result;
}
}
series(n);
return results;
}
Your use of console.log() is only accepting the output of the outermost series call. If you want to log every iteration you either need to log inside your series method or keep track of every result during the iterations in the series method and then log whatever you used to keep track.
This seems like homework so I wont give too much away, but it might help is used the inspector in browser to walked the execution and get a feel for how the code is flowing.
Try this
$(document).ready(function () {
$("#button").click(function () {
var n = $("#number").val();
function series(n) {
var val=6;
if (n != 1) {
val= 0.5 * series(n - 1) + 4;
}
console.log(val);
return val;
}
});
});
Related
I'm trying to create a simple program in javascript where the Fibonacci square can be created by a random number sequence but I can't seem to connect both parts of my code. The first side being: the call for a random number and the second part: calculating the Fibonacci square.
var n = function getRandomNum() {
return Math.floor(Math.random()*100) +1;
}
function fib(x) {
if (x < 2) {
return x;
} else {
return fib(x - 1) + fib(x - 2);
}
}
console.log(fib(n));
Tell me where I'm going wrong. These are the errors I get when I run it.
RangeError: Maximum call stack size exceeded
at fib:7:13
at fib:11:12
at fib:11:12
at fib:11:12
at fib:11:12
at fib:11:12
Aside from not invoking the random number generator, you're using a very poorly optimized algorithm. If you think through all the redundant calls that need to take place, you'll see why the stack limit is reached.
var n = function getRandomNum() {
return Math.floor(Math.random() * 100) + 1;
}(); // <-- quick inline invocation... not normally how you'd use this.
console.log(n);
function fib(x) {
function _fib(x, a, b) {
if (x < 2) {
return a;
}
return _fib(x - 1, b, a + b);
}
return _fib(x, 0, 1);
}
console.log(fib(n));
Since you don't call n function, you should call it like the following.
var n = function getRandomNum() {
return Math.floor(Math.random()*100) +1;
}
function fib(x) {
if (x < 2) {
return x;
} else {
return fib(x - 1) + fib(x - 2);
}
}
console.log(fib(n));
But, there's a huge problem in your code, as #rock star mentioned, there's no any optimizing process in your code. That is why your code has caused the problem on memory leak
To avoid this, you can simply use memoization, click this link you don't have any clue on it.
Javascript Memoization Explanation?
So, your code can be improved like the folloiwng, by adapting memoization algorithm.
var n = function getRandomNum() {
return Math.floor(Math.random()*100) +1;
}
var result = [];
result[0] = 1;
result[1] = 1;
function fib(x) {
var ix, ixLen;
for(ix = 0, ixLen = x; ix < ixLen; ix++){
if(!result[ix]){
result[ix] = result[ix-2] + result[ix-1];
}
}
console.log('n:', x, ' result: ', result[ix-1]);
return result[ix-1];
}
console.log(fib(n()));
Compare the result with this site.
http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/Fibonacci/fibtable.html
I am trying to get factorial of all the numbers of array(recurArray) using recursion and without loops.
I am getting Error "Maximum call stack size exceeded"
I think there is some issue with the for loop logic, would be helpful if someone can explain the cause of error and how to fix it
Thanks.
//code
function recur(){
var n;
var result;
if(n == 1)
return 1;
var recurArray = [5,6,7,8,9];
for (var i = 0;i<recurArray.length;i++){
n = recurArray[i];
result = n * recur(n-1);
n=n-1;
}
console.log("val of n " + n + "value of i " + i);
return result;
}
recur();
Your recur() function should probably take n as an argument, otherwise n will never be 1 (if(n == 1) return 1;) and your function will keep calling itself until it crashes.
Try function recur(n){ instead.
As you have array, you should use loop.
function recur(x) {
if(x==0) {
return 1;
}
return x * recur(x-1);
}
function getFact() {
var recurArray = [5,6,7,8,9];
for (var i = 0;i<recurArray.length;i++){
console.log(recur(recurArray[i]));
}
}
getFact();
In Each occurence you reset the factorial so it keep rolling for fact(5) you need to have a function that calculate the factorial and an other one for the loop over your array like this :
function recur(n){
if(n == 1){
return 1;
} else {
return n* recur(n-1);
}
}
var recurArray = [5,6,7,8,9];
for (var i = 0;i<recurArray.length;i++){
n = recurArray[i];
result = recur(n);
console.log("factorial of n " + n + " is " + result);
}
Try something like this:
function factorial(number) {
var temp;
if(number <= 1) return 1;
temp = number * factorial(number - 1);
return temp;
}
In this case factorial(5); will return !5 . Recursive functions are not supposed to have loops inside(They can, but the execution time would be horrendous).
Also recursive functions call themselves with different parameters(otherwise you would overflow the browser stack). In your case you call recursive() an infinite amount of times and the loop always starts from 5 , infinitely. The passed parameter is what stops the recursion.
I have range function and output functions they works correct,now I want create sum function for using as callbac function in range function,but when some function executed local variable let us say total or sum initialize 0(zero),how can solve this problem?
function range(start,end,callback,step) {
// body...
step=step || 1;
for(i=start;i<=end;i=i+step){
callback(i);
}
}
function output(a) {
// body...
console.log(a);
}
function sum(m){
var total=0;
// some code
}
range(1,5,output);
range(1,5,sum);
function range(start,end,callback,step) {
// body...
var aggregate;
step=step || 1;
for(i=start;i<=end;i=i+step){
aggregate = callback(i, aggregate);
}
}
function output(a) {
// body...
console.log(a);
}
function sum(m, aggregate){
return m + aggregate;
}
range(1,5,output);
range(1,5,sum);
This way you could even do cool stuff like
function conc(m, aggregate) {
return aggregate + m.toString();
}
range(1,5,conc,2); //prints 135
Continuition style code, like you've started it with range(), can get really weird and cumbersome.
And please, please, mind defining your local variables. like i
function range(start,end,callback,step) {
step=step || 1;
for(var i=start; i<=end; i=i+step)
callback(i);
}
function output(...label) {
return function(...args){
console.log(...label, ...args);
}
}
function sum(callback){
var total = 0;
return function(value){
//will log ever intermediate total, because sum() has no way to tell when the sequence is over.
callback(total += +value || 0);
}
}
range(1,5,output('range:'));
range(1,5,sum(output('sum:')));
In this case, I'd prefer using a generator instead, although the higher order functions get obsolete.
function *range(start,end,step) {
step = +step || (end < start? -1: 1);
for(var value = start, count = (end - start) / step; count-- >= 0; value += step)
yield value
}
function sum(iterator){
var total = 0, v;
for(v of iterator) total += +v || 0;
return total;
}
console.log("range:", ...range(1,5))
console.log("sum of range:", sum(range(1,5)))
//just to show that this works with your regular array as well
console.log("sum of array:", sum([1,2,3,4,5]));
//and some candy, as requested by Bergi ;)
//I like to stay with the interfaces as close as possible to the native ones
//in this case Array#reduce
var fold = (iterator, callback, start = undefined) => {
var initialized = start !== undefined,
acc = start,
index = 0,
value;
for(value of iterator){
acc = initialized?
callback(acc, value, index):
(initialized=true, value);
++index;
}
if(!initialized){
throw new TypeError("fold of empty sequence with no initial value");
}
return acc;
}
//and the ability to compose utility-functions
fold.map = (callback, start = undefined) => iterator => fold(iterator, callback, start);
console.log(" ");
var add = (a,b) => a + b; //a little helper
console.log('using fold:', fold(range(1,5), add, 0));
//a composed utility-function
var sum2 = fold.map(add, 0);
console.log('sum2:', sum2( range(1,5) ));
Clearly a range function should not take a callback but be a generator function in modern JavaScript, however you were asking how to write such a callback.
You've already tagged your questions with closures, and they are indeed the way to go here. By initialising a new total within each call of the outer function, you don't need to worry about how to reset a global counter.
function makeSum() {
var total=0;
return function(m) {
total += m;
return total; // so that we can access the result
}
}
var sum = makeSum();
range(1, 5, sum);
output(sum(0));
Won't simply calling the callback on the range array suffice if the callback is not undefined? Like this:
> function range(n, callback) {
const r = [...Array(n).keys()]
if (callback) {
return callback(r)
}
return r
}
> function sum(arr) {
return arr.reduce((a, b) => a + b, 0)
}
> range(10)
> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
> range(10, sum)
> 45
I want to create a function (reduce) that does the following:
Where:
var collection = [1, 2, 3];
and
function iterator(total, element) {
return total + element;
};
if initial is defined as 3:
reduce(collection, iterator, 3)
will do this:
3 + 1
4 + 2
6 + 3 = 9
if initial is undefined:
reduce(collection, iterator)
will do this:
1 + 2
3 + 3 = 6
Here is my code:
var reduce = function(collection, iterator, initial) {
if (initial === undefined) {
var total = 0;
} else {
var total = initial;
}
each(collection, function(element) {
total = iterator(total, element);
});
return total;
}
It works, but you can see that I've hard-coded total = 0, but I want this code to work in other scenarios (for example, multiplication, where I wouldn't want 0 to make the whole product 0).
This is how I would implement it:
alert(reduce([1,2,3], add, 3)); // 9
alert(reduce([1,2,3], add)); // 6
function add(a, b) {
return a + b;
}
function reduce(array, iterator, initial) {
var length = array.length;
var index = 0;
if (arguments.length < 3) {
if (length > 0) var result = array[index++]; // Note 1
else throw new Error("Reduce of empty array with no initial value");
} else var result = initial;
while (index < length) result = iterator(result, array[index++]);
return result;
}
The code is pretty self explanatory. Nevertheless, here's how it works, if the number of arguments passed are less than 3 it means that initial was not given. Hence we set result to array[0] and increment index. If array is empty then we throw an error instead. Otherwise we set the result to the initial value passed to the function. Everything else works as normal.
Note 1: The reason we don't modify initial (i.e. write initial = array[index++]) is because if we use arguments in a function and also modify the parameters of the function then the function will not be optimized in V8. Hence, it will execute slower.
Hope this helps.
I attempted to create a recursive function to iterate through a data set, but it does not properly break out and is infinite
jsfiddle of code shown
var data = [{a: 1,b: 1}, {a: 2,b: 2}],z = 0;
function some(a, b, cbk) {
console.log(a + ':' +b);
cbk();
}
function main() {
var cbk = function () {
if (z < data.length) {
main();
} else {
console.log('end');
}
z++;
}
some(data[z].a, data[z].b, cbk);
}
main();
Why is this an infinite loop?
jsFiddle Demo
There were a few things going on here that made the recursion fail involving the iteration control. By starting with z = 0, and comparing to .length, z will need to be pre-increased prior to the conditional check if( z < .length ).
The reason is that following the path of recursion, z is never incremented and so the recursion is infinite causing a lockout of the page. So, z needs to be handled before the recursive call takes place, preferably before the comparison to the .length.
In your original version, this was taking place not only after the if statement, but also after the recursive call. Fixing this iterator will fix your recursion.
if (++z < data.length) {
I was told to undelete this because it's answerable although I am gaining much hate, I found have noticed my mistake and did this.
var data = [{
a: 1,
b: 1
}, {
a: 2,
b: 2
}],
z = 0;
function some(a, b, cbk) {
console.log(a + ':' +b);
cbk();
}
function main() {
var cbk = function () {
z++;
if (z < data.length) {
main();
} else {
console.log('end');
}
}
some(data[z].a, data[z].b, cbk);
}
main();
I don't know how fluent at reading code you are, but I've tried to break down the concept of linear recursion into as generic a way as I could imagine
function recurse(data, /* fns */ step, worker, joiner, /* vals */ first, empty) {
function recursor(data, current) {
var result = worker(data, current), // do work with current iteration
next = step(data, current); // find the next iteration
if (next !== null) // if found
return joiner( // return
result, // the result from this time
recursor(data, next) // + the result from next time
);
else // if not found
return joiner( // return
result, // just this result
empty // this join is helpful for joining arrays/objects/etc
);
}
return recursor(data, first); // start it
}
So, an example based on what you were doing
var data = [{a: 1,b: 1}, {a: 2,b: 2}];
function init(data) {
function logger(data, i) { // a function describing what to do
var e = data[i]; // with this iteration
console.log(e.a + ':' + e.b);
return e.a;
}
function step(data, i) { // a function describing how to find
i = i + 1; // the next iteration
if (i < data.length) return i;
return null; // null = end
}
function add(a, b) { // a function describing how to join
return a + b; // two iterations together
}
return recurse(data, step, logger, add, 0, 0);
}
init(data); // run everything safely in it's own closure
/*
1:1
2:2
3 // === 1 + 2 + 0, from return of logger and result of add
*/
Of course in practice you could do a lot of this in-place rather than a function for each thing, and the step can usually be simplified so much that you don't need to var for result and next because you don't have to cache anything for an if test.