Recursion in JavaScript With IF and WHILE - javascript

I just come up with little strange behavior in Javascript Recursion. My code
var temp1 = function(maxLength,accNumber) {
if(accNumber.length < maxLength)
{
accNumber = '0'+accNumber;
temp1(maxLength,accNumber);
}
return accNumber;
};
console.log(temp1(5,"23"));
So Here I am expecting output as "00023" but its giving "023" which is not expected.
But same code with while loop I am getting expected output. I am not understanding why.
var temp1 = function(maxLength,accNumber) {
while(accNumber.length < maxLength)
{
accNumber = '0'+accNumber;
temp1(maxLength,accNumber);
}
return accNumber;
};
console.log(temp1(5,"23"));
Which give me output "00023" as expected.

In fact you are missing a return statement inside your if block:
var temp1 = function(maxLength,accNumber) {
if(accNumber.length < maxLength)
{
accNumber = '0'+accNumber;
return temp1(maxLength,accNumber);
}
return accNumber;
};
console.log(temp1(5,"23"));
So the code wasn't returning anything if the if condition was passed, that explains why you got 023 instead of 00023.

Change your recursive call from
temp1(maxLength,accNumber);
to
return temp1(maxLength,accNumber);
Without the new return above, your code is detecting that accNumber.length is less than maxLength and correctly adding a '0' to the front. However, your recursive call is not modifying the local variable accNumber, and not returning, so it is basically doing nothing. After the recursive call, the program will exit the if block, and return the original accNumber, which is 023.

In the if loop, it's detecting that the length is smaller than maxLength, so it adds the 0 at the start and is done with the loop. It doesn't check again, if the length is still smaller. So after adding a single 0, it is done with the loop and returns output.
On the other hand the while loop will keep checking after each iteration.
Your function with if should look something like this:
function(maxLength,accNumber) {
if(accNumber.length < maxLength)
{
accNumber = '0'+accNumber;
return temp1(maxLength,accNumber);
}
return accNumber;
};

This question appears to be a duplicate of Strange result using recursion with while loop, but I wanted to play with this to see if type coercion might be involved.
I have re-authored this here, uncomment the console.logs to see more detail: this jsfiddle.
This is a scope issue from what I can tell, the if is creating a new scope each time and upon finally exiting, returns the first recursive value for accNumber (023) rather than the innermost recursive scope value (00023). The difference is that the while loop doesn't lose scope in the same way the if version of this does.
var temp1 = function(maxLength,accNumber) {
if(accNumber.length < maxLength) // There is no iteration
{
accNumber = '0' + accNumber;
temp1(maxLength,accNumber); // This creates a new scope
}
return accNumber; // You're only returning the initial iteration result
};
console.log(temp1(5,"23"));
But in the while version...
var temp1 = function(maxLength,accNumber) {
while(accNumber.length < maxLength)
{
accNumber = '0'+accNumber;
temp1(maxLength,accNumber); // Since it is in a while, scope is maintained
}
return accNumber;
};
console.log(temp1(5,"23"));

Related

Where do I place my return true statement

This is a basic javascript question I just want to better understand. I'm trying to understand if it matters where I place my return true statement. Here's the example code:
function isValid(input) {
for (var i = 0; i < input.length - 2; i++) {
var charOne = input.charAt(i);
var charTwo = input.charAt(i + 1);
var charThree = input.charAt(i + 2);
if (charOne === charTwo && charOne === charThree) {
return false;
}
return true;
}
}
isValid("ABB");
This returns true, but also returns true if I place the return true statement here:
function isValid(input) {
for (var i = 0; i < input.length - 2; i++) {
var charOne = input.charAt(i);
var charTwo = input.charAt(i + 1);
var charThree = input.charAt(i + 2);
if (charOne === charTwo && charOne === charThree) {
return false;
}
}
return true; // Moved this return statement
}
isValid("ABB");
Is one way wrong and the other correct?
Your first version, you are returning true within the for loop. That means its only going to execute your loop once and then return. That's likely a bug.
Your second version is likely correct. The return true statement executes from the function after the for-loop completes all iterations from [i..length-2).
second one, since in the first one after each iteration , you check if characters are equal and it will return false or return true in the first iteration itself.In, second one you check for all combinations and if it's never false then it must be true.
When you return inside a for loop you finish the whole loop and carry on outside it.
So the answer is it depends, if you want to miss out an item and carry on looping after the return statement then doing a return isn't what you want.
The return you put outside of the loop allows the loop to complete before returning the result.
Note a useful keyword you can use inside a loop if you want to finish the iteration rather than breaking the whole loop is continue.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/continue
I don't think one is wrong necessarily. I actually prefer a slightly different approach.
For clarity I generally will do something like this. So it is clearly one or the other.
With a return it is obvious that calculations within the function stop at that point. I just like it to look obvious.
if(charOne === charTwo && charOne === charThree) {
return false;
} {
return true;
}

