Except where otherwise noted, the contents of this document are Copyright 2012 Stuart Reges and Marty Stepp.
lab document created by Marty Stepp and Stuart Reges
Goals for today:
while
loops for indefinite repetitionRandom
objects to produce random numbersboolean
expressions and variables to represent logical true/false expressionswhile
Loops
A while
loop repeats indefinitely until a given condition is met.
while (test) { statement(s); }
Example:
int num = 1;
while (num < 5) {
System.out.print(n + " "); // output: 1 2 3 4
n++;
}
while
loop basicsConsider the following loop:
int x = 1; System.out.print(x); while (x < 100) { x = x + x; System.out.print(", " + x); }
How many times does the code in the while loop execute?

7 
What output is produced by the overall code?  1, 2, 4, 8, 16, 32, 64, 128 
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 = 1; int z = 0; while (2 * y <= x) { y = y * 2; z++; } System.out.println(y + " " + z); } 

while
loop mystery
Fill in the boxes at right with the output produced by each method call.
public static void mystery2(int x, int y) { int z = 0; while (x % y != 0) { x = x / y; z++; System.out.print(x + ", "); } System.out.println(z); } 

while
loop mystery
Fill in the boxes at right with the output produced by each method call.
public static void mystery3(int x) { int y = 0; while (x % 2 == 0) { y++; x = x / 2; } System.out.println(x + " " + y); } 

while
loop mystery
Fill in the boxes at right with the output produced by each method call.
public static void mystery4(int n) { int x = 1; int y = 2; while (y < n) { if (n % y == 0) { n = n / y; x++; } else { y++; } } System.out.println(x + " " + n); } 

lastDigit
that returns the last digit
of an integer. For example, lastDigit(3572)
should
return 2
. It should work for negative numbers as well. For
example, lastDigit(947)
should return 7
.
firstDigit
that returns the first digit
of an integer. For example, firstDigit(3572)
should
return 3
. It should work for negative numbers as well. For
example, firstDigit(947)
should return 9
.
digitSum
that accepts an integer as a parameter and returns the sum of the digits of that number.
For example, the call digitSum(29107)
returns 2+9+1+0+7 or 19.
For negative numbers, return the same value that would result if the number were positive.
For example, digitSum(456)
returns 4+5+6 or 15.
The call digitSum(0)
returns 0.
use / 10
and % 10
operations.)
A fencepost loop is a common algorithmic pattern where you want to perform N tasks with N1 things between them. It's like a fence with N posts with N1 wires between the posts.
To achieve this, place one "post" outside your loop, then alternate between "wires" and "posts" inside the loop.
Example:
System.out.print(1); // ======== fence for (int i = 2; i <= 5; i++) { System.out.print(".." + i); // 1..2..3..4..5 }
printLetters
that takes a String
as its parameter and that prints the letters of the String, separated by commas.
For example, the call of printLetters("Rabbit")
should print:
R, a, b, b, i, t
String
object has a length
method that tells you how many characters are in the String
and a charAt
method that gets you individual characters of
the String
.)
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 the following output:
1 and 2 and 3 and 4 and 6 and 8 and 12 and 24
Random
methods
To use these methods, you need a variable of type Random
in
scope:
Random randy = new Random();
int aRandomNumber = randy.nextInt(10); // 09
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

Fill in the boxes to produce expressions that will generate random numbers in the provided ranges.
Assume that the following Random
variable has been declared:
Random rand = new Random();
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

Write a method flip
that takes a Random
object as
a parameter and that prints information about a coinflipping simulation.
Your method should use the Random
object to produce a sequence
of simulated coin flips, printing whether each flip comes up "heads" or
"tails". Each outcome should be equally likely. Your method should stop
flipping when you see three heads in a row.
Solve this problem in PracticeIt by clicking on the checkmark above.
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 PracticeIt! from the link above.
boolean
type
The boolean
type represents logical values of true
or false
.
Combine boolean
expressions with logical operators &&
(and), 
(or), and !
(not).
Example:
boolean test1 = 7 < 10; // true boolean test2 = (1 == 2); // false if ((test1  test2) && 2 + 2 != 5) { System.out.print("hello"); // output: hello }
String
methods with boolean
resultsMethod name  Description 

