Laboratory Exercises For Computer Science 153

Problem Solving in Java, Part I

Problem Solving in Java, Part I

Introduction

The past labs involving Java have examined some mechanics of Java classes and objects. This lab takes a fresh look at the role of these classes and objects in solving problems. Through the discussion, the lab also introduces the syntax for conditionals and some loops in Java.

The Role of Classes and Objects in Java

As you have seen, all work in Java is based on classes and objects. That is, Java packages all data and operations into classes. For example, code that would be a "main program" in other types of languages is designated as a


public static void main

method of a class in Java. For most other work, data and operations are grouped together in a coherent way to make natural packages. For example, we have seen operations for the input and output of basic numbers and strings grouped together in the classes SimpleInput and SimpleOutput, respectively.

With this emphasis on classes, it is not surprising that Java comes with a large number of pre-defined classes. Thus, for many applications, a programmer does not need to write code for common entities -- Java already may contain appropriate definitions.

With this wealth of class definitions available, efficiency of problem-solving may be enhanced greatly if you can identify classes that may be relevant to a problem. As you encounter new classes, therefore, you should review their capabilities (i.e., concept and methods), so you will know the operations that are built into existing classes. In a well written class, you need not concentrate on the details of how the methods work in order to use those methods. Rather, comments and a method header may be adequate to learn what the method does and how it may be invoked.

Documentation on all pre-defined Java classes is available from http://www.siteforum.com/sun/jdk118online.html. After reaching on this page, double click on the box Click to search. This will bring up an index box. Typing a name in the box at the top of this index box will retrieve documentation related to the class(es) you indicated. You may want to bookmark this site in your browser for further reference!

Example: Piles of Magazines and Bills

In an early lab on object-oriented programming, we studied a stack as a simple example of a class or abstract data type. In that lab, a stack contained the following operations:

An example then defined a stack class in Scheme, created two stacks, mag-pile and bill-pile and performed a sequence of push, empty?, pop, and top operations.

In Java, it turns out that a Stack class is already available as part of a utility library. To examine the methods of this class, go to the on-line documentation at http://www.siteforum.com/sun/jdk118online.html, as described above. Then type Stack in the index box. As you type, note that the large Pages box changes to display those entries related to what you typed (e.g., Stack). Double click on Class java.util.Stack to examine the built-in Stack class.

In the Methods sections of the documentation, you will see that this Stack class does not contain an operation top. Can you find another method that seems to do the equivalent operation?

With the definition of a stack class already done, we can follow the same steps of the previous Scheme example by adding an appropriate class framework:

  1. Create a class stackExample to provide a place for our simulation.
  2. Import the existing Stack class,
  3. Import the SimpleOutput class for printing,
  4. Create a main method for the main steps of our example,
  5. Within main, create appropriate stack and output objects, and
  6. Translate operations of the example from Scheme to Java.

While this translation involves some overhead, the Java code follows the previous simulation closely. File stackExample.java shows the resulting program.

  1. Copy the Java program stackExample to your account, compile and run it, and check the output.

  2. In the Java code, three items are pushed onto the billPile, but the program tries to pop four items from the stack. Explain what happens.

  3. Compare the various sections of the Java code with the corresponding main sequence of events for the Scheme lab.

    1. stackExample.java creates three new objects, magPile, billPile, and out. To what extent are the creation of magPile and billPile analogous in the two languages? Why is out or its equivalent needed in Java, but not in Scheme?

    2. To what extent are the sequence of stack operations parallel in the two languages?

    3. In the Java program, two lines containing a top operation are commented out. What happens if these two lines are included? For example, does the program compile? Does it run? Describe briefly.

    4. Using the Java documentation described above, replace the top method invocation by the correct method name from the documentation. Recompile, run, and check that the program now works appropriately.

Approximating Pi

A second use of classes is seen in the following application to approximate Pi.

Problem: Consider a square of side 2 in the plane, centered at the origin, so the square extends one unit along each axis in each direction.

Suppose a point P is picked at random in the square. What is the likelihood that P also will be within a circle of radius 1, centered at the origin?


Discussion: Mathematically, the desired probability depends on the relative area of the circle and the square. Since the circle and square have radius 1 and side 2, respectively, their areas are Pi and 4, respectively. Putting this together gives the following:

Probability (P in circle) = Area Circle / Area Square = Pi / 4.

A similar analysis applies if we restrict P to the first quadrant.

Applying this to an experiment, we might pick N points at random in the square in the first quadrant. We then could count the number I of points inside the circle. We would expect that

