I am working on Chapter 2 Exercise 3 in Eloquent Javascript, Chess Board. I am having an issue understanding one part and hoping someone would be able to provide a little enlightenment.
My Code:
var size = 7;
var board = "";
for(var i = 0; i <= size; i++){
for(var j = 0; j <= size; j++){
if((i + j) % 2 === 0){
board += " ";
} else {
board += "#";
}
}
board += "\n";
}
console.log(board);
The issue that I am having is with the condition of the "if" statement.
if((i + j) % 2 === 0)
I am not understanding why I need to add i and j together. Isn't the first "for" loop that contains the i variable constructing the row and how many rows? Where as, the second "for" loop that contains the j variable is creating the content within each row?
The addition of i and j is to create the checkerboard pattern. If the sum is even, a white square (" ") is printed; otherwise it is black ("#").
Also, your conditional statement contains a triple equals sign instead of the desired ==.
It is creating a checker board pattern so the rows are off by one on each iteration. If the row was not used, it would create stripes.
Currently with i + j % 2
# # # #
# # # # #
# # # #
# # # # #
If it were just j % 2
# # # #
# # # #
# # # #
# # # #
If it were just i % 2
.
########
########
########
I think I'am a little late to answer but will do so anyway.
Its because your want to create a pattern that looks like something like this.
"# # # #"
" # # # "
therefor you are going to add the variable "i" that is used to count from your outer loop and the variable "j" from your inner loop that is used to count, to decide with the help of an if/else statement to output either a "#" or " "(space). Also not that your first outer loop will stay at 0 until the vairable "j" in your inner loop is equal to "size". Meaning that one the first run (i+j) is = to 0+1, 0+2, 0+3, 0+4, 0+5, 0+6, 0+7. Once the inner loop is done the outer loop adds a "\n" and the procces is repeated but this time your outer loop vairable that is used to count changes from 0 to 1 and your inner loop variable that is used to count resets to 0 and your expression (i+j) is now equal to 1+0, 1+2, 1+3 ect
var size = 7;
var board = "";
for(var i = 0; i <= size; i++){ /*This will remain 0 the first run until the inner loop is completed then it will add the "\n" at the end*/
for(var j = 0; j <= size; j++){/* the variable j here will keep adding 1 to itslef until it j is equal to size*/
if((i + j) % 2 === 0){/* here it will add both i+j then divide it by 2 in order to see if is an even number or not.
remember it will look something like the this first run 0+1, 0+2, 0+3 ect.*/
board += " ";// here if the number is even it will output a (space)
} else {
board += "#";// here if the number is not even it adds "#"
} // finally this inner loop gets repeated until your vairable "j" is equal to "size"
}
board += "\n";/* then the outer loop adds a new line and your vairable "i"
becomes 1 and this whole loop gets reapeated until "i" is equal to "size"*/
}
console.log(board);
hope this helped excuse my grammar, my english is not that good greetings from Mexico City
Related
I'm learning on Udacity and they have a quiz which I couldn't pass myself. I decided to look at the provided solution but I need to understand the process of the code (I understand some of it). Here it is:
// creates a line of * for a given length
function makeLine(length) {
var line = "";
for (var j = 1; j <= length; j++) {
line += "* ";
}
return line + "\n";
}
// your code goes here. Make sure you call makeLine() in your own code.
function buildTriangle(length) {
// Let's build a huge string equivalent to the triangle
var triangle = "";
//Let's start from the topmost line
var lineNumber = 1;
for(lineNumber=1; lineNumber<=length; lineNumber++){
// We will not print one line at a time.
// Rather, we will make a huge string that will comprise the whole triangle
triangle = triangle + makeLine(lineNumber);
}
return triangle;
}
// test your code by uncommenting the following line
// Note that the function buildTriangle() must return a string
// because the console.log() accepts a string argument
console.log(buildTriangle(10));
I understand that makeLine() will create line of asterisks based on the value of length that passed to it when it gets called inside buildTriangle()
But I don't understand how this line works:
triangle = triangle + makeLine(lineNumber);
Is it not working like the line in makeLine () which is
line += "* ";
What's the difference between using += and triangle = triangle + makeLine(lineNumber)? If they work same then the output should be wrong.
Also please correct me if I'm wrong in my understanding to the variable length in makeLine(length) and buildTriangle (length). Are they different variables because of different scope? Can I change the name of the variable in buildTriangle function to be something like buildTriangle (passedValueToMakeLineFunc)?
Finally it would be highly appreciated if someone imitate the JavaScript engine and described how it will handle that code step by step in plain English.
what's the difference between using += and triangle = triangle + makeLine(lineNumber)
These are equivalent:
triangle = triangle + makeLine(lineNumber);
triangle += makeLine(lineNumber);
…the variable length in makeLine(length) and buildTriangle (length) ... are they different variables…
Correct.
The variables are entirely independent and
you can call them whatever you want.
step by step in plain English
Apologies if this is too verbose or not what you had in mind:
declare functions makeLine and buildTriangle (define but do not execute)
invoke buildTriangle with a single argument (10) to resolve value to be passed to console.log
Execution of buildTriangle:
function buildTriangle(length) {
// Let's build a huge string equivalent to the triangle
var triangle = "";
//Let's start from the topmost line
var lineNumber = 1;
for(lineNumber=1; lineNumber<=length; lineNumber++){
// We will not print one line at a time.
// Rather, we will make a huge string that will comprise the whole triangle
triangle = triangle + makeLine(lineNumber);
}
return triangle;
}
begin execution of buildTriangle with length = 10
declare a variable called triangle with an initial empty string value
declare a variable called lineNumber with an initial value of 1.
initialize for loop: set variable lineNumber to 1 (again)
evaluate for loop condition. is lineNumber less than or equal to length (10)?
lineNumber is 1, which is less than 10, so loop condition is true. execute loop body.
evaluate makeLine(1) (lineNumber is 1)
Execution of makeLine:
function makeLine(length) {
var line = "";
for (var j = 1; j <= length; j++) {
line += "* ";
}
return line + "\n";
}
begin execution of makeLine with length = 1
declare variable called line and initialize to empty string
begin for loop: declare and initialize variable j with initial value 1
evaluate for loop condition. is j less than or equal to length (1)?
j is 1, which is equal to 1, so loop condition is true. execute loop body.
append "* " to line. (line is now "* ")
increment j. j is now 2.
evaluate for loop condition. is j less than or equal to length (1)?
j is 2. condition is false. exit loop.
return line value with a newline appended: ("* \n")
(Resume buildTriangle execution)
set triangle to its current value (empty string) plus resolved makeLine value: triangle is now "* \n"
end of loop body. run post-loop expression (lineNumber++)
set lineNumber to 2
evaluate for loop condition. is lineNumber less than or equal to length (10)?
lineNumber is 2, which is less than 10, so loop condition is true. execute loop body.
evaluate makeLine(2) (lineNumber is 2)
Execution of makeLine:
begin execution of makeLine with length = 2
declare variable called line and initialize to empty string
begin for loop: declare and initialize variable j with initial value 1
evaluate for loop condition. is j less than or equal to length (2)?
j is 1, which is less than 2, so loop condition is true. execute loop body.
append "* " to line. (line is now "* ")
increment j. j is now 2.
evaluate for loop condition. is j less than or equal to length (2)?
j is 2, which is equal to 2, so loop condition is true. execute loop body.
append "* " to line. (line is now "* * ")
increment j. j is now 3.
evaluate for loop condition. is j less than or equal to length (2)?
j is 3. condition is false. exit loop.
return line value with a newline appended: ("* * \n")
(Resume buildTriangle execution)
set triangle to its current value "* \n" plus resolved makeLine value: triangle is now "* \n* * \n"
end of loop body. run post-loop expression (lineNumber++)
set lineNumber to 3
evaluate for loop condition. is lineNumber less than or equal to length (10)?
lineNumber is 3, which is less than 10, so loop condition is true. execute loop body.
evaluate makeLine(3) (lineNumber is 3)
Repeat steps above until lineNumber reaches 11 and loop exits.
return value of triangle to caller and exit buildTriangle. At this point the value of triangle is:
*
* *
* * *
* * * *
* * * * *
* * * * * *
* * * * * * *
* * * * * * * *
* * * * * * * * *
* * * * * * * * * *
invoke console.log with the value returned by buildTriangle.
exit
Your example included here for reference:
// creates a line of * for a given length
function makeLine(length) {
var line = "";
for (var j = 1; j <= length; j++) {
line += "* ";
}
return line + "\n";
}
// your code goes here. Make sure you call makeLine() in your own code.
function buildTriangle(length) {
// Let's build a huge string equivalent to the triangle
var triangle = "";
//Let's start from the topmost line
var lineNumber = 1;
for(lineNumber=1; lineNumber<=length; lineNumber++){
// We will not print one line at a time.
// Rather, we will make a huge string that will comprise the whole triangle
triangle = triangle + makeLine(lineNumber);
}
return triangle;
}
// test your code by uncommenting the following line
// Note that the function buildTriangle() must return a string
// because the console.log() accepts a string argument
console.log(buildTriangle(10));
Addition assignment operator (+=)
someVar += "someString" is the same as someVar = someVar + "someString"
Go ahead and replace your example with triangle += makeLine(lineNumber) and you'll see you get the same triangle.
The 2 lengths
In this case, they are both parameters to the functions makeLine and buildTriangle.
Function parameters are scoped to the function block, meaning they are only available inside the function, not accessible outside.
Name them as you like, this has no effect outside of the function block.
Note that if a length parameter did in fact exist outside of the function declarations, the length parameter would over/hide the external variable from use inside the function.
var length = 4;
console.log("outer", length); // 4
function someFunction(length) {
console.log("inner", length); // 5
}
someFunction(5);
console.log("outer", length); // 4
Code in english
I'm going to assume this is a little too detailed in some places and maybe not enough in others. Enjoy the story!
The makeLine function is declared (but not run yet)
The buildTriangle function is declared (but not run yet)
We hit a console.log() with a param of a function call (buildTriangle(10)). We'll execute that function, and the result of it will be passed to the log function call.
We've stepped into the buildTriangle function with a param length of value 10.
We make a triangle variable we'll build out the entire triangle into, new lines and all, initialized to an empty string.
We declare a lineNumber variable set to 1.
This one is just to mess with you
It did not need to be done before the for loop, would have been just the same to for (var lineNumber=1; lineNumber<=length; lineNumber++){ ... } and not declare it before hand.
It does not matter what it was or wasn't initialized to as the for loop sets it to 1 as it starts.
We hit a for loop, for(lineNumber=1; lineNumber<=length; lineNumber++)
We set lineNumber to 1
We will continue to run another iteration of this loop until lineNumber is <= length (10) (So up until and including 10)
We will, upon the completion of each iteration, before checking the continuation condition, increment the lineNumber by 1 (lineNumber++).
For each iteration of the loop (lineNumber values 1,2,3,4,5,6,7,8,9,10) we execute triangle = triangle + makeLine(lineNumber); Which just takes the current triangle string, appends the result of makeLine(lineNumber) to it, and assigns that value to triangle.
We've stepped into the makeLine function with a param length of value 1.
Note at this point, the only variable available to our scope is the length param. (Besides the 2 functions I suppose)
We initialize a new variable line to an empty string.
Note, this will be a brand new / separate line variable for every execution of this function Sounds like this is where you maybe hung up?
Since the line variable is declared inside the function, it is scoped there, and is not accessible outside or across function executions.
This would be different if it were declared outside of the function and not reset at the begining. Then every execution would continue to just add on.
We encounter another for loop, this time with the iterator variable declared inside (j) for (var j = 1; j <= length; j++) { ... }
We declare and initialize j to 1
We will continue to run another iteration of this loop until j is <= length (1) (So just 1 on this makeLine execution, subsequent times, 1-2, 1-3, ..., 1-10)
We will, upon the completion of each iteration, before checking the continuation condition, increment the j by 1 (j++).
For each iteration of the loop we execute line += "* "; which just takes the current line string, appends a "* " and assigns that value to line.
After this loop we encounter a return statement that is the result of combining our build out line with a newline character ("\n").
Assuming we've made it through all of our buildTriangle for loop iterations, we encounter our return statement and return the build out triangle.
We've now supplied the return value to be supplied as the parameter to console.log.
done.
I've recently completed a challenge in Marjin Haverbeke's book, "Eloquent Javascript, Second Edition".
One had to create this console output using a for loop:
#
##
###
####
#####
######
#######
The answer is this:
for (var i = '#'; i.length < 8; i += '#') {
console.log(i);
}
What I would like to know is why the first line is not two hashes ('##') as surely the updating section of the loop (i += '#') adds '#' to i (already = to '#'), therefor meaning that the first iteration of the loop should surely output '##'?
Perhaps I need a lesson on how this loop really works.
Yours truly,
still seemingly JS newbie.
for (init(); condition(); update()) {
body();
}
is equivalent to
init();
while (condition()) {
body();
update();
}
Thus, the first time i += '#' runs is only after the first console.log(i) (when i was just '#').
#Callum you should first check how for loop works.
if you have written .
for (var i = '#'; i.length < 8; i += '#') {
console.log(i);
}
so what happen in this loop is this .
1 ) first var i ='#' initiallize
then condition
2) i.length < 8
then it goes to executed the statement
3) console.log(i);
4) then increment
i += '#'
then from step 2 to 4
this is what for loops algorithm works
it is just like post increment. The order of execution is:
--> initialisation
--> check condition
--> execute body
--> increment value
so first it would print the value then increment it.
This would give ## in first row:
for (var i = '#'; i += '#',i.length < 8; ) {
console.log(i);
}
I just have a question about some while loop logic.
So, when you write a loop that displays a string of numbers to a document and say that while the loop is <= (less than or equal to) say, 5, and you tell the loop to add 1 each time this is true, wouldn't that mean that: while the loop is equal to 5 that it would add one to 5 too? It doesn't, but I messed up on some code when I was practicing and noticed that when it is equal to five it does not add one, but I thought it would...
console.log('2nd Loop:');
text = '';
// loop:
i = 1;
while (i <= 5) {
text += i + ' ';
i += 1
}
console.log(text); // Should print `1 2 3 4 5 `.
the reason your text doesn't display a 6 isn't because i isn't incremented. It's because the text gets added onto before it's incremented.
In other words when executing on that 5th loop, the text would add on 5, and then it would increment i, and then it would check the loop again, which would no longer be valid and therefore 6 is never printed.
In memory, it adds one. It doesn't add it to the text though.
Since you're incrementing the value after assigning it and then the loop condition fails, it doesn't get to the part where you concatenate the string.
It does. Just output i and you'll see it's 6. text never gets the 6 because of when you increment i.
console.log('2nd Loop:');
text = '';
// loop:
i = 1;
while (i <= 5) {
text += i + ' ';
i += 1
}
console.log(text,i); // Should print `1 2 3 4 5 `.
b/c you +1 after you add i to text, all you need to do is switch the two line order.
EDIT
if you want it start with one just change your i to 0 to start with.
i = 1
console.log('2nd Loop:');
text = '';
i = 0;
while (i <= 5) {
i += 1
text += i + ' ';
}
console.log(text);
So, it's about making a text search. I was told to start with 3 var: text, myNames, and hits. I was supposed to push my name that I had placed within the 'text' to 'hits'.
I understand the first for loop, which is to search through the text with:
for ( i = 0 ; i <= text.length ; i++ ) {
if(text[i] === "S");
}
But then, I don't really understand the instruction,"So if your name is 11 letters long, your loop should add 11 characters to hits if it ever sees the first letter of myName in text."
So I checked the hint, which got me more confused, it says: "Your loop should stop when it hits the value of the first iterator (say, i) plus the length of your myName variable."
What? I tried to follow the hint, and it seemed true because it allowed me to go to the next lesson. But the console merely logged 'S'
var text ="A string containing some text. \ I place my name here, Smit, \ a couple of times, so \ I need at least one more, \ Smit is it enough? \ Or we need more? \ Smit Smit Smit!";
var myName = "Smit";
var hits = [];
for ( i = 0 ; i <= text.length ; i++ ) {
if(text[i] === "S"); {
for ( j = i ; j <= (text.length + myName.length); j++ ) {
hits.push("S");}
}
}
enter image description here
But I don't understand why did I need to use "(text.length + myName.length)"?
I think you misunderstood the instruction.
The instruction "So if your name is 11 letters long, your loop should add 11 characters to hits if it ever sees the first letter of myName in text" means the following code.
for (j = i; j < (i + myName.length); j++)
You should use i + myName.length instead of text.length + myName.length. If the first character of myName lies on the i-th position, then the final character of myName will lie on the (i + myName.length - 1)-th position. You can write a few strings and check it yourself.
It seems that codecademy's checking is not very strict, so it doesn't mean that your code is 100% correct even if it allows you to move to the next section.
But I don't quite understand why the instruction says "add 11 characters to hits if it ever sees the first letter of myName in text". Shouldn't we check the whole name and then decide to push it into hit or not?
I am learning Javascript and have run into an issue with the push method. When I use it within a loop it is making my array 33 items instead of just adding 3 to the list. Initial list is 1-10 items long, user defined. I initiated all the variables in the beginning of the script, and the variable items is only manipulated when the user initially tells me how long the array will be. From there it is basic exercises in array methods, and this is the one that is giving me problems. Following is the push part of the code. I appreciate any feedback and will put more code up if anyone feels it is necessary.
for (i = 0 ; i < 3 ; i++){
newfood = prompt("Please enter food " + (i + 1) + ".");
foods.push(newfood);
}
document.write("<ol>");
i = 0; //resetting variable i to 0
for (i = 0 ; i < items + 3 ; i++){
document.write("<li>" + foods[i] + "</li><br>");
}
document.write("</ol>");
Looks like you're running into string concatenation that's then treating the string as a numeric type. Convert what I assume is a string to an int:
for (i = 0 ; i < parseInt(items) + 3 ; i++) {
document.write("<li>" + foods[i] + "</li><br>");
}