string.equals(string)

whether the two strings are identical 
string.equalsIgnoreCase(string)

whether the two strings are identical, ignoring capitalization 
string.startsWith(string)

whether this string begins with the characters of the given string 
string.endsWith(string)

whether this string ends with the characters of the given string 
string.contains(string)

whether the characters of the given string occur within this string 
String name = "Professor Smith"; if (name.startsWith("Prof")) { System.out.println("When are your office hours?"); }
Write the result of each expression as either true
or false
, given the following variables.
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 
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 PracticeIt: click on the checkmark above!
Write a method before
that takes as parameters two month/day
combinations and that returns whether or not the first date comes before
the second date (true
if the first month/day comes before the
second month/day, false
if it does not). The method will take
four integers as parameters that represent the two month/day combinations.
The first integer in each pair represents the month and will be a value between 1 and 12 (1 for January, 2 for February, etc, up to 12 for December). The second integer in each pair represents the day of the month (a value between 1 and 31). One date is considered to come before another if it comes earlier in the year.
Solve this problem in PracticeIt by clicking on the checkmark above.
season
that takes two integers as
parameters representing a month and day and that returns a String
indicating the season for that month and day. Assume that months are
specified as an integer between 1 and 12 (1 for January, 2 for February,
and so on) and that the day of the month is a number between 1 and 31.
"Winter"
. If the date falls between 3/16 and 6/15,
you should return "Spring"
. If the date falls between 6/16
and 9/15, you should return "Summer"
. And if the date falls
between 9/16 and 12/15, you should return "Fall"
.
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
.
Write a method sameDashes
that takes two strings as parameters
and that returns whether or not they have dashes in the same places
(returning true
if they do and returning false
otherwise). For example, below are four pairs of strings of equal length
that have the same pattern of dashes. Notice that the last pair has no
dashes at all.
string 1: "hithereyou." "15389" "criminalplan" "abc" string 2: "12(134)7539" "xyzzy" "(206)5551384" "9.8"To be considered a match, the strings must have exactly the same number of dashes in exactly the same positions. The Strings might be of different length.
Solve this problem in PracticeIt by clicking on the checkmark above.
This attempted solution to SelfCheck 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 PracticeIt from the link above, copy/paste this code into it, then see the next slide.
Fix the following aspects of the code:
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"); }
Scanner
methodsMethod name  Description 

next()

reads and returns the next token as a String

nextLine()

reads and returns as a String all the characters up to
the next new line (\n )

nextInt()

reads and returns the next token as an int , if
possible

nextDouble()

reads and returns the next token as double , if
possible

hasNext()

returns true if there is still a token in
the Scanner

hasNextLine()

returns true if there is still at least one line left
to be read in the Scanner

hasNextInt()

returns true if the next token can be read as
an int

hasNextDouble()

returns true if the next token can be read as
an double

Modify your previous exercise's ProcessName
code so that it reprompts until the user types a name that is at least 5 letters total in length and has at least one space in it.
Example:
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.
Identify whether each assertion is always/never/sometimes true
at each point.
x > y 
z == 0 
x == y 


A  SOMETIMES  ALWAYS  SOMETIMES 
B  SOMETIMES  SOMETIMES  NEVER 
C  ALWAYS  NEVER  NEVER 
D  NEVER  NEVER  NEVER 
E  NEVER  SOMETIMES  ALWAYS 
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); }
You can also solve this problem in PracticeIt by clicking on the checkmark above.
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 Dec 31 2008. Why? Download 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++; } }
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++; }
If you finish all the exercises, try out our PracticeIt 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 the book and try to solve them!