Solved

JavaScript - Chessboard

Posted on 2016-09-27
36
42 Views
Last Modified: 2016-09-28
Hi Gurus,

I'm currently reading a book called "Eloquent JavaScript" and working on all the projects as well.  In Chapter 2, I am stuck on an exercise I've been working on for about a week but I can't figure it out.

Here's the exercise:
Write a program that creates a string that represents an 88 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:
# # # #
# # # #
# # # #
# # # #
# # # #
# # # #
# # # #
# # # #
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.


Here's my solution but it's just not coming out correctly.  
http://codepen.io/isogunro/pen/dpvKJp?editors=1112

Any hint\help\suggestion\comments would be greatly appreciated.
0
Comment
Question by:Isaac
  • 14
  • 13
  • 9
36 Comments
 
LVL 32

Accepted Solution

by:
Stefan Hoffmann earned 300 total points
Comment Utility
Answer these two questions:

What should you print to the console?
What do you print to the console?

Hint: How many prints do you think you need?
0
 
LVL 5

Author Comment

by:Isaac
Comment Utility
Question 1:
# # # #
# # # #
# # # #
# # # #
# # # #
# # # #
# # # #
# # # #

Question 2: (Here''s what my code produced)
" # # # #"
" "
" #"
" # "
" # #"
" # # "
" # # #"
" # # # "
" # # # #"

Question 3:
8x8

Still confused
0
 
LVL 5

Author Comment

by:Isaac
Comment Utility
Actually, my code produced this. Not sure why b/c my loop is 8

" "
" #"
" # "
" # #"
" # # "
" # # #"
" # # # "
" # # # #"
" "
" #"
" # "
" # #"
" # # "
" # # #"
" # # # "
" # # # #"
" "
" #"
" # "
" # #"
" # # "
" # # #"
" # # # "
" # # # #"
" "
" #"
" # "
" # #"
" # # "
" # # #"
" # # # "
" # # # #"
" "
" #"
" # "
" # #"
" # # "
" # # #"
" # # # "
" # # # #"
" "
" #"
" # "
" # #"
" # # "
" # # #"
" # # # "
" # # # #"
" "
" #"
" # "
" # #"
" # # "
" # # #"
" # # # "
" # # # #"
" "
" #"
" # "
" # #"
" # # "
" # # #"
" # # # "
" # # # #"
0
 
LVL 5

Author Comment

by:Isaac
Comment Utility
I think I see the problem...be back. stand by..
0
 
LVL 51

Assisted Solution

by:Julian Hansen
Julian Hansen earned 200 total points
Comment Utility
Hint: chessboard squares exist in pairs.
0
 
LVL 5

Author Comment

by:Isaac
Comment Utility
YES!!!  I got it.  Thanks for the hints gentleman. Now on to the next chapter, Functions.

var num = 8;
for (var i=1; i<=num; i++) {
  var y="";
  for (var x=1; x<=num; x++){
    if(x%2===0){
      y += "#";
    }
    else {
      y += " ";
    }
  }
   console.log(y);
}

Open in new window

0
 
LVL 5

Author Closing Comment

by:Isaac
Comment Utility
Much appreciated
0
 
LVL 32

Expert Comment

by:Stefan Hoffmann
Comment Utility
Not exactly, cause:

Hint: How many prints do you think you need?

and

Passing this string to console.

Means you need one "print".. "this string" is singular. Thus you should use one print/output call.
You're currently using num prints.
0
 
LVL 51

Expert Comment

by:Julian Hansen
Comment Utility
Using pairs same result. Each row we just alternate what a square looks like ' #' then '# ';
<script>
var num = 8;
var cols = num / 2;
for(var row=1; row<=num;row++) {
  var square = row % 2 ? ' #' : '# ';
  var line = '';
  for(var col=1;col<=cols;col++) {
    line += square;
  }
  console.log(line);
}
</script>

Open in new window

0
 
LVL 32

Expert Comment

by:Stefan Hoffmann
Comment Utility
num = 9?
0
 
LVL 51

Expert Comment

by:Julian Hansen
Comment Utility
granted
0
 
LVL 32

Expert Comment

by:Stefan Hoffmann
Comment Utility
nope, the second is yours:

Capture.PNG
and the bottom, left piece is normally black.
0
 
LVL 5

Author Comment

by:Isaac
Comment Utility
ste5an,

I did use one print (console.log).  Is that what you mean?

