Eloquent JS, Chp2: Exercise 3

Exercise 3: Chess Board

Write a program that creates a string that represents an 8 x 8 grid, using newline characters to separate lines.

At each position of the grid there is either a space or a “#” character.

The characters should form a chess board.  Passing this string to console.log should show something like this:

chess board

When you have a program that generates this pattern, define a variable size = 8 and change the program so that it works for any size, outputting a grid of the given width and height.

Approach

chess board 8 by 8 with arrows

Loop – “Vertical”:

  • This will be the outermost for loop
  • This loop adds height to the output
  • Let i represent the number of iterations
  • i is of type number
  • Let size represent the width and height of the square
  • size is of type number
  • By the end of the loop, i == size

Loop – “Horizontal”:

-Increases characters horizontally per line
-Each new line is a new iteration
-Repeating characters: # and a space
-When i is an even number, the line starts with a # character
– Repeated characters when i is an even number: #_
-When i is an odd number, the line starts with a space (will rep. with _ character in notes)  -Repeated characters when i is an odd number: #_ , but one _ exists before any repeats

  • This will be an inner for loop
  • This loop adds width to the output
  • Let char represent the characters on the line
  • char is of type string
  • char.length returns the length (number of characters) of char
  • By the end of the loop, i == size == char.length

Questions:

1. How do you repeat string characters horizontally when the number of repeats required is unknown? 

You can concatenate strings i.e.

console.log("# " + "# ")
//-> # #

EDIT (after writing Solution Attempt 4 – Final Submission) : You CAN repeat strings horizontally when the number of repeats is unknown.

What is needed: Put console.log outside the for loop (so whatever is printed is the final result of repeated string concatenation).  See the next blog post “Exercise 2.3 Part 2” for this solution. 

But recall that no arithmetic operation can be applied to strings i.e.

var test = "Hi";
test *= 2;
console.log(test); 
//-> NaN

 

I will not be able to repeat characters horizontally using arithmetic multiplication i.e.

var char = "# " * 3; 
console.log(char);
//-> NaN

or

console.log("10" * 2); 
//-> 20 
console.log(typeof("10" * 2));
//-> number

 

Observe string concatenation between string values and number values:

//Example 1
console.log("150" + 1010);
//-> 1501010 
console.log(typeof("150" + 1010));
//-> string  

//Example 2
console.log(150 + "1010");
//-> 1501010
console.log(typeof(150 + "1010")); 
//-> string 

//Example 3
console.log("#" + 10);
//-> #10
console.log(typeof("#" + 10));
//-> string

Keep in mind that the Number and String functions convert a value to type number and type string respectively.

Though that still isn’t helpful in repeating string characters horizontally when the number of repeats required is unknown.

It passed the mind to replace # and space with 1 and 0, and at the end, replace 1 and 0 with # and space again. Using numbers would allow for repetition via arithmetic operations. However, this idea died a swift death upon the realisation that when a string value’s type is converted to type number, (“10” with 10), any arithmetic operation on this value will be governed by mathematical laws i.e. 10 * 2 = 20, not 1010 i.e.

ejs 2.3 repeat test with 10

And why it wouldn’t work with # :

ejs 2.3 repeat test

.
.
.

2. What is the update/final-expression in the inner for loop? 

Can it be empty?

.
.
.

Outside the scope of Chapter 2, there is a JavaScript String repeat() method. Let’s try this out for Solution 1.

// Allow any size to be inputted
 var size = prompt("Enter a positive integer.");

// Convert string value inputted in prompt to type number
 Number(size);

