Recursive array with a push - javascript

Can someone show me where I am going wrong within this Code Academy problem. I'm having a world of trouble with Recursion and am only vaguely beginning to understand how it works at a fundamental level... The first set of code is what I have written followed by the same code with the blanks I have tried to fill in.
Fill in the blanks: Write a conditional statement for the base case of multiplyEach(). We want to end the recursion when there are no more values in stack. Then we want to return the variable int, since this represents the last value evaluated. Complete the recursive case with a recursive call to the function, without any arguments.
Blank Problem with fill-in-the-blanks (___):
var stack = [];
function countDown(int) {
stack.push(int);
if (int === 1) {
return 1;
}
return countDown(int - 1);
}
function multiplyEach() {
// Remove the last value of the stack
// and assign it to the variable int
int = stack.pop();
x = stack.length;
// Base case
if (___) {
return ___;
}
// Recursive case
else {
stack[x - 1] = int * stack[x - 1];
return ___;
}
}
// Call the function countDown(7)
countDown(7);
// And then print out the value returned by multiplyEach()
console.log(multiplyEach());
This is my Try:
var stack = [];
function countDown(int) {
stack.push(int);
if (int === 1) {
return 1;
}
return countDown(int - 1);
}
function multiplyEach() {
// Remove the last value of the stack
// and assign it to the variable int
int = stack.pop(int);
x = stack.length;
// Base case
if (x === 0) {
return int;
}
// Recursive case
else {
stack[x - 1] = int * stack[x - 1];
return multiplyEach(stack);
}
}
// Call the function countDown(7)
countDown(7);
// And then print out the value returned by multiplyEach()
console.log(multiplyEach());
Thanks!

You filled in the blanks correctly!
There is just one bug you introduced in a part of the code you did not have to touch:
Replace:
int = stack.pop(int);
with:
var int = stack.pop();
Because pop returns the value you need. There is no need to pass anything.
Also, you passed the stack argument to a function that does not take that argument (the variable is global). This does no harm, but to avoid confusion, it is better to call the function without arguments, as it is supposed to be:
return multiplyEach();
Some side-comments on the code you have been provided with:
it is bad practice to name a variable int as it might become a reserved word in future versions of JavaScript;
That same variable should better be declared locally to the function, as now it is created in the global scope. So with var: var int = ...

Related

Passing arrays between functions in JavaScript

