U4 | Iteration


4.1 while Loops


  • A while loop is a fundamental control structure in programming used for repeated execution of a block of code as long as a condition is true.
  • The loop starts by evaluating the condition. If the condition is true, the code inside the loop is executed.
  • After each iteration, the condition is re-evaluated, and if it’s still true, the loop continues. If the condition is false initially, the loop code is never executed.
  • While loops are used when you don’t know in advance how many times the loop needs to execute.
  • There’s a risk of infinite loops if the condition never becomes false, so be cautious. You can use variables and complex expressions as loop conditions.
  • It’s essential to update the loop control variable within the loop to prevent infinite loops.
  • While loops are typically used for tasks such as iterating over collections or waiting for a specific condition to be met.
  • You can always break out of a while loop prematurely using the break statement.

Example of While Loops

public class PyramidPattern {
    public static void main(String[] args) {
        int height = 5;
        int row = 1;

        while (row <= height) {
            int spaces = height - row;
            int stars = 2 * row - 1;

            // Print spaces
            int spaceCount = spaces;
            while (spaceCount > 0) {
                System.out.print(" ");
                spaceCount--;
            }

            // Print stars
            int starCount = stars;
            while (starCount > 0) {
                System.out.print("*");
                starCount--;
            }

            System.out.println(); // Move to the next line for the next row
            row++;
        }
    }
}

PyramidPattern.main(null);
    *
   ***
  *****
 *******
*********

4.2 for Loops


  • Iterative statement that checks for condition
  • Repeatedly execute a a block of code as long as the condition is met
  • Condition specifies amount of times

for Loops vs. while Loops

  • while Loops: use when number of iterations is unknown
  • for Loops: use when number of iterations is known
int i = 0;
while (i < 5) {
    System.out.println(i);
    i++;
}
0
1
2
3
4
for (int i = 0; i < 5; i++) {
    System.out.println(i);
}
0
1
2
3
4
  • Three parts in for loop header: variable initialization, Boolean (conditional) expression, and increment/decrement statement

Question: Which part is which?

I will used the for loop above as demonstration. The variable initialization is the `int i = 0;` segment. The conditional expression is `i < 5;`. The increment/decrement statement (increment in this case) is that final `i++`.

  • variable initialization (int i=0): sets variable before loop starts
  • Boolean (conditional) expression (i < 5): defines condition for loop to run, in this case, the loop continues as long as i is less than 5, so loops 5 times i 05
  • increment/decrement statement (i++): increases variable each time code block in the loop is executed, in this case it increases by 1
  • variable can be used in the code block for other various reasons besides specifying how many times the loop will repeat
  • Boolean (conditional) expression and increment/decrement statement together determine how many times the loop will repeat

Popcorn Hack

  • Calculate and print the sum of all even numbers from 1 to a given positive integer ‘n’ (user input n)
public class InputEvenSums {
    public static void main(String[] args) {
        // initializing sum
        int sum = 0;

        Scanner scanner = new Scanner(System.in);
        System.out.println("To which positive integer would you like to get the sum of all even integers?");
        int upperLimit = scanner.nextInt();

        for (int i = 1; i <= upperLimit; i++) {
            if (i % 2 == 0) {
                sum += i;
            }
        }

        System.out.println("The sum of all even numbers between 1 and " + upperLimit + " (inclusive) is " + sum + ".");
        scanner.close();
    }
}

InputEvenSums.main(null);
To which positive integer would you like to get the sum of all even integers?


The sum of all even numbers between 1 and 8 (inclusive) is 20.

4.3 Developing Algorithms Using Strings


LEARNING OBJECTIVES: For algorithms in the context of a particular specification that involves String objects:

  • identify standard algorithms
  • modify standard algorithms
  • develop an algorithm

Java has many methods that are helpful when working with strings:

  • String .substring –> retrieves portion of a string
  • String .equals –> compares two strings
  • String .length –> returns length of a string
  • for Loop –> iterating through characters of a string

Finding a substring within a string

We can use the “window” method:

A “window” is created the same length as the substring. We then iterate through the main string in sections and compare to the substring

For example:

I T E R A T E

with substring “ERA”

public class StringFinder {
    public static void main(String[] args) {
        String word = "iterate";
        String sub = "era";
        boolean found = false; // will be set to true once substring is found

        // I FIXED IT HERE
        for (int i = 0; i <= (word.length() - sub.length()); i++) { //iterating forwards: starting at first index (0) and going to the length of the word.. let's try word.length
            String portion = word.substring(i, i + sub.length());
            if (portion.equals(sub)) // make sure you use .equals!!
                found = true;
        }

        if (found)
            System.out.println("substring is found within string!");
        else
            System.out.println("substring is NOT within string");
    }

    }

    StringFinder.main(null);
