A table of square numbers

exercise No. 75

A basic square number table

Q:

Write an application for creating the following table of integer square numbers ( n 2 ):

n | n * n
--+------
0 | 0
1 | 1
2 | 4
3 | 9
4 | 16
5 | 25
6 | 36
7 | 49
8 | 64
9 | 81

Your solution is expected to be flexible: Sometimes a different limit of e.g. 12 rather than 9 in the above example is being desired. This rules an obvious «solution»:

public static void main(String[] args) {
  System.out.println("n | n * n");
  System.out.println("--+------");

  System.out.println(0 + " | " + 0);
  System.out.println(1 + " | " + 1);
             ...
  System.out.println(9 + " | " + 81);
}

Tip

Use a loop printing the table's body values.

A:

The table head my be copied from the code snippet. In addition we require a loop printing the table's body:

public static void main(String[] args) {

  System.out.println("n | n * n");                 // Printing the table's head
  System.out.println("--+------");

  for (int i = 0; i <= 9; i++) {                   // Printing the table's body
            System.out.println(i + " | " + i * i);
  }
}

exercise No. 76

Tidy up the mess!

Q:

Running the previous code for values beyond 9 suffers from ugly formatting:

n | n * n
--+------
0 | 0
1 | 1
 ...
8 | 64
9 | 81
10 | 100
11 | 121
12 | 144
...
19 | 361
20 | 400

Modify your code by:

  1. introducing a single integer constant to define the number of values to be printed (i.e. 20 in the above example).

  2. Right indent all integer values being printed reserving fixed widths for printing integer values.

Your application's output shall look like:

 n | n * n
---+------
  0|     0
  1|     1
...
  8|    64
  9|    81
 10|   100
 11|   121
...
 19|   361
 20|   400

Tip

Read the track Formatting Numeric Print Output and learn how to style numeric output: Use System.out.format(...%nd...) instead of System.out.println(...) statements

A:

The $...d format specifier serves two purposes:

  1. A fixed length will be used for printing decimal values.

  2. Numbers will be printed right aligned.

Example:

Code Result (added )
System.out.format("Start:%5d:End", 12);  // Printing 12 right aligned in a field of 5 characters padded with 3 spaces to the left
                          ▲         ┃        
                          ┗━━━━━━━━━┛ 
                            replace

Start:␣␣␣12:End

The format string "%3d|%6d\n" allows for two decimal output fields of length 3 and 6 respectively. It thus corresponds to the two variables i and i * i being supplied as arguments:

public static void main(String[] args) {

  final int LIMIT = 20;              // The number of records to be printed

  System.out.println(" n | n * n");  // Printing the table's head
  System.out.println("---+------");

  for (int i = 0; i <= LIMIT; i++) { // Printing the table's body

    System.out.format("%3d|%6d\n",   // Format string
                       i , i * i);   // Values being inserted in above format
  }                                  // string.
}

exercise No. 77

HTML-ify me

Q:

Modify the previous code to generate HTML output instead of pure text and watch the result using a web browser. The expected output reads:

<html xmlns='http://www.w3.org/1999/xhtml'>
  <head>
    <title>A square table</title>

    <!-- CSS based styling -->
    <style>
      table, td, th {
        border: 1px solid black;
      }
      table {
        border-collapse: collapse;
      }
      td {
        text-align: right;
      }
    </style>
  </head>
  <body>
    <table>
      <tr>
        <th>n</th><th>n * n</th>
      </tr>
      <tr>
        <td>0</td><td>0</td>
      </tr>
      <tr>
        <td>1</td><td>1</td>
      </tr>
      <tr>
        <td>2</td><td>4</td>
      </tr>
     ...
    </table>
  </body>
</html>

A:

A complete solution is being provided by App.java. This solution uses both Java 15 multi line blocks and the String.indent(..) method.

exercise No. 78

Auxiliary Example, part 1: A multiplication table

Q:

In order to prepare a more sophisticated square number table we supply a slightly different exercise producing a multiplication table:

 * |    1    2    3    4    5    6    7    8    9   10
---+--------------------------------------------------
  1|    1    2    3    4    5    6    7    8    9   10
  2|    2    4    6    8   10   12   14   16   18   20
  3|    3    6    9   12   15   18   21   24   27   30
  4|    4    8   12   16   20   24   28   32   36   40
  5|    5   10   15   20   25   30   35   40   45   50
  6|    6   12   18   24   30   36   42   48   54   60
  7|    7   14   21   28   35   42   49   56   63   70
  8|    8   16   24   32   40   48   56   64   72   80
  9|    9   18   27   36   45   54   63   72   81   90
 10|   10   20   30   40   50   60   70   80   90  100

The number of rows and columns are equal. Provide an appropriate parameter i.e final int SIZE = 12 allowing for a configurable number of columns.

