for

Figure 163. Frequent usage of while Slide presentation
int i = 1; 

while (i < 5 ) {
   ...
   i++; 
}

Declaring and initializing a loop termination variable.

Check for loop termination.

Loop progression control

Nice to have: More concise syntax


Figure 164. Replacing while by for Slide presentation
for (int i = 0 ; i < 5 ; i++ ) {
  ...
}
int i = 0; 

while (i < 5 ) {
   ...
   i++; 
}

Figure 165. for syntax Slide presentation
for ( init ; booleanExpression ; update )
  (block | statement)

Figure 166. for variable scope Slide presentation
// i being defined in loop scope

for (int i = 0 ; i < 3; i++) {
    System.out.println(i);
}
// Error: i undefined outside
// loop body
System.out.println(i);
// i being defined in «current» scope

int i; 
for (i = 0; i < 3; i++) {
    System.out.println(i);
}
System.out.println(i); // o.K.

Figure 167. for variable scope equivalence Slide presentation
for (int i = 0 ; i < 3; i++) {
    System.out.println(i);
}

// i undefined in outer scope
{ // Beginning block scope
  int i = 0;
  for (; i < 3; i++) {
    System.out.println(i);
  }
} // Ending block scope

// i undefined in outer scope

Figure 168. for vs. while relationship Slide presentation
while ( expression )
  (block | statement)
for ( ;expression ;)
  (block | statement)

Observation: for (...) is more general than while(...).


exercise No. 72

Printing even numbers

Q:

Consider:

final int LIMIT = 14;
int i = 0;
while (i < LIMIT) {
    if (i % 2 == 0) {
        System.out.println(i);
    }
    i++;
}

This code effectively filters odd numbers and prints only even ones:

0
2
4
6
8
10
12

Modify this code:

  1. no if statement shall be used.

    Tip

    Rather then filtering unwanted values try to avoid them in the first place by modifying the enclosing loop.

  2. Use a for loop in favour of while.

A:

Rather than filtering unwanted values we use a for loop having a step width of 2:

final int LIMIT = 14;

for (int i = 0; i < LIMIT; i += 2) {
    System.out.println(i);
}

The original code could have been modified in this fashion as well:

final int LIMIT = 14;
int i = 0;
while (i < LIMIT) {
    System.out.println(i);
    i += 2; // Increment by 2 rather than by 1
}
Figure 169. Nested loops Slide presentation
for (int i = 0; i < 6; i++) {
    for (int j = 0; j < i; j++) {
        System.out.print(i + j + " ");
    }
    System.out.println(); // newline
}
1
2 3
3 4 5
4 5 6 7
5 6 7 8 9

Figure 170. Better readability: Use row and column in favour of i and j Slide presentation
// What are i and j actually meant
// to represent?

for (int i = 0; i < 6; i++) {
  for (int j = 0; j < i; j++) {
     System.out.print(i + j + " ");
  }
  System.out.println();
}
// Improved code comprehension.

for (int row = 0; row < 6; row++) {
  for (int column = 0;
        column < row; column++) {
    System.out.print(
         row + column + " ");
  }
  System.out.println();
}

exercise No. 73

Merry Xmas

Q:

Write an application to print an ASCII art Xmas tree. Provide a configurable parameter numberOfRows which allows for controlling the tree's size. The following example shows a tree spanning 6 rows excluding the top (X) and the two bottom (###) lines:

      X
      *
     ***
    *****
   *******
  *********
 ***********
     ###
     ###

