CSC 207 Grinnell College Fall, 2014 Algorithms and Object-Oriented Design

## Supplemental Problems

Supplemental Problems extend the range of problems considered in the course and help sharpen problem-solving skills. Problems numbered 8 or higher may be turned in for extra credit.

### Format:

In turning in any programs for the course, please submit the following materials, in the order specified (so the program with you name and box will be on top).

1. Print and submit a paper copy of each Java class (copying and pasting from Eclipse is ok)

• The first lines of any Java program should be comments containing your name, your mailbox number, this course number (207), an identification of assignment being solved, and an Academic Honesty certification. (You may not talk to anyone, except the instructor, a class mentor, or an evening lab tutor, for any Supplemental Problem.) For example:
```    /*****************************************************************
* Henry M. Walker                                               *
* PO Box Science II                                             *
* Program for CSC 207                                           *
*   Gambling Simulation                                         *
* Assignment for Monday, February 20                            *
*****************************************************************/

/* ***************************************************************
*   Written/online sources used:                                *
*     [include textbook(s),                                     *
*       CSC 207 labs or readings;                               *
*       complete citations for Web or other written sources]    *
*     [write "none" if no sources used]                         *
*   Help obtained                                               *
*     [indicate names of instructor, class mentors              *
*      or evening lab tutors, consulted                         *
*      according to class policy]                               *
*     [write "none" if none of these sources used]              *
*   My signature below confirms that the above list of sources  *
*   is complete AND that I have not talked to anyone else       *
*   [e.g., CSC 161 students] about the solution to this problem *
*                                                               *
*   Signature:                                                  *
*****************************************************************/

```
• Comments should identify the logical sections of the work and provide a high-level overview of the main steps being performed.
• Comments should clarify any complex logic or data structure — what is the motivating idea behind the block of complex code?
```  /***
* equals is a method
* @param first is a String
* @param last is a String
* @returns a boolean value
*/
equals (String first, String last)
```
• Any code should be reviewed for readability, including
• indenting to highlight logical structure
• descriptive variable names
• lines of code short enough to avoid line wrap when printed
• use of methods to divide complex processing into manageable parts