Tip

  1. You'll need an inner loop nested within an outer one creating rows and columns like:

    for (int row = 1; ...){
    
       for (int col = 1; ... ) {
          ... // Using System.out.print(...) rather than ...println() avoiding line breaks.
       }
       System.out.println(); // Adding a newline after each set of values
    }
  2. Having integer values of differing lengths you have to consider right justified output. The integer format specifier %...d is your friend here. The subsequent example prints four integer values in right justified style within output fields of common length 5 irrespective of differing lengths:

    Code Output
    System.out.format("|%5d|%5d|%5d|%5d|", 1, 100, 1000, 10000);
    |    1|  100| 1000|10000|

    The %...s format specifier may be used for strings accordingly.

A:

// Block 1: Configuration parameter
//
final int SIZE = 6;                             // Table size is subject to change.

// Block 2: Printing table's head
//
System.out.print(" * |  ");                     // Printing table head's first line
for (int col = 1; col <= SIZE; col++) {         // using column values ranging from 1 to SIZE:
    System.out.format("%3d  ", col);            // * |    1    2    3 ...
}
System.out.print("\n---+" +                     // Printing table head's second line
                 "-----".repeat(SIZE) );        // ---+--------------- ...

// Block 3: Printing table's content
// organized in rows and columns.
//
for (int row = 1; row <= SIZE; row++) {         // Printing rows.
    System.out.format("\n%3d|  ", row);         // Printing new line by \n and beginning of row e.g. "  5|"
    for (int col = 1; col <= SIZE; col++) {
        System.out.format("%3d  ", row * col);  // Printing row times column product values.
    }
}

exercise No. 79

Auxiliary Example, part 2: Avoiding redundant entries

Q:

It does not make sense to supply both results like e.g. 3 * 4 and 4 * 3. Modify your application to generate:

  1|    1
  2|    2    4
  3|    3    6    9
  4|    4    8   12   16
  5|    5   10   15   20   25
  6|    6   12   18   24   30   36
  7|    7   14   21   28   35   42   49
  8|    8   16   24   32   40   48   56   64
  9|    9   18   27   36   45   54   63   72   81
 10|   10   20   30   40   50   60   70   80   90  100
---+--------------------------------------------------
 * |    1    2    3    4    5    6    7    8    9   10

A:

