I wrote a function yesterday to count the number of "a" characters in a string. My teacher told me to refactor the code into a recursive function and I don't really know how to do so.
I would like some feedback on the subject, and by the way I'm an absolute beginner in JavaScript.
function numberOfA(n){
var numberA =0;
for (i=0; i<=n.length; i++){
if(n.charAt(i)== "a" ){
numberA++;}
}
return numberA;
}
to call the function following piece of code :
var n = prompt("type a word");
var output = numberOfA(n);
alert (output);
Thanks in advance !
The goal of recursion is to make a function which calls itself.
You might have mutual-recursion -- function A calls function B, calls function A... but that's certainly not needed here, and is better suited for when you know that you need to do two distinct things (one per function) and know that you need to do them in a leapfrog pattern.
Where recursion comes into play is when you're thinking about loops.
Normally, when you're doing things with loops, you might end up having two or three loops inside of one another.
Instead of worrying about managing loops, recursion is a way of thinking about what happens in a single-iteration of a loop, and writing ONLY the code needed to do that.
A really simple example of singular recursion might be to log all elements of an array to the console.
This is not a practical example -- it's a trivial example which has most of the pieces you need to make practical examples.
var array = [ "one", "two", "three", "four" ];
function listNextItem (array, index) {
var item = array[index];
if (!item) { return; }
console.log(item);
listNextItem(array, index + 1);
}
listNextItem(array, 0);
I've created a very simple function which looks like the inside of your innermost loop.
It sets an item variable, based on array[index].
If it doesn't exist, we're done, and we can return out of the function, so we don't try to go on forever (this is very important in recursion).
If it does exist, we log the item's value.
Then we call the exact same function, and pass it the exact-same array, but we pass it the value of index + 1.
Did this change anybody's life, or make loops obsolete?
Not really.
But it's the first step to getting recursion.
The next step is getting a return from recursion.
function recursiveAddOne (current, max) {
if (current === max) { return current; }
return 1 + recursiveAddOne(current + 1, max);
}
var total = recursiveAddOne(0, 3); // === 3 + 1 + 1 + 1
total; // 6
Normally in my return statement, I'd be sending the answer back to the variable in the outside world.
I'm still doing that, but here I'm adding a call to the same function, as part of my return.
What does that do?
Well, the outside function can't return a value until the inside function returns.
The inside function can't return a value until ITS inside function returns...
...and it goes all the way down until my termination-condition is met.
That condition returns a value to its outer function. That outer function returns that added value to ITS outer function... ...all the way up to where the outermost function gets handed the value of all of the other functions put together, and then returns THAT to the outside world.
It's like giving each Russian Matryoshka ("babushka") doll a piece of work.
You start with the biggest one, and go all the way inside to the tiniest one.
The tiniest one does its work first, and hands it back to the next one, which does its work and hands that back... ...all the way back until you're outside again.
Well, the basic concept of recursion is solving a problem with a smaller version of itself.
You have a function, numberOfA which gives you the length of a string(or maybe substring).
So let's say you have the string "javascript' the first string is at index 2.
It's logical to say that the number of as in your string is equal to 1 plus the number of as in the entire substring after the first a.
So what you do, is you add 1 to the number of as in the substring vascript
So here's some psudocode
function numA(str)
{
var substring = substr(index_of_first_a, str.length - index_of_first_a
return 1 + numA(substring);
}
function numberOfA(n, count){
if(!n.length) {
return count;
}
if(n.charAt(i)== "a") {
++count;
}
return numberOfA(n.substr(1), count);
}
var numberA = numberOfA('asdfafeaa', 0);
Try this:
function numberOfA(n) {
return n == "" ? 0 : (n.charAt(0) == "a" ? 1 : 0) + numberOfA(n.substring(1))
}
Here's how it works:
If n is the empty string, return 0 and finish the recursion. This is the base case of the recursion.
Else if the character at the first position in the string is an "a" add one, if not add zero and either way advance the recursion by removing the first character from the string. This is the recursive step of the recursion.
As you can see, every recursive solution must have at least a base case and a recursive step.
<!DOCTYPE html><html lang="en"><body><script>
var foo = function foo() {
console.log(arguments.callee); // logs foo()
// callee could be used to invoke recursively the foo function (e.g. arguments.callee())
}();
</script></body></html>
arguments.callee function will call the currently being executed method.
Related
I know there are many threads for recursion here. And technically I do understand the principle behind recursion, I'm just more of curious as to where the actual recursion counter is stored or how does the compiler keep track of it
This is probably better understood by code. I have created a simple recursion function in javascript.
function factorial(number){
if (number > 1) {
return number * factorial(number - 1);
} else {
return number;
}
}
Now, everybody understands how this works. We call a recursive function on the factorial which repeats recursively until a function end.
My question would be, how come the factorial function stops executing the recursion at the correct time? If we tried to debug the function in our mind, my understanding is, it would look something like this:
Let's say we called factorial(3);
Function Invoked -> Load Arguments
Calculcate the IF condition -> 3 > 1 -> apply recursive function
3 * recursive(2) * recursive(1) => 3 * 2 * 1 = 6
Now my question is, how is that possible? How come a) if we reduced the recursive counter to 1, we didn't enter the else { statement given it should be evaluated as false, and b) how come the recursive counter knew, to loop the recursive function only number-Nth amount of times?
For better illustration, I added the following line of code
document.write("entered with number " + number + "</br>"); so we'll print it out every time we enter the if condition.
function factorial(number){
if (number > 1) {
document.write("entered with number " + number + "</br>");
return number * factorial(number - 1);
} else {
return number;
}
}
document.write(factorial(3) + "<br/>");
As you can see, the if condition if condition evaluated as true and printed out the message for 3 and 2. How come the counter didn't loop lower and how come we never returned to the initial else { return number; } if we called the recursive operation on factorial(2-1)?
It is pretty difficult question to word, so if you have any idea on how to formulate it better, feel free to edit my question!
Here's a verbal description of what the recursion is doing, in too much detail:
You call factorial(3) in your document.write().
factorial(3) wants to return 3 * factorial(2). Before it can return a value, it has to work out what factorial(2) means.
So now we have that factorial(3) waiting for the results of factorial(2). factorial(2) runs, and wants to return 2 * factorial(1). Before it can return a value it has to work out what factorial(1) means.
Now we have factorial(3) waiting for the results of factorial(2), which is waiting for the results of factorial(1). factorial(1) runs, and sees that its input is 1, so hits the "else" block, so just returns 1 to its caller, the factorial(2).
Now the factorial(2) has what it needs, so can return 2 * 1 to its caller, the factorial(3).
Now the factorial(3) has what it needs, so can return 3 * 2 to its caller.
The calling document.write receives "6".
The recursion "knows" where to stop because eventually it reaches a point where it just returns the number 1, instead of returning something that depends on another call to factorial(). If the function always tried to call itself, there'd be no way out of the recursion loop; it would just keep going until the stack overflows.
Except for factorial(1), every call to factorial(n) will end up calling factorial(n-1) -- so note that factorial(0) or factorial(-1) or factorial(1.01) will never wind up reaching 1, so the recursion will just keep running until the stack overflows. When writing recursive functions, it's a good idea to watch for and handle input that will never reach an exit point; in this case you'd want to throw an error if the input is anything other than a positive integer.
How come the counter didn't loop lower and how come we never returned to the initial else { return number; } if we called the recursive operation on factorial(2-1)?
It did, but your document.write inside the function was inside the if block so nothing was printed when the function went into the else block instead. Here's a more verbose version of the same function, which may give you a clearer picture of what happened:
function factorial(number) {
document.write("entered with number " + number + "<br>");
if (number > 1) {
document.write("recursing<br>")
return number * factorial(number - 1);
} else {
document.write("Returning 1<br>")
return number;
}
}
document.write(factorial(3) + "<br>");
what exactly determines when does recursion stop? When the recursion of the function returns the same result twice (in this case 1?) or is there some different trigger?
Try not to think of this in terms of there being a "counter" of some sort keeping track of when the function should stop recursing, or a "trigger" that actively stops it -- that's a misleading way to look at it. Each instance of the function knows only what input it received, and what it wants to return. Most of the time what it wants to return happens to include a call to the same function, that's where the recursion comes from; when what it wants to return doesn't involve a function call, the recursion comes to an end.
For this particular function, for any input other than 1, it calls a new instance of itself with input n-1 (and waits for the results before it can return to its parent caller), so the recursion continues. For input of 1, it doesn't call itself, so the recursion ends. That 'else' block is your "trigger" (though, again, that's a misleading way to think of it; it's not "triggering" anything, it's just returning a number instead of calling a function to return its results.)
f(3) calls f(2) which calls f(1) which doesn't call anything. If you edited the function to call itself with n+1 instead of n-1, then f(3) would call f(4) which would call f(5) and so on until you run out of memory.
I have an assignment to count repeated strings base on a Heap's Algorithm Permutation.The first thing I want to do is output the swapped strings, I found this code from jake's answer Can someone please help me understand recursion within this code in a loop? The output of this function are swapped strings.
function permAlone(string) {
var arr = string.split(''), // Turns the input string into a letter array.
permutations = []; // results
function swap(a, b) {
debugger; // This function will simply swap positions a and b inside the input array.
var tmp = arr[a];
arr[a] = arr[b];
arr[b] = tmp;
}
function gen(n) {
debugger;
if (n === 1) {
var x =arr.join('');
permutations.push(x);
} else {
for (var i = 0; i != n; i++) { // how does this loop executes within the call stack?
gen(n - 1);
debugger;
swap(n % 2 ? 0 : i, n - 1); // i don't understand this part. i understand the swap function, but I don't get how indexes are swapped here
}
}
}
gen(arr.length);
return permutations;
}
permAlone('xyz'); // output -> ["xyz","yxz","zxy","xzy","yzx","zyx"]
I have been experimenting it on debugger but still can't get what's happening.
I'm not sure what you mean by
understand recursion within this code in a loop
If you mean you want to see the algorithm in a loop form rather than a recursion version you can see them one by side in pseudocode in the wikipedia page here.
For your questions within the code:
how does this loop executes within the call stack?
You are right to refer to the call stack, and this is a general question regarding recursion. If you don't understand how recursion works with the stack you can refer to this really nice and simple video that demonstrates recursive calls using factorial calculation in java (start around min 4:00).
The line you look at is no different than any other line in the recursive function. We start by defining i and assigning the value 0 to it. We continue to check if it satisfies the condition of the for loop. If it does we step into the loop and execute the first line inside the loop which is the recursive call. Inside the recursive call we have a new stack frame which has no knowledge of the i variable we defined before executing the recursive call, because it is a local variable. So when we get to the loop in the new call we define a new variable i, assigning it 0 at first and incrementing it as the loop repeats in this stack frame/call instance. When this call finishes we delete the stack frame and resume to the previous stack frame (the one we started with) where i=0 still, and we continue to the next line.
All the calls have access to the arr and permutations variables since the function is defined in the same scope as the variables (inside the function permAlone) so within each call - no matter what the stack frame we are in, the changes made to those are made to the same instances. That's why every push done to permutations adds to the existing results and will be there when the function returns the variable at the end.
i don't understand this part. i understand the swap function, but I don't get how indexes are swapped here
Indexes are not swapped here. It is merely a call for the swap function with the correct indices.
swap(n % 2 ? 0 : i, n - 1);
is just
swap(a, b);
with
a = n% 2 ? 0 : i;
b = n - 1;
If the a part is what confuses you, then this is a use of the ternary operator for conditional value. That is, it's symbols used to form an expression that is evaluated differently according to the circumstances. The use is by
<<i>boolean epression</i>> ? <<i>value-if-true</i>> : <<i>value-if-false</i>>
to evaluate the above, first <boolean expression> is evaluated. If it's value it true then the whole expression is evaluated as <value-if-true>. Otherwise, the whole expression is evaluated as <value-if-false>.
In the code itself, for a, n % 2 is the boolean expression - js divides n by 2 and takes the remainder. The remainder is either 1 or 0. js implicitly converts those to true and false respectively. So if n is odd we get
a = 0
and if it's even we get
a = i
as the algorithm requires.
I wrote a simple function to sort objects not expecting it to work but it does:
function sortObjs(objArr,field) {
objArr.sort(
function(a,b) {
if( isNaN(a[field]) ) {
return a[field].localeCompare(b[field]);
} else {
return parseFloat(a[field]) - parseFloat(b[field])
}
}
);
return objArr;
}
When I call this function I get my sorted objects without issue. But I was not expecting it to work because I thought the first two return statements would exit the function before it got to the last statement: return objArr.
You have a nested function. The first two returns will exit the inner function, while the last one will exit the outer one.
EDIT:
You can think of function returns as "replacing" the function with the returned value. For example:
var i = getSum(1, 3);
function getSum(a, b) {
return a + b;
}
The function getSum returns the sum of a and b. The line var i = getSum(1, 3) will execute the lines of code contained in the function with a = 1 and b = 3. The value that is returned "replaces" the function call. So now the line of code looks like var i = 4;. Although this is not exactly how it works, it's a good way to conceptualize it. This is a special case because you aren't actually running the inner method here, you're passing it as a variable.
Let me know if you have any more questions!
To understand why the inner function's return statements would not have an effect on the return statement in the outer scope, you need to understand how the Array.prototype.sort() function works.
The function arr.sort([compareFunction]), takes a function as a parameter.
compareFunction
Optional. Specifies a function that defines the sort order.
If omitted, the array is sorted according to each character's Unicode code point value,
according to the string conversion of each element.
The logic you write inside the compareFunction gets executed when
the java script engine tries to compare two elements during its
comparison operation.
Hence for each comparison that it makes, the function would return a
value, based on which the elements would be ordered.
This implies that the compareFunction that we pass on as a parameter
would be used to just obtain a value based on which two elements can
be compared and not exit the sort operation, leave alone exiting the
outer function.
Having said this, the code return objArr;, takes no effect, since the array would be sorted in place.
I'm going through Eloquent JavaScript book and am on chapter 5 (Higher-Order Functions) currently. I'm doing good so far and have understood material clearly, but I've come to realize that I don't understand what function values are exactly and how they work. I do understand what functions are and am quite comfortable with the syntax of creating them using the function keyword as you would do in C for example.
Assume the following code from the book:
function forEach(array, action) {
for (var i = 0; i < array.length; i++)
action(array[i]);
}
var numbers = [1, 2, 3, 4, 5],
sum = 0;
forEach(numbers, function(number) {
sum += number;
});
console.log(sum);
How does the forEach function, when called, determine what is the number? How does it extract number from the numbers array. I do understand that action argument in the definition of forEach function "hooks" the action to the element which is currently pointed by the for loop, but I interpret the code as follows:
function(number) {sum += number;}action(array[i])
which doesn't make much sense.
If you could shed light on this issue I'd be more than thankful and also explain what the function value is exactly? How does it differ from function and/or function return value?
Thank you.
From what I've understood, I think that you are being confused by the JavaScript callback function.
In javascript, a function like this:
Look at your code:
function forEach(array, action) {
for (var i = 0; i < array.length; i++)
action(array[i]);
}
forEach(numbers, function(number) {
...
For each item of the array (first argument, accessed via array[i]) you are calling action with that value, action(array[i]).
In forEach(numbers, function(number) {, you have passed action (the second argument) as a function with one input. This is the function being called by forEach with each array element. With each pass of the for loop within forEach, this function is called with the new value.
I think trying this with other examples (just start your js console now and begin messing around) will help you to learn this concept.
If I made a function
function run(callback){
callback();
}
and called it like so:
run(function(){
console.log('foo bar baz');
});
I'd expect to see "foo bar baz" printed to the console.
If I now make a new function, and call it,
function withTheAnswer(callback){
callback(42);
}
withTheAnswer(function(theAnswer){
alert('The answer is ' + theAnswer);
});
I'd expect 42 to be alerted.
Honestly, as you start to learn more about JS, you'll see this used a lot, and therefore fully understand it.
I don't understand what function values are exactly and how they work
A function (in JavaScript) is an object that can be called. A function call is nothing special, it is just any expression (like a variable evaluation) followed by a pair of parenthesis with arguments in between.
You could write
var addToSum = function(number) {
sum += number;
};
forEach(numbers, addToSum);
or
function addToSum(number) {
sum += number;
}
forEach(numbers, addToSum);
and it means basically the same: You have a function object, a variable addToSum that refers to it, and it is passed to the forEach call.
How does the forEach function, when called, determine what is the number?
It doesn't know anything about the numbers. All the forEach function sees are an array value (referred to by the parameter name array) and a function value (referred to by the parameter name action). Then it loops over that array, and calls the action function with each of the elements. Only inside the called function this array element is know as number.
I interpret the code as follows: function(number) {sum += number;}action(array[i]) which doesn't make much sense.
If you expand the variable to its value, the variable name disappears:
(function(number) {sum += number;})(array[i]);
which does actually make sense - as I've written above, a function call is just an expression followed by parenthesis. And that expression needs to evaluate to a callable object, which this function expression does.
You might also rewrite it as
function action(number) { sum += number; }
action(array[i]);
if that make more sense to you.
action attribute is a function. This function doesn`t called until you put: 'action([a number])'. Then inside the for loop for each element of array attribute is called the function action with corresponding number.
As #theonlygusti says this function are called callbacks.
I am trying to create a function that will trim off array values that are not 4 chars long. For some reason, it does not work. I think that it might be with the return statement but I am not sure and I need help with it. Here is the code for the function: (Please don't suggest ways of making the hasher better, I just need help on the function)
function cutit(seq){
for(var i=0;i<seq.length;i++){
var temparr=seq[i].split("");
if(temparr.length % 4 !== 0){
seq.splice(seq[i],1);
return seq;
}
}
}
Five things:
Yes, the return should happen after the loop not after the first found item to delete.
.splice() takes an index for the first parameter, not the element. Pass i instead of seq[i].
splice(…, 1) does decrease the length of the array you're iterating over by one. You need to take care of that and decrease your counter as well to have a look at the i index again, where on the next iteration the next element will sit.
Instead of splitting the string into an array of single chars and taking the length of that, just take the length of the string directly.
Your functions removes all strings that are not a multiple of 4 long, not all that are not exactly 4 characters long. Not sure whether that is intended.
function cutit(seq) {
for (var i=0; i<seq.length; i++) {
if (seq[i].length !== 4) {
seq.splice(i--, 1);
}
}
return seq;
}
Also, notice that mutating an array is seldom a good idea (especially in an inefficient way like this with multiple splices). Returning a new array is so much easier, and you can use the higher-order filter Array method for that:
function cutit(seq) {
return seq.filter(function(str) {
return str.length === 4;
});
}