I'm having trouble understanding how I can traverse between the functions, passing arrays between them, a full day of 'undefined' or 'this is not a function' has me pulling my hair out.
I'm currently doing a challenge on codewars, The task is seemingly simple, take a string that has open and closed braces and check them to see if they're opening/closing in the correct order. However, for some reason the console.log is not returning anything in this challenge so I'm having to do it blind.
Here's the first function, I set all the variables and the arrays and pass it on to the next function.
function validBraces(braces) {
var braceAr = [];
braceAr = braces.split('');
var testAr = []; // array to be used for testing the order
var i = 0; // iterator for the loop in analyse() function
analyse(...braceAr,...testAr,i); //send the arrays to the function!
}
In the last line in the function above, I'm trying to pass the arrays to the next function, I don't want to create them inside the next function since there is a third function that does the check, sending it back again to the second (analyse). I'm using a spread operator in this 'version', however, I've exhausted my understanding and resources, so I reach out to gain a better understanding. Can someone explain how I can pass these arrays to the functions. I've tried to apply things from explanations I've found but I feel I may be missing something fundamental that is limiting me.
The rest of the code is below, it may not be relevant, but it's there just in case. I'd love to solve this so try to not give too much away ;)
function analyse(braceAr,testAr,i) {
for(l = braceAr.length; i<l ;) {
switch(braceAr[i]) {
case '[':
testAr.push("]");
break;
case '{':
testAr.push("}");
break;
case '(':
testAr.push(")");
break;
case ']':
check(...braceAr,...testAr,i);
break;
case '}':
check(...braceAr,...testAr,i);
break;
case ')':
check(...braceAr,...testAr,i);
break;
} //close switch
} //close loop
return (testAr.length = 0 ? true : false);
} //close function
As you can see, I intend to switch through each element in the array, and if it's an open brace, I'll push the corresponding closing brace into an array to be compared in the third function check()
function check(braceAr,testAr,i) {
if(testAr.pop() === braceAr[i])
{
i++;
analyse(...braceAr,...testAr,i);
} else { return false; }
} //close function
If the most recent element added is the same as the closing brace, we have a matching open/close brace. Increment the index and go back to analysing the rest of the braces.
How does it look?
Don't use ..., that's spreading the array contents into separate arguments to the function, as if you'd written:
analyse(braceAr[0], braceAr[1], braceArr[2], /* rest of braceAr */,
testAr[0], testAr[1], testAr[2], /* rest of testAr */, i);
Just write:
analyse(braceAr,testAr,i);
You have the same problem when calling check().
When check() calls analyse() recursively, it needs to return its value; see Recursive function does not return specified value.
And you never use the return value of check() in analyse(), so I'm not sure what the point of it is at all. I'm not sure what it's trying to do and how the return value should be used.
validBraces("a[foo(bar).baz]");
function validBraces(braces) {
var braceAr = [];
braceAr = braces.split('');
var testAr = []; // array to be used for testing the order
var i = 0; // iterator for the loop in analyse() function
analyse(braceAr, testAr, i); //send the arrays to the function!
console.log(testAr);
}
function check(braceAr, testAr, i) {
if (testAr.pop() === braceAr[i]) {
i++;
return analyse(braceAr, testAr, i);
} else {
return false;
}
} //close function
function analyse(braceAr, testAr, i) {
for (l = braceAr.length; i < l; i++) {
switch (braceAr[i]) {
case '[':
testAr.push("]");
break;
case '{':
testAr.push("}");
break;
case '(':
testAr.push(")");
break;
case ']':
check(braceAr, testAr, i);
break;
case '}':
check(braceAr, testAr, i);
break;
case ')':
check(braceAr, testAr, i);
break;
} //close switch
} //close loop
return (testAr.length = 0 ? true : false);
} //close function
The analyse(...braceAr,...testAr,i) won't pass the arrays braceAr and testAr to function analyse(braceAr,testAr,i) {, but uses their content as arguments for the function:
var arrA = [1,2]
var arrB = [3,4]
function test(a, b, c, d) {
console.log(a, ',', b, ',', c, ',', d)
}
test(...arrA, ...arrB)
If you want to pass the array you have to remove the spreading operator ... and just write analyse(braceAr, testAr,i).
Using the spread operator (...) passes each array element as an argument. That way, when you try to use the push() function, it generates an error.
function faultyPasser(string) {
var charArr = string.split('');
logChars(...charArr);
}
function logChars(charArr) {
for (i in charArr)
console.log(charArr[i]);
}
faultyPasser("Bad code.");
Rewrite all of your function calls with arrays to get rid of the spread operator. It should work as long as there are no other bugs.

Strange behaviour of for loop in Heap's algorithm in JavaScript

I'm trying to implement Heap's algorithm to find different permutations of a string and found a strange behaviour with a for loop, here's the code
function permAlone(str) {
var strArr = str.split(''),
permutations = [];
function swap(strArr, x, y) {
var tmp = strArr[x];
strArr[x] = strArr[y];
strArr[y] = tmp;
}
function generate(n) {
if (n === 1) {
permutations.push(strArr.join());
} else {
for (var i = 0; i != n; i++) {
generate(n - 1);
swap(n % 2 ? 0 : i, n - 1);
}
}
}
generate(strArr.length);
return permutations;
}
console.log(permAlone('aab'));
In the for loop within the generate function, if I put i = 0 the output of the script is ['a,a,b', 'a,a,b'] but if I put var i = 0 the output is ['a,a,b', 'a,a,b', 'a,a,b', 'a,a,b', 'a,a,b', 'a,a,b'].
I understand that var i would create a local variable for the loop, but don't understand in this case why it would change how the loop functions as there is no i variable declared anywhere else in the script.
Thanks any help appreciated.
The reason the behaviour changes if you have a global i variable is that you have multiple recursive calls to generate() all trying to control their own partially complete for loops with the same variable, and all setting i back to 0 when they start.
Picture what happens on the second iteration of the for loop: i is 1 because it has just been incremented, but then immediately a recursive call to generate() starts its own loop and sets i back to 0 again.
If you create a local variable with var then each for loop in each recursive call is independent of all the others.
Try stepping through the code with the debugger, or try adding the following as the first line inside the for loop and watch what happens to the variables when the code runs:
console.log('n:' + n + '; i: '+i);

I don't understand function return in javascript

