How to understand the flow of this JavaScript function - javascript

I'm a beginner who is learning JavaScript, after HTML/CSS. I'm at the very beginning of the book of Head First, struggling to understand this function.
How does this function work in every step? What happens starting from thingamajig(5)?
function clunk(times) {
var num = times;
while (num > 0) {
display("clunck");
num = num - 1;
}
}
function thingamajig(size) {
var facky = 1;
clunkCounter = 0;
if (size == 0) {
display("clanck");
} else if (size == 1) {
display("thunk");
} else {
while (size > 1) {
facky = facky * size;
size = size - 1;
}
clunk(facky);
}
}
function display(output) {
console.log(output);
clunkCounter = clunkCounter + 1;
}
var clunkCounter = 0;
thingamajig(5);
console.log(clunkCounter);

Here's what will happen when we run this:
starting from the top, we define three different functions: clunk, thingamajig and display
then we initialize a variable called clunkCounter and assign to it the number 0
then we call the thingamajig function, passing in the argument 5 for the size parameter
in thingamajig, we'll enter the else branch, and we'll end up going through the while loop 4 times, so we're effectively doing facky = 1 * 5 * 4 * 3 * 2, so facky ends up with a value of 120
then we call clunk(120)
so we'll call display("clunk") 120 times
display just logs "clunk", and as a side-effect increments the clunkCounter, to record how many times we've done this
then finally we log out clunkCounter, which will be 120
Why would we want to do this? I don't know. It's a very contrived example which demonstrates how to use if/else conditionals and incrementing variables. I wouldn't worry too much about what it all "means". If you haven't already, try running it in the browser console, and messing around to see what happens if you change the value you pass in to thingamajig.
Edit: Very well explained. Just to add a little, its calculating the Factorial of a number and printing its value at the end.

The main thing to understand for those that still don't get it (like I did not understand when I first looked at this) is that "facky" changes values every time the while loop runs. So if you start with thingamajig(5), facky=5. But then size becomes "size=4" which makes it so you go through the while loop again. THIS TIME facky is going to be "facky=5x4" and therefore it is "facky=20". Then you go through the while loop again with "size=3" which makes it "facky=20x3" and there for it is "facky=60". One last time through the while loop and you get "facky=60x2" and therefore it is "facky=160".

it starts with thingamajig(5);
function thingamajig(size) {
var facky = 1;
clunkCounter = 0;
if (size == 0) {
display("clanck");
} else if (size == 1) {
display("thunk");
} else {
while (size > 1) {
facky = facky * size;
size = size - 1;
}
clunk(facky);
}
}
it takes "5" as parameter which means the "size" variable is 5 and starts to check the conditions in if blocks.
now lets see. the size is 5 so it will skip the first 2 part of the if block
`if (size == 0) {
display("clanck");
} else if (size == 1) {
display("thunk");
}`
and execute the else part
else {
while (size > 1) {
facky = facky * size;
size = size - 1;
}
clunk(facky);
}
this while loop will work until the size > 1 that means the size should be 1 to break the loop. there are some calculations in the while loop.
the "facky" variable changes but in the end the "size" variable will be "1" and the "facky" will be 96
when the "while loop" ends it will call clunk(facky);
that means
`function clunk(96) {
var num = 96;
while (96 > 0) {
display("clunck");
num = num - 1;
}
}`
this function will call "display" function 96 times. and display function will console log "clunck" word for 96 times in the console.
in the end the clucnkCounter will be consoled log.
I hope i understand the question right. because answering this question in writing is hard.

in thingamajig() function the value is passed 5.
and its is checked whether its matches with 0 or 1, then its goes to else block,
here is while loop. facky variable initial value is 1 but here its value is
assign again so its become 5, and size is decremented so become 4
again in while its greater than 1, again 5*4=20, facky become 20.
while continue until size value is 1. when size value is 1, facky become 120.
(5)x(4)x(3)x(2) = 120
now clank function is called and times = 120
here num = times, so num = 120
while num > 0, it call another function display, which console.log(output). And
here output = "clunk".
And increase the value of clunkCounter by 1.
Its keep on repeating until num = 0, and making clunkCounter = 120