• each class
• each field
• each method (including each parameter and any return data

3. A printed copy of relevant test runs (copying and pasting ok)

4. Commentary (typed or handwritten) regarding your testing of the code, including:

• A numbered listing of the circumstances that can reasonably arise in this problem.
• For example, if a program is to categorize data, the listing should include a statement of the categories; If some category could be obtained in several ways, the statement should identify each circumstance that could lead to the category.
• As another example, if the order of initial data might impact processing, then the listing should include circumstances to test the order of input data.
• A listing of test cases to be considered, with the expected outcome.
• For each numbered item in the listing of possible circumstances, a corresponding test case should be identified.
• Each test case should be specific, including what data will be considered and what output is expected.
• A listing of the actual test runs (copying and pasting into a separate document is allowed). Each test run should be annotated (writing on the printout is acceptable), identifying which test case is being run and whether or not the output produced is correct.
• Once testing is completed, prepare a separate statement that argues why your program is correct, based upon the evidence from your test runs.

Email lab each class, test plan, test runs, and statement of correctness as separate attachments to grader-207-02@cs.grinnell.edu. Please include the assignment title (e.g., Lab 2) and the name of all co-authors in the Subject line.

• Since every programming task should yield readable and carefully tested code, the grading of all programs for this course will begin with the following algorithm (expressed in C or Java format):
```
|| (missing pre- or post-conditions)
|| (formatting_does_not_show_structure)
|| (no_evidence_of_compilation)
|| (no_test_plan___no_listing_of_circumstances__OR__no_listing_of_test_cases)
|| (no_test_runs)
|| (no_commentary_on_correctness))
|| (no_signed_certification_regarding_sources_and_help)
```
• When a program is submitted according to the instructions specified above, it should be understood that the various pages reflect the same program. That is, the javadoc listings should have been generated by Eclipse from the code printed, and Eclipse should have run the code to generate the printed output. With this understanding, editing of a javadoc file or an output file is strictly forbidden and will result in automatic failure on the assignment. Such editing also may raise questions of academic dishonesty; and, by College policy, any evidence of academic dishonesty must be turned over to the Academic Standing Committee for action.

Summary: Don't even think about editing a javadoc file or an output listing.

Two grading forms will be used in the grading of each supplemental problem.

• A general form provides feedback on many elements common to most or all object-oriented programs.
(This form is under development and may evolve through this semester.)
• A problem-specific form that evaluates specifics for an individual problem.

### A Simple Class Hierarchy

1. This problem introduces some simplified elements related to a program to track shopping in a grocery store. Many details would be expanded greatly for a real application, but this problem might make a [small] start.

Items available in a grocery store might be categorized as produce (e.g., vegetables, fruit, cheese, meat, etc.), beverages (bottled water, milk, soft drinks, energy drinks, etc.), and packages (boxes of crackers, noodles, tea, etc.). A class hierarchy to model this categorization of items follows:

To clarify,

• All materials in a store fall within a general category of a class Item.

• Every Item has a protected name field of type String that indicates the name of the grocery item (e.g., can of soup, box of macaroni and cheese, bottle of Diet Pepsi, etc.).
• Every Item has a protected cost field of type double that indicates the purchase price of this grocery item.
• Every Item has a method getCost that returns the cost of the item.
• Every Item has a method costPerUnit that computes and returns the amount a user pays per unit. Since an Item knows nothing about its units, this computation for a plain Item is the same as cost — the cost for 1 Item unit. (The computation of costPerUnit may differ in subclasses.)
• Every Item has a method toString that returns a nicely-formatted string containing name and cost information.
• Class Produce is a subclass of Item of fresh, uncooked ingredients.

• Every Produce has a private field pounds of type double that gives the weight of the object in pounds.
• Every Produce has a private field category of type String that gives the type of material, such as a vegetable, fruit, cheese item, ice cream, etc.
• Within Produce, method costPerUnit will need to return the cost per pound of the object, and toString should report weight and category, in addition to the data stored as part of an item.
• A Beverage is an Item for drinking.

• Each Beverage container holds a specified amount of liquid, reported in the private int field fluidOunces.
• When sold, the customer must pay the regular price plus a deposit, recorded in a private double field containerDeposit
• Within Beverage, method costPerUnit will need to return the cost per fluid ounce of the object, and toString should report number of fluid ounces and the amount of the deposit, in addition to the data stored as part of an item. In addition, method getCost will need to include both the actual cost of the item, but also the container deposit.
• A Package is a subclass of Item that comes in a rectangular box.

• Each Package object has dimensions for length, width, and height that are stored as private double fields.
• Each Package holds an amount of materials, reported in the private int field ounces.
• Within Package, toString should report the size (length, width, height) and weight (ounces) of the object, in addition to the data stored as part of an item. (Note that a Package is considered a single unit, so the costPerUnit method of Item need not be modified for this subclass.)

For this problem, you should implement the following:

1. Class definitions for Item and its subclasses Produce, Beverage, and Package

2. A ShoppingCart class, modeled upon the SchoolDirectory class from the CSC 207 lab Generalization, Polymorphism, and Exceptions. The ShoppingCart class should have these features:

• A private array Cart of Item objects:
• The size of Cart is given by private field maxSize.
• Field currentSize gives the actual number of objects stored in Cart, in positions Cart[0] to Cart[currentSize-1].
• A method addItem places a new item object into the array, expanding the array as needed, and incrementing currentSize
• A method printCart should provide a listing of all items in the cart.
• A method totalCost should compute the total cost of all items in the cart.
• A method numberInCart should take a parameter String groceryName and return how many items in the current shopping cart have that name.
Notes:
• An easy way to compare strings is to use the built-in compareTo method. That is, if str1 and str2 are two strings, then str1.equals(str2) returns true if the two strings are the same (including case) and false if the two strings differ in any way.
• Although class Item and its subclasses contain a name field, this field is protected. Explain why numberInCart cannot be implemented in ShoppingCart with the specified fields and method for Item and its subclasses.
• To implement numberInCart, class Item could be expanded in two ways (for reasons of correctness and security, we do not consider changing name to public.)
• A method getName() could be added to class Item to return the name string.
• A method equals (String str) could be defined in class Item which returns true if the name in the Item matches str and returns false otherwise.
Modify Item with one of these approaches in order to implement numberInCart. Include a comment explaining why you chose this approach for expanding Item.

1. Students taking courses at Grinnell College may be considered to fall into one of four main categories: regular, alum, employee, and special. The following descriptions bend the rules somewhat, but provide a basic outline of each category.

• Regular: A regular student has been admitted through a an application to the Admission Office, is earning credits toward the 124 required for graduation, and at some point will declare a major. Regular students must be enrolled for at least 12 credits to be considered full time. Enrollment for more than 18 credits requires a petition and an extra fee.
• Alum: A graduate of Grinnell College may enroll for up to 4 credits during a semester following a special fee structure. Credits toward graduation and class standing are no longer relevant for enrollment in courses. A graduate's major has already been completed.
• Employee: An employee of Grinnell College (e.g., staff, faculty) may be able to enroll in courses and make progress toward a Grinnell degree. Ignoring various details, when authorized by a supervisor, the employee may take up to 4 credits during a semester.
• Special: Students from area high schools, retired persons from local retirement communities (e.g., St. Francis Manor or the Mayflower Home) may enroll in a course (up to 4 credits), on a space-available basis. Class standing, progress toward a degree, and a major are not relevant considerations for special students.

Note: The actual rules for Alum, Employee, and Special students involve courses, not credits. Alum and Employee students may take 1 course; Special students may take 2 courses. In the interests of sanity for this problem, however, the above rules will be considered in effect.

Observations:

• All student categories are subclasses of an EnrolledStudent class.
• Since Alum and Special students have elements in common (e.g., enrolled credits must be between 0 and 4, the concept of class standing does not apply), Alum and Special are subclasses of an abstract NonRegular class which implements several common methods.
• Each of the four student groups know their category, so getStudentCategory can be implemented by returning a hard-coded string.
• Alum and Special students do not have class standing and are not making good progress toward a degree, so methods getClassStanding and makingGoodProgress should throw exceptions in those cases.
• An Alum already has graduated with a major, so that information should be available in the Alum's record. However, a Special student does not have a major, so getMajor should throw an Exception for Special students.
• For Regular and Employee students, class standing is determined by the following table, based roughly on total credits earned:
Minimum Credits for Standing
Year Semester 1 Semester 2
First Year 0-11.5 12-27.5
Second Year 28-43.5 44-59.5
Junior 60-75.5 76-91.5
Senior 92-107.5 108-123.5

For example, a Regular student with 65 total credits would have class standing as "Junior, Semester 1".

(Note that various details and limits are ignored in the above table, so this problem can be moderately manageable.)

• For Regular and Employee students, making good progress often means earning enough credits consistent with the above table. However, taking the Phi Beta Kappa guidelines into account (at least a little), graduates should have at least 12 credits in each division (humanities, social studies, and science). For the purposes of this problem, therefore, making good progress means that the number of credits in each division is on track to meet this 12-credit goal. Since 12 credits is about 10% of the credits required for graduation, the makingGoodProgress method for Regular and Employees students should check that at least 10% of the student's total credits are in each of the three divisions.
• For Regular students, a registration will be considered valid if the student is enrolled for at least 12 credits (to achieve full-time status) and no more than 18 credits.
• For Employees, valid registration signifies between 0 and 4 credits.

Directions for this Problem:

1. Implement the above class hierarchy: EnrolledStudent, NonRegular, Regular, Alum, Special, and Employee.
• Use inheritance as much as possible to keep the writing of code to a minimum!
• Once you have started EnrolledStudent with the definition of the relevant fields, check the "Generate Getters and Setters" option in Eclipse under the "Source" menu.
2. Implement a Registrar class that contains an ArrayList of EnrolledStudents of the four types. (Note that Java's ArrayList is an expandable array, much like the arrays used with our SchoolDirectory example — but since ArrayList is already implemented, you need not do that!) Within the context of a Registrar class (either in an object or in main),
• Several students of each type should be created and added to the ArrayList.
• The Registrar class should contain a method to print all students in the ArrayList. For each student, the methods of EnrolledStudent should be called. If the information is available, it should be printed (Just put the method call into a print statement — do not test if the result is valid.) If an exception is thrown, processing should skip that part of output. Note that getMajor throws an exception for Special students, in which case getClassStanding and makingGoodProgress can be skipped as well. Also getClassStanding and makingGoodProgress throw exceptions for Alum students, so if one of these methods is called and generates an exception, then the other of these methods need not be called.

Note that the idea of the Registrar class is to provide a mechanism for testing the various other classes. In most (all?) cases, careful design of tests for the Registrar class may cover testing for this entire assignment.

3. Comments for each class and for all methods should be prepared in Javadoc format. Submission of the final code should include a URL where the generated Javadoc documentation can be found.

### Queues of Different Priorities for Printing

1. When a printer serves multiple users, users may sent several print requests to the operating system, but only one file can be printed at a time. Thus, the operating system can direct a file from one print request to the printer, but the other requests must be stored in some type of data structure. The simplest approach involves a single queue. Each user sends one or more files to the operating system, and the operating system places the print requests on a queue. The operating system then sends the files to the printer one-at-a-time from the print queue. Of course, once a printer starts to print a file, the printer must complete that job before moving onto the next print request. Although this approach is simple and treats all jobs equally, this approach has the disadvantage that many short printing jobs (of only a few pages) may have to wait substantial amounts of time for a large print job (hundreds of pages) to finish.

One way to give some preference to certain print jobs is to create multiple queues of varying priorities. For convenience of notation, suppose a system has n queues, labeled q0, q1, q2, ..., qn-1. Suppose qi has priority i, where priority 0 is top priority, priority 1 is the next highest priority, ..., and priority n-1 is the lowest priority. That is requests in q0 are chosen before print requests in any other queue, and requests in qn-1 must wait until requests from all other queues have been printed.

The division of print requests into queues of varying priorities can work well in many cases, but this approach has the drawback that low priority print requests may never be printed if a steady stream of higher priority requests enter the system. In operating-systems jargon, this situation is called starvation; some work is never done because the system spends all of its time on other processing.

To avoid the possibility of starvation, a typical approach is to periodically move a print request from a low-priority queue to the next higher priority queue, as this would cause any print request to eventually move up to the head of the highest priority queue. To specify this promotion from one queue to the next more precisely, suppose that every time k requests from queue qi have been sent to the printer, the system removes a request from queue qi+1 and enqueues the request on queue qi.

The Printing Protocol

The following diagram provides an overview of the process of user submission of print requests, their placement on an appropriate queue, and their subsequent transmission to the printer for printing:

The formal protocol follows:

• At any time, a user may send a print request to the operating system.

• The request specifies the name of the file and the number of pages to be printed.
• The operating system uses an enqueue operation to place the print request on a queue, based on the number of pages to be printed

• Three algorithms for determining the relevant queue are given later in this problem.
• If the printer is idle, the operating system will select a print request from the highest priority non-empty queue.

• If the printer is busy, the operating system simply collects print requests in its queues.

• If the printer completes a print request, the operating system processes print requests as follows:

• If no print requests remain unprocessed, the system waits until a new request is submitted.
• If one or more print requests are unprocessed, the operating system uses a dequeue operation on the non-empty queue of highest priority.
• Whenever a dequeue operation is executed k times for any queue qi, the operating system finds the highest priority, non-empty queue qj with j > i. The operating system then uses the dequeue operation on qj to retrieve a print request, and that request is then immediately enqueued onto qi

Determining Initial Print-request Priority

The print-queue protocol above requires the operating system to determine which queue should be used for each new print request submitted by the user. Three assignment approaches follow:

1. All print requests are put on queue q0; that is, only one queue is used, and requests are printed in strict FIFO order.
2. n queues are used, and print requests are assigned initially to queues based on their size.
• Files of size 1-10 pages go initially to queue q0,
• Files of size 11-20 pages go initially to queue q1,
• Files of size 21-30 pages go initially to queue q2,
• ...
• Files of size i pages go initially to queue qi/10 (for i < 10 (n-1)),
• ...
• All files of 10(n-1) or more pages go to queue qn-1,
3. n queues are used, and a print request for a file of size i is initially assigned to queue qi%n.

Problem to be Solved

Supplemental Problem 3 is to investigate the extent to which multiple queues and different assignment algorithms have an impact on the average waiting time for users' print requests.

For the purposes of this problem, suppose that printing one page requires one unit of time. The simulation described below will cover 1000 units of time, and the simulation will need a "clock" variable that keeps time units 0, 1, 2, ..., 999.

1. Identify a Queue class for use with this problem. (If possible, use a queue class from the Java Library, although you may need to expand it to know how many times a dequeue operation has been called since the queue was last empty.)
2. Define a PrintRequest class that contains relevant information regarding a user request for printing. Likely, this PrintRequest class will need fields to record the number of pages to be printed and the clock time when the user submitted a print request.
3. Define a Printer class with [at least] these methods (beyond a constructor)
• a boolean printerIdle() method that returns true if the printer currently is not processing a print request, and false if the printer is busy processing a Print Request (i.e., the printer is printing a requested file).
• a boolean printFile (PrintRequest pr) method:
• if the printer is idle, the printer will start processing the given print request, and the method returns true
• if the printer is already processing another Print Request, the new Print Request pr is ignored, and the method returns false
• a PrintRequest processForOneUnit() method that prints one page of the current print request
• if the printer is idle, or if the current Print Request is NOT completed within 1 unit of time, then processForOneUnit returns null. (Internally, the printer object should record that one additional page of the current Print Request has been printed.)
• if the current Print Request is completed in the current time unit, the method returns the current PrintRequest object that just finishes printing.
4. Write a Simulation class for the following simulation:
• The program will read four parameters from the terminal:
• The probability that some user will make a print request in a single time interval
• The number n of queues to be used
• The number k of dequeue operations from one queue before an item from a lower-priority queue is promoted
• The algorithm ("A", "B", or "C" from above) for determining how the operating system will decide which queue will be used for a user's print request.
• Processing proceeds one time unit at a time, based upon a "clock" variable.
Processing in one time unit involves the following:
• If the printer is in use, then 1 page of the current job is printed (so the print job is 1 page closer to completion).
• A user may or may not make a print request. For this simulation, the likelihood that a print request is generated in one time of time should be based on a random number generator and a user-entered probability. If a print request is generated, processing in the simulation should depend upon these parameters.
• The number of pages for the print request should be determined randomly between 1 and 100 pages.
• A new Print Request object is created, containing the number of pages for the job and the starting "clock" time that this request entered the queue.
• The user's request is submitted to the operating system in the form of an object with the clock time and print size.
• The operating system places the new Print Request object on the appropriate queue.
• If the printer is idle, and if at least one print request is pending, then
• a print request is selected from the multiple queues, as described above.
• the wait time (number of time intervals of waiting) for this Print Request is used to update both a maximum wait time and a total average wait.
• the print request is sent to the printer object.
• After the "clock" reaches 1000 time units, no new Print Requests should be generated, but the simulation should continue until all existing Print Requests have been processed.
5. At the end of the simulation, the program prints:
• the maximum waiting time for any Print Request
• the average waiting time for all processed Print Requests

To investigate the impact of different queue-selection strategies, testing should include each of the queue-selection approaches and several loads (numbers of Print Requests entering over the simulation).

This document is available on the World Wide Web as

```http://www.walker.cs.grinnell.edu/courses/207.sp13/suppl-prob.shtml
```