What's wrong with num=9?  It produced the correct result.
http://codepen.io/isogunro/pen/dpvKJp?editors=1112
0
 
LVL 5

Author Comment

by:Isaac
Comment Utility
Nevermind...
0
 
LVL 32

Expert Comment

by:Stefan Hoffmann
Comment Utility
Coding is a strict process. The requirements tell you that you should create one string and output this single string.

E.g.
var outputCounter = 0;
var num = 9;
for (var i=1; i<=num; i++) {
    var y="";
    for (var x=1; x<=num; x++){
        if(x%2===0){
            y += "#";
        }
        else {
            y += " ";
        }
    }
    console.log(y);
    outputCounter += 1;
}
console.log('Num outputs:' + outputCounter);

Open in new window


And for a 9x9 board the correct output is the first, yours the second:
Capture.PNG
A chess board has an alternate coloring scheme and starts with a black square in the bottom, left corner.
0
 
LVL 5

Author Comment

by:Isaac
Comment Utility
Ahhhh.....I see. dang
0
 
LVL 32

Expert Comment

by:Stefan Hoffmann
Comment Utility
A further hint: A "general" chess board is not necessarily squared, thus the task asks for working with independent width and height.
0
 
LVL 5

Author Comment

by:Isaac
Comment Utility
hmmm......looks like I'm not done.  Need to think some more.

BTW Julian, your code produced when I entered it in codepen
"####"
" # # # #"
"####"
" # # # #"
"####"
" # # # #"
"####"
" # # # #"
0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 32

Expert Comment

by:Stefan Hoffmann
Comment Utility
Just start by building the board row by row.

Hint: sequence of  pieces in a 4x4 board is (ATTENTION, ASCII ART :):
+--+--+--+--+
|16|15|14|13|
+--+--+--+--+
| 9|10|11|12|
+--+--+--+--+
| 8| 7| 6| 5|
+--+--+--+--+
| 1| 2| 3| 4|
+--+--+--+--+ 

Open in new window

0
 
LVL 32

Expert Comment

by:Stefan Hoffmann
Comment Utility
As you can rotate a chess board, try to output this:

4|3|2|1|
|5|6|7|8
12|11|10|9|
|13|14|15|16

Open in new window


And before doing this, print this:
|1|2|3|4
|5|6|7|8
|9|10|11|12
|13|14|15|16

Open in new window

0
 
LVL 5

Author Comment

by:Isaac
Comment Utility
This is harder than I thought.
0
 
LVL 32

Expert Comment

by:Stefan Hoffmann
Comment Utility
First of all start with the description  of the problem:

[..] using newline characters to separate lines. [..] Passing this string [..]

This translates to pseudo-code using chess semantics:

board =''
foreach rank
        line = 'build line'
        board += line
print board

Then examine how to build a line. Either you can use the idea behind the square sequence or (another approach) use the visual approach: the second rank is the inverse of the first rank.
0
 
LVL 5

Author Comment

by:Isaac
Comment Utility
Why would I need the "\n" if the outer loop creates a new line already?
0
 
LVL 32

Expert Comment

by:Stefan Hoffmann
Comment Utility
Well, where you place the add does not really matters. Whether it's alread at the end of the line or you do it in the outer loop, as long as it is added. The point is where do you know that the line is completed?
0
 
LVL 51

Expert Comment

by:Julian Hansen
Comment Utility
BTW Julian, your code produced when I entered it in codepen
Are you sure you entered it incorrectly - here is a link to the code - check the output in the console.
0
 
LVL 32

Expert Comment

by:Stefan Hoffmann
Comment Utility
The link return a blank page in Edge..
0
 
LVL 51

Expert Comment

by:Julian Hansen
Comment Utility
This might be jumping the gun on your learning path but there are some other techniques that can be used to solve this problem. The following is a discussion in thinking about the problem and how we can use what we know about the problem to derive a solution.

Lets look at what you are trying to achieve.
There are two possible output values a space ' ' and hash '#'
You are basically alternating between those.

The second consideration is that each odd row starts with the same character and each even row starts with the same character.

Rows can be odd or even. When even, the last character on the current row is the same as the starting character on the following row. But with odd rows the characters alternate across rows.

Example 2x2
| #|
|# |

Open in new window

If we flatten the above out we get
| ## |

Open in new window

Example 3x3
| # |
|# #|
| # |

Open in new window

If we flatten this one out we get
| # # # # |