-The code starts executing from the else code block in the function thingamajig(size), since the if and else if statement are false.
else {
while (size > 1) {
facky = facky * size;
size = size - 1; }
clunk(facky); }
}
In the else statement we have a while loop with a condition (size > 1), size is 5 inserted as an argument for the size parameter when invoked
thingamajig(5);.
The code loops till size = 1, when the condition becomes false.
LOOP 1,
while size = 5 , facky is = 1, facky = 1 * 5 = 5, size - 1 =size becomes 4.
LOOP 2,
while size = 4, facky = 5, facky = 4 * 5 = 20, size - 1 = size becomes 3.
LOOP 3,
while size = 3, facky = 20, facky = 3 * 20 = 60, size - 1 = size becomes 2.
LOOP 4,
while size = 2, facky = 60, facky = 3 * 60 = 120, size - 1 = size becomes 1.
Before loop stops The clunk() function is invoked and facky is passed as an argument to the times parameter, the function clunk starts executing.
function clunk(times) {
var num = times;
while (num > 0) {
display("clunk");
num = num - 1; }
}
Here, times = facky = 120 = num, The while loop starts executing until num = 0 when the condition becomes false, in this loop the display() function is invoked with the string 'clunk' as an argument.
function display(output) {
console.log(output);
clunkCounter = clunkCounter + 1;
}
The display('clunk') function starts executing.
'clunk' string is copied into the output parameter and it is logged into the console & clunkCounter variable increments.
-The both continues logging string 'clunk' & incrementing clunckCounter, until num = 0, as num decrements from 120 till it gets to 0.
Results
console.log(output);
'clunk' strings logs into the console 120 times.
console.log(clunkCounter);
-clunkCounter increments till its 120 so 120 is logged into the console.

Related

Why does the outcome change when the variable is declared within the while loop?

I have two simple functions here. In the loop function I have defined facky as one at the top of the function. Two things I do not understand:
The answer to console.log(loop(5)) is 120 when facky is defined at the top of loop
When I move var facky = 1; within the while loop, the answer is 2. I understand why this is two. What I don't understand is why the behavior is different when the variable is outside?
function loop(size) {
while (size > 1) {
var facky = 1;
facky = facky * size;
size = size - 1;
}
clunk(facky);
}
function clunk(times) {
var num = times;
while (num > 0) {
console.log("clunk");
num = num - 1;
}
}
loop(5);
In your while loop, whenever the loop iterates, facky is reset to 1, so it will only print twice because the last iteration of the while loop multiplies facky by 2.
When you move the declaration outside of the while loop, facky does not reset after every iteration and takes on the value of 5!, or 120 after the final iteration.
You shouldn't declare a variable inside a loop. Try this instead:
function loop(size) {
var facky = 1;
while (size > 1) {
facky = facky * size;
size = size - 1;
}
clunk(facky);
}
It doesn't really matter where you declare the var facky, it's always function-scoped.
What matters is whether you reset facky = 1 in every iteration of your loop, or whether you only initialise it once before the loop.

Write a function that flips a coin and returns the number of times landed heads?

Here is what I have so far. It keeps returning 0 no matter how many times I try to "flip" it.
**var n = prompt('How many times do you want to flip the coin?')
parseInt(n)
function coinFlip(n){
var numberOfHeads = 0
var numberOfTails = 0
for (a = 0; a === n; a++){
var flippedCoin = Math.random()
if (flippedCoin > .5)
numberOfHeads = 1 + numberOfHeads
else
numberOfTails = 1 + numberOfTails
}
return numberOfHeads**
}
console.log(coinFlip(n))
The second section of a for loop is the condition that must be true for the body of the loop to run.
You have said a === n so there are two possibilities:
The value entered is 0
a starts at 0, so a === n, the loop runs once, then a becomes 1 and it no longer matches so the loop exits.
The value entered is not 0
Since a starts at 0 it never matches and the loop is never entered.
The condition you test against should be while a < n.
change for statement to this
for (a = 0; a < n; a++)

Need Help Understanding JavaScript script