Can anyone explain why javascript return statement is used in function? when and why we should use it?
Please help me.
Why is it used in a function?
1. To return back the results of the function
The return does what is says - it returns back some values to the function caller
function sum(num1, num2) {
var result = number1 + number2
return result
}
var result = sum(5, 6) // result now holds value '11'
2. To stop the execution of the function
Another reason that return is used is because it also breaks the execution of the function - that means that if you hit return, the function stops running any code that follows it.
function sum(num1, num2) {
// if any of the 2 required arguments is missing, stop
if (!num1 || !num1) {
return
}
// and do not continue the following
return number1 + number2
}
var result = sum(5) // sum() returned false because not all arguments were provided
Why we should use it?
Because it allows you to reuse code.
If for example you're writing an application that does geometric calculations, along the way you might need to calculate a distance between 2 points; which is a common calculation.
Would you write the formula again each time you need it?
What if your formula was wrong? Would you visit all the places in the
code where the formula was written to make the changes?
No - instead you would wrap it into a function and have it return back the result - so you write the formula once and you reuse it everywhere you want to:
function getLineDistance(x1, y1, x2, y2) {
return Math.sqrt((Math.pow((x2 - x1), 2)) + (Math.pow(( y2 - y1), 2)))
}
var lineDistance1 = getLineDistance(5, 5, 10, 20);
var lineDistance2 = getLineDistance(3, 5, 12, 24);
it's used to return a value from the function.
Let's say you want a function to do some calculation... for a simple example, like calculate a div box's left position on the browser screen.
you call the function and give it the html selector, then the function 'returns' you the left position value.
You use a return statement for two reasons:
To return a specific value from a function.
To finish the execution of the function before the last line of code in the function.
Without any return value; statement, the function does not return a specific value (technically the return value is undefined).
Without a specific return statement somewhere in the function, the function runs until the last line of code in the function.
Examples:
function add(x, y) {
// return a sum of the two arguments
return x + y;
}
console.log(add(1, 3)); // 4
function findParm(str, key) {
if (!str || !key) {
// invalid parameters, so return null
return null;
}
var pieces = str.split("&");
for (var i = 0; i < pieces.length; i++) {
var loc = str.indexOf(pieces[i] + "=");
if (loc >= 0) {
// when we've found a match, return it and finish execution of the function
return str.slice(loc + key.length + 1);
}
}
// no match found, return null
return null;
}
var str = "user=John&login=yes"
findParam(str, "login"); // "yes"

Eloquent Javascript 2nd. Chapter 4. Computing Correlation. Final Analysis - [Variable Recursion & in operator] Pt 2