Open in new window


The third consideration is the last row should always end in a space (if we follow the rule that a chessboard always has a white square in the bottom right hand corner)

Consider the grids above. Both of them satisfy this consideration. What do we notice about the first row in each case? In both cases the row starts with a space.
 
How can we use the information in the above considerations to solve the problem.
Instead of using if statements why don't we rather store the output characters in an array like so
var square=['#',' '];

Open in new window

We need an index into this array - lets call it k.

We need k to alternate between the two squares on each output within a row i.e. k needs to flip between 1 and 0.
There is a neat trick to getting a variable to flip between 1 and 0
k = 1 - k

Open in new window

When k is 1 the result is 0
When k is 0 the result is 1
Using the above we can put the following together
var num = 8;
var square=['#', ' '];
for(var row=1; row<=num;row++) {
  line = '';
  for(var col=1; col<=num;col++) {
    line += square[k];
    k = 1 - k; 
  }
  console.log(line);
}

Open in new window

This code is not quite ready yet. Firstly, we have not initialised k to a starting value. If we look at our discovery in the third consideration above we see that the first row must always start with a ' ' which means, given our square array k needs to start as a 1.
We could therefore do this
var num = 8;
var square=['#', ' '];
var k = 1;
for(var row=1; row<=num;row++) {
  line = '';
  for(var col=1; col<=num;col++) {
    line += square[k];
    k = 1 - k; 
  }
  console.log(line);
}

Open in new window

This is also still not quite there - if we run it for num = odd number it works - but for even numbers it just prints out N of the same row. This is because of what we found in the second consideration i.e. N = odd number characters alternate across rows, N = even number the last character of the current row is the same as the first character of the next. This means that we need to initialise k differently on each row. This is easily done. We already have the outer loop that is alternating between odd and even numbers - we can use that to initialise k. Whatever row N starts with row N + 1 must be the other character.
We know the first row must start with a space, and we know that the space is index 1 in the square array so k must start at 1. In other words when
row = 1, k = 1
row = 2, k = 0
row = 3, k = 1
...

Open in new window

If you study the pattern of the above you will see it follows row modulus 2
To complete our code we can therefore put an initialiser for k on each iteration of the outer loop like this
var num = 8;
var square=['#', ' '];
for(var row=1; row<=num;row++) {
  line = '';
  k = row % 2;
  for(var col=1; col<=num;col++) {
    line += square[k];
    k = 1 - k; 
  }
  console.log(line);
}

Open in new window

0
 
LVL 51

Expert Comment

by:Julian Hansen
Comment Utility
The link return a blank page in Edge..
As it should - it is pure JavaScript to see the output you need to F12 and for Edge you need to refresh the page when the console is open. console is not available when the console window is not open.
0
 
LVL 51

Expert Comment

by:Julian Hansen
Comment Utility
If we want to stick to the exact requirements of the problem which is to separate lines with \n chars and have one output statement then we need to
a) Initialise line outside the loop
b) Remove the re-initialisation of the line in the loop
c) Terminate line with a \n at the completion of each inner loop
d) Move the console.log(line) outside both loops.
<script>
var num = 8;
var square=['#', ' '];

// a) Initialise line outside the loop
var line = '';
for(var row=1; row<=num;row++) {

  // b) Remove the re-initialisation of the line in the loop
  //  line = '';

  k = row % 2;
  for(var col=1; col<=num;col++) {
    line += square[k];
    k = 1 - k; 
  }

  // c) Terminate line with a \n at the completion of each inner loop
  line += '\n';
}

// d) Move the console.log(line) outside both loops.
console.log(line);
</script>

Open in new window

0
 
LVL 32

Expert Comment

by:Stefan Hoffmann
Comment Utility
using the square sequence
var height = 8;
var width = 10;
var board = '';
for (var rank = 1; rank <= height; rank++) {
    var line = '';
    for (var file = 1; file <= width; file++ ) {
        line = ((file + (rank % 2 === 0 ? 0 : 1)) % 2 === 0 ? '#' : '.') + line;
    }
    board += line + '\n';
}
console.log(board);

Open in new window

0
 
LVL 5

Author Comment

by:Isaac
Comment Utility
Thanks Julian!

I need to dissect your scripts in chrome, especially the last one.  The "\n" is throwing me off.  I would think that the outerloop would cause the newline implicitly.
0
 
LVL 32

Expert Comment

