Computer Science 101 Lab 6: Recursion and Palindromes
Due: November 4, 1998

Objectives and Overview: This lab provides experience with recursion in problem solving, along with an introduction to String variables and their uses.

Part 1 - Exercising the Towers of Hanoi Program

Below is an abbreviated version of the Towers of Hanoi program that was introduced in class. A copy of this program is available for your use in the file Hanoi.java inside the CS101 (Tucker) folder.

The Towers of Hanoi problem starts with some number (n) of disks, all with different diameters, stacked in a pile on one of three pegs, with the largest disk on the bottom of the pile.  To solve the problem, a sequence of single-disk moves should result in a transfer of the entire pile to the third peg, using the second peg at each stage as an auxiliary peg. The solution has the additional proviso that at no time should a larger disk be placed on top of a smaller disk.
 
The solution can be expressed as a recursive method, say Move, which breaks the n-disk problem into two n-1 disk problems and a 1-disk transfer.  This is the essence of the "Divide and Conquer" strategy of problem solving.

public class Hanoi {

  static void Move( int nDisks, char StartPeg, char AuxPeg, char EndPeg) {

      if (nDisks == 1)    // base case -- stopping point for recursion
         System.out.println( "   Move disk from " + StartPeg + " to " + EndPeg); 
          else  {             // recursive calls to Move with n - 1 disks

         // Move n - 1 disks from StartPeg to AuxPeg using EndPeg
            Move( nDisks - 1, StartPeg, EndPeg, AuxPeg );

         // Move 1 disk from StartPeg to EndPeg - no auxiliary peg needed
            Move( 1, StartPeg, ' ', EndPeg );

         // Move n - 1 disks from AuxPeg to EndPeg using StartPeg
            Move( nDisks - 1, AuxPeg, StartPeg, EndPeg );

      }
  }

  public static void main (String argv[]) {
   final char   Peg1 = 'A',     // Identities of the three pegs
                Peg2 = 'B',
                Peg3 = 'C';
   int   NumDisks;              // number of disks for the problem

   System.out.print( "Enter number of disks:  " );
   NumDisks = Keyboard.readInt();
   while(!Keyboard.eof()) {
      Move( NumDisks, Peg1, Peg2, Peg3 );
      System.out.print( "\nEnter number of disks:  " );
      NumDisks = Keyboard.readInt();
   }  
  }
}

After running this program several times for some different values of n, answer the following questions about its behavior.
 

  1. For NumDisks = 3, make a table that shows the sequence of calls to the method Move, and for each call the values of the parameters NumDisks, Peg1, Peg2, and Peg3.
  2. How many times is the method Move called for NumDisks = 0? for NumDisks = 4? for NumDisks = 5?
  3. What about the general case? That is, can you derive an expression for the number of calls to method Move for NumDisks = n (where n is any integer greater than or equal to 0)?

Part 2 - String Variables and Methods

