Anda di halaman 1dari 31

Chapter 8: Recursion

Solutions
Multiple Choice
Solutions
1. b
2. c
3. c
4. c
5. b
6. a
7. e
8. d
9. e
10. a

True/False
Solutions
1. T
2. T
3. F
4. T
5. F
6. F
7. T
8. F
9. T
10. F

Short Answer Solutions


8.1.

Write a recursive definition of a valid Java identifier (see Chapter 1).


A valid Java Identifier is a Java Letter followed by zero or more Java Identifier
Substrings.
A Java Identifier Substring consists of zero or more valid Java Letters or zero or
more Java Digits.
A Java Letter is any of the 26 English alphabetic characters in both uppercase and
lowercase, the $ and the _ (underscore) characters, as well as alphabetic
characters from other languages.
A Java Digit includes the digits 0 through 9.

8.2.

Write a recursive definition of xy (x raised to the power y), where x and y are integers and y > 0.
If y = 0, then xy

= 1.

otherwise x = x * x(y-1).

8.3.

Write a recursive definition of i * j (integer multiplication), where i > 0. Define the multiplication process in
terms of integer addition. For example, 4 * 7 is equal to 7 added to itself 4 times.
If i = 1, then i * j = j
otherwise i * j = j + (i-1) * j
where * refers to recursive multiplication as defined here and would be provided
by a method such as recursiveMult (i,j). To avoid confusing * with
conventional multiplication, the definition could be rewritten as
If i = 1, then recursiveMult (i,j) = j
otherwise, recursiveMult (i,j) = j + recursiveMult (i, j-1)

8.4.

Write a recursive definition of the Fibonacci numbers. The Fibonacci numbers are a sequence of integers, each
of which is the sum of the previous two numbers. The first two numbers in the sequence are 0 and 1. Explain
why you would not normally use recursion to solve this problem.
Fib(0) = 0
Fib(1) = 1

2007 Pearson Education

S 183

S 184

Lewis/Loftus/Cocking: 2/e Chapter 8 Solutions

Fib(j) = Fib(j-1) + Fib(j-2), j > 1


You would not normally use recursion to solve this problem since a Fibonacci
number less than Fib(j-1) would be calculated at least twice in order to calculate
Fib(j).
The recalculation of each such number would lead to the further
recalculation of other Fibonacci numbers with the accompanying inefficiency.

8.5.

Modify the method that calculates the sum of the integers between 1 and N shown in this chapter. Have the
new version match the following recursive definition: The sum of 1 to N is the sum of 1 to (N/2) plus the sum
of (N/2 + 1) to N. Trace your solution using an N of 7.
public int sum (int num)
{
int result;
if (num == 1)
result = num;
else
{
int half = num/2;
int span = num - half; // span is used to "shift" upper range
result = sum(half) + sum(span) + (half * span);
}
return result;
}

8.6.

Write a recursive method that returns the value of N! (N factorial) using the definition given in this chapter.
Explain why you would not normally use recursion to solve this problem.
public int factorial (int num)
{
int result;
if (num == 1)
result = 1;
else
result = num * factorial (num - 1);
return result;
}
You would not normally use recursion to solve this problem because it can be done
more efficiently using iteration and because the recursive solution it no more
intuitive than the iterative solution.

8.7.

Write a recursive method to reverse a string. Explain why you would not normally use recursion to solve this
problem.
public String reverse (String text)
{
if (text.length() == 1)
return text;
else
{
String result;
result = text.charAt(text.length() - 1)
+ reverse (text.substring(0, text.length()-1));
return result;
}
}

8.8.

Design or generate a new maze for the MazeSearch program in this chapter and rerun the program. Explain the
processing in terms of your new maze, giving examples of a path that was tried but failed, a path that was
never tried, and the ultimate solution.
A new maze could be generated with nested for loops which randomly place either a
1 or a 0 in each cell of a two-dimensional array. Since the likelihood of

2007 Pearson Education

Lewis/Loftus/Cocking, 2/e: Chapter 8 Solutions

S 185

generating a maze with a solution is generally low, subsequent mazes could be


generated using a while loop until a maze with a solution is generated.
A maze with a solution could be hard-coded with the following statement:
private int [][] grid = {

{1,0,1,0,1,1,1,1,1},
{1,0,1,0,1,0,1,0,1},
{1,0,1,0,1,0,1,0,1},
{1,0,1,0,1,0,1,0,1},
{1,0,1,0,1,0,1,0,1},
{1,1,1,0,1,0,1,0,1},
{0,0,1,0,1,0,1,0,1},
{1,0,1,0,1,0,1,0,1},
{1,0,1,0,1,0,1,0,1},
{1,0,1,0,1,0,1,0,1},
{1,0,1,1,1,1,1,0,1} };

After the search arrives at position (5,0), it attempts position (6,0).


Encountering a 0 causes this path to fail. It then attempts position (5,1) which
succeeds. Subsequently, position (6,1) fails and position (5,2) succeeds.
Because the maze is traversed successfully from position (5,2), no attempt is ever
made to find a path from position (4,1)
The solution is marked with 7s.
7
7
7
7
7
7
0
1
1
1
1

8.9.

0
0
0
0
0
7
0
0
0
0
0

1
1
1
1
1
7
7
7
7
7
7

0
0
0
0
0
0
0
0
0
0
7

1
1
1
1
1
1
1
1
1
1
7

1
0
0
0
0
0
0
0
0
0
7

7
7
7
7
7
7
7
7
7
7
7

7
0
0
0
0
0
0
0
0
0
0

7
7
7
7
7
7
7
7
7
7
7

Annotate the lines of output of the SolveTowers program in this chapter to show the recursive steps.
Move
Move
Move
Move
Move
Move
Move
Move
Move
Move
Move
Move
Move
Move
Move

one
one
one
one
one
one
one
one
one
one
one
one
one
one
one

disk
disk
disk
disk
disk
disk
disk
disk
disk
disk
disk
disk
disk
disk
disk

from
from
from
from
from
from
from
from
from
from
from
from
from
from
from

1
1
2
1
3
3
1
1
2
2
3
2
1
1
2

to
to
to
to
to
to
to
to
to
to
to
to
to
to
to

2
3
3
2
1
2
2
3
3
1
1
3
2
3
3

//
//
//
//
//
//
//
//
//
//
//
//
//
//
//

called
called
called
called
called
called
called
called
called
called
called
called
called
called
called

with
with
with
with
with
with
with
with
with
with
with
with
with
with
with

numDisks
numDisks
numDisks
numDisks
numDisks
numDisks
numDisks
numDisks
numDisks
numDisks
numDisks
numDisks
numDisks
numDisks
numDisks