// Outer loop to track vertical iteration
 for (var i = 0; i <= size; i++) {

// Inner loop to add characters horizontally per line
 for(var char = ""; char.length <= size; ) {

//If the line number is odd
 if (size % 2 !== 0) {

// Begin the line with a space
 char = " ";
 // How many times does the pattern have to repeat?
 var numRepeats1 = (((size + 1)/2) - 1);
 var pattern1 =  "# ";

// Concatenate the first space with the pattern
 // Use string repeat() method to repeat the pattern the appropriate number of times
 char += pattern1.repeat(numRepeats1);

}

//If the line number is even
 if (size % 2 == 0) {

//Pattern to be repeated
 var pattern2 = "# ";

// Repeat the pattern this amount of times
 var numRepeats2 = size/2;

//Update char value
 char += pattern2.repeat(numRepeats2);
 }

.
.
.

EPIPHANY: I don’t need the second for loop. With the string repeat method, there is no need for a loop to repeat the characters horizontally.

EPIPHANY 2 (after Solution Attempt 1 Test 1): Nevermind, I do need the second loop. Without this loop, a conditional branch would be left out depending on what the value of size is i.e. if size = 2, the odd number if-statement branch is not considered at all, so instead of printing out line 1, line 2, only line 2 with weird stuff is printed.

Solution Attempt 1

var char = ""
var size = prompt("Enter a positive integer.");
Number(size); 

for (var i = 0; i <= size; i++) {
    if (size % 2 !== 0) {
       char = " "; 
       var pattern1 = "# "; 
       var numRepeats1 = (((size + 1)/2) - 1);
       char += pattern1.repeat(numRepeats1); 
       console.log(char);
}

    if (size % 2 == 0) { 
       var pattern2 = "# "; 
       var numRepeats2 = size/2; 
       char += pattern2.repeat(numRepeats2); 
       console.log(char); 
}}

 

chessboard repeatmethod soln1
size = 2

No plan survives first contact with the enemy. I think I’ll become quite fond of that saying.

What I think went wrong:

Firstly, the initial value of i should be set to 1, not zero. This way, the iteration number is equal to the row number (of the output).

ejs 2.3 s1t1 iequals1
size = 2; change is highlighted

 

Secondly, the if-statement conditions are wrong. Variable i instead of variable size should be used. That is:

// for odd-number lines 
 if (i % 2 !== 0) {
  }
// for even-number lines 
  if (i % 2 == 0) {
  }

Why? Because it is the iteration value that tracks the row that we are on. The value of i increases with each iteration, while the value of size stays the same (it is whatever value was inputted in prompt). Size is the maximum width and height of the grid. We just need the current row number of the grid (i).

Let’s say size = 2. The odd-numbered line if-statement branch {check wording} is evaluated to be false since size is an even-numbered value. That’s why char = ” ” didn’t manifest. Execution moves to the even-numbered line if-statement branch, and its statement body is executed.

NB: The value of i is compared to the value of size at the beginning of each iteration to see if another iteration is required. {check wording and understanding: is the updated value compared with the value in the condition at the END or the BEGINNING of each ITERATION (or do we say LOOP)?}

ejs 2.3 s1t2
size = 2; changes are highlighted

What happened?

Look at numRepeats1 and numRepeats2. Are their formulas correct? Seems to be so, yes. Next, look at char +=.

ejs 2.3 s1t4 char +=
size = 2; change is highlighted

QUESTION 1: Why did a change from Line 17 char += pattern2.repeat(numRepeats2); to char = pattern2.repeat(numRepeats2); give the correct output for the 2nd line?

Testing

1)  Line 17 –>  char += re-added
Line 7 –> char = “1”
Changes are to see whether the new value of char bleeds out of its if-statement into the rest of the program. Apparently yes. char = “1” should only affect odd number iterations.

2.3 ejs repeat test char +=
size = 2

ANSWER to QUESTION 1: For some reason, the value of char remains “1# # # … #” even when the iteration is a new, even-numbered iteration. That the iteration is even-numbered means that execution should bypass the first if statement (Line 6) and go on to the second if statement (Line 14). char’s value should be an empty string when execution starts at Line 14, not holding on to whatever value it gained from Line 10.

We must also consider the += operator on Line 17. What happens when it is removed?

2) Line 17 –> = operator replaces += operator

2.3 ejs repeat test char += 2
size = 2

ANSWER to QUESTION 1: When char (whose value seems to cling to the result from Line 10) is not concatenated to pattern2 on Line 17, the output for iteration number 2 looks proper.

 

 

9 repeats
size = 2

if-statement for even-number lines seem to be working properly. Something’s wrong with the if-statement for odd-number lines branch. Suspect are Lines 9 and/or 10.

 

Looking at Line 9 — changed (((size + 1)/2) – 1); to (size):

it's the repeat formula
Line 9, testing the repeat formula

 

Testing the repeat formula:

repeat testing

That means something is wrong with char += or size input, not the formula.

EDIT: At least, for when size holds ODD NUMBERS. How about EVEN NUMBERS?

odd formula doesn't work with even numbers

EPIPHANY: Whenever size is an odd number, the repeating formula in the first if-statement works fine. But the repeating formula in the second if-statement doesn’t work properly. AND VICE VERSA. All because of variable size, which is used in the repeating formula. FIX THE FORMULAS.

 

Repeating a string 2.5 times doesn’t happen. It repeats 2 times.

even and odd repeating formula testing

But the if-statement for odd-number and the if-statement for even numbers should filter incoming numbers, and slide them into their respective formulas.

 

 

The String repeat() method and char += … seems to be working fine.

what's wrong is the loop or lack of one

 

 

 

Testing prompt input:

it's the prompt input that's the problem omg
size = 3 ; highlighted is the output you’re supposed to have gotten

 

Something’s wrong with the prompt input.

More proof:

2.3 ejs no prompt9 repeats

 

By process of elimination, these are the remaining potential errors:

  • Repeating formulas — fix both the odd and even one; use something other than size or adjust the numbers to accommodate variable size
  • REPEATING PATTERN ISSUE and discrepancy between value of i and value of size
  • Don’t cheat with using blanks as noncharacters. Spaces count as characters and you want to print the specified character amount, no more no less.
  •  Prompt input
  • for loop? lack of a secondary loop?

 

 

THE BIG EPIPHANY

When size holds an odd number value, the numRepeats1 formula works properly. But the numRepeats2 formula does not. When size holds an even number value, the numRepeats2 formula works properly, but the numRepeats1 formula does not.