The Java class String can be used to support programming in a wide range of text processing software applications, like word processors and spelling checkers.

 String Constants and variables

 A String constant is any sequence of characters enclosed in single double quotes ("). In our Java programs, all messages displayed on the screen, like the message

"Enter number of disks:  "

are String constants.

A String variable is any variable declared with the type String. The following are String variables:

String s, t, u;

The value of a String variable can be any String constant, including the empty String "" (the one that has no characters between the quotes).

The String class has a number of methods that allow programs to manipulate String values in different ways. The table on page 326 of your text summarizes many of these methods. The discussion below illustrates how these methods can be used by showing some simple examples.

 String Length, Assignment, Concatenation, and Comparison

The length of a String is the number of characters that appear between the quotes, including blanks and all other special characters.  String variables can be assigned values, just like numerical variables. This can be done with an assignment statement or a Keyboard.readString() statement. The following statement assigns a String value to the variable s declared above:

s = "Hello World!";

The length of this String value of s is 12, and the method length returns the length of any String. Thus, the expression s.length() returns 12 in this example.

The ith character of a String variable can be isolated by using the charAt method. String values can be viewed as arrays of characters in this sense, so s.charAt(0) returns the first character 'H', s.charAt(1) returns the second character 'e', and so forth. [Note that single characters are enclosed in single quotes (') rather than double quotes ("), which enclose strings. Thus the character H is written as 'H', while the 1-character String H is written as "H".]

Two String values can be concatenated (joined together) to form a single String, either using the + sign or using the concat method, which is part of the String class. Either of the following statements leaves the variable u with the value "Hello World! Hello!".

u = s + " Hello!";
u = s.concat(" Hello!"); 

Two String values can be compared for equality or nonequality using the equals method. Equality for String values means that one is an identical copy of the other, letter for letter. So we might write

if (s.equals("Hello!")) ...

to test whether or not the current value of s is the String "Hello!".

 Substring Extraction, Insertion, and Deletion

A String can be formed by extracting a copy of an embedded String, called a substring, from another string. For example, the following statement extracts a copy of "World" from the String s and assigns it to the String t::

t = s.substring(6, 11);

Here, the 6 designates the starting position of the substring to be copied, and the 11 designates the position of the next character in s following the substring (counting the first character at position 0, not 1). Note that the value of s itself is not affected by this action.

If we wanted to delete that same substring from s, we would need to concatenate the beginning part of s with that part which follows that substring. That is, we would write

s = s.substring(0, 5) + s.substring(11);

to obtain the string "Hello" and assign it to s. Note here that the expression s.substring(11) takes that substring which begins at position 11 and ends at the end of s. That is, it is the entire righthand end of s.

Finally, to insert a new substring within an existing String, we use concatenation and substring in a different way. For instance, to insert the word "Cruel" inside the string s = "Hello World!" to form s = "Hello Cruel World!" we would write the following assignment:

s = s.substring(0, 5) + " Cruel " + s.substring(6);

 String Searching and Replacement

Two other useful String methods search a String for the position of a particular character or substring that may occur within it, and replace a character within a String by another character. The first is called indexOf, and the second is called replace. Here are two examples (assuming i and j are integer variables, and s has the value "Hello Cruel World!").

i = s.indexOf("Cruel");
s = s.replace(s.charAt(i), 'c');

The resulting value of i in this example is 6 (the position of the first character of the leftmost occurrence of the substring "Cruel" within s). The resulting value of s is "Hello cruel World!" since s.charAt(i) returns the character 'C'.

  1. Write a Java statement that locates the position of the first blank character in String u and assigns it to the integer variable i. 
  2. Using this value of i, write another statement that extracts the first word from u and assigns it to t. That is, if u = "Hello Hello Cruel World", your statement should leave t = "Hello" and u = "Hello Cruel World".
  3. Design a loop that one-by-one extracts single words from the String u and displays them on the screen.
  4. Design another loop that extracts all blanks from u, leaving only its nonblank characters.
  5. Design a method WordCount that determines, for a single String parameter s, the number of words in s. (Assume that a word is any String of nonblank characters, separated from the next word by one or more blanks.)
  6. Design a recursive method Reverse that reverses the order of the characters in a String. For example, Reverse("Hello") would return the String "olleH".

Part 3 - Discovering Palindromes

A palindrome is a word that is spelled the same when written backwards or forwards. For example, each of the following Strings is a palindrome:

"abba"
"abbadabba"
"abbadabbadabba"
"ablewasiereisawelba"
"amanaplanacanalpanama"

The purpose of this program is to accept any number of input Strings typed by the user, and determine whether or not each one is a palindrome. The program should display the message "palindrome" or "no palindrome" accordingly, for each word entered.

Your program should have a recursive method, called Palindrome(s), which returns true or false depending respectively on whether or not s is a palindrome.

Optional Extra Credit: Add features to your program by which the following are also identified as palindromes -- that is, spaces are ignored in the determination. (Hint: consider removing all the blanks from a string before considering it as a possible palindrome.)

"abba dabba dabba"
"able was i ere i saw elba"
"a man a plan a canal panama"

Extra Extra Credit!!! Add more features to your program by which palindromes that include blank spaces and capital letters are allowed. That is, the following Strings would be discovered as palindromes. (Hint: look at the method toLowerCase that is described on page 326 of your text. It translates all upper case letters in a string to lower case.)

"Abba dabba dabba"
"Able was I ere I saw Elba"
"A man a plan a canal Panama"

Lab 6 Deliverables:

Answer all questions in parts 1 and 2, and hand in a hard copy of your answers. Also submit a copy of your complete program for part 3, which should be labeled lab6yourname.java, by dragging it to the Drop Box in the CS101 (Tucker) folder.