=
=
=
=
=
=
=
=
=
=
=
=
=
=
=

1
2
1
3
1
2
1
4
1
2
1
3
1
2
1

Note the symmetry about the line where a call is made with numDisks = 4.

8.10.

Produce a chart showing the number of moves required to solve the Towers of Hanoi puzzle using the
following number of disks: 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, and 25.
Disks

Moves

2:
3:
4:
5:
6:
7:
8:
9:
10:

3
7
15
31
63
127
255
511
1023

2007 Pearson Education

S 186

Lewis/Loftus/Cocking: 2/e Chapter 8 Solutions

15:
20:
25:

8.11.

32767
1,048,575
33,554,431

Describe a strategy for choosing a pivot value in quick sort so that the list will always be partitioned into two
equal halves. Does your strategy change the time efficiency of quick sort?
In order to partition the list into two equal halves, the pivot value would have
to be the median of the list. One way to find the median is the sort the list
using insertion sort and take the value in the middle of the list. This would
certainly affect the time efficiency!

8.12.

How many line segments are used to construct a Koch snowflake of order N? Produce a chart showing the
number of line segments that make up a Koch snowflake for orders 1 through 9.
A Koch snowflake of order N has 3(4N-1) line segments.
Order
Line Segments
1: 3
2: 12
3: 48
4: 192
5: 768
6: 3072
7: 12,288
8: 49,152
9: 196,608

Programming Project Solutions


