University of Washington, CSE 142 (190)

Lab 5: while loops, fencepost, Random numbers, boolean logic, midterm practice

Except where otherwise noted, the contents of this document are Copyright 2010 Stuart Reges and Marty Stepp.

lab document created by Whitaker Brand and Marty Stepp

Today's lab

Goals for today:

Exercise : while loop mystery

Fill in the boxes at right with the output produced by each method call.

public static void mystery(int x, int y) {
    int z = 0;
    while (x % y != 0) {
        x = x / y;
        z++;
        System.out.print(x + ", ");
    }

    System.out.println(z);
}
mystery(25, 2);
12, 1
mystery(32, 4);
0
mystery(10345, 10);
1034, 103, 10, 3
mystery(63, 2);
31, 15, 7, 3, 1, 0, 6

Exercise : digitSum practice-it

Exercise : digitSum - solution

public static int digitSum(int n) {
    n = Math.abs(n);            // handle negatives
    int sum = 0;
    while (n > 0) {
        int lastDigit = n % 10;
        sum = sum + lastDigit;  // add last digit to sum
        n = n / 10;             // remove last digit from n
    }
    return sum;
}

Recall: Random Methods

To use these methods, you need a variable of type Random in scope:

Random randy = new Random();
int aRandomNumber = randy.nextInt(10);  // 0-9
Method name Returns...
nextInt() a random integer
nextInt(max) a random integer between 0 (inclusive) and max (exclusive)
nextDouble() a random real number between 0.0 and 1.0
nextBoolean() a random boolean value: true or false

Exercise : Random Expressions

Example: a random integer from 1 to 5 inclusive: rand.nextInt(5) + 1
a random integer from 0 to 3 inclusive: rand.nextInt(4)
a random integer from 5 to 10 inclusive: rand.nextInt(6) + 5
a random integer from -4 to 4 inclusive: rand.nextInt(9) - 4
a random even integer from 16 to 28 inclusive:
(Hint: To get only even numbers, scale up.)
rand.nextInt(7) * 2 + 16

Exercise : Boolean Expressions

Write the result of each expression as either true or false, given the following variables. Recall the logical operators: && (and), || (or), ! (not).

int x = 12;
int y = 7;
int z = 28;
String s = "mid term";
x < 14
true
!(x % 2 < 1)
false
x < y || x < z
true
z / x < x / y * x
true
s.length() == y
false
s.toUpperCase().equals("MID TERM")
true
!s.equals("mid term") || x * y != z
true
s.substring(z / x).length() > y
false

Exercise : makeGuesses practice-it

Write a method named makeGuesses that will output random numbers between 1 and 50 inclusive until it outputs one of at least 48. Output each guess and the total number of guesses made. Below is a sample execution:

guess = 43
guess = 47
guess = 45
guess = 27
guess = 49
total guesses = 5

Try solving this problem in Practice-It! from the link above.

Exercise : assertions practice-it

Identify whether each assertion is always/never/sometimes true at each point.

x > y z == 0 x == y
A
B
C
D
E
public static void mystery(int x, int y) {
    int z = 0;

    // Point A
    while (x != y) {
        // Point B
        z++;

        if (x > y) {
            // Point C
            x = x / 10;
        } else {
            // Point D
            y = y / 10;
        }
    }

    // Point E
    System.out.println(x + " " + y + " " + z);
}

Exercise : allDigitsOdd practice-it

Write a method named allDigitsOdd that returns whether every digit of a positive integer is odd. Your method should return true if the number consists entirely of odd digits and false if any of its digits are even. 0, 2, 4, 6, and 8 are even digits, and 1, 3, 5, 7, 9 are odd digits.

For example, allDigitsOdd(135319) returns true but allDigitsOdd(9145293) returns false.

Hint: You can pull apart a number into its digits using / 10 and % 10.

Exercise : hopscotch practice-it

Write a method named hopscotch that accepts an integer parameter for a number of "hops" and prints a hopscotch board of that many hops.

For example, the call hopscotch(3); would produce the following output:

   1
2     3
   4
5     6
   7
8     9
   10

Try solving this problem in Practice-It: click on the check-mark above!

Exercise : hasMidpoint practice-it

Write a method hasMidpoint that accepts three integers as parameters, and returns true if one of the numbers is the midpoint of the other two and returns false otherwise.

For example, the call hasMidpoint(3, 7, 5) would return true because one of the parameters (5) is the midpoint of the other two (3 and 7).

Try to solve this problem in Practice-It: click on the check-mark above!

Exercise : longestName practice-it

Write a method named longestName that reads names typed by the user and prints the longest name (the name that contains the most characters) in the format shown below. Your method should accept a console Scanner and an integer n as parameters and should then prompt for n names.

A sample execution of the call longestName(console, 4) might look like the following:

name #1? roy
name #2? DANE
name #3? sTeFaNiE
name #4? Erik
Stefanie's name is longest

Try to solve this problem in Practice-It: click on the check-mark above!

Exercise : Syntax errors

Exercise - answer

  1. line 5: nextString should be next
  2. line 9: string should be String
  3. line 9: name should not be in quotes
  4. line 10: Whitaker should be in quotes
  5. line 10: cannot compare strings with ==; must use .equals
  6. line 13: cannot call replace without specifying a string object (name)
  7. line 14: toUppercase should be toUpperCase
  8. line 14: name. should come before toUpperCase, not passed as a parameter to it
  9. line 14: must say name = to store the result of toUpperCase
  10. line 15: must say name = to store the result of substring
  11. line 16: must use parentheses () when calling length