We need two changes with respect to the previous exercise:

  1. The number of columns to be printed has to be limited depending on which row we currently print. We thus replace

    for (int col = 1; col <= SIZE; col++) {      // Printing columns.

    by

    for (int col = 1; col <= row; col++) {       // Printing columns depending on current row value.
  2. Having a table tail now rather than a head we also have to defer our former solution's second block to the end thereby reversing the order of print statements. The following code also includes some minor newline character fiddling:

    // Block 1: Configuration parameter
    //
    final int SIZE = 10;                            // Table size is subject to change.
    
    // Block 2: Printing table's content
    // organized in rows and columns.
    //
    for (int row = 1; row <= SIZE; row++) {         // Printing rows.
        System.out.format("%3d|  ", row);           // Printing new line by \n and beginning of row e.g. "  5|"
        for (int col = 1; col <= row; col++) {
            System.out.format("%3d  ", row * col);  // Printing row times column product values.
        }
        System.out.println();                       // New line after printing row.
    }
    
    // Block 3: Printing table's tail.
    //
    System.out.print("---+" +                       // Printing table tail's first line
            "-----".repeat(SIZE) +                  // ---+--------------- ...
            '\n');                                  // being finished by a newline character.
    
    System.out.print(" * |  ");                     // Printing table tail's second line
    for (int col = 1; col <= SIZE; col++) {         // using column values ranging from 1 to SIZE:
        System.out.format("%3d  ", col);            // * |    1    2    3 ...
    }

exercise No. 80

Creating a real square table

Q:

The last square number table solution is only appropriate for smaller amounts of data. Growing numbers of elements require rearranging values in blocks avoiding waste of space:

  n |   n²       n |   n²       n |   n²       n |   n²       n |   n²     
----+--------------+--------------+--------------+--------------+----------
  0 |    0      20 |  400      40 | 1600      60 | 3600      80 | 6400     
  1 |    1      21 |  441      41 | 1681      61 | 3721      81 | 6561     
  2 |    4      22 |  484      42 | 1764      62 | 3844      82 | 6724     
  3 |    9      23 |  529      43 | 1849      63 | 3969      83 | 6889     
  4 |   16      24 |  576      44 | 1936      64 | 4096      84 | 7056     
  5 |   25      25 |  625      45 | 2025      65 | 4225      85 | 7225     
  6 |   36      26 |  676      46 | 2116      66 | 4356      86 | 7396     
  7 |   49      27 |  729      47 | 2209      67 | 4489      87 | 7569     
  8 |   64      28 |  784      48 | 2304      68 | 4624      88 | 7744     
  9 |   81      29 |  841      49 | 2401      69 | 4761      89 | 7921     
----+--------------+--------------+--------------+--------------+----------
 10 |  100      30 |  900      50 | 2500      70 | 4900      90 | 8100     
 11 |  121      31 |  961      51 | 2601      71 | 5041      91 | 8281     
 12 |  144      32 | 1024      52 | 2704      72 | 5184      92 | 8464     
 13 |  169      33 | 1089      53 | 2809      73 | 5329      93 | 8649     
 14 |  196      34 | 1156      54 | 2916      74 | 5476      94 | 8836     
 15 |  225      35 | 1225      55 | 3025      75 | 5625      95 | 9025     
 16 |  256      36 | 1296      56 | 3136      76 | 5776      96 | 9216     
 17 |  289      37 | 1369      57 | 3249      77 | 5929      97 | 9409     
 18 |  324      38 | 1444      58 | 3364      78 | 6084      98 | 9604     
 19 |  361      39 | 1521      59 | 3481      79 | 6241      99 | 9801

Building a table this way requires additional parameters:

  • The number of blocks in x-direction (5 in the above example)

  • The number of blocks in y-direction (2 in the above example)

  • The number of entries per block (10 in the above example)

You require three nested loops.

A:

// Table parameter

final int
        numBlocksHorizontal = 5,
        numBlocksVertical = 2,
        entriesPerBlock = 10;

// Derived parameter
final int numRows = numBlocksVertical * entriesPerBlock;

System.out.println("  n |   n²     ".repeat(                    // Printing the overall
        numBlocksHorizontal));                                  // table's head section

for (int y = 0;  y < numBlocksVertical; y++) {                  // Looping through vertically stacked blocks.

    System.out.println(                                         // Supplementary separator line between
            "----+----------".repeat(numBlocksHorizontal));     // two vertically adjacent blocks

    for (int row = 0;                                           // Stepping through the given
         row < entriesPerBlock; row++) {                        // block's rows ...

        for (int col = 0; col < numBlocksHorizontal; col++) {   // ... columns within each row.

            final int cellValue = y * entriesPerBlock           // The cell's value
                    + col * numRows + row;                      // to be squared.

            System.out.format("%3d | %4d     ",                 // Pretty print cell value
                    cellValue, cellValue * cellValue);          // and its square.
        }
        System.out.println();
    }
}

exercise No. 81

Creating a sophisticated HTML version of your square table

Q:

On top of the previous square number table we may also create a HTML version.Modify your console output from the previous exercise accordingly. The expected outcome looks like:

Tip

  1. You find a suitable HTML code sample to be generated at squareTable.html.

  2. Depending on your advance in HTML and CSS you may want to postpone this exercise until these two have been thoroughly covered in related lectures.

  3. You may also create an expected output HTML table manually e.g. in a separate file squaretable.html until its browser view satisfies your expectations. Only then do you know which output your Java application is about to generate.

A:

The following solution uses CSS style definitions in the generated HTML's header section being referenced from the document's body.

// Block 1: Setting table parameter
final int numBlocksHorizontal = 5,
        numBlocksVertical = 2,
        entriesPerBlock = 10;

final int numRows = numBlocksVertical * entriesPerBlock;

// Block 2: Printing table's static head
System.out.println("""
        <html xmlns='http://www.w3.org/1999/xhtml'>
          <head>
            <meta charset="UTF-8">
            <title>A square table</title>
            <style>
              table, th, td {border: 1px solid black;}
              table {border-collapse: collapse;}
              td {text-align: right;}
              .greyColumn {background-color:LightGray;}
              </style>
          </head>
          <body>
            <table>
              <colgroup>""");

// Block 3: Creating »n | n² | n  | n² ...« table header
for (int x = 0; x < numBlocksHorizontal; x++) {                 // Creating the overall
                                                                // table's head section.
    if (0 == x % 2) {
        System.out.println("        <col span='2'/>");
    } else {
        System.out.println("        <col span='2' class='greyColumn'/>");
    }
}
System.out.println("      </colgroup>");

System.out.println("      <tr>");
for (int x = 0; x < numBlocksHorizontal; x++) {                 // n | n² header line
    System.out.println("        <th>n</th><th>n²</th>");
}
System.out.println("      </tr>\n");

// Block 4: The table's »payload«.
for (int y = 0; y < numBlocksVertical; y++) {                   // Blocks stacked below another

    System.out.println("      <tr><td></td></tr>");            // extra row.

    for (int yBlock = 0;
         yBlock < entriesPerBlock; yBlock++) {                  // Stepping through values vertically ...
        System.out.println("      <tr>");
        for (int x = 0; x < numBlocksHorizontal; x++) {         // and horizontally within each line.
            final int cellValue = 1 + yBlock                    // The individual value to be squared.
                    + x * numRows + y * entriesPerBlock;

            System.out.println(                                 // Pretty print output
                    "        <td>" + cellValue + "</td><td>"    // value and its square.
                            + cellValue * cellValue + "</td>");
        }
        System.out.println("      </tr>");
    }
}

// Block 5: The table's tail
System.out.print("""
            </table>
          </body>
        </html>""");