substring is found within string!

POPCORN HACK: Run the code...what happened? How can we fix it?

Tell us below!

It threw an out-of-bounds exception because the loop ends up trying to grab indexes beyond the length of the word because it adds the length of `sub`. This can be fixed by changing the conditional to `i < (word.length() - sub.length() + 1);`. This prevents out of bounds indexes from being called. The +1 corrects for the offset of the lengths, allowing for the last letters of the word to be tested. They would otherwise be untested because the loop ends early.

Another issue:

I T E R A T E

What if our substring was the word “RATE”? Note that RATE is at the end of the whole string

With the fix I made above, it finds the substring "RATE" as long as it's lowercase.

public class StringFinder2 {
    public static void main(String[] args) {
        String word = "iterate";
        String sub = "rate";
        boolean found = false; // will be set to true once substring is found

        // I FIXED IT HERE
        for (int i = 0; i <= (word.length() - sub.length()); i++) { //iterating forwards: starting at first index (0) and going to the length of the word.. let's try word.length
            String portion = word.substring(i, i + sub.length());
            if (portion.equals(sub)) // make sure you use .equals!!
                found = true;
        }

        if (found)
            System.out.println("substring is found within string!");
        else
            System.out.println("substring is NOT within string");
    }
}

StringFinder2.main(null);
substring is found within string!

HACKS

Create a algorithm similar to the one above. Except this time, use iteration to count the number of vowels within the main string.

HINT: Use the boolean expressions we have learned in previous lessons. Which would you use when comparing your “window” with multiple options of substrings?

I did that below. It also asks for the user to input the string. I did it efficiently with the `.contains()` list method. It can also check more than one word for vowels if you input a whole sentence.

public class VowelFinder {
    public static void main(String[] args) {
        // initializing
        String[] vowels = {"a", "e", "i", "o", "u"};
        int numberOfVowels = 0;

        // user input
        Scanner scanner = new Scanner(System.in);
        System.out.println("Which word(s) would you like to parse for vowels?");
        String word = scanner.nextLine();

        // looping through for vowels
        for (int i = 0; i < word.length(); i++) { // iterating forward through the word
            String character = word.substring(i, i+1); // keeps it a string so that I can make it lowercase
            if (Arrays.asList(vowels).contains(character.toLowerCase())) numberOfVowels += 1; // incrementing if vowel
        }

        // final statement
        System.out.println(numberOfVowels + " vowel(s) were found in the word(s) \"" + word + "\".");
        scanner.close();
    }
}

VowelFinder.main(null);
Which word(s) would you like to parse for vowels?


3 vowel(s) were found in the word(s) "this phrase".

4.4 Nested Iteration

nested iteration