Tip

  1. Copy and execute the following code snippet printing a triangle for the sake of a starting point:

    final int numberOfRows = 7; 
    
    for (int row = 0; row < numberOfRows; row++) { 
        for (int x = 0; x <= row; x++) { 
            System.out.print('*'); 
        }
        System.out.println(); 
    }
    *
    **
    ***
    ****
    *****
    ******
    *******

    The number of rows to be printed. Adjusting is easy and allows for printing larger or smaller triangles retaining its shape:

    final int numberOfRows = 3;
    ...
    *
    **
    ***

    The outer loop. Each step will:

    1. Print one more line.

    2. Advance the subsequent inner loop by one '*'.

    Print a number of '*' characters. The exact number equals the outer loop's row value plus 1. So a value of row == 4 will print 4 + 1 '*' characters.

    Print an individual character. Notice the presence of a print(....) rather than a println() method call. This way printing continues within a given line rather than breaking to a new one.

    After each line we need a line break '\n' for starting the next one using println(). If you prefer explicit code you may use System.out. print('\n') instead.

  2. Before coding the actual tree start by modifying the above triangle code to produce:

          *
         **
        ***
       ****
      *****
     ******
    *******

    Hint: You will need a second loop inside the outer loop for creating spaces using the ' ' character. The number of spaces depends on the line you are printing. In the current example you'll need 6 spaces for the first line, 5 spaces for the second and so on. Thus the inner loop depends on the line number to be printed.

A:

We start coding the proposed helper exercise. Each line has to be indented using space ' ' characters being represented by in the right diagram:

final int numberOfRows = 7;

for (int row = 0; row < numberOfRows; row++) {
  // Start line print preceding white spaces
  for (int x = 1; x < numberOfRows - row; x++) {
      System.out.print(' ');
  }
  // continue line printing asterisks
  for (int x = 0; x <= row; x++) {
      System.out.print('*');
  }
  System.out.println();
}
␣␣␣␣␣␣*
␣␣␣␣␣**
␣␣␣␣***
␣␣␣****
␣␣*****
******
*******

A complete solution is available at the MI Gitlab repository. We start dissecting the problem in a version being fully covered by our current knowledge. Our aim is printing:

                   X       Part 1: Tree's top.
Row index 0        *       Part 2: Tree's body
Row index 1       ***
Row index 2      *****
Row index 3     *******
Row index 4    *********
Row index 5   ***********
                  ###      Part 3: Bottom trunk lines.
                  ###

We require the precise indentation values when e.g. starting the tree's body. The following sketch shows two trees of different sizes representing invisible spaces by . In the »bigger« tree's first line we need e.g. 5 spaces before actually printing the tree's very top 'X' character.

  A tree with         A tree with
  6 body rows         2 row groups

␣␣␣␣␣X                ␣␣␣X
␣␣␣␣␣*                ␣␣␣*
␣␣␣␣***               ␣␣***
␣␣␣*****              *****
␣␣*******             *******
*********            ␣␣###
***********
␣␣␣␣###
␣␣␣␣###

The precise amounts of these indentations depend on the tree's size. Printing larger trees requires larger indentation values. The tree's size is being controlled by the parameter numberOfRows:

final int numberOfRows = 6;

We start printing the tree's top. This requires numberOfRows space characters followed by the top's 'X' character:

Code Result (added )
for (int x = 0; x < numberOfRows - 1; x++) {      // Printing the tree's "X" top. We need
  System.out.print(' ');                          // numberOfRowGroups preceding spaces (␣)
}                                                 // before eventually printing the
System.out.println('X');                          // "X" String followed by a newline (println).
␣␣␣␣␣X

( denoting space)

Next we focus on the tree's body requiring numberOfRows lines. We index these lines by a variable row ranging from 0 to numberOfRows - 1. Each line then requires a by row index decreasing number of indenting spaces followed by an increasing number of asterisks (*):

Code Result (added )
for (int row = 0; row < numberOfRows ; row++) {       // Outer row per line loop

  for (int x = 0; x < numberOfRows - row - 1; x++) {  // Starting each line with
     System.out.print(' ');                           // (numberOfRows - row)
   }                                                  // space (␣) characters ...

  for (int x = 0; x < 2 * row + 1; x ++) {            // .. then printing (2 * row + 1)
                                                      // asterisk('*') characters ...
    System.out.print('*');                            // (May try  '' instead?)
  }
  System.out.print("\n");                             // ... and finally terminating the
}                                                     // current body row.
␣␣␣␣␣X
␣␣␣␣␣*
␣␣␣␣***
␣␣␣*****
␣␣*******
*********
***********

We finally print the tree's two trunk lines both requiring an indent of numberOfRows - 1.