I'm very new to JavaScript and I'm trying to understand the flow of this particular script (it's an example from a textbook).
var clunkCounter = 0;
thingamajig(5);
console.log(clunkCounter);
function clunk(times){
var num = times;
while (num > 0){
display("clunk");
num = num - 1;
}
}
function thingamajig(size){
var facky = 1;
clunkCounter = 0;
if (size == 0){
display("clank");
}
else if (size ==1){
display("thunk");
}
else{
while (size > 1){
facky = facky * size;
size = size - 1;
}
clunk(facky);
}
}
function display(output){
console.log(output);
clunkCounter = clunkCounter + 1;
}
I know that the result of this particular set of functions calls is that the string "clunk" should be outputted to the console 120 times, and then the value 120 should be outputted to the console.
My question is this - why declare the global variable clunkCounter and set its value to 0, only to do the same thing within the thingamajig function? Is this not redundant? I know that if the var clunckCounter = 0; statement didn't exist, the same effect would be achieved (without declaring clunkCounter with the 'var' keyword within the the thingamajig function, it becomes a global rather than local variable). Am I correct in this assumption?
It looks like the author wants clunkCounter to be reset to 0 every time thingamajig is called because display (which thingamajig calls) modifies the counter.
The purpose of the original declaration of clunkCounter is to make it global, and the initialization is redundant.

recursive function breaking in if statement javascript

i'm in the process of trying to write a function that converts an amount into a specified number of coins. For this I'm calling a function on itself (I think this is recursive programming?). I'm having 2 problems.
When i call the function on itself in the else section of the if statement I get the error message. "Maximum call stack size exceeded" ? Not sure why this is as the call above is the same and works fine when this second call is commented out.
Also when the second call is commented out and the function runs the variable total should be increasing by 1 with each call. However it doesn't make it past 1. I thought this may be because the variable was being reset at the top to 0 with each call. However the remainder variable is also set to 0 decreases its value each time.
Can anyone explain what is happening here ? How is this problem best solved ?
Thanks
function amountCoins(amt, coins) {
var remainder = 0;
total = 0;
if(amt >= coins[0]) {
total += 1;
remainder = (amt - coins[0]);
return amountCoins(remainder, coins);
} else {
coins.shift();
//return amountCoins(remainder,coins);
}
alert(total);
}
amountCoins(121,[20,15,6,1]);
You can use .reduce() for this as an alternative.
And we don't really need loops where simple math can handle it.
var total = [20,15,6,1].reduce(function(obj, denomination) {
return {
total: obj.total + Math.floor(obj.amount / denomination),
amount: obj.amount % denomination
};
}, {amount:121, total:0}).total;
Or iterate the array.
var arr = [20,15,6,1], amount = 121, total = 0;
for (var i = 0; i < arr.length; ++i) {
total += Math.floor(amount / arr[i]);
amount %= arr[i];
}
I'd use a regular for loop instead, if I was you:
var amt = 121;
var coins = [20, 15, 6, 1];
var coinsUsed = {};
var totalCoins = 0;
for (var i = 0; i < coins.length; i++) {
if (coins[i] <= amt) {
coinsUsed[coins[i]] = Math.floor(amt / coins[i]);
amt -= coinsUsed[coins[i]] * coins[i];
totalCoins += coinsUsed[coins[i]];
} else {
coinsUsed[coins[i]] = 0;
}
}
console.log(coinsUsed, totalCoins);
Output:
Object {
1: 1,
6: 0,
15: 0,
20: 6
}
7
The problem is that your algorithm never ends. Every recursive function must have an end, if not it will produce a stack overflow (xD), because recursive calls are stored in a stack.
This would be a solution:
function amountCoins(amt, coins, total) {
var remainder = 0;
total = total || 0; //Default value 0 (for the first call)
if(coins.length == 0) return total; //This is the ending condition (no coins)
if(amt >= coins[0]) {
total += 1;
remainder = (amt - coins[0]);
return amountCoins(remainder, coins, total);
} else {
coins.shift();
return amountCoins(remainder, coins, total);
}
}
var coins = amountCoins(121,[20,15,6,1]); //Returns: 6
alert(coins);
As you can see, I turned total into a param so we can store it from call to call.
Hope this helps. Cheers
i think this is what you are trying to do:
function amountCoins(amt, coins) {
var remainder = 0;
if(coins.length == 0) {
return 0;
} else if(amt >= coins[0]) {
remainder = (amt - coins[0]);
return amountCoins(remainder, coins)+1;
} else {
coins.shift();
return amountCoins(remainder,coins);
}
}
var total = amountCoins(121,[20,15,6,1]);
alert(total)
There are a few things here
A recursive algorithm needs a terminating condition. ie. when the function is calling itself recursively it should stop the chain at some point. If it doesnt, the program will run out of memory to accomodate all the calls in the chain. Because this is a potentially dangerous condition, programming languages like javascript limit the depth of a recursive call. This is what is meant by the Maximum call stack size exceeded error.
In your program, logically, the terminating condition is when we run out of coins. so a
coins.length == 0 check that returns a 0 total (which in turn seeds the upward chain) will fix the problem
Usually in recursive algorithms the result is passed backwards, up the call chain and not stored in an external variable. So the incrementing total value is expressed with a return statement like return amountCoins(remainder, coins)+1;
Finally, this problem can be much easily implemented with for loops. Try to think by unwinding the recursive call chains and you'll figure out a loop solution.
You must return total not only if no coins left, but also if the last coin's value is bigger then the remaining value:
function amountCoins(amt, coins, total) {
total = total || 0;
if (coins.length == 0 || (amt < coins[0] && coins.length == 1)) return total;
if (amt >= coins[0]) {
total += 1;
remainder = (amt - coins[0]);
return amountCoins(amt - coins[0], coins, total);
} else {
coins.shift();
return amountCoins(remainder, coins, total);
}
}
This correction to your original code will work:
function amountCoins(amt, coins, total) {
total = total || 0;
if (amt === 0) return total;
// throw out all the coins that are too big
while (amt < coins[0]) coins.shift();
// use the largest coin possible, then recurse
total += 1;
remainder = amt - coins[0];
return amountCoins(remainder, coins, total);
}
alert(amountCoins(121,[20,15,6,1])); // alerts 7
It has the advantage of avoiding unnecessary if ... else statements, and the logic is bit clearer imo

JS - Prime numbers script - explanation

I'm learning JS and stumbled upon a script to output the prime numbers < 100 . But I'm not sure I fully understood how it works. If somebody could explain it, I would be glad. :)
So here it is:
for (var counter = 0; counter <= 100; counter++)
{
for (var i = 2; i <= counter-1; i++)
if (counter%i === 0) break;
if(i === counter)
console.log(counter);
}
Primes are by definition only divisible by themselves and 1.
The outer loop for var(counter = 0; ...) loops through the numbers from 0 to 100.
The inner loop for (var i = 2; ...) then tries to divide the outer number by every number between 2 and the counter's value. If any of them divide the number without a remainder the loop is broken. That's the if (counter%i === 0) break; line.
If we broke out of loop and i === counter, it's a prime, else it's not - by definition.
/* For every number from 0 to 100, do the following: */
for (var counter = 0; counter <= 100; counter++)
{
/* Loop through values from 2 to 1 before the counter. */
for (var i = 2; i <= counter-1; i++) {
/* if the remainder of dividing counter by the current value of `i` is zero,
* we know we don't have a prime, so break out of the loop:
*/
if (counter%i === 0) break;
}
/* If the loop completed and `i` is equal to the counter, that means counter is not
* divisible by anything except for 1 and itself, making it prime
*/
if(i === counter)
console.log(counter);
}
I'm not sure how much JavaScript you know, so some of this might be really basic.
First, remember that a prime number is one whose only factors are 1 and itself.
So the first line says it loops from 0 to 100, with counter as the variable holding this number.
The next line for (var i = 2; i <= counter-1; i++) loops from 2 to counter-1 (notice it excludes 1 and counter) and uses i to hold this number.
Next, if (counter%i === 0) break; tests whether counter is divisible by i: the remainder operator % returns the remainder (like from long division), e.g. 11 % 3 will return 2 because 11 divided by 3 gives 3 remainder 2; if the remainder counter % i is 0 (=== is a stricter equality than ==, but that's a different answer altogether) that means that counter is divisible by i and so is not prime. The break statement tells it to exit the innermost loop (that is, the loop over i), so the program increments counter and goes on.
If the previous line did not break for any value of i, then counter is prime — specifically, at the end of the loop body, i is incremented (now equal to counter), the statement i <= counter-1 evaluates to false, and the loop ends. So now i === counter is true, so console.log(counter) shows this value in the console.

Categories

Resources