Documents
Resources
Learning Center
Upload
Plans & pricing Sign in
Sign Out

Review Exercises

VIEWS: 2 PAGES: 51

									Solutions Manual: Chapter 6              Big Java, by Cay Horstmann                         1


Review Exercises

R6.1
Java supports while, for, and do/while loops. While loops are used when the loop must
continue until a certain condition is met; for loops are used when an integer runs from a
starting to an ending value with a constant increment or decrement; do/while loops are
appropriate when the loop body must be executed at least once.

R6.2
The program prints a "multiplaction table"--the remainders of the products of the
numbers 0 . . . 9.

R6.3
for    (i   =   1; i <= 10; i++) . . .      10 times
for    (i   =   0; i < 10; i++) . . .       10 times
for    (i   =   10; i > 0; i--) . . .       10 times
for    (i   =   -10; i <= 10; i++) . . .    21 times
for    (i   =   10; i >= 0; i++) . . .      never ends
for    (i   =   -10; i <= 10; i = i + 2)    . . . 11 times
for    (i   =   -10; i <= 10; i = i + 3)    . . . 7 times

R6.4
            int s = 0;
            int i = 1;
            while (i <= 10)
            {
               s = s + i;
               i = i + 1;
            }

R6.5
int n = 1;
double x =        0;
double s =        1; /* dirty trick to make sure the loop passes the first time
*/
while (s >        0.01)
{
   s = 1.0        / (n * n);
   x = x +        s;
   n++;
}

R6.6
An infinite loop is a loop that does not terminate.
On many computers, you can kill the program by closing the console window in which
the program executes, or by hitting a special key combination such as CTRL+C. If all
else fails, you can always restart the computer :-)
Solutions Manual: Chapter 6              Big Java, by Cay Horstmann                       2


R6.7
You can type input at the keyboard. End of file is signaled by typing a character such as
[Ctrl+Z] or [Ctrl+D], depending on the operating system. Or you can supply all input in a
file, and use redirection:
java myprog < input.txt
Then the end of file is not indicated by any special character. Either way, the program can
find out if the end of file has been reached by testing for a null return value from
ConsoleReader.readLine().


R6.8
There are 21 bytes, 15 for the characters and 6 for the \r\n pairs at the end of each line.
When saving a file, then the file contains a record of the number of characters in it, so no
special end-of-file character is needed. But when typing on the console, there is no way
of telling how much longer the user wants to type. When the user hits [Enter], that doesn't
mean that the input should be ended--it just signifies the end of a line. There is no
"File|Save" command when typing input to the console. Hence a special character (such
as [Ctrl+Z] or [Ctrl+D]) has been set aside to signify end of input. That character is NOT
passed on to System.in.

R6.9
String input = "Hello, cruel world!";
StringTokenizer tokenizer = new StringTokenizer(input);
while (tokenizer.hasMoreTokens)
{
   String token = tokenizer.nextToken();
   /* do something with token...
      this string has three tokens:
         Hello,
         cruel
         world!
   */
}

R6.10
        String s = "Hello, cruel world!";

        for(int i = 0; i < s.length(); i++)
        {
           char ch = s.charAt(i);
           /*
              Do something with character...
              The resulting characters are
              'H', 'e', 'l', 'l', 'o', and so on
           */

        }

R6.11
Solutions Manual: Chapter 6             Big Java, by Cay Horstmann                        3


A "loop and a half" is a loop whose termination condition is in the middle of the loop.
while (!done)
{
   read employee name
   if not OK,
      done = true;
   else
   {
      read employee salary
      if not OK,
         done = true;
      else
      {
           give employee 5 percent raise
           print employee data
      }
   }
}

while (true)
{
   read employee name
   if not OK, break;
   read employee salary
   if not OK, break;
   give employee 5 percent raise
   print employee data
}
void readEmployees()
{
   while (true)
   {
      read employee name
      if not OK, return;
      read employee salary
      if not OK, return;
      give employee 5 percent raise
      print employee data
   }
}

R6.12
The challenge is that the last token is a number, and all tokens before that should be taken
as part of the name. Fortunately, you can use the countTokens method of the
StringTokenizer class to count the tokens.

Here is how we find the last token:
int n = tokenizer.countTokens();
for (int i = 1; i < n; i++) tokenizer.nextToken();
String lastToken = tokenizer.nextToken();
double length = Double.parseDouble(lastToken);
Solutions Manual: Chapter 6              Big Java, by Cay Horstmann                          4