occurs when we have a loop inside of another loop, similar to nested conditional statements in unit 3 When you have one loop inside another, the inner loop has to finish all its rounds before the outer loop moves to the next round. If the inner loop has a "stop" command, it only stops for that round of the outer loop. The next time the outer loop starts a new round, the inner loop starts over. If you have two nested loops without stops, and the outer one runs n times while the inner one runs m times each time the outer one goes around, the inner loop will run m times n times, which is m * n times in total. This rule also applies if you have more than two nested loops. To find the total number of times the innermost loop runs, just multiply how many times each loop runs per round. ```Java public class NestedLoopsDemo { public static void main(String[] args) { int n = 3; //numb of times the outside loop runs int m = 2; //numb of times the inside loop runs //the nested loops for (int i = 1; i <= n; i++) { System.out.println("Outer loop iteration: " + i); for (int j = 1; j <= m; j++) { System.out.println("Inner loop iteration: " + j); } } } } NestedLoopsDemo.main(null) ``` Outer loop iteration: 1 Inner loop iteration: 1 Inner loop iteration: 2 Outer loop iteration: 2 Inner loop iteration: 1 Inner loop iteration: 2 Outer loop iteration: 3 Inner loop iteration: 1 Inner loop iteration: 2 ### Break Statement **break statement**
is used to exit a loop prematurely, typically when a certain condition is met. In the case of nested loops, it can be used to break out of the innermost loop. ```Java public class BreakExample { public static void main(String[] args) { for (int i = 1; i <= 3; i++) { System.out.println("Outer loop iteration " + i); for (int j = 1; j <= 3; j++) { System.out.println("Inner loop iteration " + j); if (i == 2 && j == 2) { System.out.println("Breaking inner loop"); break; //break out of the inside loop when i is 2 and j is 2. } } } } } BreakExample.main(null) ``` ### Popcorn HACK When the targetNumber is found, you can print a message and use the break statement to exit the loop. When it's not found, you can print a message indicating that the number was not found. I did that below. ```Java public class BreakHack { public static void main(String[] args) { int targetNumber = 42; //numb we want int[] numbers = {10, 20, 30, 40, 50, 60, 70}; //numb array boolean numberFound = false; // i added this for the code to function correctly for (int number : numbers) { if (number == targetNumber) { System.out.println("The target number " + targetNumber + " was found!"); numberFound = true; break; } } if (!numberFound) {System.out.println("The number was not found.");} } } BreakHack.main(null); ``` The number was not found. ### Continue Statement **continue statement**
is used to skip the current iteration of a loop and move to the next iteration. In the case of nested loops, it applies to the innermost loop. ```Java public class ContinueExample { public static void main(String[] args) { for (int i = 1; i <= 3; i++) { System.out.println("Outer loop iteration " + i); for (int j = 1; j <= 3; j++) { if (i == 2 && j == 2) { System.out.println("Skipping inner loop iteration " + j); continue; //skip the iteration when i is 2 and j is 2. } System.out.println("Inner loop iteration " + j); } } } } ContinueExample.main(null) ``` ### Patterns and Shapes ```Java import java.util.Scanner; public class InteractivePyramid { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Enter the symbol you want to use: "); char symbol = scanner.next().charAt(0); System.out.print("Enter the number of rows for the pyramid: "); int numRows = scanner.nextInt(); for (int i = 1; i <= numRows; i++) { //print space before the symbol for (int j = 1; j <= numRows - i; j++) { System.out.print(" "); } //print for (int k = 1; k <= 2 * i - 1; k++) { System.out.print(symbol); } System.out.println(); //next line } scanner.close(); } } InteractivePyramid.main(null); ``` Enter the symbol you want to use: Enter the number of rows for the pyramid: B BBB BBBBB BBBBBBB BBBBBBBBB ## Hacks 1. **Modify pyramid code:** - Create different patterns (other then pyramid) by modifying nested loop structure I'm not very artistic, so I made a grid pattern with nested loops. ```Java // grid pattern public class InteractiveGrid { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Enter the symbol you want to use: \n"); char symbol = scanner.next().charAt(0); System.out.print("Enter the height of the grid: \n"); int gridHeight = scanner.nextInt(); System.out.print("Enter the width of the grid: \n"); int gridWidth = scanner.nextInt(); for (int i = 1; i <= gridHeight; i++) { // nested loop for alternating pattern for (int j = 1; j <= gridWidth; j++) { if ((i + j) % 2 == 0) { System.out.print(symbol); } else { System.out.print(" | "); } } System.out.println(); //next line } scanner.close(); } } InteractiveGrid.main(null); ``` Enter the symbol you want to use: Enter the height of the grid: Enter the width of the grid: # | # | # | # | # | # | # | # | # | # | # | # | # | # | # | # | # | # | # | # | # | # | # | # | # | # | # | # | # | # | # | # | # | # | # | # | # | # 2. **Questions** - What is a nested iteration, continue statement, and break statement (in your own words)? Nested iteration is when a loop/loops are used within another loop to add another layer of iteration to a process. They can be used for things like repeating iteration processes multiple times across multiple variables/values and iterating through multi-dimensional arrays/hashmaps. Continue statements skip to the next iteration of a loop. They can be used to, for example, skip over a process if not necessary under certain conditions in a loop. Break statements can be used to break out of a loop early. They can be used to stop an iteration process if a certain goal has already been achieved or act as a means of leaving an infinite loop. - Create a simple example of a continue statement **or** break statement I gave examples of both below. ```Java // setup for statements Scanner scanner = new Scanner(System.in); System.out.println("Input a phrase with numbers. The numbers within the phrase will be added up."); String numberPhrase = scanner.nextLine(); // continue statement int numberSum = 0; for (int i = 0; i < numberPhrase.length(); i++) { char currentChar = numberPhrase.charAt(i); if (!(Character.isDigit(currentChar))) { continue; // HERE IT IS } numberSum += Integer.parseInt(String.valueOf(currentChar)); } System.out.println("Sum of numbers in the phrase \"" + numberPhrase + "\": " + numberSum); ``` Input a phrase with numbers. The numbers within the phrase will be added up. Sum of numbers in the phrase "f0f8d370k5748f73kkh3": 55 ```Java // setup for guessing game Scanner scanner = new Scanner(System.in); Random random = new Random(); int randomNumber = random.nextInt(10) + 1; System.out.println("Guess a number between 1 and 10!"); // use of break in a loop while (true) { int guess = scanner.nextInt(); if (guess == randomNumber) { System.out.println("Congrats! You guessed the number: " + randomNumber); break; // here's the break } else if (guess > randomNumber) { System.out.println("Your guess was greater than the actual number."); } else { System.out.println("Your guess was less than the actual number."); } } ``` Guess a number between 1 and 10! Your guess was less than the actual number. Congrats! You guessed the number: 7 --- # 4.5 Informal Code Analysis Learning objective: Compute statement execution counts & informal run-time comparison of iterative statements Essential Knowledge: A statement execution count indicates the number of times a statement is executed by the program