chessboard big epiphany

The solution: 

if size = odd number { 
   if i = odd number 
     Adjust repeating formula accordingly
   if i = even number 
     Adjust repeating formula accordingly 
}
else if size = even number {
   if i = odd number
     Adjust repeating formula accordingly
   if i = even number
     Adjust repeating formula accordingly 
}

Place these if statements after the for loop. Each if statement will have a nested if statement (for i = odd number) and else-if statement (for i = even number).

Solution Attempt 2

var char = "";
var size = 2;
Number(size);

for (var i = 1; i <= size; i++) {
  // if size is an odd number
  if (size % 2 !== 0) {
    //if the row number (iteration) is an odd number 
    if (i % 2 !== 0) {
      char = " ";
      var pattern1 = "# ";
      var numRepeats1 = (((size + 1)/2) - 1);
      char += pattern1.repeat(numRepeats1);
      console.log(char);
    }
    //if the row number is an even number 
    if (i % 2 == 0) {
      char = "#"
      var pattern2 = " #";
      var numRepeats2 = ((size -1)/2);
      char += pattern2.repeat(numRepeats2);
      console.log(char);
}}
  //If size is an even number 
  else if (size % 2 == 0) {
    //if the row number is odd
    if (i % 2 !== 0) {
      var pattern1 = " #";
      var numRepeats1 = (size/2);
      char += pattern1.repeat(numRepeats1);
      console.log(char);
     }
  //if the row number is even 
  if (i % 2 == 0) {
     var pattern2 = "# ";
     var numRepeats2 = (size/2);
     char += pattern2.repeat(numRepeats2);
     console.log(char);
 }}}

^Makes more structural sense for the currently outermost for loop to be inside “if size is odd” and “if size is even” statements. Is the structure causing the following problem though? This structure, while disorganized, should still work properly.
** “if size is odd” if statement branch is working properly. Something’s wrong with the “if size is even” statement

2.3 ejs size is even if statements
size = 2

 

Get rid of += on Line 33:
Highlighted yellow is the change:

2.3 ejs size is even if statements rid of +=
size = 2

Why this change when += was replaced by = , on Line 33?

 

Now there are issues with the += on Line 26:

2.3 why why why

The pattern marked “2” is the pattern on Line 24, repeated twice. But where did the pattern marked “1” come from?

char += pattern1.repeat(numRepeats1); 
//equivalent to:
char = char + pattern1.repeat(numRepeats1);

char should be an empty string, until it is concatenated with pattern1.

Highlighted yellow is the change from += to + on Line 26:

2.3 what is char in the else if statement

So char = “# # ” when execution hit upon Line 26? QUESTION 2: How?

 

Using other values for size i.e. 3, 5, 6, 8, 10, the program now displays the proper output. On Line 2, I re-added prompt(), which also works fine now.

EDIT (during Solution Attempt 3): Oh no, prompt() doesn’t work fine for odd numbers.

 

Solution Attempt 3 

1     var char = "";
2     var size = prompt("Enter a positive integer.");
3     Number(size);
4
5     for (var i = 1; i <= size; i++) {
6         if (size % 2 !== 0) {
7             if (i % 2 !== 0) {
8                 char = " ";
9                 var pattern1 = "# ";
10                var numRepeats1 = (((size + 1)/2) - 1);
11                char += pattern1.repeat(numRepeats1);
12                console.log(char);
13            }
14
15            if (i % 2 == 0) {
16                char = "#";
17                var pattern2 = " #";
18                var numRepeats2 = ((size -1)/2);
19                char += pattern2.repeat(numRepeats2);
20                console.log(char);
21    }}
22        else if (size % 2 == 0) {
23            if (i % 2 !== 0) {
24                var pattern1 = " #";
25                var numRepeats1 = (size/2);
26                char = pattern1.repeat(numRepeats1);
27                console.log(char);
28            }
29
30            if (i % 2 == 0) {
31               var pattern2 = "# ";
32               var numRepeats2 = (size/2);
33               char = pattern2.repeat(numRepeats2);
34               console.log(char);
35    }}}

I celebrated too soon.

When size = 11 without prompt(), we get this:

i celebrated too soon 2.3 ejs
Output is proper as expected

 

When size = 11 via prompt(), we get this mess:

wtf 2.3 ejs prompt

Inputting size values into prompt() that are even and greater than 10 i.e. 12, 14, 16, etc., the output is proper as expected. However, when inputting size values into prompt() that are ODD and greater than 10 i.e. 11, 13, 15, 17, etc., the output is all wrong.

EDIT: Nope, odd-numbers below 10, when inputted via prompt() for size, also do not work properly.

Therefore, we’re dealing with either an error(s) with 1)  Lines 5 – Line 18 (when size is an odd number) or 2) the prompt() method or 3) both or 4) something else.

Note that the even-numbered rows do show the expected output. The odd-numbered rows show more than the expected characters. So the error is somewhere in Lines 6-11 if we’re looking at option 1).