recursion on returning vectors c++

Hey guys I am trying trying to right this javascript code into c++. I am doing quick sort and everything is straight forward minus the last step.
function quickSort(arr)
{
//base case if the arr is 1 or 0 then return the array
if(arr.length === 1 || arr.length === 0)
{
return arr;
}
var pivotIndex = Math.floor(arr.length/2);
var pivotValue = arr[pivotIndex];
var before = [];
var after = [];
for(var counter = 0; counter < arr.length; counter++)
{
if(counter === pivotIndex)
continue;
if(pivotValue <= arr[counter])
{
before.push(arr[counter])
}
else
{
after.push(arr[counter])
}
}
//this step I am having trouble rewriting in c++
return quickSort(after).concat(pivotValue).concat(quickSort(before));
}
I am having a hard time rewriting the recursive step in c++. I am not sure how concat 2 vector. I tried using the insert method but I keep getting an error about invalid use of void expression.
vector<int> quickSort(vector<int> arr)
{
if(arr.size() == 1 || arr.size() == 0)
{
return arr;
}
int pivotIndex = arr.size()/2;
int pivotValue = arr[pivotIndex];
vector<int> before;
vector<int> after;
//put values in before or after the piv
for(size_t counter = 0; counter < arr.size(); counter++)
{
if(counter == pivotIndex)
continue;
if(pivotValue <= arr[counter])
before.push_back( arr[counter]);
else
after.push_back( arr[counter]);
}
return //????? not sure how to do this
}
So, you realized that your core question was "how to concatenate two vectors", and you found a right answer: using insert. Now your question is about why you were getting "an error about invalid use of void expression." (That's the assumption my answer is for, at least.)
That's because you were likely trying to do something like the following:
return quickSort(after).insert( /* stuff */ );
which is wrong. In JavaScript, array.concat returns the concatenated array. It's return type is effectively Array, and so doing return arr.concat(arr2) returns an Array because arr.concat would return an Array. Further, in JavaScript, array.concat doesn't modify the array it was called on, but rather returns a new array.
In C++, however, vector.insert (#4 in the reference) returns void. That means it returns nothing. So when you try to return the result of insert, you get that error about invalid use of a void expression. Further, in C++, vector.insert does modify the vector it was called on.
So how do you use insert in this case?
vector<int> quickSort(vector<int> arr)
{
// ...
// Sort `before` and `after`
before = quickSort(before);
after = quickSort(after);
// Modify `after` and return it.
after.push_back(pivotValue);
after.insert(after.end(), before.begin(), before.end());
return after;
}
Note: My code isn't optimal and the idea of rewriting JS in C++ is also oddly specific. My answer is to simply outline the problem asked in the question, not to give a good C++ implementation of quick sort.
To concat two vector , you can use std::merge
like:std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(dst));

Javascript: For Loop, need help understanding this exercise with if/else

I have this exercise that already got the answer, but after hearing the explanations, still don't understand. This is the exercise:
"write a function isUniform() which takes an array as an argument and
returns true if all elements in the array are identical"
This is the solution
function isUniform(numArr) {
var first = numArr[0];
for (var i = 1; i < numArr.length; i++) {
if (numArr[i] !== first) {
return false;
}
}
return true;
}
I got it almost right, but i did a else statement with the "return true" and it didn't work. Why does it work with the "return true" outside of the for loop?
(edited) This is how i did the first time:
function isUniform(numArr) {
var first = numArr[0];
for (var i = 1; i < numArr.length; i++) {
if (numArr[i] !== first) {
return false;
}
else {
return true;
}
}
}
If you return true outside the loop, then it checks every element in the loop until one matches the if test or it gets to the end of the loop.
If you return true inside the loop then it will always hit a return statement for the first element and then stop the loop.
I got it almost right, but i did a else statement with the "return
true" and it didn't work
The solution below would return the wrong results in some cases because all it does is find the first element within the array that's equal to first variable and return true, even though it hasn't searched the entire array.
function isUniform(numArr) {
var first = numArr[0];
for (var i = 1; i < numArr.length; i++) {
if (numArr[i] !== first) {
return false;
}
else {
return true;
}
}
}
I have this exercise that already got the answer, but after hearing
the explanations, still don't understand.
let's assume this is your array:
[10,10,13,10,10]
let's assume this is the variable first:
first = 10;
The if statement below which is within the for loop basically says if the variable first ( 10 ) is not equal to the element at the current index i (nth number within the array) then return false. This makes sense because if at this moment the variable first is not the same with the element at the specified index for example index 2 (number 13) then there is no point to carry on. Hence, it will return false.
if (numArr[i] !== first) {
return false;
}
now let's assume the array is:
[10,10,10,10,10]
let's assume this is the variable first:
first = 10;
now the variable first will be compared against each elementwithin the array and it says "is 10 not equal to the current element". in this case that's false because 10 is equal to 10. This will propagate down the array and control will never pass inside the if block. Eventually, control passes down to the return true statement.
if (numArr[i] !== first) {
return false;
}
It works because is the final statement in your function. Basically your function will return true if the condition inside for loop will not be triggered
Let's say you've got a broken printer which once in a while messes the printout. Now you printed 20 copies and want to know if every paper is fine. So now you would have to iteratively compare every copy until you found one which is not matching (and know it's time to get a new printer?). Or you've gone the way through the hole stack and know every copy is fine (and you've wasted time for nothing).

Why is the first argument of reduce() returning undefined?

I'm trying to write a function that takes in an array as an input. If the integer is positive, it counts it. If the integer is negative, it sums it.
I figured that that the reduce() helper in js would be the best way to go about this, but I keep returning undefined for my first argument when it runs.
Here's my code:
function countPositivesSumNegatives(input) {
let countPositive = 0;
let sumNegative = 0
if (input === null || input === []){
return [];
} else {
return input.reduce(function(prev,num){
if (num > 0) {
countPositive++;
}else{
sumNegative = prev + num};
}, 0);
}
return [countPositive, sumNegative];
}
It throws me a TypeError that says:
TypeError: Cannot read property '0' of undefined
When I log 'prev' to the console inside of the reduce function, it logs undefined for all inputs except the first one. The first one, as expected, is 0. But for each following input it logs undefined. Why is this happening?
Thanks in advance.
The callback you pass to .reduce() needs to return the cumulative value (the value that will be passed as prev to the next iteration of the loop. Since you are returning nothing, you get undefined for the next iteration of your loop.
This complicates what you're trying to do because you are trying to keep track of two values in your loop. As such, you would either have to avoid using prev at all or you'd have to make it be a data structure that had both your values in it. Your use is not a textbook example for .reduce(). Your code is probably simpler with an iteration using .forEach() or for/of.
function countPositivesSumNegatives(input) {
let countPositive = 0;
let sumNegative = 0
if (!input || input.length === 0){
return [];
} else {
input.forEach(function(num){
if (num > 0) {
++countPositive;
} else {
sumNegative += num;
});
}
return [countPositive, sumNegative];
}
Well sorry but this is not a good implementation of this function. But we can correct your function as follows;
function countPositivesSumNegatives(input) {
let countPositive = 0;
let sumNegative = 0;
if (input === null || input === []){
return [];
} else {
sumNegative = input.reduce(function(prev,num){
if (num > 0) {
countPositive++;
} else {
prev += num;
}
return prev; // <---- THE MISSING PART
}, 0);
}
return [countPositive, sumNegative];
}
var data = [1,2,3,4,5,-4,7,-3];
console.log(countPositivesSumNegatives(data));
However while the code works just fine it still involves many issues. When getting into functors like .reduce() you should be able to keep everthing contained within itself and should not refer to variables at the outer scope. Accordingly one can simply rephrase this code as follows;
var data = [1,2,3,4,5,-4,7,-3],
cpsn = a => a.reduce((p,c) => c > 0 ? (p[0]++,p) : (p[1]+=c,p) ,[0,0]);
console.log(cpsn(data))

What does a function with multiple return statements return?

This is from an exercise out of Head First JavaScript Programming book.
function findCarInLot(car) {
for (var i = 0; i < lot.length; i++) {
if (car === lot[i]) {
return i;
}
}
return -1;
}
var lot = [chevy, taxi, fiat1, fiat2];
I'm not going to write all the code basically the chevy, taxi, etc, are objects and the function is assigned one of the four objects and that value is give to a variable in this exercise. My question is what is going on with:
return -1;
So doesn't that get returned when the function completes? Or is it negated when
return i;
happens? Or are both values returned? Could someone sort this out for my poor brain and tell me what the rules are here.
Depending on which return it hits, that will be the only thing it returns
function findCarInLot(car) {
for (var i = 0; i < lot.length; i++) {
if (car === lot[i]) {
return i; // If this if statement is true I will return here and this function will end and I will never make it to the next return
}
}
return -1; // This will only get called if the above if statement is false
}
var lot = [chevy, taxi, fiat1, fiat2];
To me this function looks like, if you called it, it will loop through the car array, and if it finds said car in the array, it will return the index for that car.
If no car is found in the array, it will return -1 meaning the car doesn't have an index thus it is not in the array.
So, if we have
var lot = [chevy, taxi, fiat1, fiat2];
and we run
console.log(findCarInLot("fiat1")); // This will return 2 (Third element of the array)
This is returned from the return i inside the if statement and you will never see return -1
But if we do
console.log(findCarInLot("lamadamadingdong")); // This will return -1 as it was never found in the array of cars
Hope this helps.

Categories