What IS informal code analysis?

Answer: Computing the informal runtime based on the number of times the statement is executed. ```Java // CODE EXAMPLE #1 (for loop) public class InformalCodeAnalysis { public static void main(String[] args) { int count = 0; for (int k = 0; k < 30; k++) { if (k % 3 == 0) // statement 1 { count++; // statement 2 } } } } ``` How many times will statement 1 execute? Answer: 30 times. How many times will statement 2 execute? Answer: 10 times, since 10 numbers between 0 and 29 (inclusive) are divisible by 3 (including 0). ```Java // CODE EXAMPLE #2 (for loop) public class InformalCodeAnalysis { public static void main(String[] args) { int count = 0; for (int k = 4; k < 30; k+=3) { count++; // statement 3 } } } ``` How many times will statement 3 execute? Answer: 9 times, starting with 4 and then 8 more times as k becomes 7, 10, 13..., and finally 28. I made the code below more efficient by incrementing k by 5 each time and getting rid of the modulo divsion. ```Java // Rewrite the code segment below to have a faster run-time based on statement execution counts for (int k = 0; k < 135; k+=5) { System.out.println(k); } ``` ```Java // CODE EXAMPLE #3 (while loop) int num = (int)(Math.random() * 10); while (num % 2 != 0) { num = (int)(Math.random() * 10) // statement 4 } ``` What is the min/max number of times statement 4 will execute? Answer: The minimum is 0 if the random generator generates a number divisible by 2 first. If it never generates one somehow, the maximum number of times is theoretically infinite. ```Java // CODE EXAMPLE #4 (nested loop) for (int outer = 0; outer < 3; outer++) { for (int inner = 0; inner < 4; inner++) { // statement #5 } } ``` How many times will statement #5 execute? Answer: It will execute 12 times (4 times in all 3 of the outer loops). ```Java // CODE EXAMPLE #5 (nested loop) int k = 0; while (k < 5) { int x = (int)(Math.random() * 6) + 1; while (x != 6) { // statement #6 x = (int)(Math.random() * 6) + 1; } k++; } ``` How many times will statement #6 execute? Answer: We have no way of knowing because it's based on a random condition. It could theoretically execute an infinite number of times or 0 times. # 4.5 Hacks #1 How many times will statement #1 and statement #2 execute in the code segments below? Statement #1 will execute 1000 times. Statement #2 will execute 44 times. ```Java for (int k = 0; k < 1000; k++) { // statement #1 } ``` ```Java for (int k = 6; k < 50; k++) { // statement #2 } ``` #2 How many times will statement #3 execute for the code segment below? 7 * 4 = 28, so statement #3 will execute 28 times. ```Java int k = 1; while (k <=7) { for (int z = 0; z < 4; z++) { // statement #3 } k++; } ``` #3 Create 3 seperate code segments that execute a statement 10 times using: (a) a for loop (b) a while loop (c) a nested loop ```Java // 3a code (for loop) for (int i = 0; i < 10; i++) { // the statement in question System.out.println("The statement has executed " + (i + 1) + " time(s)."); } ``` The statement has executed 1 time(s). The statement has executed 2 time(s). The statement has executed 3 time(s). The statement has executed 4 time(s). The statement has executed 5 time(s). The statement has executed 6 time(s). The statement has executed 7 time(s). The statement has executed 8 time(s). The statement has executed 9 time(s). The statement has executed 10 time(s). ```Java // 3b code (while loop) int i = 0; while (i < 10) { // the statement in question i++; System.out.println("The statement has executed " + i + " time(s)."); } ``` The statement has executed 1 time(s). The statement has executed 2 time(s). The statement has executed 3 time(s). The statement has executed 4 time(s). The statement has executed 5 time(s). The statement has executed 6 time(s). The statement has executed 7 time(s). The statement has executed 8 time(s). The statement has executed 9 time(s). The statement has executed 10 time(s). ```Java // 3c code (nested loops) int executions = 0; for (int i = 0; i < 5; i++) { int j = 0; while (j < 2) { // the statement in question executions++; System.out.println("The statement has executed " + executions + " time(s)."); j++; } } // I nested a while loop within a for loop ``` The statement has executed 1 time(s). The statement has executed 2 time(s). The statement has executed 3 time(s). The statement has executed 4 time(s). The statement has executed 5 time(s). The statement has executed 6 time(s). The statement has executed 7 time(s). The statement has executed 8 time(s). The statement has executed 9 time(s). The statement has executed 10 time(s).