8.1 PalindromeTester
//********************************************************************
// PalindromeTester.java
Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.1
//
// Modifies code from Chapter 3 to use recursion to identify a
// palindrome
//********************************************************************
import java.util.Scanner;
public class PalindromeTester {
private String testString;
public PalindromeTester(String test)
{
testString = convertString(test);
}
//----------------------------------------------------------------// Converts a string to correct format; removes all characters
// except for number and digits
//----------------------------------------------------------------private String convertString(String str)
{
StringBuffer convertedString = new StringBuffer();
// convert string to lowercase, remove punctuation and whitespace
for (int i = 0; i<str.length(); i++)
{
char c = str.charAt(i);
c = Character.toLowerCase(c);
if (Character.isLetterOrDigit(c))
2007 Pearson Education

Lewis/Loftus/Cocking, 2/e: Chapter 8 Solutions

S 187

convertedString.append(c);
}
/*
String.substring(first, last) includes first char up to but not
including last char. Adding a dummy character on the end of the
string prevents an ArrayIndexOutOfBounds exception when the
isPalindrome()
methods uses String.substring() to access the entire string
*/
convertedString.append('*');
return convertedString.toString();
}
//----------------------------------------------------------------// Determines if the string is a palindrome.
//----------------------------------------------------------------public boolean isPalindrome()
{
return testPalindrome(0, testString.length()-1);
}
//----------------------------------------------------------------// Method determines if the string is a palindrome by
// recursively testing smaller substrings of the string.
//----------------------------------------------------------------private boolean testPalindrome(int subStringStart, int subStringEnd)
{
// base case
if (subStringEnd - subStringStart <= 1)
return true;
// compare the first and last characters
if (testString.charAt(subStringStart) != testString.charAt(subStringEnd1))
return false;
// first and last equal, try smaller substring
testPalindrome(subStringStart+1, subStringEnd-1);
return true;
}
//----------------------------------------------------------------// Tests strings to see if they are palindromes.
//----------------------------------------------------------------public static void main (String args[])
{
String str, another = "y";
Scanner scan = new Scanner (System.in);
while (another.equalsIgnoreCase("y"))
{
System.out.println ("Enter a potential palindrome:");
str = scan.nextLine();
PalindromeTester p = new PalindromeTester(str);
if (p.isPalindrome())
System.out.println ("That string IS a palindrome.");
else
System.out.println ("That string is NOT a palindrome.");
System.out.println();
System.out.print ("Test another palindrome (y/n)? ");
another = scan.nextLine();
}
}
2007 Pearson Education

S 188

Lewis/Loftus/Cocking: 2/e Chapter 8 Solutions

}
8.2 DivisorCalc
//********************************************************************
// DivisorCalc.java
Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.2
//
// Contains a static method to calculate the greatest common
// divisor of two positive integers.
//********************************************************************
public class DivisorCalc {
public static int gcd(int num1, int num2)
{
if (num2 % num1 == 0)
return num1;
else
return gcd(num2, num1 % num2);
}
}
8.3 Maze
//********************************************************************
// Maze.java
Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.3
//
// Represents a maze of characters. The goal is to get from the
// top left corner to the bottom right, following a path of 1s.
// Prints the path of the final solution as it is discoverd.
//********************************************************************
public class Maze
{
private final int TRIED = 3;
private final int PATH = 7;
private int[][] maze = { {1,1,1,0,1,1,0,0,0,1,1,1,1},
{1,0,1,1,1,0,1,1,1,1,0,0,1},
{0,0,0,0,1,0,1,0,1,0,1,0,0},
{1,1,1,0,1,1,1,0,1,0,1,1,1},
{1,0,1,0,0,0,0,1,1,1,0,0,1},
{1,0,1,1,1,1,1,1,0,1,1,1,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0},
{1,1,1,1,1,1,1,1,1,1,1,1,1} };
private int[][] grid;
//----------------------------------------------------------------// Creates a working copy of the maze to compute the final solution.
// The original maze is not modified. Calls traverse to recursively
// traverse the maze.
//----------------------------------------------------------------public boolean traverseMaze (int row, int column)
{
// make copy
grid = new int[maze.length][maze[0].length];
for (int i = 0; i < maze.length; i++)
for (int j = 0; j < maze[i].length; j++)
grid[i][j] = maze[i][j];
return traverse(row, column);
2007 Pearson Education

Lewis/Loftus/Cocking, 2/e: Chapter 8 Solutions

S 189

}
//----------------------------------------------------------------// Attempts to recursively traverse the maze. Inserts special
// characters indicating locations that have been tried and that
// eventually become part of the solution.
//----------------------------------------------------------------private boolean traverse (int row, int column)
{
boolean done = false;
if (valid (row, column))
{
grid[row][column] = TRIED;

// this cell has been tried

if (row == grid.length-1 && column == grid[0].length-1)


done = true; // the maze is solved
else
{
done = traverse (row+1, column);
// down
if (!done)
done = traverse (row, column+1); // right
if (!done)
done = traverse (row-1, column); // up
if (!done)
done = traverse (row, column-1); // left
}
if (done) // this location is part of the final path
{
grid[row][column] = PATH;
System.out.println("[" + row + "], [" + column + "]");
}
}
return done;
}
//----------------------------------------------------------------// Determines if a specific location is valid.
//----------------------------------------------------------------private boolean valid (int row, int column)
{
boolean result = false;
// check if cell is in the bounds of the matrix
if (row >= 0 && row < grid.length &&
column >= 0 && column < grid[row].length)
// check if cell is not blocked and not previously tried
if (grid[row][column] == 1)
result = true;
return result;
}
//----------------------------------------------------------------// Returns the maze as a string.
//----------------------------------------------------------------public String toString ()
{
String result = "\n";
for (int row=0; row < maze.length; row++)
{
for (int column=0; column < maze[row].length; column++)
2007 Pearson Education

S 190

Lewis/Loftus/Cocking: 2/e Chapter 8 Solutions

result += maze[row][column] + "";


result += "\n";
}
return result;
}
}
8.3 MazeSearch
//********************************************************************
// MazeSearch.java
Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.3
//
// Demonstrates recursion.
//********************************************************************
public class MazeSearch
{
//----------------------------------------------------------------// Creates a new maze, prints its original form, attempts to
// solve it, and prints out its final form.
//----------------------------------------------------------------public static void main (String[] args)
{
Maze labyrinth = new Maze();
System.out.println (labyrinth);
System.out.println("\nTraversal path [row],[column]");
if (labyrinth.traverseMaze (0, 0))
System.out.println ("The maze was successfully traversed!");
else
System.out.println ("There is no possible path.");
System.out.println (labyrinth);
}
}
8.4 Maze3D
//********************************************************************
// Maze3D.java
Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.4
//
// Represents a 3D maze of characters. The goal is to get from the
// top left near corner to the bottom right far corner, following a path of 1s.
// Prints the path of the final solution as it is discoverd.
//********************************************************************
public class Maze3D
{
private final int TRIED = 3;
private final int PATH = 7;
private int[][][] maze;
private int[][][] grid;
public Maze3D(int[][][] newMaze)
{
maze = newMaze;
}
2007 Pearson Education

Lewis/Loftus/Cocking, 2/e: Chapter 8 Solutions

S 191

//----------------------------------------------------------------// Creates a working copy of the maze to compute the final solution.
// The original maze is not modified. Calls traverse to recursively
// traverse the maze.
//----------------------------------------------------------------public boolean traverseMaze (int row, int column, int page)
{
// make copy of maze
grid = new int[maze.length][maze[0].length][maze[0][0].length];
for (int i = 0; i < maze.length; i++)
for (int j = 0; j < maze[i].length; j++)
for (int k = 0; k < maze[i][j].length; k++)
grid[i][j][k] = maze[i][j][k];
return traverse(row, column, page);
}
//----------------------------------------------------------------// Attempts to recursively traverse the maze. Inserts special
// characters indicating locations that have been tried and that
// eventually become part of the solution.
//----------------------------------------------------------------private boolean traverse (int row, int column, int page)
{
boolean done = false;
if (valid (row, column, page))
{
grid[row][column][page] = TRIED;

// this cell has been tried

if (row == grid.length-1 && column == grid[0].length-1 && page ==


grid[0][0].length-1)
done = true; // the maze is solved
else
{
done = traverse (row+1, column, page);
// down
if (!done)
done = traverse (row, column+1, page); // right
if (!done)
done = traverse (row, column, page+1); // forward
if (!done)
done = traverse (row-1, column, page); // up
if (!done)
done = traverse (row, column-1, page); // left
if (!done)
done = traverse (row, column, page-1); // back
}
if (done) // this location is part of the final path
{
grid[row][column][page] = PATH;
System.out.println("[" + row + "], [" + column + "], [" + page +
"]");
}
}
return done;
}
//----------------------------------------------------------------// Determines if a specific location is valid.
//----------------------------------------------------------------private boolean valid (int row, int column, int page)
{
boolean result = false;
2007 Pearson Education

S 192

Lewis/Loftus/Cocking: 2/e Chapter 8 Solutions

// check if cell is in the bounds of the matrix


if (row >= 0 && row < grid.length &&
column >= 0 && column < grid[row].length
&& page >= 0 && page < grid[row][column].length)
// check if cell is not blocked and not previously tried
if (grid[row][column][page] == 1)
result = true;
return result;
}
}
8.4 Maze3Dsearch
//********************************************************************
// Maze3DSearch.java
Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.4
//
// Creates a random 3D maze and attempts to solve it. Repeats until
// a maze is solved and prints out the traversal steps.
//********************************************************************
import java.util.Random;
public class Maze3DSearch {
private static final int MAX_SIZE = 10;
//----------------------------------------------------------------// Generates a random 3D maze
//----------------------------------------------------------------public static int[][][] generateRandom3DMaze()
{
Random gen = new Random();
int[][][] maze = new int[MAX_SIZE][MAX_SIZE][MAX_SIZE];
for (int i = 0; i < MAX_SIZE; i++)
for (int j = 0; j < MAX_SIZE; j++)
for (int k = 0; k < MAX_SIZE; k++)
{
if (gen.nextBoolean())
maze[i][j][k] = 1;
else
maze[i][j][k] = 0;
}
return maze;
}
//----------------------------------------------------------------// Creates a random maze and attempts to solve it. Repeats until
// a maze is solved and prints out the traversal steps
//----------------------------------------------------------------public static void main(String[] args)
{
boolean done = false;
int numMazes = 0;
while (!done)
{
Maze3D labyrinth = new Maze3D(Maze3DSearch.generateRandom3DMaze());
numMazes++;
if (labyrinth.traverseMaze (0, 0, 0))
{
System.out.println ("The maze was successfully traversed!");
2007 Pearson Education

Lewis/Loftus/Cocking, 2/e: Chapter 8 Solutions

System.out.println("Num mazes generated : " + numMazes);


done = true;
}
}
}
}
8.5 MirroredPictures
//********************************************************************
// MirroredPictures.java
Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.5
//
// Demonstrates the use of recursion.
//********************************************************************
import java.applet.Applet;
import java.awt.*;
public class MirroredPictures extends Applet
{
private final int APPLET_WIDTH = 320;
private final int APPLET_HEIGHT = 320;
private final int MIN = 20; // smallest picture size
private Image world, everest, goat;
//----------------------------------------------------------------// Loads the images.
//----------------------------------------------------------------public void init()
{
world = getImage (getDocumentBase(), "world.gif");
everest = getImage (getDocumentBase(), "everest.gif");
goat = getImage (getDocumentBase(), "goat.gif");
setSize (APPLET_WIDTH, APPLET_HEIGHT);
}
//----------------------------------------------------------------// Draws the three images, then calls itself recursively.
//----------------------------------------------------------------public void drawPictures (int x, int y, int size, Graphics page)
{
page.drawImage (everest, x, y + size/2, size/2, size/2, this);
page.drawImage (goat, x + size/2, y, size/2, size/2, this);
page.drawImage (world, x, y, size/2, size/2, this);
if (size > MIN)
drawPictures (x + size/2, y + size/2, size/2, page);
}
//----------------------------------------------------------------// Performs the initial call to the drawPictures method.
//----------------------------------------------------------------public void paint (Graphics page)
{
drawPictures (0, 0, APPLET_WIDTH, page);
}
}
8.6 NonAttackingQueens
//********************************************************************
// NonAttackingQueens.java
Author: Lewis/Loftus/Cocking
//
2007 Pearson Education