I / N = (approx) Pi / 4.

Solving for Pi gives

Pi = (approx) 4 I / N

To use this estimate in a program to approximate Pi, we need to be able to create random points in the square, determine their distance from the origin, and count if they are in the circle. This work is done in the following outline:

Code Outline:

  1. Read number N of points to be selected.
  2. Set counter to 0.
  3. Repeat N times:
    1. Create a point P in the unit square in the first quadrant.
    2. Check if P's distance to the origin is less than or equal to 1.
    3. If so,increment counter by 1.
  4. Print number of times point was in circle.
  5. Print estimate of Pi by the formula, Pi = (approx) 4 I / N.

Implementing the Outline: In implementing the outline, we first consider what properties we need for points. In the outline, we must create points and determine how far they are from the origin. Fortunately, these operations are present in the class Point, which we already have used in previous labs. Thus, we need look no further, but can use this class directly.

Random number operations are common in many languages. In Java, the mathematics library class contains such a mechanism to generate random numbers between 0 and 1, and we will use that library operation.

Code: The resulting program approxPi.java follows the outline very closely. While several parts of this program are familiar, both the conditionals and the looping involve some Java constructs which have not yet been introduced in this course.

  1. Copy the Java program approxPi.java to your account, compile it, run it for several values of N, and check the output.

  2. Review how each part of this program implements the solution outline above.

Some Syntax: Program approxPi.java provides examples of both conditional (if statements) and for loops. if statements have two forms, analogous to Scheme:


if (condition)
   statement;

if (condition)
   statement1;
else
   statement2;

In each case, the overall condition must be in parentheses and only a single statement can be given. However, as in Scheme, multiple statements can be placed in then or else by grouping them together in brackets { } -- just as a (begin ... ) was used in Scheme.

Also as in Scheme, the condition may be made up of several clauses, combined by such operations as:

   ! not
   && and
   || or

for loops have the following general syntax:


for (initialization ; continue-condition ; update)
   statement;

Here, initialization contains one or more statements (separated by commas) which initialize variables. continue-condition is a Boolean condition. Every time execution gets to the top of the loop, this condition is re-evaluated. If the condition is true, the statement is executed as the body of the loop. The update portion of the code allows variables to be updated from one iteration of the loop to the next.

  1. Consider the following Scheme code to compute the sum of the numbers from N to 1:

    
    (do ((sum 0 (+ sum I))
         (I N (- I 1)))
        ((<= I 0) sum))
    )
    
    

    Write the corresponding loop as a Java for loop. As in Scheme, the body of the for loop will be null. Remember to separate multiple clauses in the initialization or update sections by commas.

  2. Solve the following problem using the various ideas of random numbers, conditionals, and looping discussed in this lab.

    Family Size Simulation: A couple decides that they want to raise at least one boy and one girl. They decide to keep having children until they have one child of each gender, and then stop having children. Assume that having a boy or a girl is equally likely, and assume the gender of one child has no influence on the gender of the next. Investigate how many children such a couple could expect to have.

    Partial Solution: In the simulation, the gender of a child for a couple could depend on a random number generator. For example, you might decide that the child might be a boy if a random number were less than 0.5, and a girl otherwise. The overall program might proceed according to the following outline:

    1. Repeat for 20 couples:
      1. Initialization: Set the number of boys and number of girls to 0.
      2. Continue until there is at least one boy and one girl:
        1. Determine gender of next child.
        2. If child is a boy, increase number of boys by 1.
        3. If child is a girl, increase number of girls by 1.
      3. Print number of boys, number of girls, and total number of children.

  3. Modify the previous program to simulate the family size for 1000 couples. In this modification, do NOT print the size of each couple's family. Rather, keep track of the minimum, maximum, and average family sizes.

Finally for this lab, we return to the simulation to approximate Pi. Suppose we want to plot the points in a window as well as to count how many points are in the unit circle. To do this, we would need a graphical window. While we could try writing such a window class from scratch, a previous lab described such a class, called Plane.java.

  1. Using Plane.java, add code to approxPi.java to plot the points as they are generated. In writing your code, read the methods in Plane.java to determine how to turn off the printing of coordinates. (For simulations of any size, the diagram of points will be hard to read if both points and their coordinates are printed.)

    Hint: Once you examine the methods of Plane.java, the actual new coding for this step will be rather short.

Work To Turn In:


This document is available on the World Wide Web as

http://www.math.grin.edu/~walker/courses/153.sp00/lab-java-prob.sol-1.html

created April 16, 2000 by Henry M. Walker
last revised April 18, 2000