Now you want to remove the last token from the input line: First find the last token, then
go backwards to skip white space. Finally, extract the substring that belongs to the head
portion of the input.
int end = input.lastIndexOf(lastToken);
while (end >= 0 && Character.isWhitespace(input.charAt(end - 1)) end--;
bridgeName = input.substring(0, end);
Alternatively, you could concatenate all tokens except for the last one. However, then any
repeated spaces in the middle of the name would be replaced by a single space:
for (int i = 1; i < n; i++)
{
   bridgeName += tokenizer.nextToken();
   if (i < n - 1) bridgeName += " ";
}

R6.13
Using a special number, such as a 0, as a sentinel works if there is some restriction on the
input. In many cases, though, there isn't.
What if the program requires the number 0 for some input? Then the programmer must
select a different sentinel. This can be troublesome
because the programmer needs to think of a lucky number that the program doesn't use.

R6.14
First call generator.nextInt(4) to get the card suit (e.g. 0 = clubs, 1 = spades, 2 =
hearts, 3 = diamonds).

Then call generator.nextInt(13) to get the card value (1 = ace, 2 - 10 = face value, 11
= Jack, 12 = Queen, 13 = King).

R6.15
An "off by one" error is when the index of a loop is one less or more than the actual
iteration. From experience, the most common occurence would have to be the for loop
indexing, especially when used with strings:
   for (i = 0; i <= s.length(); i++) /* oops...should be < s.length() */

R6.16
An example of a for loop where symmetric bounds are more natural would be in the case
of executing a block of statements a given number of times:
for (int i = 1; i <= 10; i++) // do ten times
When looking inside a string, you usually use an asymmetric loop
for (int i = 0; i < s.length(); i++)

R6.17
Nested loops are loops that have one situated inside another. An example is the code that
is needed to print a table:
Solutions Manual: Chapter 6           Big Java, by Cay Horstmann    5

      for (row = first; row <= last; row++)
      {
         for (column = first; column <= last; column++)
            print the (row, column) value
         print a newline
      }

Programming Exercises

P6.1
Converter.java

/**
      This class is used to find the conversion rate between
      US dollars and the Euro
*/
public class Converter
{
   /**
       Constructs a Converter object to convert
          between US dollars and the Euro
       @param aRate the exchange rate
   */
   public Converter(double aRate)
   {
       rate = aRate;
   }

      /**
            Calculate the exchange rate between
               US dollar and the Euro
            @param amount the amount to convert
      */
      public double convert(double amount)
      {
         double exchange = rate * amount;

            return exchange;
      }

      private double rate;
}

ExP6_1.java

import javax.swing.JOptionPane;

/**
   This is a test driver class for Converter class
*/
public class ExP6_1
{
   public static void main (String[] args)
   {
      String input = JOptionPane.showInputDialog(
         "Please enter the exchange rate between US$ and Euro:");
Solutions Manual: Chapter 6         Big Java, by Cay Horstmann         6

          double rate = Double.parseDouble(input);

          Converter c = new Converter(rate);

          boolean done = false;
          while (!done)
          {
             input = JOptionPane.showInputDialog(
                "Please enter the amount in US$ to be converted:");

             if (input == null)
                done = true;
             else
             {
                double amount = Double.parseDouble(input);

            if (amount > 0)
            {
               double exchange = c.convert(amount);
               System.out.print("The conversion to Euro is: " + exchange
+ " Euro\n");
            }
            else
               done = true;
         }
      }

          System.exit(0);
      }
}

P6.2
Drunkard.java

import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.util.Random;

/**
      This class provides methods to simulate the movement
         of a drunkard
*/
public class Drunkard
{
   /**
       Creates a Drunkard object representing an
          intoxicated person
       @param anX the x coordinate size
       @param aY the y coordinate size
       @param aSize the size of the grid
   */
   public Drunkard(double anX, double aY, int aSize)
   {
       x = anX;
       y = aY;
       size = aSize;
Solutions Manual: Chapter 6             Big Java, by Cay Horstmann       7

            generator = new Random();
      }

      /**
            Method used to simulate the moves
               of the intoxicated person
      */
      public void move()
      {

            int move = generator.nextInt(4);

            if (move == 0) // up
               y--;
            else if (move == 1) // down
               y++;
            else if (move == 2) // left
               x--;
            else if (move == 3) // right;
               x++;

      }

      /**
            Method used to draw the dots on the grid
               simulating the intoxicated person
            @param g2 the graphics context
      */
      public void draw(Graphics2D g2)
      {
         final int RADIUS = 3;

      Ellipse2D.Double e = new Ellipse2D.Double(x * size - RADIUS, y *
size - RADIUS,
         2 * RADIUS, 2 * RADIUS);
      g2.draw(e);
   }

      private    int size;
      private    double x;
      private    double y;
      private    Random generator;
}

Grid.java

import java.awt.Graphics2D;
import java.awt.geom.Line2D;

/**
      This class is used to draw a grid, 10 blocks horizontal and
      10 blocks vertical, representing 10 city blocks
*/
public class Grid
{
   /**
Solutions Manual: Chapter 6           Big Java, by Cay Horstmann   8

            Creates a Grid object to draw a grid
            @param aSize the size of grid
            @param aNSquares the number of squares in the grid
      */
      public Grid(int aSize, int aNSquares)
      {
         size = aSize;
         nSquares = aNSquares;
      }

      /**
            Method used to draw the grids
            @param g2 the graphics content
      */
      public void draw(Graphics2D g2)
      {
         // draw the x-direction of the grid

            double x;
            for (x = 0; x <= nSquares; x++)
            {
               Line2D.Double l = new Line2D.Double(x * size, 0,
                  x * size, nSquares * size);
               g2.draw(l);
            }

            // draw the y-direction of the grid

            double y;
            for (y = 0; y <= nSquares; y++)
            {
               Line2D.Double l = new Line2D.Double(0, y * size,
                  nSquares * size, y * size);
               g2.draw(l);
            }

      }

      private static final int RADIUS = 3;
      int size;
      int nSquares;
}

ExP6_2.java

import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Graphics2D;

/**
   This class tests the Drunkard and Grid classes
*/
public class ExP6_2 extends Applet
{
   public void paint(Graphics g)
   {
Solutions Manual: Chapter 6              Big Java, by Cay Horstmann    9

            Graphics2D g2 = (Graphics2D)g;

            final int NSQUARES = 10;
            final int RADIUS = 3;
            final int MAX_MOVES = 100;

            int size = Math.min(getWidth(), getHeight()) / NSQUARES;

            Grid myGrid = new Grid(size, NSQUARES);
            myGrid.draw(g2);

            double x = NSQUARES / 2;
            double y = NSQUARES / 2;

            Drunkard d = new Drunkard(x, y, size);

            for (int i = 1; i <= MAX_MOVES; i++)
            {
               d.move();
               d.draw(g2);
            }
      }
}

P6.3
CannonBall.java

/**
   This class simulates a cannonball fired up in the air
*/
public class CannonBall
{
   /**
       Creates a CannonBall object and measure its velocity
          and the exact location of which it lands
       @param aIvel the inital velocity
   */
   public CannonBall(double aIvel)
   {
       ivel = aIvel;
       pos = 0;
   }

      /**
            Method used to calculate the velcoity of the cannonball
            @param deltaT the time interval
      */
      public void move(double deltaT)
      {
         pos = pos + ivel * deltaT;
         ivel = ivel - G * deltaT;
      }

      /**
            Method used to get the velocity of the cannonball
            @return the velocity
Solutions Manual: Chapter 6           Big Java, by Cay Horstmann    10

      */
      public double getVelocity()
      {
         return ivel;
      }

      /**
            Method used to get the position of the cannonball
            @return the position
      */
      public double getPosition()
      {
         return pos;
      }

      private static final double G = 9.81;

      private double ivel;
      private double pos;
}

ExP6_3.java

import javax.swing.JOptionPane;

/**
   Test driver class for CannonBall class
*/
public class ExP6_3
{
   public static void main(String[] args)
   {
      String input = JOptionPane.showInputDialog(
         "Enter the initial velocity:");
      double ivel = Double.parseDouble(input);

            final double G = 9.81;
            double deltaT = 0.01;
            double t = 0;
            double exactPos = 0;
            double vel = ivel;

            CannonBall cb = new CannonBall(ivel);

            while (vel > 0)
            {
               for (int i = 0; vel > 0 && i < 100; i++)
               {
                  cb.move(deltaT);
                  t = t + deltaT;
                  vel = cb.getVelocity();
               }

               exactPos = -0.5 * G * t * t + ivel * t;

               System.out.println("Position: " + cb.getPosition()
Solutions Manual: Chapter 6          Big Java, by Cay Horstmann           11

                 + " Velocity: " + cb.getVelocity());
              System.out.println("The exact position is: " + exactPos);

          }

          System.exit(0);
      }
}

P6.4
CannonBall.java

import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;

/**
   This class implements a cannon ball's flight through the air
*/
public class CannonBall
{
   /**
       Constructs a CannonBall object to display
       @param anIvel the initial velocity of the ball
       @param anAng the angle of the projectile
       @param aHeight the height of the applet window
   */
   public CannonBall(double ivel, double ang)
   {
       posX = 0;
       posY = 0;
       velX = Math.cos(ang) * ivel;
       velY = Math.sin(ang) * ivel;
   }

      public void move()
      {
         final double G = 9.81;
         final double DELTA_T = 0.01;

          posX = posX + velX * DELTA_T;
          posY = posY + velY * DELTA_T;
          velY = velY - G * DELTA_T;
      }

      public double getX()
      {
         return posX;
      }

      public double getY()
      {
         return posY;
      }

      private double posX;
Solutions Manual: Chapter 6             Big Java, by Cay Horstmann   12

      private double posY;
      private double velX;
      private double velY;
}

ExP6_4.java

import       java.applet.Applet;
import       java.awt.Graphics;
import       java.awt.Graphics2D;
import       java.awt.geom.Ellipse2D;
import       javax.swing.JOptionPane;

/**
   This is a test driver for the CannonBall class
*/
public class ExP6_4 extends Applet
{
   public void init()
   {
      String input1 = JOptionPane.showInputDialog(
         "Enter the initial velocity: (e.g. 50)");
      ivel = Double.parseDouble(input1);

            String input2 = JOptionPane.showInputDialog(
               "Enter the angle in degrees: (e.g. 60)");
            ang = Math.toRadians(Double.parseDouble(input2));
      }

      public void paint(Graphics g)
      {
         Graphics2D g2 = (Graphics2D)g;

            CannonBall ball = new CannonBall(ivel, ang);
            while(ball.getY() >= 0)
            {
               ball.move();
               double x = xpixel(ball.getX());
               double y = ypixel(ball.getY());
               Ellipse2D.Double circle = new Ellipse2D.Double(
                  x - RADIUS, y - RADIUS, 2 * RADIUS, 2 * RADIUS);
               g2.draw(circle);
            }
      }

      /**
            Converts from user coordinates to pixel coordinates
            @param xuser an x-value in user coordinates
            @return the corresponding value in pixel coordinates
      */
      public double xpixel(double xuser)
      {
         return (xuser - XMIN) * (getWidth() - 1) / (XMAX - XMIN);
      }

      /**
Solutions Manual: Chapter 6                  Big Java, by Cay Horstmann   13

            Converts from user coordinates to pixel coordinates
            @param yuser a y-value in user coordinates
            @return the corresponding value in pixel coordinates
      */
      public double ypixel(double yuser)
      {
         return (yuser - YMAX) * (getHeight() - 1) / (YMIN - YMAX);
      }

      private    double    ivel;
      private    double    ang;
      private    static    final   double   XMIN =   0;
      private    static    final   double   XMAX =   300;
      private    static    final   double   YMIN =   0;
      private    static    final   double   YMAX =   100;
      private    static    final   double   RADIUS   = 2;
}

P6.5
FibonacciGenerator.java

/**
   Class used to generate a Fibonacci number with a given input
*/
public class FibonacciGenerator
{
   /**
       Construct a FibonacciGenerator object to
          generate a Fibonacci number
   */
   public FibonacciGenerator()
   {
       fold1 = 1;
       fold2 = 1;
       fnew = 1;
   }

      /**
            Method used to calculate a fibonacci number
            @return fnew the fibonacci number
      */
      public int nextNumber()
      {
         fnew = fold1 + fold2;

            fold2 = fold1;
            fold1 = fnew;

            return fnew;
      }

      private int fold1;
      private int fold2;
      private int fnew;
}
Solutions Manual: Chapter 6         Big Java, by Cay Horstmann         14

ExP6_5.java

import javax.swing.JOptionPane;

/**
   Test driver class for FibonacciGenerator class
*/
public class ExP6_5
{
   public static void main(String[] args)
   {
      String input = JOptionPane.showInputDialog(
         "Enter n:");
      int n = Integer.parseInt(input);

          FibonacciGenerator fg = new FibonacciGenerator();

          int next = 0;

          if (n <= 2)
             next = 1;
          else
          {
             for (int i = 3; i <= n; i++)
             {
                next = fg.nextNumber();
             }
          }

          System.out.println("fib(" + n + ") = " + next);

          System.exit(0);
      }
}

P6.6
BarChart.java

import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.util.StringTokenizer;

/**
   This class draws a bar chart based on user input of a data set
*/
public class BarChart
{
   /**
       Creates a BarChart object to be drawn w/ the given parameters
       @param anInput the input from the user
       @param aWidth the width of the applet
       @param aHeight the height of the applet
   */
   public BarChart(String anInput, int aWidth, int aHeight)
   {
       input = anInput;
Solutions Manual: Chapter 6           Big Java, by Cay Horstmann      15

            width = aWidth;
            height = aHeight - 1;
      }

      /**
            Method used to draw each individual bar
            @param g2 the graphics content
      */
      public void draw(Graphics2D g2)
      {
         StringTokenizer tokenizer = new StringTokenizer(input);

            int bars = tokenizer.countTokens();

            width = width / bars;

            int x = 0;

            for (int i = 0; i < bars; i++)
            {
               int y = height;
               int value = Integer.parseInt(tokenizer.nextToken());
               Rectangle bar = new Rectangle(x, y - value,
                  width - 15, value);
               g2.draw(bar);
               x += width;
            }
      }

      private String input;
      private int width;
      private int height;

}

ExP6_6.java

import       java.applet.Applet;
import       java.awt.Graphics;
import       java.awt.Graphics2D;
import       javax.swing.JOptionPane;
import       java.util.StringTokenizer;

/**
   Test driver class for BarChart class
*/
public class ExP6_6 extends Applet
{
   public void init()
   {
      input = JOptionPane.showInputDialog(
         "Enter the data values: (e.g. 40 60 50)");
   }

      public void paint(Graphics g)
      {
Solutions Manual: Chapter 6             Big Java, by Cay Horstmann         16

            Graphics2D g2 = (Graphics2D)g;

            int width = getWidth();
            int height = getHeight();

            BarChart myBarChart = new BarChart(input, width, height);

            myBarChart.draw(g2);
      }

      private String input;
}

P6.7
DataSet.java

/**
      This class is used to calculate the average and standard deviation
         of a data set
*/
public class DataSet
{
   /**
       Constructs a DataSet object to hold the total
          number of inputs, the sum, and the sum of square
   */
   public DataSet()
   {
       sum = 0;
       sum_square = 0;
       n = 0;
   }

      /**
            Method used to calculate the average of the data set
            @return average the average of the data set
      */
      public double getAverage()
      {
         double average = sum / n;
         return average;
      }

      /**
            Method used to calculate the standard deviation
            @return stddev the standard deviation of data set
      */
      public double getDeviation()
      {
         double stddev = Math.sqrt((sum_square - sum / n) / (n - 1));
         return stddev;
      }

      /**
            Gets the total number of input values
            @return n the total number of inputs
Solutions Manual: Chapter 6            Big Java, by Cay Horstmann     17

      */
      public int getIncrementNumber()
      {
         return n;
      }

      /**
            Method used to add the total square sum of the data set
            @param x the input value
      */
      public void add(double x)
      {
         sum = sum + x;
         sum_square = sum_square + x * x;
         n++;
      }

      private double sum;
      private double sum_square;
      private int n;
}

ExP6_7.java

import javax.swing.JOptionPane;

/**
      This is a test driver class for DataSet class
*/

public class ExP6_7
{
   public static void main(String[] args)
   {
      DataSet a = new DataSet();

            boolean done = false;
            while(!done)
            {
               String input = JOptionPane.showInputDialog(
                  "Enter Value:");

                if(input == null)
                   done = true;
                else
                {
                   double x = Double.parseDouble(input);
                   a.add(x);
                }
            }

      System.out.println("There is a total of " + a.getIncrementNumber()
+ " values.");
      System.out.println("The average is " + a.getAverage());
      System.out.println("The standard deviation is " +
a.getDeviation());
Solutions Manual: Chapter 6              Big Java, by Cay Horstmann   18


            System.exit(0);
      }
}

P6.8
RandomCircle.java

import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.util.Random;

/**
      This class provides a method to draw a circle
         with random center and random radius.
*/
public class RandomCircle
{
   /**
       Creates a Circle object used to draw random circles
       @param aWidth the width of the applet window
       @param aHeight the height of the applet window
   */
   public RandomCircle(double aWidth, double aHeight)
   {
       width = aWidth;
       height = aHeight;

            // random generator object

            generator = new Random();
            x = generator.nextDouble() * width;
            y = generator.nextDouble() * height;
            r = generator.nextDouble() * MAX_RADIUS;
      }

      /**
            Method used to draw the circles
            @param g2 the graphics context
      */
      public void draw(Graphics2D g2)
      {
         Ellipse2D.Double circle =
            new Ellipse2D.Double(x, y, 2 * r, 2 * r);
         g2.draw(circle);
      }

      final double MAX_RADIUS = 50;

      Random    generator;
      double    x;
      double    y;
      double    r;
      double    width;
      double    height;
}
Solutions Manual: Chapter 6             Big Java, by Cay Horstmann            19


ExP6_8.java

import       java.applet.Applet;
import       java.awt.Graphics;
import       java.awt.Graphics2D;
import       javax.swing.JOptionPane;

/**
   Test driver class for Circle class
*/
public class ExP6_8 extends Applet
{
   public void init()
   {
      String input = JOptionPane.showInputDialog(
         "Enter the circle count: (e.g. 10)");
      count = Integer.parseInt(input);
   }

      public void paint(Graphics g)
      {
         Graphics2D g2 = (Graphics2D)g;

            for (int i = 1; i <= count; i++)
            {
               RandomCircle rc = new RandomCircle(getWidth(), getHeight());
               rc.draw(g2);
            }
      }

      private int count;
}

P6.9
Word.java

/**
      This class provides methods to calculate the
         number of words, sentences, and syllables in
         a document
*/
public class Word
{
   /**
       Constructs an empty word
   */
   public Word()
   {
       syllables = 0;
       words = 0;
       sentences = 0;
   }

      /**
            Method used to add words to the index
Solutions Manual: Chapter 6         Big Java, by Cay Horstmann       20

      @param word is the word to be added
   */
   public void addWord(String word)
   {
      words++;

         if (isSentenceEnd(word.charAt(word.length() - 1)))
         {
            sentences++;
            word = word.substring(0, word.length() - 1);
         }

         syllables = syllables + countSyll(word);
   }

   /**
         Method used to count the syllables in a given string
         @param w the string input
         @return count the syllables count
   */
   public int countSyll(String w)
   {
      int count = 0;
      int i;
      boolean inVowelGroup = false;

         for (i = 0; i < w.length(); i++)
         {
            char c = w.charAt(i);

             if (isVowel(c) && !(c == 'e' && i == w.length() - 1))
             {
                if (!inVowelGroup)
                {
                   count++;
                   inVowelGroup = true;
                }
             }
             else if (inVowelGroup) inVowelGroup = false;
         }

         if (count == 0)
            count++;

         return count;
   }

   /**
         Determine if it is an end of a sentence
         @param e the input character value
         @return true a sentence has ended
   */
   public boolean isSentenceEnd(char e)
   {
      return e == '.' || e == ':' || e == ';'
         || e == '?' || e == '!';
   }
Solutions Manual: Chapter 6           Big Java, by Cay Horstmann       21


      /**
            Determine if a character is a vowel
            @param ch the input character value
            @return true a character is a vowel
      */
      public boolean isVowel(char ch)
      {
         return ch == 'e' || ch == 'a' || ch == 'i'
            || ch == 'o' || ch == 'u' || ch == 'y';
      }

      /**
            Get the number of syllables
            @return syllables number of syllables
      */
      public int getSyllables()
      {
         return syllables;
      }

      /**
            Get the number of words
            @return words the number of words
      */
      public int getWords()
      {
         return words;
      }

      /**
            Get the number of sentences
            @return sentences the number of sentences
      */
      public int getSentences()
      {
         return sentences;
      }

      private int syllables;
      private int words;
      private int sentences;
}

Document.java

/**
   The class provides methods to generate a Flesch Readability Index
*/
public class Document
{
   /**
       Constructs an empty document
   */
   public Document()
   {
Solutions Manual: Chapter 6        Big Java, by Cay Horstmann   22

         index = 0;
         words = 0;
         sentences = 0;
         syllables = 0;
   }

   /**
         Add the total of each of words, syllables,
            and sentences from the Word object
         @param w the Word object containing a current
            count of words, syllables, and sentences
   */
   public void add(Word w)
   {
      words = words + w.getWords();
      syllables = syllables + w.getSyllables();
      sentences = sentences + w.getSentences();
   }

   /**
         Get the Flesch Readability Index value
         @return index the Flesch Readability Index value
   */
   public double getIndex()
   {
      index = 206.835 - 84.6 * syllables / words
         - 1.015 * words / sentences;

         return index;
   }

   /**
         Get the education level of the
            Flesch Readability Index
         @return output of the education level
   */
   public String getEducationLevel()
   {
      String output = "";

         if (index >= 91 && index <= 100)
            output = "5th Grader";
         else if (index >= 81 && index <= 90)
            output = "6th Grader";
         else if (index >= 71 && index <= 80)
            output = "7th Grader";
         else if (index >= 66 && index <= 70)
            output = "8th Grader";
         else if (index >= 61 && index <= 66)
            output = "9th Grader";
         else if (index >= 51 && index <= 60)
            output = "High School Student";
         else if (index >= 31 && index <= 50)
            output = "College Student";
         else if (index >= 0 && index <= 30)
            output = "College Graduate";
         else if (index <= 0)
Solutions Manual: Chapter 6       Big Java, by Cay Horstmann          23

           output = "Law School Graduate";
        else
           output = "Error in index";
        return output;
    }

    private   double index;
    private   int syllables;
    private   int words;
    private   int sentences;
}

article.txt

Curious Creatures to Whom the Ant is La Haute Cuisine

Redford, Kent H.

Smithsonian, August, 1983, ( Vol. 14 ; Pg. 74; ISSN: 0037-7333)

Curious creatures to whom the ant is la haute cuisine. One day recently
I picked up a few termites and ate them, wondering at their widespread
appeal. These particular ones proved to be dry and hard and with a
faintly resinous aftertaste; in fact, I have yet to eat ants or termites
that tasted good raw. My opinion notwithstanding, these insects are the
preferred food of some of the most unusual animals alive today: the
myrmecophagous (ant- and termite-eating) mammals. This group includes
anteaters, armadillos, pangolins, the aardwolf, echidnas, the numbat
and, beloved of crossword-puzzle addicts and amateur poets, the
aardvark. With the exception of armadillos and anteaters, these mammals
are not closely related, sharing only a common passion for ants and
termites. For a long time termites were called "white ants," and so the
descriptive name "anteater" was used to refer to both ant- and termite-
eating mammals. Most myrmecophagous mammals eat both, although some
species appear to restrict themselves to one or the other.

Only 22 mammals can be considered true ant and termite eaters: not many
out of the 4,170 known species. This is particularly striking when one
considers that in some areas ants and termites comprise up to 75 percent
of the total animal biomass. In fact, the number of individual ants and
termites alive at this moment is greater than the number of all humans
who have ever lived. That is a lot of potential food. Where you find a
lot of ants or termites you usually find one of these curious predators.

Each of the world's tropical areas has its own anteaters. In South and
Central America, where I spent two and a half years, anteaters share the
myrmecophagous niche with a variety of armadillos. The anteaters range
from the giant at 100 pounds or so down to the pygmy at about a pound.
Armadillos, which range from Kansas and Missouri to Argentina, are
unique in the mammal world in possessing a hardened shell made of bony
plates and teeth with no enamel.

Africa has the most myrmecophages. The aardvark is a heavy-bodied
digging machine with a penchant for turning somersaults before entering
its burrow. The aardwolf, on the other hand, is a degenerate termite-
eating hyena. Then there are four species of pangolins, which resemble
Solutions Manual: Chapter 6     Big Java, by Cay Horstmann            24

toothless, living pinecones, covered with scales. Another three species
occupy the myrmecophagous niche in Asia. Like aardvarks, pangolins have
no living relatives.

Australia, an island continent where evolution has marched to the beat
of a different drummer, has produced its own versions of anteating
mammals. The echidna, or spiny anteater, is related to the platypus,
while the second Australian myrmecophage, related to the American
opossum, is the marsupial numbat, or banded anteater, a creature of the
eucalyptus forests.

The practice of eating ants and termites differs from eating other
insects in important ways. The key to the difference lies partially in
the existence of different castes of ants and termites specialized for
different tasks. There are two sterile castes: workers for gathering
food and building the nest, and soldiers for defending the colony. As
nonreproductive defenders of the colony, soldier ants and termites
demonstrate a remarkable range of antipredator behaviors. Termites, to a
much grater degree than ants, have a soldier caste highly specialized
for colony defense, a caste that has been called one of "nightmarish
monsters, which recall the most fantastic revelries of hieronymus Bosch,
Bruegel the Elder and Callot." This nightmarish quality arises from the
strange shapes into which soldier-termite heads have been contorted in
developing different forms of colony defense. Many of these forms
involve chemical secretions. This sort of chemical warfare has reached
its apogee in termite soldiers that spray their predators with sticky,
repellent and sometimes toxic compounds from a nozzle-shaped head.

Monstrous soldiers notwithstanding, termites and ants are eaten by
mammals, and eaten in great numbers: an estimated 124,000 termites were
found in one South African aardwolf stomach.

It is hard to pick up this many swarming insects one by one, as I can
attest after spending many weeks trying. Most anteaters would agree;
they gave up long ago. Teeth and the precision they allow have been
traded for tongues: relatively long, mobile tongues and large salivary
glands to keep them moist are trademarks of this group of mammals. A
pangolin tongue is so long that one end is attached to the pelvis. These
long tongues can be manipulated very rapidly; I have estimated a giant
anteater's to flick in and out faster than twice a second. The tongue
can be extended 18 inches and drips with saliva as it sweeps through
termite galleries securing hapless insects.

Those myrmecophages that still have teeth appear to be losing them. Most
of the grinding action of the teeth has been taken over by heavily
muscularized portions of the stomach, or, in the case of the echidna, by
pseudoteeth located on the tongue. Teeth may also have been lost or
become nonfunctional because so much earth is taken in by the sticky
tongue as it picks up ants and termites. As much as 47 percent of the
contents of aardvark stomachs has been reported as sand, an observation
common to all ant and termite eaters. If this abrasive material were
ground between chewing teeth, it would rapidly wear down the enamel.

Most of the myrmecophagous mammals are diggers; virtually all the
terrestrial forms live in holes excavated by themselves or other
animals. The giant armadillo, giant pangolin and aardvark are immensely
powerful diggers. The burrow system of the aardvark appears to be the
Solutions Manual: Chapter 6     Big Java, by Cay Horstmann            25

most extensive of any of these animals. A gruesome story is told of
three Africans who went down an aardvark burrow and disappeared. Their
friends started digging for them, but gave up after having excavated a
labyrinth 18 feet below ground. The echidna and naked-tailed armadillo,
though smaller, are powerful diggers; I have seen a two-pound armadillo
completely bury itself in hard ground in less than 30 seconds. These
strong diggers all seem to obtain the majority of their ant and termite
prey from colonies they excavate, often feeding for long periods of time
in the excavated colony.

Claws rip open ant hills--and attackers The myrmecophages with the
greatest ability to dig are appropriately equipped with strong forelegs
and claws capable of moving a lot of dirt. The giant anteater, which has
extremely powerful forelegs, is equipped with several long, narrow,
sharp claws, one much longer than the rest. Giant anteaters walk on the
sides and knuckles of their hands with the claws carried back, thus
protecting them from wear. The powerful forelegs and long claws are used
for defense as well. Slow-moving anteaters, when threatened, will sit
back on their hind feet, balancing with their bushy tails, and strike
out with their front feet. Any animal unwary enough to be caught in
their grasp will be clutched to the body and torn apart. Reports exist
of the disemboweling of dogs, jaguars and even people; I have seen the
scars left on the arm of a man who, in a drunken state, had accepted a
dare to wrestle with a giant anteater.

The claws and powerful forefeet are not just for defense, however. In my
research, I frequently saw anteaters use their claws to rip open ant
hills and termite mounds. Unlike giant armadillos, giant anteaters
usually did not excavate a colony but rather used their powerful
forelimbs and sharp claws to tear narrow deep gashes into the sides of
termite mounds. Observations on captive animals showed that all but two
of the claws can be held back, which allows the longest one to be used
with great precision and with great force immediately adjacent to the
nose of the feeding anteater. The quarter-inch-thick aluminum trays on
which I served termites were frequently gashed through with one motion
of this claw.

Most of the other myrmecophagous mammals find their food without
digging. They seek out groups of social insects that are away from their
nests, scraping away covered termite-foraging areas or turning over
termite-infested branches. Any foraging ants and termites found
unprotected above ground are eaten. Some pangolins are reported to pick
up termite-inhabited cow patties an turn over on their backs before
commencing to feed. Holding the cow patty in its claws, the pangolin
breaks it open and consumes the termites as they fall onto its belly.

Myrmecophages, like herbivores, tend to graze, feeding for only a short
time in each place. Almost half of the times I saw giant anteaters
feeding, they fed for less than ten seconds. Several factors seem to
affect a myrmecophage's decision to leave a given feeding spot. First,
there may be nothing left on which to feed, since the defense of many
ant and termite species is simply to flee. Second, the available food
may all have been eaten, as in the case of small foraging parties of
termites. Third, and most interesting, are the occasions on which ants
and termites are still abundant when the anteater stops feeding and
leaves. Some researchers have suggested that this may be an adaptation
on the part of the predator, a way of harvesting instead of destroying
Solutions Manual: Chapter 6     Big Java, by Cay Horstmann            26

social-insect colonies; they consider it a form of what has been called
"prudent predation." Others have shown, however, that the short feeding
bouts that characterize many myrmecophages are probably not the result
of a prudent decision made by the predator, but are forced on it by its
prey. Not all ants and termites take predation lying down.

From my observations on giant anteaters and the observation of others on
tamandua anteaters and aardwolves, it appears that those insects that
fight back, especially termites, exhibit a coordinated defense connected
with the use of a form of chemical repellent. Worker termites are
defenseless and are usually preferred by anteaters over the soldiers
that protect them. So when the anteater starts feeding on workers, the
few soldiers present discharge their load of chemicals, attracting other
soldiers. The reinforcements swarm to the site of the attack and in turn
discharge their chemicals. In a very short while the concentration of
chemicals, different ones smelling to us like blue cheese, lemon-scented
furniture polish or pine woods, is sufficiently high to drive the
anteater away, leaving a spot covered with very upset soldiers. Termite
soldiers using chemical defenses appear to be effective in limiting, if
not preventing, predation by many kinds of mammals.

Ants and termites can reach staggering abundance in some areas, and so
it is not surprising that even with their array of defensive strategies
they are a major food source. Many mammals that do not depend on ants
and termites to survive still eat them frequently. Such species can be
termed "amateur myrmecophages."

Among the amateurs are the sloth bear, the bateared fox (above), some
mongooses and some mice, which are more semipro than amateur. Termites
and ants comprise about half of the total diet of sloth bears and bat-
eared foxes, while half of the black-legged mongoose's diet seems to be
composed of the unlikely food of driver ants--the Old World's army ants.

Most of the rest of the amateur ant and termite eaters, however,
probably eat significant numbers of social insects only because they are
there. These animals, including some jackals, some armadillos, some
monkeys, some squirrels and some elephant shrews, feed in a manner and
in a location which causes them to encounter many ants and termites.
And, not being overly fussy, they eat what is available.

At one point of their life cycle, ants and termites become irresistible
to an even broader range of animals. Usually following the first rains,
ant and termite colonies pour forth alates, winged males and females
which mostly end up as food. These alates appear by the hundreds of
thousands and flutter weakly about seeking mates and appropriate places
to found new colonies. Alates are very appetizing because they have a
lot of stored fat and less chitinous armor. They make particularly easy
prey because they themselves are virtually defenseless and are away from
whatever protection their soldier caste might have provided.

Many mammals feed on these alates, and it is quite likely that the
energetically expensive business of reproduction in some mammals is tied
to the appearance of these winged reproductives. Such a correlation has
already been suggested for birds. Foxes and hyenas have been seen
standing outside termite exit holes, snapping up alates just as they
emerge on their perilous journey. Some African monkeys, who have
apparently learned that alates of a certain species of termite
Solutions Manual: Chapter 6        Big Java, by Cay Horstmann         27

congregate near the tops of trees, climb these trees and grab the flying
reproductives out of the air.

Chimpanzees can also be found swaying in the tree-tops during swarms,
but search out and eat many kinds of ants and termites. They fish for
termites by sticking twigs or blades of grass down holes in a termite
mound. The tool is then withdrawn, with up to a dozen termite soldiers
biting into it. These are bitten directly off, like toasted
marshmallows, or picked off with the fingers. Five chimpanzees sitting
around a driver ant nest with their tools create a scene reminiscent of
guests, forks in hand, around a fondue pot.

Chimpanzees are not the only myrmecophagous higher primates, for humans
consume large quantities of both ants and termites. Human beings are
particularly fond of alate ants and termites; especially in Africa they
will go to great lengths to secure them. All sorts of devices and
stratagems have been designed to collect alates; one is to water the
termite mound before the first rains, thereby tricking the alates into
leaving the mound prematurely. Humans have also developed the technique
of "fishing" for termites. One person can collect a basketful of
soldiers which, dried, can be seen for sale in some African markets. One
wonders who learned how to fish from whom.

The female alates of the big South American leafcutting ants are also a
delicacy; in some areas they may even be a seasonally significant source
of nutrition. In 1953, A. R. Wallace commented on his disquietude at
observing that in one Indian tribe of the Amazon, breakfast began by
opening a stoppered calabash and allowing a few live ant alates
collected the day before to crawl out. The alates were then consumed raw
with handfuls of manioc flour.

Humans are not built to be myrmecophages, of course; we do not have long
snouts or 18-inch tongues. But then neither do mice, mongooses, bat-
eared foxes or sloth bears. The individual shown opposite, which happily
eats ants when it finds them, could never be mistaken for an anteater.
Yet where culture encourages it, ants and termites are an important
source of protein in the human diet. In the end, it all comes down to a
question of taste. Henry Smeathman, in 1781, expressed surprise that the
European palate would enjoy the taste of the alates of African
Macrotermes, saying, "I have discoursed with several gentlemen upon the
taste of the white ants termites ; and on comparing notes we have always
agreed that they are most delicious and delicate eating. One gentleman
compared them to sugared marrow, another to sugared cream, and a paste
of sweet almonds." While I have never tasted sugared marrow, I can add
my comment that, unlike raw workers or soldiers, fried, salted alates
are probably the best cocktail snacks I have ever tried. But then I'm
not a true myrmecophage.

ExP6_9.java

import    java.io.BufferedReader;
import    java.io.InputStreamReader;
import    java.io.IOException;
import    java.util.StringTokenizer;

/**
      Test class for Word class
Solutions Manual: Chapter 6           Big Java, by Cay Horstmann            28

*/
public class ExP6_9
{
   public static void main(String[] args)
      throws IOException
   {
      BufferedReader console = new BufferedReader(
         new InputStreamReader(System.in));
      Word w = new Word();
      Document d = new Document();
      boolean done = false;

            while (!done)
            {
               String input = console.readLine();
               if (input == null)
                  done = true;
               else
               {
                  StringTokenizer tokenizer = new StringTokenizer(input);
                  while (tokenizer.hasMoreTokens())
                     w.addWord(tokenizer.nextToken());
                     d.add(w);
               }
            }

            double index = d.getIndex();
            String level = d.getEducationLevel();

            System.out.println("The legibility index is " + index);
            System.out.println("The education level is " + level);

            System.exit(0);
      }
}

P6.10
FactorGenerator.java

/**
   This class prints out all the factors of an input value.
*/
public class FactorGenerator
{
   /**
       Creates a FactorGenerator object used to determine the
          factor of an input value
       @param aNum is the input value
   */
   public FactorGenerator(int aNum)
   {
       num = aNum;
       factor = 2;
   }

      /**
Solutions Manual: Chapter 6           Big Java, by Cay Horstmann         29

            Determine whether or not
               there are more factors
            @return true there are more factors
      */
      public boolean hasMoreFactors()
      {
         while (factor <= num && num % factor != 0)
            factor++;
         return factor <= num;
      }

      /**
            Calculate the next factor of a value
            @return factor the next factor
      */
      public int nextFactor()
      {
         if(!hasMoreFactors())
            return 0;
         num = num / factor;
         return factor;
      }

      int num;
      int i;
      int factor;
}

ExP6_10.java

import javax.swing.JOptionPane;

/**
   Test driver class for FactorGenerator class
*/
public class ExP6_10
{
   public static void main (String[] args)
   {
      String input = JOptionPane.showInputDialog(
         "Enter an integer:");
      int num = Integer.parseInt(input);

            FactorGenerator myFacGenerator = new FactorGenerator(num);

            while (myFacGenerator.hasMoreFactors())
               System.out.println(myFacGenerator.nextFactor());

            System.exit(0);
      }
}

P6.11
PrimeGenerator.java

/**
Solutions Manual: Chapter 6           Big Java, by Cay Horstmann   30

   This class prints out all the prime numbers of an input value
*/
public class PrimeGenerator
{
   public PrimeGenerator()
   {
      current = 1;
   }

      /**
            Calculate the next prime number of an input
            @return the next prime number
      */
      public int nextPrime()
      {
         do
         {
            current++;
         } while (!isPrime());

            return current;
      }

      public boolean isPrime()
      {
         if (current <= 1)
            return false;
         if (current > 2 && current % 2 == 0)
            return false;

            for (int i = 3; i * i <= current; i = i + 2)
               if (current % i == 0)
                  return false;

            return true;
      }

      private int current;
}

Exp6_11.java

import javax.swing.JOptionPane;

/**
   Test driver class for PrimeGenerator class
*/
public class ExP6_11
{
   public static void main (String[] args)
   {
      String input = JOptionPane.showInputDialog(
         "Enter upper limit:");
      int limit = Integer.parseInt(input);

            PrimeGenerator pg = new PrimeGenerator();
Solutions Manual: Chapter 6           Big Java, by Cay Horstmann   31

            while (true)
            {
               int prime = pg.nextPrime();
               if (prime > limit) System.exit(0);
               System.out.println(prime);
            }
      }
}

P6.12
RootApproximator.java

/**
   This class approximates the square root of a number
*/
public class RootApproximator
{
   /**
       Creates a RootApproximator object used to
          approximate the root answer of a number
       @param aNum is the input value
   */
   public RootApproximator(double aNum)
   {
       num = aNum;
       xold = 1;
       xnew = num;
   }

      /**
            Method used to calculate the next root number
            @return the next guess number
      */
      public double nextGuess()
      {
         xold = xnew;
         if(xold != 0)
            xnew = (xold + (num / xold)) / 2;
         return xnew;
      }

      /**
            Determine if there are more guesses
            @return true we are close enough to the answer
      */
      public boolean hasMoreGuesses()
      {
         final double EPS = 0.000001;

            return (Math.abs(xnew - xold) > EPS);
      }

      private double num;
      private double xold;
      private double xnew;
}
Solutions Manual: Chapter 6           Big Java, by Cay Horstmann           32


ExP6_12.java

import javax.swing.JOptionPane;

/**
   This is a test class for RootApproximator class
*/
public class ExP6_12
{
   public static void main(String[] args)
   {
      String input = JOptionPane.showInputDialog(
         "Enter an integer that you want a square root of:");
      double n = Double.parseDouble(input);

            RootApproximator r = new RootApproximator(n);

            while (r.hasMoreGuesses())
               System.out.println(r.nextGuess());

            System.exit(0);
      }
}

P6.13
RootApproximator.java

/**
      This class implements the Newton-Raphson method to approximate the
         root of an input value
*/
public class RootApproximator
{
   /**
       Creates a RootApproximator object used to
          approximate the root answer of a number
       @param anA the input value
       @param aN the root number extracted
   */
   public RootApproximator(double anA, int aN)
   {
       a = anA;
       n = aN;
       xold = 1;
       xnew = a;
   }

      /**
            Method used to calculate the next root number
            @return the next guess number
      */
      public double nextGuess()
      {
         xold = xnew;
         xnew = xold * (1 - 1.0 / n) + a / (n * Math.pow(xold, n - 1));
Solutions Manual: Chapter 6           Big Java, by Cay Horstmann   33

            return xnew;
      }

      /**
            Determine if there are more guesses
            @return true we are close enough to the answer
      */
      public boolean hasMoreGuesses()
      {
         final double EPS = 0.000001;

            return (Math.abs(xnew - xold) > EPS);
      }

      private    double a;
      private    int n;
      private    double xold;
      private    double xnew;
}

ExP6_13.java

import javax.swing.JOptionPane;

/**
   Test class for RootApproximator class
*/
public class ExP6_13
{
   public static void main(String[] args)
   {
      String input = JOptionPane.showInputDialog(
         "Please enter a number:");
      double a = Double.parseDouble(input);

            input = JOptionPane.showInputDialog(
               "Extract which root?");
            int n = Integer.parseInt(input);

            RootApproximator r = new RootApproximator(a, n);

            while (r.hasMoreGuesses())
               System.out.println(r.nextGuess());

            System.exit(0);
      }
}

P6.14
ExPApproximator.java

/**
   This class calculates e^x as a power series
*/
public class ExpApproximator
{
Solutions Manual: Chapter 6           Big Java, by Cay Horstmann   34

      /**
            Creates a ExpApproximator object to calculate e^x
            @param anX is the input value
      */
      public ExpApproximator(double anX)
      {
         x = anX;
         summand = 1;
         i = 1;
         total = 1;
      }

      /**
            Method used to calculate the next e number
            @return the next e number
      */
      public double nextGuess()
      {
         summand = summand * x / i;
         i++;
         total = total + summand;
         return total;
      }

      /**
            Determine if there are more numbers from the input
            @return true input value has more numbers
      */
      public boolean hasNextGuess()
      {
         final double EPS = 0.000001;

            return summand > EPS;
      }

      private    double x;
      private    double summand;
      private    int i;
      private    double total;
}

ExP6_14.java

import javax.swing.JOptionPane;

/**
   Test class driver for ExpApproximator class
*/
public class ExP6_14
{
   public static void main(String[] args)
   {
      String input = JOptionPane.showInputDialog(
         "x:");
      double x = Double.parseDouble(input);
Solutions Manual: Chapter 6             Big Java, by Cay Horstmann       35

            ExpApproximator exp = new ExpApproximator(x);

            while(exp.hasNextGuess())
               System.out.println("e ^ x = " + exp.nextGuess());

            System.exit(0);
      }
}

P6.15
CheckerBoard.java

import java.awt.Graphics2D;
import java.awt.Rectangle;

/**
      This class displays a checkerboard with 64 squares,
         alternating between white and black.
*/
public class CheckerBoard
{
   /**
       Creates a CheckerBoard object with 64 squares
       @param aNumSquares the number of squares on the board
       @param aSize the size of the board
   */
   public CheckerBoard(int aNumSquares, int aSize)
   {
       numSquares = aNumSquares;
       size = aSize;
   }

      /**
            Method used to draw the checkerboard
            @param g2 the graphics content
      */
      public void draw(Graphics2D g2)
      {
         for (int i = 0; i < numSquares; i++)
         {
            for (int j = 0; j < numSquares; j++)
            {
               int inj = (i + j) % 2;

                    if (inj == 0)
                    {
                       Rectangle r = new Rectangle(i * size, j * size,
                          size, size);
                       g2.fill(r);
                    }
                }
            }
      }

      int numSquares;
      int size;
Solutions Manual: Chapter 6           Big Java, by Cay Horstmann       36

}

ExP6_15.java

import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Graphics2D;

/**
   Test driver for CheckerBoard class
*/
public class ExP6_15 extends Applet
{
   public void paint(Graphics g)
   {
      Graphics2D g2 = (Graphics2D)g;

            final int NSQUARES = 8;

            int size = Math.min(getWidth(), getHeight()) / NSQUARES;

            CheckerBoard cb = new CheckerBoard(NSQUARES, size);

            cb.draw(g2);
      }
}

P6.16
GameOfNim.java

import java.util.Random;

/**
   This class provides methods to play the Game Of Nim
*/
public class GameOfNim
{
   /**
       Construct a GameOfNim object
   */
   public GameOfNim()
   {
       generator = new Random();
   }

      /**
         Start the game by generating a stack size
      */
      public void start()
      {
         size = 10 + generator.nextInt(91);
      }

      /**
            Get the number of marbles in the stack
            @return size the number of marbles in stack
Solutions Manual: Chapter 6           Big Java, by Cay Horstmann   37

      */
      public int getMarbles()
      {
         return size;
      }

      /**
            Determine if the user took more marbles
               than allowed
            @return true the user took more than half
               the marbles
      */
      public boolean take(int n)
      {
         return (n > getMarbles() / 2);
      }

      private    Random generator;
      private    int size;
      private    int turn;
      private    int mode;
}

ComputerPlayer.java

import java.util.Random;

/**
      This class provides methods for the computer
         to play the Game Of Nim
*/
public class ComputerPlayer
{
   /**
       Construct a ComputerPlayer object
   */
   public ComputerPlayer()
   {
       generator = new Random();
   }

      /**
            Set the mode of the computer to smart
               or stupid
            @param b the mode of the computer
      */
      public void setSmartMode(boolean b)
      {
         stupid = true;

            if (b != stupid)
               stupid = false;
      }

      /**
            Get the number of marbles the computer takes
               either in smart or stupid mode
Solutions Manual: Chapter 6         Big Java, by Cay Horstmann         38

          @param marbleOnPile the size of the stack
          @return compTake the number of marbles the
             computer takes
      */
      public int computeMarblesToTake(int marblesOnPile)
      {
         int compTake;

          if (stupid)
             compTake = 1 + generator.nextInt(marblesOnPile / 2);
          else // smart
          {
             if (marblesOnPile > 3 && marblesOnPile < 7)
                compTake = marblesOnPile - 3;
             else if (marblesOnPile > 7 && marblesOnPile < 15)
                compTake = marblesOnPile - 7;
             else if (marblesOnPile > 15 && marblesOnPile < 31)
                compTake = marblesOnPile - 15;
             else if (marblesOnPile > 31 && marblesOnPile < 63)
                compTake = marblesOnPile - 31;
             else if (marblesOnPile > 63)
                compTake = marblesOnPile - 63;
             else
                compTake = 1 + generator.nextInt(marblesOnPile / 2);
          }

          return compTake;
      }

      private boolean stupid;
      private Random generator;
}

ExP6_16.java

import java.util.Random;
import javax.swing.JOptionPane;

/**
      This is a test class for GameOfNim and ComputerPlayer
         to play the Game Of Nim
*/
public class ExP6_16
{
   public static void main(String[] args)
   {
      GameOfNim g = new GameOfNim();
      ComputerPlayer cp = new ComputerPlayer();
      g.start();

          int size = g.getMarbles();
          System.out.println("Initial stack size: " + size);

          Random generator = new Random();

          int turn = generator.nextInt(2);
Solutions Manual: Chapter 6           Big Java, by Cay Horstmann            39

          int mode = generator.nextInt(2);

          while(size > 1)
          {
             if (turn == 0) // computer turn
             {
                boolean stupid = true;

                  if (mode == 0) // stupid
                     cp.setSmartMode(stupid);
                  else
                     cp.setSmartMode(!stupid);

                  int compTake = cp.computeMarblesToTake(size);

                  size = size - compTake;
                  System.out.println("Computer takes off " + compTake + "
marbles");
                  System.out.println("Current stack size is " + size);
              }

              else //player's turn
              {
                 String input = JOptionPane.showInputDialog(
                    "Please enter no. of marbles to be taken:");
                 int userTake = Integer.parseInt(input);

                  if (g.take(userTake))
                  {
                     System.out.println("Cheating! You lose");
                     return;
                  }

                  size = size - userTake;
                  System.out.println("Current stack size is " + size);
              }

              turn = 1 - turn;
          }

          if (turn == 1)
             System.out.println("The computer wins!");
          else
             System.out.println("You win!");

          System.exit(0);
      }
}

P6.17
Dart.java

import java.util.Random;

/**
      This class implements the throwing of a dart to approximate pi
Solutions Manual: Chapter 6           Big Java, by Cay Horstmann   40

*/
public class Dart
{
   /**
       Creates a Dart object for game play
   */
   public Dart()
   {
       generator = new Random();
       hits = 0;
       tries = 0;
   }

      /**
         Method used to generate the plays of the dart
      */
      public void throwDart()
      {
         double x = -1 + 2 * generator.nextDouble();
         double y = -1 + 2 * generator.nextDouble();
         double xySquare = x * x + y * y;

            if (xySquare <= 1)
               hits++;

            tries++;
      }

      /**
            Get the number of hits inside
               a dart board
            @return hits number of hits
      */
      public int getHits()
      {
         return hits;
      }

      /**
            Get the number of tries
            @return tries number of tries
      */
      public int getTries()
      {
         return tries;
      }

      private Random generator;
      private int hits;
      private int tries;

}

ExP6_17.java

/**
Solutions Manual: Chapter 6       Big Java, by Cay Horstmann          41

   Test class driver for Dart class
*/
public class ExP6_17
{
   public static void main (String[] args)
   {
      Dart myDart = new Dart();
      final int TRIES1 = 10000;
      final int TRIES2 = 100000;
      final double AREA_OF_SQUARE = 4.0;

        for (int i = 1; i <= TRIES1; i++)
           myDart.throwDart();
        System.out.println("Tries / Hits = "
           + ((double)myDart.getHits() * AREA_OF_SQUARE)
           / myDart.getTries());

        for (int i = TRIES1 + 1; i <= TRIES2; i++)
           myDart.throwDart();
        System.out.println("Tries / Hits = "
           + ((double)myDart.getHits() * AREA_OF_SQUARE)
           / myDart.getTries());

        System.exit(0);
    }
}

P6.18
CubicCurve.java

import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;

public class CubicCurve
{
   public CubicCurve(double anA, double aB, double aC, double aD)
   {
      a = anA;
      b = aB;
      c = aC;
      d = aD;
   }

    public void draw(Graphics2D g2, double xmin, double xmax)
    {
       final double SEGMENTS = 100;
       double d = (xmax - xmin) / SEGMENTS;
       Point2D.Double last = new Point2D.Double(xmin, value(xmin));
       double x = xmin;
       for (int i = 1; i <= SEGMENTS; i++)
       {
          x = x + d;
          Point2D.Double next = new Point2D.Double(x, value(x));
          g2.draw(new Line2D.Double(last, next));
          last = next;
Solutions Manual: Chapter 6                     Big Java, by Cay Horstmann   42

          }
      }

      public double value(double x)
      {
         return a * x * x * x + b * x * x + c * x + d;
      }

      private     double   a;
      private     double   b;
      private     double   c;
      private     double   d;
}

ExP6_18.java

import        java.applet.Applet;
import        java.awt.Graphics;
import        java.awt.Graphics2D;
import        java.awt.BasicStroke;

/**
   Test driver class used for Curve class
*/
public class ExP6_18 extends Applet
{
   public void paint(Graphics g)
   {
      Graphics2D g2 = (Graphics2D)g;

          double xscale = (getWidth() - 1.0) / (XMAX - XMIN);
          double yscale = (getHeight() - 1.0) / (YMIN - YMAX);
          g2.scale(xscale, yscale);
          g2.translate(-XMIN, -YMAX);
          g2.setStroke(new BasicStroke(0));

          double width = getWidth();
          double height = getHeight();

          CubicCurve myCurve = new CubicCurve(A, B, C, D);

          myCurve.draw(g2, XMIN, XMAX);
      }

      private     static   final   double   XMIN      =   -10;
      private     static   final   double   XMAX      =   10;
      private     static   final   double   YMIN      =   -10;
      private     static   final   double   YMAX      =   30;

      private     static   final   double   A    =   0.01;
      private     static   final   double   B    =   0;
      private     static   final   double   C    =   1;
      private     static   final   double   D    =   10;
}

P6.19
Solutions Manual: Chapter 6              Big Java, by Cay Horstmann   43

Rose.java

import java.awt.Graphics2D;
import java.awt.geom.Line2D;

/**
   This class is used to draw a "four-leaved rose"
*/
public class Rose
{
   /**
       Creates a Rose object to draw the "four-leaved rose"
       @param aWidth the width of the rose
       @param aHeight the height of the rose
   */
   public Rose(double aWidth, double aHeight)
   {
       width = aWidth;
       height = aHeight;
   }

      /**
            Method used to draw the "four-leaved rose"
            @param g2 the graphics content
      */
      public void draw(Graphics2D g2)
      {
         final double XMIN = -1;
         final double XMAX = 1;
         final double YMIN = -1;
         final double YMAX = 1;

            final    double ANGLE_MIN = 0;
            final    double ANGLE_MAX = 2 * Math.PI;
            final    int STEPS = 100;
            final    int NPETALS = 4;

            double theta = ANGLE_MIN;
            double r = f(theta, NPETALS);
            double d = ANGLE_MAX / STEPS;

            double    x = r * Math.cos(theta);
            double    y = r * Math.sin(theta);
            double    x1 = width * (x - XMIN) / (XMAX - XMIN);
            double    y1 = height * (YMAX - y) / (YMAX - YMIN);

            for (theta = d; theta <= ANGLE_MAX; theta = theta + d)
            {
               r = f(theta, NPETALS);

               x = r * Math.cos(theta);
               y = r * Math.sin(theta);
               double x2 = width * (x - XMIN) / (XMAX - XMIN);
               double y2 = height * (YMAX - y) / (YMAX - YMIN);

               Line2D.Double l = new Line2D.Double(x1, y1, x2, y2);
               g2.draw(l);
Solutions Manual: Chapter 6              Big Java, by Cay Horstmann   44

                 x1 = x2;
                 y1 = y2;
            }
      }

      /**
            Method used to calculate the curve of the petal
            @param theta the angle of the petal
            @param n the number of petals
      */
      public double f(double theta, int n)
      {
         if (n % 2 == 0)
            return Math.cos((n / 2) * theta);
         else
            return Math.cos(n * theta);
      }

      private double width;
      private double height;
}

ExP6_19.java

import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Graphics2D;

/**
   Test class driver for Rose class
*/
public class ExP6_19 extends Applet
{
   public void paint(Graphics g)
   {
      Graphics2D g2 = (Graphics2D)g;

            double width = getWidth();
            double height = getHeight();

            Rose myRose = new Rose(width, height);
            myRose.draw(g2);
      }
}

P6.20
Split.java

import          java.io.BufferedReader;
import          java.io.InputStreamReader;
import          java.io.IOException;
import          java.util.StringTokenizer;

/**
      This program splits the lines read from System.in into
         individual words.
Solutions Manual: Chapter 6           Big Java, by Cay Horstmann   45

*/
public class Split
{
   public static void main(String[] args)
      throws IOException
   {
      BufferedReader console = new BufferedReader(
         new InputStreamReader(System.in));
      boolean done = false;
      while (!done)
      {
         String inputLine = console.readLine();
         if (inputLine == null)
            done = true;
         else
         {
            // break input line into words

                  StringTokenizer tokenizer =
                     new StringTokenizer(inputLine);
                  while (tokenizer.hasMoreTokens())
                  {
                     // print each word
                     String word = tokenizer.nextToken();
                     System.out.println(word);
                  }
              }
          }
      }
}

Unique.java

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

/**
      This program removes adjacent duplicate lines from
         the input read from System.in.
*/
public class Unique
{
   public static void main(String[] args)
      throws IOException
   {
      BufferedReader console = new BufferedReader(
         new InputStreamReader(System.in));

          String lastLine = "";

          boolean done = false;

          while(!done)
          {
             String inputLine = console.readLine();
Solutions Manual: Chapter 6        Big Java, by Cay Horstmann         46

            if (inputLine == null)
               done = true;
            else if (!inputLine.equals(lastLine))
            {
               // it's a different line from its predecessor
               System.out.println(inputLine);
               lastLine = inputLine;
            }
        }
    }
}

article.txt

Curious Creatures to Whom the Ant is La Haute Cuisine

Redford, Kent H.

Smithsonian, August, 1983, ( Vol. 14 ; Pg. 74; ISSN: 0037-7333)

Curious creatures to whom the ant is la haute cuisine. One day recently
I picked up a few termites and ate them, wondering at their widespread
appeal. These particular ones proved to be dry and hard and with a
faintly resinous aftertaste; in fact, I have yet to eat ants or termites
that tasted good raw. My opinion notwithstanding, these insects are the
preferred food of some of the most unusual animals alive today: the
myrmecophagous (ant- and termite-eating) mammals. This group includes
anteaters, armadillos, pangolins, the aardwolf, echidnas, the numbat
and, beloved of crossword-puzzle addicts and amateur poets, the
aardvark. With the exception of armadillos and anteaters, these mammals
are not closely related, sharing only a common passion for ants and
termites. For a long time termites were called "white ants," and so the
descriptive name "anteater" was used to refer to both ant- and termite-
eating mammals. Most myrmecophagous mammals eat both, although some
species appear to restrict themselves to one or the other.

Only 22 mammals can be considered true ant and termite eaters: not many
out of the 4,170 known species. This is particularly striking when one
considers that in some areas ants and termites comprise up to 75 percent
of the total animal biomass. In fact, the number of individual ants and
termites alive at this moment is greater than the number of all humans
who have ever lived. That is a lot of potential food. Where you find a
lot of ants or termites you usually find one of these curious predators.

Each of the world's tropical areas has its own anteaters. In South and
Central America, where I spent two and a half years, anteaters share the
myrmecophagous niche with a variety of armadillos. The anteaters range
from the giant at 100 pounds or so down to the pygmy at about a pound.
Armadillos, which range from Kansas and Missouri to Argentina, are
unique in the mammal world in possessing a hardened shell made of bony
plates and teeth with no enamel.

Africa has the most myrmecophages. The aardvark is a heavy-bodied
digging machine with a penchant for turning somersaults before entering
its burrow. The aardwolf, on the other hand, is a degenerate termite-
eating hyena. Then there are four species of pangolins, which resemble
Solutions Manual: Chapter 6     Big Java, by Cay Horstmann            47

toothless, living pinecones, covered with scales. Another three species
occupy the myrmecophagous niche in Asia. Like aardvarks, pangolins have
no living relatives.

Australia, an island continent where evolution has marched to the beat
of a different drummer, has produced its own versions of anteating
mammals. The echidna, or spiny anteater, is related to the platypus,
while the second Australian myrmecophage, related to the American
opossum, is the marsupial numbat, or banded anteater, a creature of the
eucalyptus forests.

The practice of eating ants and termites differs from eating other
insects in important ways. The key to the difference lies partially in
the existence of different castes of ants and termites specialized for
different tasks. There are two sterile castes: workers for gathering
food and building the nest, and soldiers for defending the colony. As
nonreproductive defenders of the colony, soldier ants and termites
demonstrate a remarkable range of antipredator behaviors. Termites, to a
much grater degree than ants, have a soldier caste highly specialized
for colony defense, a caste that has been called one of "nightmarish
monsters, which recall the most fantastic revelries of hieronymus Bosch,
Bruegel the Elder and Callot." This nightmarish quality arises from the
strange shapes into which soldier-termite heads have been contorted in
developing different forms of colony defense. Many of these forms
involve chemical secretions. This sort of chemical warfare has reached
its apogee in termite soldiers that spray their predators with sticky,
repellent and sometimes toxic compounds from a nozzle-shaped head.

Monstrous soldiers notwithstanding, termites and ants are eaten by
mammals, and eaten in great numbers: an estimated 124,000 termites were
found in one South African aardwolf stomach.

It is hard to pick up this many swarming insects one by one, as I can
attest after spending many weeks trying. Most anteaters would agree;
they gave up long ago. Teeth and the precision they allow have been
traded for tongues: relatively long, mobile tongues and large salivary
glands to keep them moist are trademarks of this group of mammals. A
pangolin tongue is so long that one end is attached to the pelvis. These
long tongues can be manipulated very rapidly; I have estimated a giant
anteater's to flick in and out faster than twice a second. The tongue
can be extended 18 inches and drips with saliva as it sweeps through
termite galleries securing hapless insects.

Those myrmecophages that still have teeth appear to be losing them. Most
of the grinding action of the teeth has been taken over by heavily
muscularized portions of the stomach, or, in the case of the echidna, by
pseudoteeth located on the tongue. Teeth may also have been lost or
become nonfunctional because so much earth is taken in by the sticky
tongue as it picks up ants and termites. As much as 47 percent of the
contents of aardvark stomachs has been reported as sand, an observation
common to all ant and termite eaters. If this abrasive material were
ground between chewing teeth, it would rapidly wear down the enamel.

Most of the myrmecophagous mammals are diggers; virtually all the
terrestrial forms live in holes excavated by themselves or other
animals. The giant armadillo, giant pangolin and aardvark are immensely
powerful diggers. The burrow system of the aardvark appears to be the
Solutions Manual: Chapter 6     Big Java, by Cay Horstmann            48

most extensive of any of these animals. A gruesome story is told of
three Africans who went down an aardvark burrow and disappeared. Their
friends started digging for them, but gave up after having excavated a
labyrinth 18 feet below ground. The echidna and naked-tailed armadillo,
though smaller, are powerful diggers; I have seen a two-pound armadillo
completely bury itself in hard ground in less than 30 seconds. These
strong diggers all seem to obtain the majority of their ant and termite
prey from colonies they excavate, often feeding for long periods of time
in the excavated colony.

Claws rip open ant hills--and attackers The myrmecophages with the
greatest ability to dig are appropriately equipped with strong forelegs
and claws capable of moving a lot of dirt. The giant anteater, which has
extremely powerful forelegs, is equipped with several long, narrow,
sharp claws, one much longer than the rest. Giant anteaters walk on the
sides and knuckles of their hands with the claws carried back, thus
protecting them from wear. The powerful forelegs and long claws are used
for defense as well. Slow-moving anteaters, when threatened, will sit
back on their hind feet, balancing with their bushy tails, and strike
out with their front feet. Any animal unwary enough to be caught in
their grasp will be clutched to the body and torn apart. Reports exist
of the disemboweling of dogs, jaguars and even people; I have seen the
scars left on the arm of a man who, in a drunken state, had accepted a
dare to wrestle with a giant anteater.

The claws and powerful forefeet are not just for defense, however. In my
research, I frequently saw anteaters use their claws to rip open ant
hills and termite mounds. Unlike giant armadillos, giant anteaters
usually did not excavate a colony but rather used their powerful
forelimbs and sharp claws to tear narrow deep gashes into the sides of
termite mounds. Observations on captive animals showed that all but two
of the claws can be held back, which allows the longest one to be used
with great precision and with great force immediately adjacent to the
nose of the feeding anteater. The quarter-inch-thick aluminum trays on
which I served termites were frequently gashed through with one motion
of this claw.

Most of the other myrmecophagous mammals find their food without
digging. They seek out groups of social insects that are away from their
nests, scraping away covered termite-foraging areas or turning over
termite-infested branches. Any foraging ants and termites found
unprotected above ground are eaten. Some pangolins are reported to pick
up termite-inhabited cow patties an turn over on their backs before
commencing to feed. Holding the cow patty in its claws, the pangolin
breaks it open and consumes the termites as they fall onto its belly.

Myrmecophages, like herbivores, tend to graze, feeding for only a short
time in each place. Almost half of the times I saw giant anteaters
feeding, they fed for less than ten seconds. Several factors seem to
affect a myrmecophage's decision to leave a given feeding spot. First,
there may be nothing left on which to feed, since the defense of many
ant and termite species is simply to flee. Second, the available food
may all have been eaten, as in the case of small foraging parties of
termites. Third, and most interesting, are the occasions on which ants
and termites are still abundant when the anteater stops feeding and
leaves. Some researchers have suggested that this may be an adaptation
on the part of the predator, a way of harvesting instead of destroying
Solutions Manual: Chapter 6     Big Java, by Cay Horstmann            49

social-insect colonies; they consider it a form of what has been called
"prudent predation." Others have shown, however, that the short feeding
bouts that characterize many myrmecophages are probably not the result
of a prudent decision made by the predator, but are forced on it by its
prey. Not all ants and termites take predation lying down.

From my observations on giant anteaters and the observation of others on
tamandua anteaters and aardwolves, it appears that those insects that
fight back, especially termites, exhibit a coordinated defense connected
with the use of a form of chemical repellent. Worker termites are
defenseless and are usually preferred by anteaters over the soldiers
that protect them. So when the anteater starts feeding on workers, the
few soldiers present discharge their load of chemicals, attracting other
soldiers. The reinforcements swarm to the site of the attack and in turn
discharge their chemicals. In a very short while the concentration of
chemicals, different ones smelling to us like blue cheese, lemon-scented
furniture polish or pine woods, is sufficiently high to drive the
anteater away, leaving a spot covered with very upset soldiers. Termite
soldiers using chemical defenses appear to be effective in limiting, if
not preventing, predation by many kinds of mammals.

Ants and termites can reach staggering abundance in some areas, and so
it is not surprising that even with their array of defensive strategies
they are a major food source. Many mammals that do not depend on ants
and termites to survive still eat them frequently. Such species can be
termed "amateur myrmecophages."

Among the amateurs are the sloth bear, the bateared fox (above), some
mongooses and some mice, which are more semipro than amateur. Termites
and ants comprise about half of the total diet of sloth bears and bat-
eared foxes, while half of the black-legged mongoose's diet seems to be
composed of the unlikely food of driver ants--the Old World's army ants.

Most of the rest of the amateur ant and termite eaters, however,
probably eat significant numbers of social insects only because they are
there. These animals, including some jackals, some armadillos, some
monkeys, some squirrels and some elephant shrews, feed in a manner and
in a location which causes them to encounter many ants and termites.
And, not being overly fussy, they eat what is available.

At one point of their life cycle, ants and termites become irresistible
to an even broader range of animals. Usually following the first rains,
ant and termite colonies pour forth alates, winged males and females
which mostly end up as food. These alates appear by the hundreds of
thousands and flutter weakly about seeking mates and appropriate places
to found new colonies. Alates are very appetizing because they have a
lot of stored fat and less chitinous armor. They make particularly easy
prey because they themselves are virtually defenseless and are away from
whatever protection their soldier caste might have provided.

Many mammals feed on these alates, and it is quite likely that the
energetically expensive business of reproduction in some mammals is tied
to the appearance of these winged reproductives. Such a correlation has
already been suggested for birds. Foxes and hyenas have been seen
standing outside termite exit holes, snapping up alates just as they
emerge on their perilous journey. Some African monkeys, who have
apparently learned that alates of a certain species of termite
Solutions Manual: Chapter 6     Big Java, by Cay Horstmann            50

congregate near the tops of trees, climb these trees and grab the flying
reproductives out of the air.

Chimpanzees can also be found swaying in the tree-tops during swarms,
but search out and eat many kinds of ants and termites. They fish for
termites by sticking twigs or blades of grass down holes in a termite
mound. The tool is then withdrawn, with up to a dozen termite soldiers
biting into it. These are bitten directly off, like toasted
marshmallows, or picked off with the fingers. Five chimpanzees sitting
around a driver ant nest with their tools create a scene reminiscent of
guests, forks in hand, around a fondue pot.

Chimpanzees are not the only myrmecophagous higher primates, for humans
consume large quantities of both ants and termites. Human beings are
particularly fond of alate ants and termites; especially in Africa they
will go to great lengths to secure them. All sorts of devices and
stratagems have been designed to collect alates; one is to water the
termite mound before the first rains, thereby tricking the alates into
leaving the mound prematurely. Humans have also developed the technique
of "fishing" for termites. One person can collect a basketful of
soldiers which, dried, can be seen for sale in some African markets. One
wonders who learned how to fish from whom.

The female alates of the big South American leafcutting ants are also a
delicacy; in some areas they may even be a seasonally significant source
of nutrition. In 1953, A. R. Wallace commented on his disquietude at
observing that in one Indian tribe of the Amazon, breakfast began by
opening a stoppered calabash and allowing a few live ant alates
collected the day before to crawl out. The alates were then consumed raw
with handfuls of manioc flour.

Humans are not built to be myrmecophages, of course; we do not have long
snouts or 18-inch tongues. But then neither do mice, mongooses, bat-
eared foxes or sloth bears. The individual shown opposite, which happily
eats ants when it finds them, could never be mistaken for an anteater.
Yet where culture encourages it, ants and termites are an important
source of protein in the human diet. In the end, it all comes down to a
question of taste. Henry Smeathman, in 1781, expressed surprise that the
European palate would enjoy the taste of the alates of African
Macrotermes, saying, "I have discoursed with several gentlemen upon the
taste of the white ants termites ; and on comparing notes we have always
agreed that they are most delicious and delicate eating. One gentleman
compared them to sugared marrow, another to sugared cream, and a paste
of sweet almonds." While I have never tasted sugared marrow, I can add
my comment that, unlike raw workers or soldiers, fried, salted alates
are probably the best cocktail snacks I have ever tried. But then I'm
not a true myrmecophage.

ExP6_20.java

/* This filter changes all lines in the input to lowercase.
   Run

   java ExP6_20 < article.txt | java Split | sort | java Unique >
sorted.txt
*/
Solutions Manual: Chapter 6        Big Java, by Cay Horstmann   51

import    java.io.BufferedReader;
import    java.io.InputStreamReader;
import    java.io.IOException;
import    java.util.StringTokenizer;

public class ExP6_20
{
   public static void main(String[] args)
      throws IOException
   {
      BufferedReader console = new BufferedReader(
         new InputStreamReader(System.in));

         boolean done = false;

         while (!done)
         {
            String line = console.readLine();
            if (line == null)
               return;
            System.out.println(line.toLowerCase());
         }
    }
}

								
To top