S 193

S 194

Lewis/Loftus/Cocking: 2/e Chapter 8 Solutions

// Solution to Programming Project 8.6


//
// A recursive program that solves the Non-attacking Queens problem.
//********************************************************************
public class NonAttackingQueens {
int[] queens;

//
//
//
//

Queen i is always placed in row i. The


column is variable.
queens[i] represents the column of the ith row
where the ith queen is

final int NUM_QUEENS = 8;


public NonAttackingQueens()
{
queens = new int[NUM_QUEENS];
}
//----------------------------------------------------------------// Returns true if a queen queenNumber can be placed in column
//----------------------------------------------------------------boolean canPlace(int queenNumber, int column)
{
for (int row = 0; row < queenNumber; row++) // check all rows above
queenNumber row
{
if (queens[row] == column) // in the same column
return false;
if (Math.abs(queens[row] - column) == Math.abs(row - queenNumber))
// same diagonal
return false;
}
return true;
}
//----------------------------------------------------------------// Starting with the row represented by queenNumber, find all correct
// placements in the row and below the row.
//----------------------------------------------------------------public void solve(int queenNumber)
{
for (int column = 0; column < NUM_QUEENS; column++) // iterate through
all columns
{
if (canPlace(queenNumber, column)) // queen can be placed in current
column
{
queens[queenNumber] = column; // place queen in current column
if (queenNumber + 1 >= NUM_QUEENS) // solved
printSolution();
else
// keep looking
solve(queenNumber + 1);
}
}
}
//----------------------------------------------------------------// Computes and displays all solutions to the problem
//----------------------------------------------------------------public void showSolutions()
{
solve(0); // start with the first row
}
2007 Pearson Education

Lewis/Loftus/Cocking, 2/e: Chapter 8 Solutions

//----------------------------------------------------------------// Prints a grid showing the postion of the queens on the chessboard.
// Queen = X
// Empty space = O
//----------------------------------------------------------------private void printSolution()
{
int column;
for (int row=0; row<NUM_QUEENS; row++)
{
for (column = 0; column<NUM_QUEENS; column++)
if (queens[row] == column)
System.out.print(" X");
else
System.out.print(" 0");
System.out.print("\n");
}
System.out.println("\n-----------------------");
}
public static void main (String args[]) {
new NonAttackingQueens().showSolutions();
}
}
8.7 BlurbGenerator
//********************************************************************
// BlurbGenerator.java
Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.7
//
// Generates random Blurbs using recursion
//********************************************************************
import java.util.Scanner;
import java.util.Random;
public class BlurbGenerator {
Random chooser;
public BlurbGenerator()
{
chooser = new Random();
}
//----------------------------------------------------------------// Recursively generates a random Whoozit 'y' string.
// A Whoozit 'y' string is zero or more 'y's
//----------------------------------------------------------------private String getWhoozitYs()
{
StringBuffer y = new StringBuffer();
boolean stop = chooser.nextBoolean();
if (!stop)
y.append(getWhoozitYs());
else
return y.toString();
y.append("y");
return y.toString();
}
//----------------------------------------------------------------// Generates a random Whoozit.
2007 Pearson Education

S 195

S 196

Lewis/Loftus/Cocking: 2/e Chapter 8 Solutions

// A Whoozit is the character 'x' followed by zero or more 'y's


//----------------------------------------------------------------private String getWhoozit()
{
StringBuffer whoozit = new StringBuffer();
whoozit.append("x");
whoozit.append(getWhoozitYs());
return whoozit.toString();
}
//----------------------------------------------------------------// Generates a random Whatzit.
// A Whatzit is a 'q' followed by either a 'z' or a 'd', followed
// by a Whoozit.
//----------------------------------------------------------------private String getWhatzit()
{
StringBuffer whatzit = new StringBuffer();
whatzit.append("q");
boolean z = chooser.nextBoolean();
if (z)
whatzit.append("z");
else
whatzit.append("d");
whatzit.append(getWhoozit());
return whatzit.toString();
}
//----------------------------------------------------------------// Recursively generates a string of one or more Whatzits.
//----------------------------------------------------------------private String getMultipleWhatzits()
{
StringBuffer whatzits = new StringBuffer();
whatzits.append(getWhatzit());
boolean stop = chooser.nextBoolean();
if (!stop)
whatzits.append(getMultipleWhatzits());
else
return whatzits.toString();
return whatzits.toString();
}
//----------------------------------------------------------------// Generates a random Blurb.
// A Blurb is a Whoozit followed by one or more Whatzits
//----------------------------------------------------------------public String generateBlurb()
{
StringBuffer blurb = new StringBuffer();
blurb.append(getWhoozit());
blurb.append(getMultipleWhatzits());
return blurb.toString();
}
public static void main(String args[])
{
BlurbGenerator blurbs = new BlurbGenerator();
2007 Pearson Education

Lewis/Loftus/Cocking, 2/e: Chapter 8 Solutions

S 197

Scanner scan = new Scanner (System.in);


System.out.println("How many blurbs would you like? ");
int numBlurbs = scan.nextInt();
if (numBlurbs < 0)
numBlurbs = 0;
for (int i=0; i<numBlurbs; i++)
System.out.println("Blurb : " + blurbs.generateBlurb());
}
}
8.8 BlurbParser
//********************************************************************
// BlurbParser.java
Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.8
//
// Parses a string using recursion and determines if
// the string is a valid Blurb,
//********************************************************************
import java.util.Scanner;
public class BlurbParser {
//----------------------------------------------------------------// Parses a Whatzit.
// A Whatzit is a 'q' followed by either a 'z' or a 'd', followed
// by a Whoozit.
//----------------------------------------------------------------private boolean parseWhatzit(String aString)
{
if (aString.length() >= 3) // long enough
if (aString.charAt(0) == 'q')
if (aString.charAt(1) == 'z' || aString.charAt(1) == 'd')
return parseWhoozit(aString.substring(2));
return false; // does not begin with 'q'
}
//----------------------------------------------------------------// Parses a Whoozit.
// A Whoozit is the character 'x' followed by zero or more 'y's
// A Whoozit may be followed by a Whatzit
//----------------------------------------------------------------private boolean parseWhoozit(String aString)
{
int charIndex = 0;
if (aString.length() < 1)
return false; // too short
if (aString.charAt(charIndex++) == 'x')
{
while (charIndex < aString.length() && aString.charAt(charIndex) ==
'y')
charIndex++;
if (charIndex >= aString.length()) // done
return true;
if (aString.charAt(charIndex) == 'q') // valid Whatzit
return parseWhatzit(aString.substring(charIndex));
else
return false; // not followed by a Whatzit
}
else
return false; // does not begin with 'x'
}
//---------------------------------------------------------------- 2007 Pearson Education

S 198

Lewis/Loftus/Cocking: 2/e Chapter 8 Solutions

// Parses a Blurb.
// A Blurb is a Whoozit followed by one or more Whatzits
//----------------------------------------------------------------public boolean isABlurb(String aString)
{
return parseWhoozit(aString);
}
public static void main (String args[])
{
BlurbParser parser = new BlurbParser();
Scanner scan = new Scanner (System.in);
String another = "y";
while (another.equalsIgnoreCase("y"))
{
System.out.println("Enter a Blurb:");
String blurb = scan.nextLine();
if (parser.isABlurb(blurb))
System.out.println(blurb + " IS a valid Blurb");
else
System.out.println(blurb + " is NOT a valid Blurb");
System.out.println("Parse another Blurb (y/n/)?");
another = scan.nextLine();
}
}
}
8.9 PascalTriangle
//********************************************************************
// PascalTriangle.java
Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.9
//
// Determines and prints the Nth line of Pascal's Triangle
//********************************************************************
import java.util.Scanner;
public class PascalTriangle {
private int rowNumber;
private int rowCount;
private int[] newRow;
//----------------------------------------------------------------// Creates an new PascalTriangle
//----------------------------------------------------------------public PascalTriangle()
{
rowNumber = 1;
}
//----------------------------------------------------------------// Creates a new PascalTriangle with the row number n
//----------------------------------------------------------------public PascalTriangle(int n)
{
setRow(n);
}
//----------------------------------------------------------------// Sets the row of the triangle to n. If n is less than 1, sets
// row to 1
2007 Pearson Education

Lewis/Loftus/Cocking, 2/e: Chapter 8 Solutions

//----------------------------------------------------------------public void setRow(int n)


{
if (n < 1)
rowNumber = 1;
else
rowNumber = n;
}
//----------------------------------------------------------------// Returns the row number setting
//----------------------------------------------------------------public int getRow()
{
return rowNumber;
}
//----------------------------------------------------------------// Recursively computes successive rows of Pascal's triangle
// until the Nth row (represented by the variable rowNumber) is
// reached.
//----------------------------------------------------------------private void expand(int[] row)
{
//base case
if (rowCount >= rowNumber)
return;
newRow = new int[row.length+1];
newRow[0] = 1;
for (int i=1; i<row.length; i++)
newRow[i] = row[i-1] + row[i];
newRow[row.length] = 1;
rowCount ++;
expand(newRow);
return;
}
//----------------------------------------------------------------// Computes and returns the Nth row (represented by
// the variable rowNumber) of Pascal's Triangle.
//----------------------------------------------------------------public int[] computeRow()
{
rowCount = 1;
newRow = new int[rowCount];
newRow[0] = 1;
expand(newRow);
return newRow;
}
public static void main (String args[])
{
String another = "y";
Scanner scan = new Scanner (System.in);
while (another.equalsIgnoreCase("y"))
{
System.out.println("Enter the line number to compute of Pascal's
Triangle:");
int row = scan.nextInt();
PascalTriangle p = new PascalTriangle(row);
int[] result = p.computeRow();
2007 Pearson Education

S 199

S 200

Lewis/Loftus/Cocking: 2/e Chapter 8 Solutions

System.out.println("Line " + p.getRow() + " of Pascal's Triangle");


for (int i=0; i<result.length;i++)
System.out.print(result[i] + " ");
System.out.println("\n\nAnother (y/n)?");
another = scan.nextLine();
}
}
}
8.10 RecursiveSorts
//********************************************************************
// RecursiveSorts.java
Author: Lewis/Loftus/Cocking
//
// Implements a quick sort of doubles
//********************************************************************
public class RecursiveSorts
{
//----------------------------------------------------------------// Sorts the specified array of doubles using quick sort.
//----------------------------------------------------------------public static void quickSort (double[] numbers)
{
doQuickSort(numbers, 0, numbers.length - 1);
}
//----------------------------------------------------------------// Recursively sorts the portion of the given array beginning
// at start and ending at end.
//----------------------------------------------------------------private static void doQuickSort (double[] numbers, int start, int end)
{
if (start < end)
{
int middle = partition(numbers, start, end);
doQuickSort(numbers, start, middle);
doQuickSort(numbers, middle + 1, end);
}
}
//----------------------------------------------------------------// Partitions the array such that each value in [start, middle]
// is less than or equal to each value in [middle + 1, end].
// The index middle is determined in the procedure and returned.
//----------------------------------------------------------------private static int partition (double[] numbers, int start, int end)
{
double pivot = numbers[(start + end) / 2];
int i = start - 1;
int j = end + 1;
// As the loop progresses, the indices i and j move towards each other.
// Elements at i and j that are on the wrong side of the partition are
// exchanged. When i and j pass each other, the loop ends and j is
// returned as the index at which the elements are partitioned around.
while (true)
{
i = i + 1;
while (numbers[i] < pivot)
i = i + 1;
j = j - 1;
while (numbers[j] > pivot)
j = j - 1;
if (i < j)
2007 Pearson Education

Lewis/Loftus/Cocking, 2/e: Chapter 8 Solutions

{
double tmp = numbers[i];
numbers[i] = numbers[j];
numbers[j] = tmp;
}
else return j;
}
}
}
8.10 SortPrices
//********************************************************************
// SortPrices.java
Author: Lewis/Loftus/Cocking
//
// Sorts an array of prices using quick sort
//********************************************************************
public class SortPrices
{
//----------------------------------------------------------------// Creates an array of prices, sorts them, then prints them.
//----------------------------------------------------------------public static void main (String[] args)
{
double[] prices = {1.99, 2.45, 23.35, 0.25, 119.99, 5.55, 19.85};
RecursiveSorts.quickSort (prices);
for (int index = 0; index < prices.length; index++)
System.out.print (prices[index] + "
");
System.out.println();
}
}
8.11 Disk
//********************************************************************
// Disk.java
Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.11
//
// Encapsulates a disk in the grapical Towers of Hanoi solution
//********************************************************************
import java.awt.Color;
import java.awt.Graphics;
class Disk
{
int diskSize;
static
static
static
static

final
final
final
final

int
int
int
int

HEIGHT = 20;
WIDTH_STEP = 20;
ARC_WIDTH = 5;
ARC_HEIGHT = 5;

static final Color[] DISK_COLORS = {


Color.black,
Color.red,
Color.blue,
Color.yellow,
Color.green,
Color.orange,
Color.magenta,
Color.gray,
2007 Pearson Education

S 201

S 202

Lewis/Loftus/Cocking: 2/e Chapter 8 Solutions

Color.pink
};
//----------------------------------------------------------------// Creates a disk of specified size
//----------------------------------------------------------------Disk(int size)
{
diskSize = size;
}
//----------------------------------------------------------------// Returns the size of the disk
//----------------------------------------------------------------int getSize()
{
return diskSize;
}
//----------------------------------------------------------------// Returns the width of the disk to be drawn on the screen
//----------------------------------------------------------------int getScreenWidth()
{
return diskSize * WIDTH_STEP;
}
//----------------------------------------------------------------// Returns the color of the disk as indexed in DISK_COLORS
//----------------------------------------------------------------Color getDiskColor()
{
return DISK_COLORS[diskSize % DISK_COLORS.length];
}
//----------------------------------------------------------------// Draws the disk using graphics context g. Position x
// represents the x coordinate of the center of the tower,
// position y represents the top position of the disk on the tower
//----------------------------------------------------------------void draw(Graphics g, int x, int y)
{
int width = getScreenWidth();
int diskX = x - width / 2;
g.setColor(getDiskColor());
g.fillRoundRect(diskX, y, width, HEIGHT, ARC_WIDTH, ARC_HEIGHT);
g.setColor(Color.black);
g.drawRoundRect(diskX, y, width, HEIGHT, ARC_WIDTH, ARC_HEIGHT);
}
}
8.11 Tower
//********************************************************************
// Tower.java
Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.11
//
// Encapsulates a tower in the grapical Towers of Hanoi solution
//********************************************************************
import java.util.Stack;
import java.awt.Color;
import java.awt.Graphics;
class Tower
2007 Pearson Education

Lewis/Loftus/Cocking, 2/e: Chapter 8 Solutions

{
Stack disks;
int towerHeight;
static final int WIDTH = 10;
//----------------------------------------------------------------// Creates a new tower, height should be set to the max number of
// disks the tower will hold.
//----------------------------------------------------------------public Tower(int height)
{
disks = new Stack();
towerHeight = height;
}
//----------------------------------------------------------------// Adds disk to the top of the tower
//----------------------------------------------------------------void addDisk(Disk d)
{
disks.push(d);
}
//----------------------------------------------------------------// Removes the top disk from the tower
//----------------------------------------------------------------Disk removeDisk()
{
if (disks.empty())
return null;
else
return (Disk)disks.pop();
}
//----------------------------------------------------------------// Draws the tower using graphics context g. The coordinates (x,y)
// represent the bottom left corner of the tower
//----------------------------------------------------------------void draw(Graphics g, int x, int y)
{
// draw tower
int height = Disk.HEIGHT * towerHeight;
g.setColor(Color.black);
g.fillRect(x,y-height, WIDTH, height);
// draw disks
if (!disks.isEmpty())
{
// create a stack of disks in reverse order
Stack temp = new Stack();
while (!disks.empty())
temp.push(disks.pop());
// draw the disks
int location = 1;
int diskX = x + WIDTH / 2;
while (!temp.isEmpty())
{
Disk d = (Disk)temp.pop();
int diskY = y - Disk.HEIGHT * location;
d.draw(g, diskX, diskY);
// put disk back on stack
disks.push(d);
2007 Pearson Education

S 203

S 204

Lewis/Loftus/Cocking: 2/e Chapter 8 Solutions

location ++;
}
}
}
}
8.11 Move
//********************************************************************
// Move.java
Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.11
//
// Encapsulates a disk move
//*********************************************************************
public class Move {
private int from;
private int to;
public Move(int fromTower, int toTower)
{
from = fromTower;
to = toTower;
}
public String toString()
{
return "Move from tower " + from + " to tower " + to;
}
public int getFrom()
{
return from;
}
public int getTo()
{
return to;
}
}
8.11 TowerFrame
//********************************************************************
// TowerFrame.java
Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.11
//
// Main progrma to run the Graphical Towers of Hanoi
//********************************************************************
import
import
import
import
import

javax.swing.*;
javax.swing.border.TitledBorder;
java.awt.event.*;
java.awt.*;
java.util.Hashtable;

public class TowerFrame extends JFrame{


TowerPanel towerViewer;
//----------------------------------------------------------------// Sets up the main GUI
//---------------------------------------------------------------- 2007 Pearson Education

Lewis/Loftus/Cocking, 2/e: Chapter 8 Solutions

public TowerFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
towerViewer = new TowerPanel(TowerPanel.DEFAULT_NUM_DISKS);
getContentPane().add(towerViewer, BorderLayout.CENTER);
// create listeners
SliderListener sliderHandler = new SliderListener();
ButtonListener buttonHandler = new ButtonListener();
//create animation button panel
JPanel animationButtonPanel = new JPanel();
animationButtonPanel.setLayout(new GridLayout(1,2));
JButton pause = new JButton("Pause Animation");
pause.setName("pause");
pause.addActionListener(buttonHandler);
animationButtonPanel.add(pause);
JButton start = new JButton("Resume Animation");
start.setName("resume");
start.addActionListener(buttonHandler);
animationButtonPanel.add(start);
//create animation speed slider
JSlider speed = new JSlider();
speed.setName("speed");
speed.setMinimum(TowerPanel.MIN_PAUSE_TIME);
speed.setMaximum(TowerPanel.MAX_PAUSE_TIME);
speed.setValue(TowerPanel.DEFAULT_PAUSE_TIME);
speed.setBorder(new TitledBorder("Animation Speed"));
// make label table
Hashtable labelTable = new Hashtable();
labelTable.put(new Integer(TowerPanel.MIN_PAUSE_TIME), new
JLabel("Faster"));
labelTable.put(new Integer(TowerPanel.MAX_PAUSE_TIME), new
JLabel("Slower"));
speed.setLabelTable(labelTable);
speed.setPaintLabels(true);
speed.addMouseListener(sliderHandler);
// create options button panel
JPanel buttonPanel = new JPanel();
JButton animate = new JButton("Animate");
animate.setName("animate");
animate.addActionListener(buttonHandler);
buttonPanel.add(animate);
JButton user = new JButton("Let Me Try");
user.setName("user");
user.addActionListener(buttonHandler);
buttonPanel.add(user);
JButton reset = new JButton("Reset");
reset.setName("reset");
reset.addActionListener(buttonHandler);
buttonPanel.add(reset);
JPanel controls = new JPanel();
controls.setLayout(new BoxLayout(controls, BoxLayout.Y_AXIS));
controls.add(buttonPanel);
controls.add(speed);
controls.add(animationButtonPanel);
2007 Pearson Education

S 205

S 206

Lewis/Loftus/Cocking: 2/e Chapter 8 Solutions

getContentPane().add(controls, BorderLayout.SOUTH);
// make disk selector
JSlider diskNum = new JSlider();
diskNum.setName("disks");
diskNum.setMinimum(TowerPanel.MIN_DISKS);
diskNum.setMaximum(TowerPanel.MAX_DISKS);
diskNum.setValue(TowerPanel.DEFAULT_NUM_DISKS);
diskNum.setBorder(new TitledBorder("Disks"));
diskNum.setMajorTickSpacing(1);
diskNum.setPaintLabels(true);
diskNum.setPaintTicks(true);
diskNum.setSnapToTicks(true);
diskNum.addMouseListener(sliderHandler);
getContentPane().add(diskNum, BorderLayout.NORTH);
pack();
}
public static void main (String args[]) {
new TowerFrame().show();
}
//********************************************************************
// Represents the mouse listener class for the sliders.
//********************************************************************
class SliderListener extends MouseAdapter
{
public void mouseReleased(MouseEvent event)
{
JSlider source = (JSlider)event.getSource();
if (source.getName() == "speed")
towerViewer.setPauseTime(source.getValue());
else
if (source.getName() == "disks")
towerViewer.setNumDisks(source.getValue());
}
}
//********************************************************************
// Represents the button listener class for the buttons.
//********************************************************************
class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
JButton source = (JButton)e.getSource();
String name = source.getName();
if (name == "reset")
towerViewer.resetTowers();
else
if (name == "animate")
towerViewer.animate();
else
if (name == "user")
towerViewer.userSolve();
else
if (name == "pause")
towerViewer.stopTimer();
else
if (name == "resume")
towerViewer.resumeTimer();
}
}
2007 Pearson Education