I'm working through the end of the first example in Chapter 4 Eloquent Javascript. Here is the full piece of code (It's the last piece that I have questions regarding but I attached the first portion for reference).
var journal = [];
function addEntry(events, didITurnIntoASquirrel) {
journal.push({
events: events,
squirrel: didITurnIntoASquirrel
});
function phi(table) {
return (table[3] * table[0] - table[2] * table[1]) /
Math.sqrt((table[2] + table[3]) *
(table[0] + table[1]) *
(table[1] + table[3]) *
(table[0] + table[2]));
}
function hasEvent(event, entry) {
return entry.events.indexOf(event) != -1;
}
function tableFor(event, journal) {
var table = [0, 0, 0, 0];
for (var i = 0; i < journal.length; i++) {
var entry = journal[i], index = 0;
if (hasEvent(event, entry)) index += 1;
if (entry.squirrel) index += 2;
table[index] += 1;
}
return table;
}
function gatherCorrelations(journal) {
var phis = {};
for (var entry = 0; entry < journal.length; entry++) {
var events = journal[entry].events;
for (var i = 0; i < events.length; i++) {
var event = events[i];
if (!(event in phis))
phis[event] = phi(tableFor(event, journal));
}
}
return phis;
}
var correlations = gatherCorrelations(JOURNAL);
console.log(correlations.pizza);
My questions are:
What is the purpose of the .events in
var events = journal[entry].events;
Does it call on itself as a recursion? If so why? Couldn't we have just had journal[entry] and the function would run calling on the entry from the tableFor function? Does it call back to the AddEntry function (where the events variable was established) in an important way?
What is the purpose of (!(event in phis)).
I read it as : if event in phis is true then flip it to be not true and then trigger necessary phi calculation. Wouldn't it make more sense to eliminate the ! (does not equal) or that piece of code altogether? If we already have a for loop won't the function run on it's on until the max length of journal and stop?
var events = journal[entry].events; you are getting the events object from the object at index entry in the array journal and assigning it to a temporary variable called events.
This is just done for convenience so you don't have to keep referring to journal[entry].events. For example, later on it has this line:
var event = events[i];
which would become:
var event = journal[entry].events[i];
Without the assignment to a temporary variable.
if(!(event in phis)) it's testing to see if the object phis does not have a property with the name contained in the variable event. If the object doesn't already have that property, it adds it with the next line:
phis[event] = phi(tableFor(event, journal));
See in operator
Here's a very simple snippet of code to help understand the in operator:
var foo = {};
console.log("bar" in foo); // logs "false" because foo doesn't have a "bar" property
foo.bar = 1; // or foo["bar"] = 1;
console.log("bar" in foo); // logs "true" because foo now has a "bar" property
What is the purpose of the .events in
var events = journal[entry].events;
The purpose of this declaration conforms with 2 concepts of scripting convenience and economy. Every level of an object depth adds to the overall recall time when called. Certainly modern browsers have done much to flatten an objects variable stack, but if you think about it logically, any call to say object1.object2["Memeber3"].object4 has to go through 4 steps to get to the value itself. Flattening the value to a local object is more economic. Second, the readability (and therefore maintainability) of the code is enhanced in that you don't have the extra "journal[entry]." clogging up your expressions. As a general rule of thumb, if you are going to use a member of an object more than once in a block, then you should create a local variable of that member.
What is the purpose of
(!(event in phis)).
The purpose of this evaluation is to determine if a particular member(event) is NOT in the object(phis). In this example, the next line creates that member if it is indeed missing.

Trouble pushing to an array in JS

Below is just a section of my code but I know it's problematic because I can't get it to return any value except 'undefined'. I have been over this for hours and cannot figure it out.
I want to be able to input a number and have its factors pushed to an array. I have tested it by alerting the first item in the array and I get nothing. I'm sure this is a pretty easy but I just can't figure it out. Here is the code:
var numberInQuestion = prompt("Of what number are you wanting to find the largest prime factor?");
//determine factors and push to array for later use
var factorsArray = [];
function factors(numberInQuestion){
for(var i = 2; i < numberInQuestion-1; i++){
if(numberInQuestion % i === 0){
return factorsArray.push[i];
} else {
continue;
}
}
};
factors(numberInQuestion);
alert(factorsArray[0]);
Thanks for any help!
you can only return one value
you must use (), not [] for calling push
factorsArray should be local to factors (put the definition inside the function)
the else { continue; } is useless
Here is the fully corrected code:
var numberInQuestion = prompt("Of what number are you wanting to find the factors of?");
//determine factors
function factors(numberInQuestion){
var factorsArray = []; // make it local
for (var i = 2; i < numberInQuestion-1; i++){
if(numberInQuestion % i === 0){
factorsArray.push(i); // use (), and don't return here
} // no need for else { continue; } because it's a loop anyway
}
return factorsArray; // return at the end
};
var result = factors(numberInQuestion); // assign the result to a variable
alert(result);
Here's a JSFiddle.
You have an error in your pushing syntax. Correct syntax for pushing is -
factorsArray.push(i);
Also returning immediately from the function after finding the first divisor will not give you the full list. You probably want to return after you've found out all the divisors.
Taking all of the above into consideration, you should rewrite your function as follow -
function factors(numberInQuestion){
for(var i = 2; i < numberInQuestion - 1; i++){
if(numberInQuestion % i === 0) {
factorsArray.push(i);
}
}
}
and you will be OK.
You've coded this so that when you find the first factor your function returns immediately. Just get rid of the return keyword in that statement. (What "return" means in JavaScript and other similar languages is to immediately exit the function and resume from where the function was called.)
Oh, also, you call functions (like .push()) with parentheses, not square brackets.
The function should not return when pushing to the array. Return the array after executing the loop. The else clause is also unnecessary.
var numberInQuestion = prompt("Of what number are you wanting to find the largest prime factor?");
function factors(numberInQuestion){
var factorsArray = [];
for(var i = 2; i < numberInQuestion-1; i++){
if(numberInQuestion % i === 0 && isPrime(i)){
factorsArray.push(i);
}
}
return factorsArray;
};
var factors = factors(numberInQuestion);
alert(factors[factors.length-1]);
//From: http://stackoverflow.com/questions/11966520/how-to-find-prime-numbers
function isPrime (n)
{
if (n < 2) return false;
var q = Math.sqrt (n);
for (var i = 2; i <= q; i++)
{
if (n % i == 0)
{
return false;
}
}
return true;
}
Given the purpose of the example two items must be considered
The code does not determine if the number is actually prime. The code will return the smallest factor possible since the loop starts at two and increments, then returns the first element in the array. The largest factor would actually be the last element in the array. I have corrected the example to find the greatest prime factor. You can test it via this fiddle: http://jsfiddle.net/whKGB/1/

Categories

Resources