Suspects:

  • Indentation? Line 13 if statement is indented more than it should be? This is unlikely to be the problem. (Check: Yeah, it isn’t the issue.)
  • prompt()       The main suspect
  • The += operator on Line 10  (Check: Not the issue.)
  • usage of same variable for different values i.e. char (Line 7, Line 10) ?? (Check:Not an issue.)

Tentative conclusion: It looks like a prompt() issue, because inputting any value manually gives the correct output. RETURN TO THIS.

 

Cleaning up the code:

see Solution Attempt 4

  • defined the variable char, but did not initialize it –> its value is undefined; will give char a value depending on the nested if statement
  • declared and initialized variables patternsharp and patternspace outside of the for loop –> prevents re-writing these four times inside the loop’s nested if and else if statement bodies
  • renamed numRepeats1 and numRepeats2 –> under one variable name: numRepeats (see Line 9), because they are contained within their nested if statements
  • under the else-if statement on Line 19, pulled two numRepeats out of their nested if-statements, and placed it as one numRepeats statement (Line 20) –> this applied to both nest if-statements and saves space (no need to rewrite numRepeats twice since they have the same formula of size/2)

 

Solution Attempt 4: Final Submission

using String repeat() method

still having issues with prompt()

2.3 solution 1 final

Solution Attempt 4 with Comments

var char; var patternsharp = "# "; var patternspace = " #"; 
var size = 3;
Number(size);

    for (var i = 1; i <= size; i++) {
         // size is an odd number
         if (size % 2 !== 0) {
             // row number is an odd number
             if (i % 2 !== 0) { 
                //odd rows start with a space
                char = " "; 
                // the number of times patternsharp shoud be repeated
                var numRepeats = (((size + 1)/2) - 1);
                /*concatenating " " and patternsharp however 
                many times it's repeated*/ 
                char += patternsharp.repeat(numRepeats); 
                console.log(char); 
             }
            //row number is an even number
            if (i % 2 == 0) {
               //even rows start with a sharp
               char = "#";
               //the number of times patternspace should be repeated
               numRepeats = ((size-1)/2);
               char += patternspace.repeat(numRepeats);
               console.log(char);
 }}
        //size is an even number 
        else if (size % 2 == 0) {
             /*the number of times patternsharp or patternspace 
             should be repeated */
             numRepeats = (size/2);
            //row number is odd
            if (i % 2 !== 0) {
                char = patternspace.repeat(numRepeats); 
                console.log(char); 
        }
            //row number is even
            if (i % 2 == 0) {
               char = patternsharp.repeat(numRepeats);
               console.log(char);
 }}}

 

QUESTION 3: 

I defined and initialized the variable numRepeats on Line 9. The later usage of numRepeats on Lines 15, 21, and 27 do no require being defined again, even when they are inside different if/else-if statements. QUESTION: Was that defining a variable ‘locally’? Versus ‘globally’ before the for loop?

var numRepeats inside a nested if statement
still works properly

 

QUESTION 4: 

What happens when you take out the console.log(char); from the if statement body, and place it outside of it? See Line 13.

console 2.3 ejs

 

 

For the Future

  • I didn’t try a solution without String repeat() method. Try that.
  • Answer Questions 1-4 properly.
  • Figure out what is wrong with prompt() or Lines 6-11.
  • Consider other methods to solve Chess Board — replace(), a second for loop, newline character, etc.
  • Then check your solutions with the Book Solutions.

TBC 

Eloquent JS, Chp2: Exercise 1

Exercise 1: Looping a Triangle

Write a loop that makes seven calls to console.log to output the following triangle:

#
##
###
####
#####
######
#######

Useful to know: You can find the length of a string by writing .length after it.

Example:

var abc = "abc";
console.log(abc.length);
//-> 3

Approach:

Given info: 
– need a loop
– seven calls to console.log
– the sharp/number symbol (#) is the string text that needs to be repeated

What do I know? :
– conditional statements (if, else, switch)
– looping statements (while, do…while, for)
– .length after a string gives me the length of the string
– need to concatenate # incrementally

Questions:
-How do I choose which kind of looping statement to use?

Putting together info: 
– counter variable starts at 0 (there is no # yet)
EDIT – encountered epiphany during first line of  Solution Attempt 1: # is of type string. So counter variable should hold an empty string initially.
EDIT 2 – after writing out Solution Attempt 1, I realize that starting at an “” string is unnecessary. It will not be outputted. Counter variable should hold “#” initially.

– condition: counter variable holds a value less than seven
EDIT – same epiphany time: the length of the string value of the counter variable should hold a value … less than 8? less than or equal to 7? less than 7? NOT SURE YET
EDIT 2: At the end of everything — should have given this more thought.

– update/final-expression: counter variable = counter variable + “#”

Didn’t consider:
-what the counter variable represents, and its value type in this exercise — length of the sign/word/symbol (type number)? Number of repeats (type number)? Type string?
EDIT: so the counter variable represents the value to be repeated; since it will be displayed, it is the base symbol of the whole triangle;  it is of type string. At the same time, its length is what keeps track of the number of iterations.

(I actually wrote this down under Given Information, but then forgot about it.)

 

Solution Attempt 1:

for (var signLength = ""; signLength.length < 8; signLength = signLength + "#") {
    console.log(signLength);
}

Checking Understanding: 

First iteration–
The variable signLength holds an empty string.
The length of an empty string is 0.
This means that the condition holds.
The statement inside the loop body is executed {right wording?}.
Nothing is shown as output, because counter variable holds an empty string.
signLength’s value is ‘updated’ from “” to “#”.
Execution goes to the beginning of the loop for the next iteration {right wording?} 

Issues:
– nothing is outputted for the first iteration if I start the counter variable as holding the value of an empty string —> let the counter variable grasp “#” as its initial value
– signLength as the variable name doesn’t make sense, and is made redundant in the condition signLength.length < 8 —> change the variable name to reflect that it holds the base symbol for the whole triangle, but the symbols continue to expand

Questions:
-Would the update shortcut work with strings? i.e. signLength = signLength + “#” becomes signLength += “#” ?
Remember that it’s string concatenation though, not arithmetic addition.
ANSWER – after writing out everything up to “Solution with symbol <= 7”, I checked Hints, and yes, += “#” is usable.

 

Solution Attempt 2

for (var symbol = "#"; symbol.length < 8; symbol = symbol + "#") {
    console.log(symbol);
}

Checking Understanding:

First iteration–
The variable symbol holds a string character “#”.
The length of symbol is 1.
This means that the condition holds.
The statement inside the loop body is executed.
# is outputted.
symbol’s value is ‘updated’ from “#” to “##”.
Execution goes to the beginning of the loop for the next iteration.

Second iteration–
The variable symbol holds the string text “##”.
The length of symbol is 2.
This means that the condition holds.
The statement inside the loop body is executed.
## is outputted. (as a whole, it goes underneath the # from the first iteration)
symbol’s value is ‘updated’ from “##” to “###”.

Third iteration–
The variable symbol holds the string text “###”.
The length of symbol is 3.
This means that the condition holds.
The statement inside the loop body is executed.
### is outputted.
symbol’s value is ‘updated’ from “###” to “####”.

Fourth iteration–
The variable symbol holds the string text “####”.
The length of symbol is 4.
This means that the condition holds.
The statement inside the loop body is executed.
#### is outputted.
symbol’s value is ‘updated’ from “####” to “#####”.

Fifth iteration–
The variable symbol holds the string text “#####”.
The length of symbol is 5.
This means that the condition holds.
The statement inside the loop body is executed.
##### is outputted.
symbol’s value is ‘updated’ from “#####” to “######”.

Sixth iteration–
The variable symbol holds the string text “######”.
The length of symbol is 6.
This means that the condition holds.
The statement inside the loop body is executed.
###### is outputted.
symbol’s value is ‘updated’ from “######” to “#######”.

Seventh iteration–
symbol holds the string text “#######”.
Length of symbol is 7.
Condition holds.
Statement is executed.
####### is outputted.
symbol’s value is ‘updated’ from “#######” to “########”.

Eighth iteration–
symbol holds the string text “########”.
Length of symbol is 8.
Condition evaluates to false.
Execution jumps outside the for loop.
Nothing is outputted (as a whole, the triangle should be outputted).

CONCLUSION: Solution Attempt 2 should work properly.

Issues:
-Should place something outside the loop body? Not sure if the whole triangle is outputted??
EDIT: after testing it in JS console, yes it works.

looping triangle less than 8
Solution with symbol < 8 works properly

Solution with symbol <= 7

looping triangle less than and equal to 7
Also works properly

Sixth iteration–
The variable symbol holds the string text “######”.
The length of symbol is 6.
This means that the condition holds.
The statement inside the loop body is executed.
###### is outputted.
symbol’s value is ‘updated’ from “######” to “#######”.

Seventh iteration–
symbol holds the string text “#######”.
Length of symbol is 7.
Condition holds (symbol.length <= 7).
Statement is executed.
####### is outputted.
symbol’s value is ‘updated’ from “#######” to “########”.

Eighth iteration–
symbol holds the string text “########”.
Length of symbol is 8.
Condition evaluates to false.
Execution jumps outside the for loop.
Nothing is outputted (as a whole, the triangle should be outputted).

 

Solution with symbol < 7

looping triangle less than 7
Does not work properly

Sixth iteration–
The variable symbol holds the string text “######”.
The length of symbol is 6.
This means that the condition holds.
The statement inside the loop body is executed.
###### is outputted.
symbol’s value is ‘updated’ from “######” to “#######”.

Seventh iteration–
symbol holds the string text “#######”.
Length of symbol is 7.
Condition evaluates to false (symbol.length < 7).
Execution jumps outside the for loop.
Nothing is outputted (as a whole, a triangle with six levels is outputted).

 

CONSIDER: Both Solution with symbol.length < 8 and symbol.length <= 7 outputs the desired result. But which one is processed more quickly?

 

Solution Attempt 3: Final submission

for (var symbol = "#"; symbol.length < 8; symbol += "#") {
    console.log(symbol);
}

NB: Changed from symbol = symbol + “#” to symbol += “#”

looping triangle update shortcut
symbol += “#”     works properly

.
.
.

BOOK SOLUTION

 

 ejs chp3 e2 soln

  • variable name is line, which seems more reasonable than symbol, since the string value’s length is used to keep track of the progress of the program
  • the condition – < 8 is used, instead of <= 7
  • my solution is more or less the same to the book solution

Eloquent JavaScript – Chapter 1: Values, Types, and Operators; Rough Notes

  • Data is stored as bits – any kind of two-valued things
  • Bits – usually described as zeros and ones
  • Inside the computer, bits – high or low electrical charge, a strong or weak signal, a shiny or dull spot on a CD
  • “Any piece of discrete information can be reduced to a sequence of zeros and ones and thus represented in bits” {?}

NB: Discrete data can only take distinct values; can be numeric or categorical (male or female, green or yellow) –stackexchange 

Example: Show the number 13 in bits

-Have only 2 digits (0 and 1)
-The weight of each digit increases by a factor of 2 from right to left

13 in bits

-The binary number 00001101, or 8+4+1, is the decimal number 13

NB: a binary number is expressed in the binary numeral system or base-2 numeral system which represents numeric values using two different symbols: usually 0 and 1 –Wikipedia 

Values

  • modern computer has > 30 billion bits in its volatile data storage; more in nonvolatile data storage

NB: Volatile memory is computer memory that requires power to maintain the stored info; stored data is lost if the power is off or interrupted —Wikipedia 

  • hard to work with this large quantity of bits
  • Solution: separate bits into chunks (called values) that represent pieces of information
  • Every value has a type that determines its role
  • The 6 basic types of values in JS:
    -numbers
    -strings
    -Booleans
    -objects
    -functions
    -undefined values
  • To create a value — invoke its name
  • Every value has to be stored somewhere
  • Might run out of bits if you use many, many values simultaneously
  • “When you no longer use a value, it will dissipate {?}, leaving behind its bits to be recycled as building material for the next values”

 

Numbers

[make more concise]

  • The value of the number type is a numeric value
  • JS uses 64 bits to store a single number value
  • The amount of different numbers that can be represented is limited
  • With 64 binary digits, 264 different numbers can be represented
  • Computer memory used to be smaller; 8 bits or 16 bits were used to represent numbers
  • Easy to overflow such small numbers – end up with a number that did not fit into the given amount of bits
  • Today, computers have plenty of memory, so overflow occurs only when dealing with astronomical numbers
  • Bits can store negative numbers (one bit indicates the sign of the number)
  • Nonwhole numbers must also be represented (some of the bits store the position of the decimal point)
  • Calculations with integers (whole numbers) are precise
  • Treat fractional digital numbers as ap and proximations, not as precise values (because fractions cannot be expressed by a finite number of decimal digits — and there is only 64 bits available to store them)

 

Arithmetic

  • 100 + 4*11
  • + and * are operators 
  • + represents addition
  • * represents multiplication
  • <<value>> <<operator>> <<value>>
  • An operator between two values applies itself to those values to produce a new value
  • Order of operator application (precedence) is determined by BEDMAS
  • Apply Left to Right if there are multiple operators with the same precedence
  • % : represents the remainder operation — known as modulo or remainder 
  • X % Y : the remainder of dividing X by Y
  • Example: 314 % 100 produces 14, 144 % 12 produces 0 

 

Special Numbers

3 JS values considered numbers but don’t behave like normal numbers:

  1. Infinity : positive infinity
  2. -Infinity : negative infinity
  3. NaN : “Not a Number” – a value of the number type; will get NaN when i.e.  0/0 (zero divided by zero), Infinity – Infinity, any numeric operation that does not yield a precise result

 

Strings

  • string – a basic data type
  • represent text
  • content enclosed in quotes (single, double – but start and end quote must match)
  • i.e. “Hello there!”, ‘On the way to the moon, hold up.’
  •  Characters that are difficult to place within quotes: quotes, newlines (characters you get when you press Enter – basically spaces on a new line)
  • Solution: escaping the character — using: backslash (\)  — when this is inside a quoted text,  it indicates the the character after it has a special meaning
  • i.e. ‘She\’s my sister\’s dog’ means the quotes are a part of the string
  • i.e. ‘ \n ‘ means a newline
  • i.e. ‘ \t ‘ means a tab character
  • i.e. “This is the first line\nAnd this is the second”
    Actual  text:
    This is the first line
    And this is the second
  • When you want a backslash in a string to be just a backslash:
    use \\ (two backslashes)

Example:

console.log(“A newline character is written like \”\\n\”.”)
// -> A newline character is written like “\n”.

  • Strings cannot be divided, multiplied, or subtracted
  • + operator used on strings to concatenate – combines two strings together

Example:

console.log(“con” + “cat” + “e” + “nate”)
// -> concatenate               [not enclosed by single quotes like in Python]

 

Unary Operators

unary operator: operator that takes\operates on one value

binary operator: operator that uses two values

ternary operator: operator that operates on three values

typeof: an unary operator that produces a string value naming the type of the value given to it

Example 1: 
console.log(typeof 4.5)
//-> number

Example 2:
console.log(typeof Infinity)
//-> number

Example 3:
console.log(typeof NaN)
//->number

Example 4:
console.log(typeof 3 > 2)
//-> false

Example 5:
console.log(typeof “x”)
//-> string

NB1: console.log() outputs a message to the Web Console (a way for us to see the result of evaluating something)

NB2: The minus operator (-) can be used as both a binary and an unary operator

Example 6: 
console.log(-(10-2))
//-> -8

 

Boolean Values

Distinguish between two possibilities i.e. yes and no, on and off, …

Boolean type: has two values — true and false

Comparisons

A way to produce Boolean values

Example 1: 
console.log(3 > 2)
//-> true                                     Indicates 3 is greater than 2

Example 2: 
console.log(3 < 2)
//-> false

 

Strings can be compared to each other :

  • strings are ordered alphabetically i.e. “a” < “z”
  • uppercase letters are “less” than lowercase letters i.e. “Z” < “a”
  • non-alphabetic characters (!, -, ?, etc.) are included in the ordering i.e. “.” > “!”,  “?” > “!”
  • comparison is based on the Unicode standard : assigns a number to every character ever needed, including characters from other languages i.e. Japanese, Arabic, Greek, …
  • comparing strings : Left to Right, compare numeric codes of characters one by one
  • other comparison operators:
    >=    greater than or equal to 
    <=    less than or equal to
    ==    equal to
    !=     not equal to
  • one value in JS is not equal to itself : NaN (“not a number”)

Example: 
console.log(NaN == NaN)
//-> false

NB: NaN denotes the result of a nonsensical computation; therefore it isn’t equal to the result of other nonsensical computations.

 

Logical Operators

 Operators on Boolean values

and, or, not
used to “reason” about Booleans 

 

&& represents logical and 
-a binary operator
-its result is true iff both values given to it are true

Example 1:
console.log(true && false)
//-> false

Example 2: 
console.log(true && true)
//-> true

|| represents logical or
-a binary operator
– proudces true if either of the values given to it is true

Example 1:
console.log(false || true)
//-> true

Example 2:
console.log(false || false)
//-> false

! represents not 
-an unary operator
-flips the value given to it

Example 1: 
console.log(!true)
//-> false

Example 2: 
console.log(!false)
//-> true

 

Order of Precedence 

Arithmetic operators (highest)
Comparison operators
&&
|| (lowest)

NB: This order minimizes the use of parentheses.

Example:
console.log(1+1 == 2 && 10*10 > 50)
// 2 == 2 && 100 > 50
// true && true
//-> true

<<value1>> ? <<value2>> : <<value3>>
-represents the conditional/ternary operator
– a ternary operator
-written with a question mark and a colon
– The first value “picks” which of the other two values will come out :
-if true, the second value is chosen
-if false, the third value is chosen

NB: << … >> just represents that a value is written; <<…>> itself is not included in the value

Example 1:
console.log(true ? 1 : 2)
//-> 1

Example 2: 
console.log(false ? 1 : 2)
//-> 2

Undefined Values

Two special values:

null

undefined

represent the absence of a meaningful value (carry no information)

NB1: operations that don’t produce a meaningful value yield undefined because they have to yield some value

NB2:
-there is a difference in meaning between undefined and null (but it doesn’t matter most of the time)
-this is an accident of JS’ design
-treat them as interchangeable (for now)

Automatic Type Conversion

Here we’ll see how JS accepts almost any program given to it, even if they are odd.

type coercion:
– an operator is applied to the “wrong” type of value i.e. “three” + 3
-JS converts that value to the type it wants
-JS uses a set of unpredictable rules to do this

Example 1: 
console.log(8*null)
//-> 0                             null becomes 0

Example 2: 
console.log(“5” – 1)
//-> 4                             string -> number ; “5” becomes 5

Example 3: 
console.log(“5” + 1)
//-> 51                     + tries string concatenation before numeric addition; 1 converted to “1”

Example 4:
console.log(“five” * 2)
//-> NaN

Example 5:
console.log(false == 0)
//-> true

Regarding Ex. 4: When something that doesn’t map to a number i.e. “five”, “undefined”, is converted to a number, the value NaN is produced.

NB: Further arithmetic operations on NaN keep producing NaN.

 

Comparing values of different types using == 

  • most cases: JS converts one of the values to the other value’s type
  • For true to be produced —
    if null is on one side, undefined must be on the other and vice versa

Example 1:
console.log(null == undefined)
//-> true

Example 2: 
console.log(undefined == null)
//-> true

Example 3: 
console.log(null == 0)
//-> false

Example 4:
console.log(undefined == 1)
//-> false

NB: to test whether a value has a real value instead of null or undefined, compare it to null with the == or != operator.

QUESTION: Can you compare it to undefined too?

 

Rules for converting strings and numbers to Boolean values:

  • 0, NaN, the empty string (“”) count as false
  • all other values count as true

Ex. 1: 
console.log(0 == false)
//-> true

Ex. 2: 
console.log(“” == false)
//-> true

For these cases, automatic type conversion is unwanted.

To test whether something refers to the precise value false: 

  • Use two extra operators:
=== 
!==

=== tests whether a value is precisely equal to the other

!== tests whether a value is not precisely equal to the other

Ex: 
console.log(“” === false)
//-> false

In this example, “” counts as false, but it is not precisely equal to the value false.

NB: Use the three-character comparison operators to make certain that both sides are the same type.

QUESTION: Because automatic type conversion could change the type of a value in the comparison?  

 

Short Circuiting of Logical Operators

  • Logical operators && and || handle values of different types strangely
  • They will convert the value on their left side to Boolean type (to decide what to do)
  • Depending on the operator and the result of that conversion, either the original LH-value or RH-value is returned

|| operator
– returns the value to its left when that can be converted to true
-returns RH-value otherwise

Ex. 1:
console.log(null || “user”)
//-> user

Ex. 2
console.log(“Karl” || “user”)
Karl

NB: Therefore || operator can be used as a way to fall back on a default value i.e. give it an expression that might produce an empty value on the left, the value on the right will be used as a replacement

&& operator
– works the other way around
-when LH-value is something that converts to false, it returns that original LH-value
-otherwise, RH-value is returned

Property of && and || operators:
Short-circuit evaluation: expression on right evaluated only when necessary

Ex. 1: true || X
-LH-value is true so the result is true
-X is never evaluated, no what X is

Ex. 2: false && X
-result is false
-X is ignored

Conditional operator
-works similarly
-first expression is always evaluated
-second or third value (the one not picked) is ignored {?}

 

Summary

We made some values and applied operators to them to get new values.

  • Went through four types of JS values: numbers, strings, Booleans, undefined values
  • Values are created by typing in their name (true, false, null, undefined) or value (“abc”, 13)
  • Can combine and transform values with operators
  • Binary operators for
    -arithmetic (+, -, *, /, %)
    -string concatenation (+)
    -comparison (==, !=, ===, !==, <, >, <=, >=)
    -logic (&&, ||)
  • Unary operators:
    -(!) to negate logically
    -(-) to negate a number
    -(typeof) to find a value’s type
  • Ternary operator:
    ( ? : ) – to pick one of two values based on a third value
  • NaN (“not a number”) is the only JS value not equal to itself, because the result of a nonsensical computation cannot equal the result of another nonsensical computation

 

Progress: We can now use JS as a pocket calculator. LOL FML.

 

Eloquent Javascript: Intro – What is Javascript? ;Rough Notes

Resource: Eloquent Javascript, 2nd Edition by Marijn Haverbeke

What is Javascript?

  •  JavaScript (henceforth JS) created in 1995 to add programs to web pages in the Netscape Navigator browser
  • Major graphical web browsers have since adopted JS
  • JS has made modern web applications possible
  • “Modern web applications = applications with which you can interact directly without doing a reload for every action”
  • Also used in websites to provide interactivity

NB: Netscape – a series of web browsers produced by Netscape Communications Corporation (now a subsidiary of AOL); original browser once the dominant browser in terms of usage share (proportion of visitors to web sites that use a certain web browser), but lost to Internet Explorer in the first browser war (competition for dominance in the usage share of web browsers) (first war — Microsoft’s Internet Explorer vs. Netscape’s Navigator)
—Wikipedia: Netscape (web browser)

  • ECMAScript standard : a standard document that describes the way JS should work to ensure that software claiming to support JS really does support JS ; named after Ecma International, the organization that did the standardization
  • ECMAScript and JS can be used interchangeably (two names for the same language)

Disadvantages of JS

  • JS is “ridiculously liberal in what it allows” — almost any command is accepted, but is then interpreted differently
  • Idea behind this design: make programming in JS easier for beginners
  • Reality: Makes finding program errors harder because the system will not point them out to you

Advantages of JS

  • Flexibility allows for many techniques that are impossible in more rigid languages

Different versions

  • Version 3 — widely supported version btwn ~ 2000-2010, the time of JS’s ascent to dominance
  • Version 4 — “changing a living, widely used language … turned out to be politically difficult” — work abandoned in 2008
  • Version 5 — came out in 2009
  • Version 5.1 — 2011 — Editorial changes —w3schools
  • Version 6 — 2015 —  Added classes and modules —w3schools
  • Version 7 — 2016 — added exponential operator (**); added Array.prototype.includes –w3schools
  • This book’s edition came out in 2014 so it will focus on Version 5, which all major browsers support; we should focus on using Version 6, which all major browsers are in the process of supporting

 

  • Platforms on which JS is used: Web browsers, databases i.e. MongoDB, CouchDB (use JS as their scripting and query language)
  • Several platforms for desktop and server programming i.e. notably, Node.js, provides a powerful environment for programming JS outside of the browser