Code Result (added )
for (int x = 0; x < numberOfRows - 2; x++) {         // Indenting the first
  System.out.print(' ');                             // bottom trunk line ...
}
System.out.println("###");                           // ... finishing print.

for (int x = 0; x < numberOfRows - 2; x++) {         // Indenting the second
  System.out.print(' ');                             // bottom trunk line
}                                                  
System.out.println("###");                           // ... finishing print.
␣␣␣␣␣X
␣␣␣␣␣*
␣␣␣␣***
␣␣␣*****
␣␣*******
␣*********
***********
␣␣␣␣###
␣␣␣␣###

So far quite an amount of energy has been invested into printing fixed numbers of space ('') characters using loop statements. The System.out.format() method as in Tidy up the mess! allows for getting rid of these. As an example printing the tree's top simplifies to:

Indenting using loops Common result
for (int x = 0; x < numberOfRows + 1; x++) { 
  System.out.print(' '); 
}                    
System.out.println("X");     
␣␣␣␣␣X
Indenting using format()
System.out.format("%"+ numberOfRows + "s ", "X");

Moreover starting with Java 11 the String class features a repeat() method:

String repetitions using loops Common result
final int repetitions = 5;
for (int i = 0; i < repetitions; i++) {
  System.out.print("*");
}
*****
Using repeat(int) instead
final int repetitions = 5;
System.out.println("*".repeat(repetitions));

Combining both methods completely obsoletes all inner loops thereby considerably enhancing our code's readability. You'll see a re-implementation in XmasUsingFormat.java:

final int numberOfRows = 6;                             // You may easily change this value.

// Part one: The tree's top

System.out.format("%"+ numberOfRows + "s\n", "X");     // Printing the tree's top.

// Part two: The tree's body

for (int row = 0; row < numberOfRows; row++) {          // Outer row per line loop
  System.out.format(
    "%"+ (numberOfRows + row) + "s \n",                 // Printing asterisk(s)
    "*".repeat(2 * row + 1));
  }

// Part three: The tree's two bottom trunk lines

System.out.format("%"+ (numberOfRows + 1) + "s\n", "###");
System.out.format("%"+ (numberOfRows + 1) + "s\n", "###");

Both implementation variants allow for setting e.g. final int numberOfRows = 10 creating trees of different sizes albeit sharing the same trunk size:

         X 
         * 
        *** 
       ***** 
      ******* 
     ********* 
    *********** 
   ************* 
  *************** 
 ***************** 
******************* 
        ### 
        ###

exercise No. 74

More fun with Xmas trees

Q:

The following ASCII art for configurable Xmas tree sizes is slightly more challenging :

            \ /
          -->*<--
            /_\
           /_\_\
          /_/_/_\
          /_\_\_\
         /_/_/_/_\
         /_\_\_\_\
        /_/_/_/_/_\
        /_\_\_\_\_\
       /_/_/_/_/_/_\
       /_\_\_\_\_\_\
      /_/_/_/_/_/_/_\
           [___]

Tip

  1. Inside a string literal a backslash \ has to be escaped by using a double backslash \\.

  2. Read about using System.out.format() and repeat(int) in the previous exercises solution.

  3. The indent(int) method allows for indenting multi line blocks:

    Code Result ('␣' denoting space)
    final String block = """
        A simple block
        consisting of
        three lines""";
    
    System.out.println(block);
    
    System.out.println(
         "\n------------------------\n");
    
    System.out.println(block.indent(10));
    A simple block
    consisting of
    three lines
    
    ------------------------
    
    ␣␣␣␣␣␣␣␣␣␣A simple block
    ␣␣␣␣␣␣␣␣␣␣consisting of
    ␣␣␣␣␣␣␣␣␣␣three lines

A:

Looping through         \ /           Part 1: The tree's top.
groups of 2 lines     -->*<--
                        /_\
Row group index 0      /_\_\          Part 2: The tree's body, printing
                      /_/_/_\         two lines per group index 
Row group index 1     /_\_\_\         loop iteration.
                     /_/_/_/_\
Row group index 2    /_\_\_\_\
                    /_/_/_/_/_\
Row group index 3   /_\_\_\_\_\
                   /_/_/_/_/_/_\
