for

Figure 199. Frequent usage of while Slide presentation Create comment in forum
int i = 1; 

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

Declaring and initializing a loop termination variable.

Check for loop termination.

Loop progression control

More concise syntax?


Figure 200. Replacing while by for Slide presentation Create comment in forum
for (int i = 0 ; i < 5 ; i++ ) {
  ...
}
int i = 0; 

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

Figure 201. for syntax Slide presentation Create comment in forum
for ( init ; booleanExpression ; update )
  (block | statement)

Figure 202. for variable scope Slide presentation Create comment in forum
for (int i = 0 ; i < 3; i++) {
    System.out.println(i);
}
// Error: i undefined outside
// loop body
System.out.println(i);
// i defined in «current» scope
int i; 
for (i = 0; i < 3; i++) {
    System.out.println(i);
}
System.out.println(i); // o.K.

Figure 203. for variable scope equivalence Slide presentation Create comment in forum
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 204. for vs. while relationship Slide presentation Create comment in forum
while ( expression )
  (block | statement)
for ( ;expression ;)
  (block | statement)

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


exercise No. 67

Printing even numbers Create comment in forum

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 205. Nested loops Slide presentation Create comment in forum
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 206. Using row and column in favour of i and j Slide presentation Create comment in forum
// 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. 68

Merry Xmas Create comment in forum

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:

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();
}
      *
     **
    ***
   ****
  *****
 ******
*******

The actual tree requires:

  1. Printing the top.

  2. Printing the body in a similar fashion as in the above triangle adjusting the loop parameters.

  3. Printing the trunk.

public static void main(String[] args) {

  // Example: 6 rows, tree's body loop index ranging from 0 to 5
  //
  //           X            The tree's top.
  //  0        *
  //  1       ***
  //  2      *****
  //  3     *******         The tree's body.
  //  4    *********
  //  5   ***********
  //          III           The tree's two bottom trunk lines.
  //          III

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

  // Part one: The tree's top
  //
  for (int x = 0; x < numberOfRows; x++) {   // Printing the tree's top. We need
    System.out.print(' ');                   // numberOfRows preceeding spaces
  }                                          // before printing the
  System.out.println("X");                   // 'X' (top) character.

  // Part two: The tree's body
  //
  for (int row = 0; row < numberOfRows ; row++) {    // Outer loop printing the
                                                     // tree's body.

    for (int x = 0; x < numberOfRows - row;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)
                                                     // body ('*') characters ...
      System.out.print('*');                         // May try Unicode '▲' instead
    }
    System.out.print("\n");                          // ... and finally terminating the
  }                                                  // current body row.

  // Part three: The tree's bottom trunk
  //
  for (int x = 0; x < numberOfRows-1; x++) {         // Preparing the first line

    System.out.print(' ');                           // of bottom trunk part ...
  }
  System.out.println("###");                         // ... finished.

  for (int x = 0; x < numberOfRows-1; x++) {         // Preparing the second
    System.out.print(' ');                           // line of bottom trunk
  }                                                  // part ...
  System.out.println("###");                         // ... finished.
}

exercise No. 69

More fun with Xmas trees Create comment in forum

Q:

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

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

Tip

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

A:

We start from a version being fully covered by our current knowledge:

public static void main(String[] args) {

  // Example: 5 row groups, tree's body loop index ranging from 0 to 4

  //          \ /           The tree's top.
  //        -->*<--
  //          /_\
  //  0      /_\_\          Start of tree's body
  //        /_/_/_\
  //  1     /_\_\_\
  //       /_/_/_/_\
  //  2    /_\_\_\_\
  //      /_/_/_/_/_\
  //  3   /_\_\_\_\_\
  //     /_/_/_/_/_/_\
  //  4  /_\_\_\_\_\_\
  //    /_/_/_/_/_/_/_\     End of tree's body
  //         [___]          Bottom trunk line.


  final int numberOfRowGroups = 5;                  // You may easily change this
                                                    // value.
  // Part one: The tree's top
  //
  for (int x = 0; x < numberOfRowGroups + 1; x++) { // Printing the tree's very
                                                    // top. We need numberOfRows+1
    System.out.print(' ');                          // preceding spaces
  }                                                 // before printing the
  System.out.println("\\ /");                       // "\ /" String.

  for (int x = 0; x < numberOfRowGroups - 1; x++) { // Printing the tree's top '*'
                                                    // We need numberOfRows-1
    System.out.print(' ');                          // 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 again numberOfRows+1
  }                                                 // preceding spaces.
  System.out.println("/_\\");

  // Part two: The tree's body
  //
  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.
  }

  // 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.
}

This solution is a bit cumbersome: It involves a repeating task namely indenting lines by a given amount of spaces.

So far we have not yet introduced methods. In anticipation of class methods we provide an alternate solution introducing a method printIndented(...) printing a given string a configurable number of times being indented by a given number of whitespace characters. This method uses System.out.format(...) as in Tidy up the mess! .

Using printIndented(...) considerable enhances our code's readability. We do no longer need the inner loops. On the downside fiddling with values describing indentations and repetitions is still being required:

public class XmasTree {

    // Helper method.
    //
    // Print string s a number of times defined by the repeat value being preceded by a number
    // of whitespace characters ' ' given by the indentation value.
    // Thus printIndent(5, "axb", 2) will generate "_____axbaxb" with "_" denoting white space.
    //
    private static void printIndent(final int indentation, final String s, final int repeat) {
        if (0 < indentation) {
            final String format = "%" + indentation + "s";
            System.out.format(format, "");
        }
        for (int i = 0; i < repeat; i++) {
            System.out.print(s);
        }
    }

    public static void main(String[] args) {

        // Example: 5 row groups of two lines each, tree's body loop index ranging from 0 to 4
        //
        //          Each groups consists of two lines having identical structure among all groups:
        //           Group n:  /_\_\ ... _\     «/» followed by repeating «_\» n+2 times
        //                    /_/_  ...  /_\   Repeating «/_» n+3 times ending with «\»

        //          \ /           The tree's top.
        //        -->*<--
        //          /_\
        //  0      /_\_\          Start of tree's body
        //        /_/_/_\
        //  1     /_\_\_\
        //       /_/_/_/_\
        //  2    /_\_\_\_\
        //      /_/_/_/_/_\
        //  3   /_\_\_\_\_\
        //     /_/_/_/_/_/_\
        //  4  /_\_\_\_\_\_\
        //    /_/_/_/_/_/_/_\     End of tree's body
        //         [___]          Bottom trunk line.


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

        // Part one: The tree's top
        //
        printIndent(numberOfRowGroups + 1,  "\\ /\n"  ,1);
        printIndent(numberOfRowGroups - 1, "-->*<--\n",1);
        printIndent(numberOfRowGroups + 1,   "/_\\\n" ,1);

        // Part two: The tree's body
        //
        for (int rowGroup = 0;                             // Outer loop printing the
             rowGroup < numberOfRowGroups; rowGroup++) {   // tree's body group by group.

            printIndent(numberOfRowGroups - rowGroup,"/", 1);// Starting first line of group
            printIndent(0,"_\\", rowGroup + 2);              // print leaves
            System.out.println();                                               // Finishing first line of group.

            // Second body line of current group
            //
            printIndent(numberOfRowGroups - rowGroup - 1, "", 1); // Starting second line
            printIndent(0, "/_", rowGroup + 3);                   //  of row group

            System.out.println("\\");                                                // Finish second line of group.
        }

        // Part three: The tree's bottom trunk
        //
        printIndent (numberOfRowGroups, "[___]", 1);      // Indenting the bottom trunk ...
    }
}

Both variants allow for setting e.g. final int numberOfRowGroups = 8 creating a larger tree (albeit having the same trunk size):

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