JavaScript Closure: array.push is not reflecting current value

I am trying to complete “No Repeats Please” challenge of #FreeCodeCamp.

I am not able to understand there is difference in output of result.push(array); and result.push(array.join()); Below is my code.

function permAlone(str) {

//Variables for main function

var result = [];
str = str.split("");
generateArray(str,3);


//function to swap the array members

function swap(array,pos1,pos2){
 var temp;
 temp = array[pos1];
 array[pos1] = array[pos2];
 array[pos2] = temp;
}
  
//function to generate array Permutations

function generateArray(array,n){
	 if(n == 1){
			
		result.push(array); //returns 2d array and with each element has "ABC"
		//result.push(array.join('')); //return correct value
		console.log(array);
	}
	else{
		for(var i = 1;i<=n;i++){
			generateArray(array,n-1);
			if(n%2){ //If n is Odd
				var j = 1;
			}
			else{
				var j = i;
			}
		swap(array,j-1,n-1);//to counter zero indexing of JavaScript	
		}//end for
	} //end else

} // end generateArray
 
 
  console.log(result);
}

permAlone('ABC');

Hm. The quick answer is array.join produces a string, not an array. So pushing its results to array yields a 1-dimensional array, while pushing individual arrays into array yields a 2-d one.

I’m more puzzled by why you’re coding in the “3” in generateArray(str,3) instead of using str.length, but maybe that’s for initial testing purposes?

2 Likes

What I really want to understand is, why array value is getting duplicated in result.push(array)?. Which gives a 2d array having each element same as 1d array.

Yes “3” is for testing as I am still not done.

Thanks for help.

I’m sorry to say it’s still perplexing me. See, I’m not clear why the result.push portion is getting executed at all. Among the things that confuses me is that you’re calling generateArray() from within its own definition. That seems to me like it ought not to work, but clearly something is happening.

Anyway, as you call generateArray(str,3), the first if block oughtn’t to execute at all, because n !== 1. And, within the else block, as you call generateArray(array,n-1), that’s still just 2… right? So why is anything ever getting pushed? I’m afraid it’s lost me. (Another thing that might not be affecting the functionality, but makes it problematic to reason about: in the definition of generateArray you name the first argument array, but what you pass to it at the top is a string (and is named str).)

Let me think backwards here:

  1. You want to solve the whole algorithm by returning a number.
  2. That number is likely the length of an array that you’re trying to build by pushing permutations.
  3. It looks like that array is what you named result
  4. The only time I see anything getting added to result is in the if block

That’s as far as I get without getting lost–my console tells me that the if block must be executing at some point–executing 3 times, apparently–but I can’t see why.

He’s using recursion. A recursive definition calls itself, removing parts until it hits the so-called base case. The problem with recursion is that people have a hard time explaining it. Another problem is that if you define it incorrectly, you will infinitely call the function.

Now I have figured out why the result.push(array); was duplicating the values.

Basically array is pointing to same memory location and its just reflecting the final value of array as [A,B,C] after all the iterations as objects are pass by reference in JS.

This has nothing to do with closure, so the question statement is wrong.

This was my first question on FCC and it showed my immaturity.

Thanks for you help. This is the final code that for the question.

Please use debugger; in chrome dev tools to fully understand the calls,var values etc.

function permAlone(str) {

//Variables for main function

var result = [];
str = str.split("");
var count = 0;
generateArray(str,str.length);

//checking the permArray for repetitions and returning the count.

function arrayCount(arr){
arr.forEach(function(element){
var re = /(.)\1+/;
if(!re.test(element)){
count++; }
});
}

//function to swap the array members

function swap(array,pos1,pos2){
var temp;
temp = array[pos1];
array[pos1] = array[pos2];
array[pos2] = temp;
}

//function to generate array Permutations

function generateArray(array,n){
if(n == 1){

	//result.push(array); //returns 2d array and with each element has "ABC"
	result.push(array.join('')); //return correct value
	//console.log(array);
}
else{
	for(var i = 1;i<=n;i++){
		generateArray(array,n-1);
		if(n%2){ //If n is Odd
			var j = 1;
		}
		else{
			var j = i;
		}
	swap(array,j-1,n-1);//to counter zero indexing of JavaScript	
	}//end for
} //end else

} // end generateArray

arrayCount(result);
return count;

}

permAlone(‘ABC’);

I understand , I also had the same doubt. please just use “debugger;” as first line of generatearray function, to fully understand the call stack.

In order to properly use recursion, you need to be taking chunks out of the starting array, in addition to the decrementing n value. Otherwise, you’re using the entire array every pass.

Edit: God, I type slow on this phone…