Exercise - Corrected version

public class StringOops {
    public static void main(String[] args) {
        Scanner console = new Scanner(System.in);
        System.out.print("Type your name: ");
        String name = console.next();
        process(name);
    }

    public static void process(String "name") {
        if (name.equals("Whitaker")) {
            System.out.println("You must be really awesome.");
        }
        name = name.replace("a", "e");
        name = name.toUpperCase();
        name = name.substring(0, 3);
        System.out.println(name + " has " + name.length() + " letters");
    }
}

Exercise : ProcessName

Exercise - code to add

Exercise - answer

Exercise : ProcessName2

Type your name: Joe
Error, must be at least 5 chars with a space.
Type your name: O K!
Error, must be at least 5 chars with a space.
Type your name: what
Error, must be at least 5 chars with a space.
Type your name: Tyler Durden
Your name is: Durden, T.

Exercise - answer

import java.util.*;  // for Scanner

public class ProcessName2 {
    public static void main(String[] args) {
        Scanner console = new Scanner(System.in);
        System.out.println("Type your name: ");
        String name = console.nextLine();
        
        while (name.length() < 5 || name.indexOf(" ") < 0) {
            System.out.println("Error, must be at least 5 chars with a space.");
            System.out.println("Type your name: ");
            name = console.nextLine();
        }
        
        int space = name.indexOf(" ");
        String first = name.substring(0, space);
        String last = name.substring(space + 1, name.length());
        String firstInitial = first.substring(0, 1);
        name = last + ", " + firstInitial + ".";
        System.out.println("Your name is: " + name);
    }
}

Exercise : repl practice-it

Exercise : ZuneBug

The following code from Microsoft's Zune music player calculates today's date from the years/days passed since 1980. But all Zune players locked up on Jan 1 2009. Why? Download icon ZuneBug.java and modify it to fix the bug.

int days = getTotalDaysSince1980();   // pretend this method exists
int year = 1980;
while (days > 365) {                  // subtract out years
    if (isLeapYear(year)) {           // pretend this method exists
        if (days > 366) {
            days = days - 366;
            year++;
        }
    } else {
        days = days - 365;
        year++;
    }
}

Exercise : ZuneBug - answer

The bug occurs when the current year is a leap year and there are exactly 366 days left (i.e., if today is Jan 1 on a year after a leap year). The code gets stuck in an infinite loop with days == 366 because the while test is true but the if (days > 366) is false. Here is a fixed version:

int days = getTotalDaysSince1980();   // pretend this method exists
int year = 1980;
while (days > 365 || (isLeapYear(year) && days > 366)) {
    if (isLeapYear(year)) {
        days = days - 366;
    } else {
        days = days - 365;
    }
    year++;
}

Exercise : printLetters practice-it

Consider the following flawed method printLetters, which accepts a String as its parameter and attempts to print the letters of the String, separated by dashes. For example, the call of printLetters("Rabbit") should print R-a-b-b-i-t .

public static void printLetters(String text) {
    for (int i = 0; i < text.length(); i++) {
        System.out.print(text.substring(i, i + 1) + "-");
    }
    System.out.println();   // to end the line of output
}

What is wrong with the code? Paste the code in Practice-It! and fix it.

Exercise : printLetters - answer

public static void printLetters(String text) {
    if (text.length() > 0) {
        System.out.print(text.substring(0, 1));   // fencepost
        for (int i = 1; i < text.length(); i++) {
            System.out.print("-" + text.substring(i, i + 1));
        }
        System.out.println();   // to end the line of output
    }
}

Exercise : printFactors practice-it

Write a method named printFactors that accepts an integer as its parameter and uses a fencepost loop to print the factors of that number, separated by the word "and". For example, the call printFactors(24) should print as the following output:

1 and 2 and 3 and 4 and 6 and 8 and 12 and 24

You may assume that the parameter value passed is greater than 0.

Exercise : swapPairs practice-it

Exercise : "Boolean Zen" practice-it

This attempted solution to Self-Check 5.15 (isVowel) has several problems:

// Returns whether the given string represents a vowel:
// a, e, i, o, or u, case insensitively.
public static boolean isVowel(String s) {
    if (s == "a") {
        return true;
    } else if (s == "e") {
        return true;
    } else if (s == "i") {
        return true;
    } else if (s == "o") {
        return true;
    } else if (s == "u") {
        return true;
    } else {
        return false;
    }
}

Open Practice-It from the link above, copy/paste this code into it, then see the next slide.

Exercise - things to fix

Fix the following aspects of the code:

Exercise - answer

public static boolean isVowel(String s) {
    s = s.toLowerCase();
    if (s.equals("a") || s.equals("e") || s.equals("i")
            || s.equals("o") || s.equals("u")) {
        return true;
    } else {
        return false;
    }
}

The above can be improved. "Boolean Zen" version:

public static boolean isVowel(String s) {
    s = s.toLowerCase();
	return s.equals("a") || s.equals("e") || s.equals("i")
	        || s.equals("o") || s.equals("u");
}

If you finish them all...

If you finish all the exercises, try out our Practice-It web tool. It lets you solve Java problems from our Building Java Programs textbook.

You can view an exercise, type a solution, and submit it to see if you have solved it correctly.

Choose some problems from Chapter 5 and try to solve them!