by:Stefan Hoffmann
Comment Utility
0
 
LVL 51

Expert Comment

by:Julian Hansen
Comment Utility
I would think that the outerloop would cause the newline implicitly.
If you are console.log()'ing on each iteration of the outer loop it would - but we are only doing the console.log() after all iterations of both loops are complete i.e. just 1 single console.log() of a long line with all the rows. Therefore the \n is needed to break those lines up.

The two samples show the two different approaches - the first does N console.log() output (1 for each row - so no \n is required) the second as a single output - which needs \n

The original question stated
Write a program that creates a string that represents an 8x8 grid, using newline characters to separate lines
I also interpret the question to mean a square board rather than one allowing for a different height and width. They ask for a variable called size - not width and height, so diverging into code on how to handle non-square boards might be clouding the issue.
0
 
LVL 5

Author Comment

by:Isaac
Comment Utility
Ahh...Ok.  I see now.
0
 
LVL 32

Expert Comment

by:Stefan Hoffmann
Comment Utility
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.
Does imho not impose a constraint on width and height.. otherwise replace height and width by size.
0
 
LVL 51

Expert Comment

by:Julian Hansen
Comment Utility
Does imho not impose a constraint on width and height.. otherwise replace height and width by size.
It is ambiguous but I put it down to bad phrasing. If they wanted variable width and height they would have probably said
"define variables width and height ..."
But they said size - one variable for me implies a square. Given the level of this teaching example and what it is trying to achieve I would not think that a non-square output would not be a requirement for this question - maybe a follow up question. This seems to be teaching about how to obtain a specific output (8x8) and then change to the generic (size x size)
Having said that - I would solve it like this - building on the above example
First we would need to define a row and col value to replace num.
We would need to replace the loop terminators with these values.
Finally, we need to change how we determine the start value for k in the outer loop.
Once that is correct the rest will follow.
There are 4 possible scenarios we need to look at
Rows: EVEN
Cols: EVEN
| x|
|x |

Open in new window

Rows: EVEN
Cols: ODD
|x_x|
| x |

Open in new window

Rows: ODD
Cols: EVEN
|x |
| x|
|x |

Open in new window

Rows: ODD
Cols:ODD
| x |
|x x|
| x |

Open in new window

To keep true to the white square bottom right we need a truth table of what character to start on for each of the above
ROWS COLS  :  RESULT
EVEN EVEN  :    1
EVEN ODD   :    0
ODD  EVEN  :    0
ODD  ODD   :    1

Open in new window

That looks like an XOR result
So what if we set start to the following
var start = (rows % 2 ^ cols % 2);

Open in new window

That will give us the opposite of what we want i.e
ROWS COLS  :  RESULT
EVEN EVEN  :    0
EVEN ODD   :    1
ODD  EVEN  :    1
ODD  ODD   :    0

Open in new window

But this is ok because we can use the same trick we are using to flip k to flip start and we can start off by setting k to start flipped which will give us the required result.
In other words in the outer loop we have
   k = 1 - start;
   start = k;

Open in new window

Because the XOR initialistion of start resulted in a 0 for an EVEN / EVEN pairing the result for the initialisation of k will be 1. After that the flip will ensure we stay on track.
Putting it all together
<script>
// REPLACE num WITH totalrows AND totalcols
// PREFIX WITH total SO AS NOT TO CONFUSE
// WITH LOOP row / col
var totalrows = 3;
var totalcols = 3;
var square=['#', ' '];
var line = '';

// INTIALISE START WITH XOR OF MOD's
var start = (totalrows % 2 ^ totalcols % 2);
for(var row=1; row<=totalrows;row++) {
  // INITIALISE k WITH INVERSE OF START
  k = 1 - start;

  // SET start FOR NEXT ITERATION
  start = k;

  // THE REST REMAINS THE SAME
  for(var col=1; col<=totalcols;col++) {
    line += square[k];
    k = 1 - k; 
  }
  line += '\n';
}
console.log(line);
</script>

Open in new window

0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Introduction HyperText Transfer Protocol (http://www.ietf.org/rfc/rfc2616.txt) or "HTTP" is the underpinning of internet communication.  As a teacher of web development I have heard many questions, mostly from my younger students who have come to t…
Introduction Chart.js, used properly, can visually add a difference to your charting applications. It engages your visitors and allows them to interact with data they otherwise wouldn't be able to without expensive and complicated systems. For this…
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now