Row group index 4  /_\_\_\_\_\_\      End of tree's body
                  /_/_/_/_/_/_/_\     
                       [___]          Part 3: Bottom trunk line.

For each row group (albeit having different length) the two patterns "/_\_ ... \_\" and "/_/ ... /_\" keep repeating. Like in the previous exercises we need the precise indentation values for e.g. starting the tree's body. The following output shows two trees of different sizes representing invisible spaces by for better readability. In the »bigger« tree's first line we need e.g. 6 spaces before actually printing the tree's very top "\/".

  A tree with          A tree with
  5 row groups         2 row groups

␣␣␣␣␣␣\ /                ␣␣␣\ /
␣␣␣␣-->*<---->*<--
␣␣␣␣␣␣/_\                ␣␣␣/_\
␣␣␣␣␣/_\_\               ␣␣/_\_\  
␣␣␣␣/_/_/_\              ␣/_/_/_\  
␣␣␣␣/_\_\_\              ␣/_\_\_\   
␣␣␣/_/_/_/_\             /_/_/_/_\
␣␣␣/_\_\_\_\             ␣␣[___]
␣␣/_/_/_/_/_\
␣␣/_\_\_\_\_\
␣/_/_/_/_/_/_\
␣/_\_\_\_\_\_\
/_/_/_/_/_/_/_\
␣␣␣␣␣[___]

The precise amounts of these indentations again depend on the tree's size. Printing larger trees requires larger indentation values. The tree's size is being controlled by the parameter numberOfRowGroups:

final int numberOfRowGroups = 5;

Now we start printing the tree's top \/. Printing a backslash \ in Java is surprisingly difficult: The character is being used to escape double quotes, newline, tab, Unicode and other characters within strings:

Code Result (added )
System.out.println("\"");       // Print a double quote "
System.out.println("Hello\n");  // Print 'Hello' followed by an extra new line.

System.out.println("\t Hello"); // Print a tab indented 'Hello' string.
System.out.println("\u2B95");   // Print a unicode right arrow 
System.out.println("\\");       // Print a single backslash \ character
" 
Hello

    Hello

\

The above snippet shows a solution: Within a given string the backslash character must itself be escaped by a second one to get a single backslash character on output. In addition we need preceding spaces (' ') being represented by in the output screen to the right.

Printing our tree's very top thus requires:

Code Result (added )
for (int x = 0; x < numberOfRowGroups + 1; x++) { // Printing the tree's "\ /" top. We need
  System.out.print(' ');                          // numberOfRowGroups+1 preceding spaces (␣)
}                                                 // before eventually printing the
System.out.println("\\ /");                       // "\ /" String followed by a newline (println).
␣␣␣␣␣␣\ /  

( denoting space)

The expression numberOfRowGroups + 1 equals an indent of 6 in case of 5 row groups with respect to the illustration given before. Likewise the top's next two of lines are straightforward:

Code Result (added )
for (int x = 0; x < numberOfRowGroups - 1; x++) { // Printing the tree's top '-->*<--' we
  System.out.print(' ');                          // need numberOfRows-1 preceding spaces (␣)
}                                                 // before printing the "-->*<--" 
System.out.println("-->*<--");                    // string.

for (int x = 0; x < numberOfRowGroups + 1; x++) { // The tree's lower top "/ \":
  System.out.print(' ');                          // We need another numberOfRows+1
}                                                 // preceding spaces (␣).
System.out.println("/_\\");
␣␣␣␣␣␣\ /
␣␣␣␣-->*<--
␣␣␣␣␣␣/ \

We now turn to the tree's body. Following the idea of row groups each consisting of two lines we require:

Code Result
for (int rowGroup = 0; rowGroup < numberOfRowGroups; rowGroup++) {

   // print first row of group e.g.    /_\_\
   // print second row of group       /_/_/_\
}
␣␣␣␣␣␣\ /
␣␣␣␣-->*<--
␣␣␣␣␣␣/ \
␣␣␣␣␣/_\_\
␣␣␣␣/_/_/_\
      ...

We now show the loop's gory details:

Code Result
for (int rowGroup = 0;                            // Outer loop printing the
     rowGroup < numberOfRowGroups; rowGroup++) {  //  tree's body.

  // First body line of current group
  //
  for (int x = 0;                                 // Starting first line
       x < numberOfRowGroups - rowGroup;x++) {    // of row group with
                                                        // (numberOfRows - row)
     System.out.print(' ');                       // space (␣) characters 
  }
  System.out.print("/");                         // Start of current row group's
  for (int x = 0; x < rowGroup + 2;x++) {        // first line tree body content
    System.out.print("_\\");                     // finishing.
  }
  System.out.println();

  // Second body line of current group
  //
  for (int x = 0;                                // Starting second line of row
    x < numberOfRowGroups - rowGroup - 1; x++) { // group with (numberOfRows -
    System.out.print(' ');                       // row - 1) space (␣) characters
  }
  for (int x = 0; x < rowGroup + 3;x++) {        // tree body content
    System.out.print("/_");
  }
  System.out.println("\\");                      // finishing.
}
␣␣␣␣␣␣\ /
␣␣␣␣-->*<--
␣␣␣␣␣␣/ \
␣␣␣␣␣/_\_\
␣␣␣␣/_/_/_\
␣␣␣␣/_\_\_\
␣␣␣/_/_/_/_\
␣␣␣/_\_\_\_\
␣␣/_/_/_/_/_\
␣␣/_\_\_\_\_\/_/_/_/_/_/_\/_\_\_\_\_\_\
/_/_/_/_/_/_/_\

Finally printing the tree's trunk:

Code Result (added )
// Part three: The tree's bottom trunk
//
for (int x = 0; x < numberOfRowGroups; x++) {     // Indenting the bottom trunk ...
  System.out.print(' ');
}
System.out.println("[___]");                      // printing the trunk.
␣␣␣␣␣␣\ /
␣␣␣␣-->*<--
␣␣␣␣␣␣/ \
␣␣␣␣␣/_\_\
␣␣␣␣/_/_/_\
␣␣␣␣/_\_\_\
␣␣␣/_/_/_/_\
␣␣␣/_\_\_\_\
␣␣/_/_/_/_/_\
␣␣/_\_\_\_\_\
␣/_/_/_/_/_/_\
␣/_\_\_\_\_\_\
/_/_/_/_/_/_/_\
␣␣␣␣␣[___]

Similar to the previous exercise Merry Xmas this time we replace all inner loops by using String.indent() and String.repeat(). This variant's full source code is on offer at XmasUsingFormat.java.

final int numberOfRowGroups = 5;      // You may easily change this parameter.

// Printing the tree's top. We have to escape the backslash using \\.
System.out.print("""                
      \\ /
    -->*<--
      /_\\""".indent(numberOfRowGroups));

// Printing the tree's body

// Loop printing the tree's body row group wise.
for (int rowGroup = 0; rowGroup < numberOfRowGroups; rowGroup++) {
    final int indentation = numberOfRowGroups - rowGroup + 1;
    // First body line of current group
    System.out.print(('/' + "_\\".repeat(rowGroup + 2)).indent(indentation));

    // Second body line of current group
    System.out.print(("/_".repeat(rowGroup + 3) + '\\').indent(indentation - 1));
}
// Printing the tree's trunk
System.out.print("[___]".indent(numberOfRowGroups + 1));

Both implementation variants allow for setting e.g. final int numberOfRowGroups = 8 creating trees of different sizes albeit sharing the same trunk size:

         \ /
       -->*<--
         /_\
        /_\_\
       /_/_/_\
       /_\_\_\
      /_/_/_/_\
      /_\_\_\_\
     /_/_/_/_/_\
     /_\_\_\_\_\
    /_/_/_/_/_/_\
    /_\_\_\_\_\_\
   /_/_/_/_/_/_/_\
   /_\_\_\_\_\_\_\
  /_/_/_/_/_/_/_/_\
  /_\_\_\_\_\_\_\_\
 /_/_/_/_/_/_/_/_/_\
 /_\_\_\_\_\_\_\_\_\
/_/_/_/_/_/_/_/_/_/_\
        [___]