Lewis/Loftus/Cocking, 2/e: Chapter 8 Solutions

S 207

}
8.11 TowerPanel
//********************************************************************
// TowerPanel.java
Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.11
//
// Controls the graphical display of the Towers of Hanoi
//********************************************************************
import
import
import
import
import

javax.swing.*;
javax.swing.Timer;
java.awt.*;
java.awt.event.*;
java.util.ArrayList;

public class TowerPanel extends JPanel {


TowersOfHanoi towerEngine;
Tower[] towers;
int numDisks;
int pauseTime;
int firstTower;
// boolean solved;
boolean userSolve;
boolean firstTowerSelected;
ArrayList solution;
Timer animationTimer;
static
static
static
static
static
static
static

final
final
final
final
final
final
final

int
int
int
int
int
int
int

MIN_PAUSE_TIME = 50;
MAX_PAUSE_TIME = 1500;
DEFAULT_PAUSE_TIME = 900;
MIN_DISKS = 1;
MAX_DISKS = 8;
DEFAULT_NUM_DISKS = 4;
NUM_TOWERS = 3;

final String TRY_AGAIN_MESSAGE = "Incorrect move\n Try Again?";


final String SOLVED_MESSAGE = "Congratulations!\nYou solved the puzzle!";
//----------------------------------------------------------------// Creates a new tower panel to diplay the Towers of Hanoi
//----------------------------------------------------------------public TowerPanel(int disks)
{
numDisks = disks;
pauseTime = DEFAULT_PAUSE_TIME;
solution = new ArrayList();
userSolve = false;
firstTowerSelected = false;
towers = new Tower[NUM_TOWERS];
for (int i=0; i<NUM_TOWERS; i++)
towers[i] = new Tower(numDisks);
//add sized disks to first tower
for (int i=numDisks; i>0; i--)
towers[0].addDisk(new Disk(i));
towerEngine = new TowersOfHanoi(numDisks);
setBackground(Color.white);
addMouseListener(new TowerSelectListener());
2007 Pearson Education

S 208

Lewis/Loftus/Cocking: 2/e Chapter 8 Solutions

}
//----------------------------------------------------------------// Overrides JPanels getPreferredSize().
//----------------------------------------------------------------public Dimension getPreferredSize()
{
// panel width is length of largest disk * num towers + 2 width step
between towers
int panelWidth = MAX_DISKS * Disk.WIDTH_STEP * NUM_TOWERS + 2 *
Disk.WIDTH_STEP + NUM_TOWERS;
// panel height 1.2 as tall as largest towers
int panelHeight = Disk.HEIGHT * MAX_DISKS;
panelHeight = Math.round(1.2f * (float)panelHeight);
return new Dimension(panelWidth, panelHeight);
}
//----------------------------------------------------------------// Draws the Towers of Hanoi.
//----------------------------------------------------------------public void paintComponent(Graphics g)
{
super.paintComponent(g);
int towerSpacing = getSize().width / NUM_TOWERS;
int towerX = towerSpacing/2 - Tower.WIDTH/2;
int towerY = getSize().height;
for (int i=0; i<NUM_TOWERS; i++)
{
towers[i].draw(g, towerX, towerY);
towerX += towerSpacing;
}
}
//----------------------------------------------------------------// Sets the amount of time in milliseconds to pause between each
// animation step. If in animation mode, resets the animation
// timer
//----------------------------------------------------------------public void setPauseTime(int time)
{
pauseTime = time;
if (animationTimer == null)
return;
if (userSolve) // no animation
return;
// update animation speed
if (!solution.isEmpty() && animationTimer.isRunning())
{
stopTimer();
animationTimer = new Timer(pauseTime, new UpdateAnimation());
animationTimer.start();
}
}
//----------------------------------------------------------------// Sets the number of disks and resets the puzzle.
//----------------------------------------------------------------public void setNumDisks(int num)
{
numDisks = num;
stopTimer();
// stop any animation
userSolve = false;
// stop any user solution
resetTowers();
2007 Pearson Education

Lewis/Loftus/Cocking, 2/e: Chapter 8 Solutions

}
//----------------------------------------------------------------// Animates the current solution. Stops any user solution
// If the solution is empty, resets the towers.
//----------------------------------------------------------------public void animate()
{
userSolve = false; // stop user solution
stopTimer(); // temporarily stop timer
if (solution.isEmpty())
resetTowers();
// start new timer
animationTimer = new Timer(pauseTime, new UpdateAnimation());
animationTimer.start();
}
//----------------------------------------------------------------// Allows a user to step-by-step solve the puzzle.
// Stops any animation and starts user solution mode.
// If solution is empty, resets the towers.
//----------------------------------------------------------------public void userSolve()
{
stopTimer(); // stop animation
if (solution.isEmpty())
resetTowers(); // start over
userSolve = true; // check for mouse motion
}
//----------------------------------------------------------------// Resets the towers to current settings.
// Creates new towers, tower engine, solution, and
// redraws the screen.
//----------------------------------------------------------------public void resetTowers()
{
towers = new Tower[NUM_TOWERS];
for (int i=0; i<NUM_TOWERS; i++)
towers[i] = new Tower(numDisks);
for (int i=numDisks; i>0; i--)
towers[0].addDisk(new Disk(i));
towerEngine = new TowersOfHanoi(numDisks);
solution = towerEngine.getSolution();
repaint();
}
//----------------------------------------------------------------// Stops the animation timer.
//----------------------------------------------------------------public void stopTimer()
{
if (animationTimer == null)
return;
if (animationTimer.isRunning())
animationTimer.stop();
}
//----------------------------------------------------------------// Resumes the animation timer, stops any user solutions
//----------------------------------------------------------------public void resumeTimer()
{
2007 Pearson Education

S 209

S 210

Lewis/Loftus/Cocking: 2/e Chapter 8 Solutions

if (animationTimer == null)
return;
if (!animationTimer.isRunning()) // get new settings and restart
{
userSolve = false;
animationTimer = new Timer(pauseTime, new UpdateAnimation());
animationTimer.start();
}
}
//********************************************************************
// Represents the listener class for the animation timer.
//********************************************************************
class UpdateAnimation implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if (!solution.isEmpty())
{
Move nextMove = (Move)solution.remove(0);
Disk d = towers[nextMove.getFrom()].removeDisk();
towers[nextMove.getTo()].addDisk(d);
repaint();
}
}
}
//********************************************************************
// Represents the mouse listener class for the panel. Used in
// the user solve mode.
//********************************************************************
class TowerSelectListener extends MouseAdapter
{
public void mousePressed(MouseEvent e)
{
if (!userSolve)
return;
if (solution.isEmpty())
return;
int towerSpacing = getSize().width /

NUM_TOWERS;

// determine tower choosen


int selectedTower;
int xValue = e.getX();
if (xValue < towerSpacing)
selectedTower = 0;
else
if (xValue < 2 * towerSpacing)
selectedTower = 1;
else
selectedTower = 2;
if (!firstTowerSelected)
{
firstTower = selectedTower;
firstTowerSelected = true;
}
else
{
// determine if valid move was selected
firstTowerSelected = false;
Move currentMove = (Move)solution.get(0);
// if currentMove correct . . .
if (currentMove.getFrom() == firstTower &&
currentMove.getTo() == selectedTower)
2007 Pearson Education

Lewis/Loftus/Cocking, 2/e: Chapter 8 Solutions

S 211

{
solution.remove(0);
Disk d = towers[currentMove.getFrom()].removeDisk();
towers[currentMove.getTo()].addDisk(d);
repaint();
}
else // incorrect move
{
int result =JOptionPane.showConfirmDialog(null,
TRY_AGAIN_MESSAGE,
"",
JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE);
// show solution anyway?
if (result != JOptionPane.YES_OPTION)
{
solution.remove(0);
Disk d = towers[currentMove.getFrom()].removeDisk();
towers[currentMove.getTo()].addDisk(d);
repaint();
}
}
}
// display solved message
if (solution.isEmpty())
{
JOptionPane.showMessageDialog(null,
SOLVED_MESSAGE,
"",
JOptionPane.INFORMATION_MESSAGE);
}
}
}
}
8.11 TowersofHanoi
//********************************************************************
// TowersOfHanoi.java
Author: Lewis/Loftus/Cocking
//
// Represents the classic Towers of Hanoi puzzle.
//********************************************************************
import java.util.ArrayList;
public class TowersOfHanoi
{
private int totalDisks;
ArrayList moves;
//----------------------------------------------------------------// Sets up the puzzle.
//----------------------------------------------------------------public TowersOfHanoi (int numDisks)
{
totalDisks = numDisks;
moves = new ArrayList();
}
//----------------------------------------------------------------// Performs the initial call to moveTower to solve the puzzle.
// Moves the disks from tower 1 to tower 3 using tower 2.
// Returns an ArrayList of the moves made.
//---------------------------------------------------------------- 2007 Pearson Education

S 212

Lewis/Loftus/Cocking: 2/e Chapter 8 Solutions

public ArrayList getSolution()


{
moveTower (totalDisks, 0, 2, 1);
return moves;
}
//----------------------------------------------------------------// Moves the specified number of disks from one tower to another
// by moving a subtower of n-1 disks out of the way, moving one
// disk, then moving the subtower back. Base case of 1 disk.
//----------------------------------------------------------------private void moveTower (int numDisks, int start, int end, int temp)
{
if (numDisks == 1)
moveOneDisk (start, end);
else
{
moveTower (numDisks-1, start, temp, end);
moveOneDisk (start, end);
moveTower (numDisks-1, temp, end, start);
}
}
//----------------------------------------------------------------// Stores instructions to move one disk from the specified start
// tower to the specified end tower.
//----------------------------------------------------------------private void moveOneDisk (int start, int end)
{
moves.add(new Move(start, end));
}
}
AP-Style Multiple Choice
Solutions
1. C
2. A
3. A
4. D
5. C
6. D

AP-Style Free Response Solution


8.1
a.
// precondition: n > 0
public static int factorial (int n)
{
if (n == 1)
return 1;
else
return n * factorial(n-1);
}

b.
// precondition: exp >= 0
public static int power (int base, int exp)
{

2007 Pearson Education

Lewis/Loftus/Cocking, 2/e: Chapter 8 Solutions

if (exp == 0)
return 1;
else
return base * power(base, exp-1);
}

c.
// precondition: a has size at least 1
public static void triple (int[] a)
{
tripleHelp (a, 0);
}
// triples the elements from k to a.length-1
private static void tripleHelp (int[] a, int k)
{
a[k] = a[k] * 3;
if (k < a.length-1)
tripleHelp(a, k+1);
}

2007 Pearson Education

S 213

Anda mungkin juga menyukai