I’m currently going through the highly recommended “Eloquent Javascript” textbook (which is also available for free as a pdf here) and wanted to document all of the problem sets and projects to:
- log my current skill level at solving coding challenges and assess my knowledge
- compare with the text-book provided solutions to see how my code can be refactored, and
- track progress on how my overall coding and problem-solving hopefully improves over time
The purpose is to get a deeper understanding of the Javascript language by methodically going through each problem set, and then ‘translating’ the code into human language to drive home what it is I am actually trying to solve. The reason I’m taking this low and slow approach is because ever since I was younger, I always had to work five times harder to understand math and science subjects. And I think over time as an adult, I had convinced myself that I wasn’t good at either of those subjects. However, at the end of the day I find solving problems to be extremely fulfilling so I’m hoping this method of self-learning and keeping myself accountable by logging everything will help me master my own insecurities and become a more confident and competent programmer, i.e. a person who solves problems eloquently with code and technology.
The goal of this chapter is to understand Javascript is structured as an actual program
Problem 2.1 – Looping a triangle – My Solution
let result = "";
for (let counter = 0; counter <= 7; counter ++) {
console.log (result += "#"); }
// ->
#
##
###
####
#####
######
#######
My Solution Translated
// this practice helps keep me accountable in logging the theory that I learned but more importantly, to assess how I’m actually applying what I’ve learned into solving each coding challenge.
First, I initialized the result to be an empty string. Then I created a for loop (which is a more streamlined version of the while loop) where I initialize a counter to 0; then the expression “counter is less than 7” to check if the loop should continue; and then the final part, incrementing counter by 1 to update the loop.
While the counter is less than 7; the program is to execute the statement in the body (code between the {}) which is to log the result and add the “#” each time. This is why I had to initialize result as an empty string so that the result doesn’t start with “##”, and instead starts with “#” as the challenge dictated.
Marijn Solution
for (let line = "#"; line.length < 8; line += "#") {
console.log (line);}
While, I was able to solve the problem on my own and the result was the same, this is a much more eloquent solution.
The concept I didn’t leverage was the length property of a string, since “#” is a string.
str.length // syntax, this property returns the number of code units in the string
str.length(""); // empty string will return 0
Problem 2.2 FizzBuzz – My Solution
//Part 1 - prints a program that console logs 1 through 100, but for every number //divisible by 3, print "Fizz", and for every number divisible by 5, print "Buzz"
for (let counter = 1; counter <= 100; counter++) {
if (counter % 3 == 0) {console.log ("Fizz");}
else if (counter % 5 == 0) {console.log ("Buzz");}
else {console.log (counter);}}
//Part 2 - in addition to above, for every number that is divisible by both 3 and 5, print "FizzBuzz"
// See Iteration 1. *did not solve*
My Solution Translated
First, I initialize the counter as 1 and write the rest of the conditions for the for loop. Here, I have to apply what I know about conditional statements so that I can get any number divisible by 3 to be replaced by “Fizz”, and the same for 5 but with “Buzz”. I actually found this initial part fairly easy as it built upon the loop exercise from 2.1.
That said, the second part of the challenge which is to add another condition, so that if a number is divisible by BOTH 3 and 5, then replace that number with “FizzBuzz”.
I looked at the hint provided since my code solution wasn’t working:
// Iteration 1
for (let counter = 1; counter <=100; counter ++) {
if (counter % 3 == 0) {console.log ("Fizz");}
else if (counter % 5 == 0 ) {console.log ("Buzz");}
else if (counter % 3 == 0 && counter % 5 == 0) {console.log ("FizzBuzz");}
else {console.log (counter);}
}
This 1st iteration printed out the same thing as only part 1 of the solution, and didn’t print out “FizzBuzz” for the number 15, as an example.
The Hint:
The first simple solution for the “FizzBuzz” is to just add this additional conditional branch to the first part, which is what I attempted above. However this didn’t work.
The reason is because my conditions were in the wrong order – my code would never reach the block inside the && operator because either the first condition (counter % 3 == 0) or the 2nd condition (counter % 5 == 0) would be true first. (Thank you Stackoverflow)
// Iteration 2 with the conditions in correct order
for (let counter = 1; counter <=100; counter ++) {
if (counter % 3 == 0 && counter % 5 == 0) {console.log ("FizzBuzz");}
else if (counter % 3 == 0 ) {console.log ("Fizz");}
else if (counter % 5 == 0 ) {console.log ("Buzz");}
else {console.log (counter);}
}
The alternative, supposedly more ‘clever’ solution is to build up a string containing the words to output and print either this word or the number if there is no word, by potentially leveraging the || (or) operator.
Marijn Solution
for (let n = 1; n <= 100; n++) {
let output = "";
if (n % 3 == 0) output += "Fizz";
if (n % 5 == 0) output += "Buzz";
console.log (output || n);
}
This is really eloquent, and to be honest I would’ve never come up with this solution even after reading the hint (which I struggled with). That said, let’s dissect this.
The for loop is the same – there is no question there. The body statement is what I had to read a couple of times over to see how the “FizzBuzz” actually came into play.
If I translate the first condition: if the number if divisible by 3, then print output = “” + “Fizz”, or just “Fizz”.
Then, instead of an ‘else’ statement, it’s just a secondary ‘if’ statement separate from the first condition: if the number is diviislbe by 5, then print “Buzz”.
Finally, the last || operator is what makes this so succinct – print either the string output or the number depending on which conditions are met
So for example, when the counter reaches 15, it satisfies both the first condition, so will print “Fizz”, but then also satisfies the 2nd condition which would output “Buzz”, so that end result would be “FizzBuzz”.
Essentially, having 2 separate if statements like above acted as the && condition in this case. Lesson learned – I definitely have a long way to go.
Problem 2.3 Chessboard
My Solution (or lack thereof)
// Iteration 1 which was admittedly half baked. Maybe I was tired, but I am sorry to admit that I had given up after this first iteration. My mind went blank.
let hash = "#";
let space = "_";
let size = 8;
for (let counter = 1; counter <= size; counter ++) {
if (counter % 2 == 0) {console.log (space);}
else {console.log(hash)};
}
/* printed out below result which was incorrect. I just set it to "_" to help visualize the solution, but otherwise it should've been an empty space.
#
_
#
_
#
_
#
_
*/
Admittedly, I was partially on the right path by leveraging the modulo %2 to denote even or odd, which would help determine if a # or “” should be placed at a given position. Now below is the actual solution:
Marijn Solution
let size = 8;
let board = "";
for (let y = 0; y <size; y++) {
for (let x = 0; x < size; x++) {
if ((x+y) % 2 == 0) {
board +="";}
else {board += "#";}
}
board += "/n";
}
console.log(board);
//result
# # # #
# # # #
# # # #
# # # #
# # # #
# # # #
# # # #
# # # #
Marijn Solution Translated:
First, initialize the binding size of the board which is 8. Size refers to the size of the grid (so 8 units wide, 8 units long).
Then, initialize a second binding, board, which is set to an empty string.
The double for loop: the order of the loops must follow the order in which the lines are built up, so line by line left to right, then top to bottom
Outer loop – handles the lines (i.e. board ‘height’ or ‘y’)
Standard for loop. No question there. Right before the outer loop closes, we include the code to add the “/n” new line character.
Inner loop – handles the characters within the line (i.e. board ‘width’ or ‘x’)
To determine whether to put the # or the ” ” for the given width, which shouldn’t exceed the size value, an if statement is used:
While y is less than 8, and x is less than 8:
If x + y is even, then print board (which was initialized to an empty string)+ ” “, otherwise if the sum of x + y is odd, then print board +”#”.
Today’s score: 50% (out of the 4 coding challenges, I got 2.1 and first half of 2.2 correct)
Today’s Lesson / Feedback to Self: Build up more stamina and focus to push through challenges I don’t get, instead of overly relying on hints and/or giving up.