A table of square numbers

exercise No. 72

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
10 | 100

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 out an obvious «solution»:

System.out.println("n | n * n");
System.out.println("——+——————");

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

Your code shall start like:

final int LIMIT = 9; // Upper limit to be printed
...

Tip

  • Use a loop printing the table's body values.

  • Don't care too much about formatting: This will be resolved in the next exercise.

A:

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

final int LIMIT = 9;                       // Upper limit to be printed.

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

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

exercise No. 73

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
...
20 | 400

We'd like to see all values being uniformly right aligned. Depending on the desired limit we also require different column widths:

limit = 3 limit = 8 limit = 10
n | n * n
——+——
0 | 0
1 | 1
2 | 4
3 | 9
n | n * n
——+———
0 |  0
1 |  1
2 |  4
3 |  9
4 | 16
5 | 25
6 | 36
7 | 49
8 | 64
 n | n * n
———+————
 0 |   0
 1 |   1
 2 |   4
 3 |   9
 4 |  16
 5 |  25
 6 |  36
 7 |  49
 8 |  64
 9 |  81
10 | 100
11 | 121
12 | 144

Modify your code accordingly.

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

  • Consider:

    final int length = 2;
    String formatString = "This integer placeholder reservers %" + length + "d positions\n";
    System.out.format(formatString, length);
  • Consider:

    int length = 5;
    System.out.println("x".repeat(length));
  • An int's number of digits can be obtained by:

    Code
    int value = 223232;
    System.out.println( value + " has got " + Integer.toString(value).length() + " digits");
    Result
    223232 has got 6 digits

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

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.

This solution works for a particular LIMIT value. A more general solution constructs the format string itself depending on the value of LIMIT:

final int LIMIT = 12; // Upper limit to be printed

// Field lengths for »n« and »n * n« depending on LIMIT
final int
        limitDigitCount = Integer.toString(LIMIT).length(),
        limitSquaredDigitCount = Integer.toString(LIMIT * LIMIT).length();

// Header like » n | n * n«
final String formatHead = "%" + limitDigitCount + "s |%" + limitSquaredDigitCount + "s\n";
System.out.format(formatHead, "n", " n * n");                 // Printing the table's head

// Header like »———+——————«
System.out.println("—".repeat(limitDigitCount + 1) + "+" + "—".repeat(limitSquaredDigitCount + 1));


// Formatting table body entries like e.g. » 9 |  81«
final String format = "%" + limitDigitCount + "d | %" + limitSquaredDigitCount + "d\n";

for (int i = 0; i <= LIMIT; i++) {                   // Printing the table's body
    System.out.format(format, i, i * i);
}

exercise No. 74

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. 75

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. 76

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 require 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 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.println("———+" +                     // Printing table head's second line
            "—————".repeat(SIZE));                  // ———+——————————————— ...
    
    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 ...
    }

You may want to use a debugger to get a quicker code understanding.

exercise No. 77

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. 78

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>""");