Wellesley College, Summer 2003

Problem Set 8

Due: Tue., July 8 by 6pm


Reading

  • (Fall'01 text) Chapter 7: Iteration
  • IntListList Contract
  • IntListListOps Contract
  • Study the code in the file IntListListFunctions.java within the lec10_lists/IntListLists folder.
  • Study the code in the file IterationWorld.java within the lec11_iteration/BuggleIteration folder.
  • Study the code in the file IntFunctions.java within the lec11_iteration/IntIteration folder.
  • Study the code in the file IntListFunctions.java within the lec11_iteration/IntListIteration folder.
  • Study the code in the files GraphicsDemo.java, Circles.java, and Ovals.java within the lec12_graphics_objects/GraphicsDemo folder.

    About this Problem Set

    The purpose of this problem set is to give you with lists of lists, iteration (tail recursion, while loops, and for loops), and Java graphics. In Task 1, you will use list of lists to determine all the different ways to make change for a given amount of money. In Task 2, you will use iteration to manipulate lists. In Task 3, you will use Java graphics to draw simple cartoon faces.

    There are also an optional open-ended extra-credit opportunity for you to use Java Graphics to draw any picture(s) of your own design.

    All code for this assignment is available in the ps8_programs folder in the cs111d download directory on the cs file server.

    How to turn in this Problem Set

    You are required to turn in both a hardcopy and a softcopy. For general guidelines on problem set submission, including how to submit a softcopy and how to check if you softcopy submission was successful, click here. Please make sure to keep a copy of your work, either on a zip disk, or in your private directory (or, to play it safe, both).

    Hardcopy Submission

    Your hardcopy packet should consist of:
    1. The cover page;
    2. Your modified ChangeMaker.java file from Task 1.
    3. Your iteration table from Task 2a;
    4. Your modified Partition.java file from Tasks 2b, 2c, 2d, and 2e;
    5. The final version of Faces.java from Task 3.
    6. The final version of MyPicture.java from (optional) Extra Credit Challenge 1.
    Staple these together, and put them in the box in the back of 257.

    Softcopy Submission

    You should submit your final version of your ps8_programs folder. In particular,

    Task 1: Making Change

    Lists of lists are useful data structures for holding lists of possibilities. We can use them to hold the list of all subsets of a set of numbers like we saw in lecture. We could also use them to hold a list of all permutations of a list of numbers, using an approach similar to computation of string permutations considered in the previous problem set. In this problem, we will use lists of lists to represent all the possible ways of making change for a given amount of money given an unlimited number of coins with certain denominations. Some examples are given below (assume all values are in cents).

    Amount to change Denominations Ways to Make Change
    5 [5,1]
    [[5],            // 1 nickel
     [1, 1, 1, 1, 1] // 5 pennies
     ]
    16 [10,5,1]
    [[10, 5, 1],               // 1 dime, 1 nickel, and 1 penny
     [10, 1, 1, 1, 1, 1, 1],   // 1 dime and 10 pennies
     [5, 5, 5, 1],             // 3 nickels and 1 penny
     [5, 5, 1, 1, 1, 1, 1, 1], // 2 nickels and 6 pennies
     [5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], // 1 nickel and 11 pennies
     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] // 16 pennies.
     ]

    Your goal is to formulate a strategy that will list all the possible ways to make change for a given amount of money with a list of possible coin denominations provided in descending order of value. You will be completing the method makeChange of the ChangeMaker class. The skeleton for the method is provided below:

    public static IntListList makeChange (int amount, IntList coins)
    Returns a list of possible ways to make change for amount using the coin denominations in the list coins. Assume the integers in coins are in descending order of value.

    Complete this problem by fleshing out the definition of makeChange in the ChangeMaker.java file within the ChangeMaker folder.

    Notes

    Correct Test Case Answers

    
    ----------------------------------------------------
    There are 1 ways to make change for 5 cents using [5]:
    [[5]
     ]
    ----------------------------------------------------
    There are 1 ways to make change for 5 cents using [10, 5]:
    [[5]
     ]
    ----------------------------------------------------
    There are 1 ways to make change for 10 cents using [5]:
    [[5, 5]
     ]
    ----------------------------------------------------
    There are 2 ways to make change for 10 cents using [10, 5]:
    [[10],
     [5, 5]
     ]
    ----------------------------------------------------
    There are 1 ways to make change for 15 cents using [5]:
    [[5, 5, 5]
     ]
    ----------------------------------------------------
    There are 2 ways to make change for 15 cents using [10, 5]:
    [[10, 5],
     [5, 5, 5]
     ]
    ----------------------------------------------------
    There are 0 ways to make change for 16 cents using [10, 5]:
    []
    ----------------------------------------------------
    There are 2 ways to make change for 5 cents using [5, 1]:
    [[5],
     [1, 1, 1, 1, 1]
     ]
    ----------------------------------------------------
    There are 3 ways to make change for 10 cents using [5, 1]:
    [[5, 5],
     [5, 1, 1, 1, 1, 1],
     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
     ]
    ----------------------------------------------------
    There are 4 ways to make change for 10 cents using [10, 5, 1]:
    [[10],
     [5, 5],
     [5, 1, 1, 1, 1, 1],
     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
     ]
    ----------------------------------------------------
    There are 4 ways to make change for 15 cents using [5, 1]:
    [[5, 5, 5],
     [5, 5, 1, 1, 1, 1, 1],
     [5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
     ]
    ----------------------------------------------------
    There are 6 ways to make change for 15 cents using [10, 5, 1]:
    [[10, 5],
     [10, 1, 1, 1, 1, 1],
     [5, 5, 5],
     [5, 5, 1, 1, 1, 1, 1],
     [5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
     ]
    ----------------------------------------------------
    There are 6 ways to make change for 16 cents using [10, 5, 1]:
    [[10, 5, 1],
     [10, 1, 1, 1, 1, 1, 1],
     [5, 5, 5, 1],
     [5, 5, 1, 1, 1, 1, 1, 1],
     [5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
     ]
    ----------------------------------------------------
    There are 13 ways to make change for 26 cents using [25, 10, 5, 1]:
    [[25, 1],
     [10, 10, 5, 1],
     [10, 10, 1, 1, 1, 1, 1, 1],
     [10, 5, 5, 5, 1],
     [10, 5, 5, 1, 1, 1, 1, 1, 1],
     [10, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 5, 5, 5, 5, 1],
     [5, 5, 5, 5, 1, 1, 1, 1, 1, 1],
     [5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
     ]
    ----------------------------------------------------
    There are 60 ways to make change for 56 cents using [25, 10, 5, 1]:
    [[25, 25, 5, 1],
     [25, 25, 1, 1, 1, 1, 1, 1],
     [25, 10, 10, 10, 1],
     [25, 10, 10, 5, 5, 1],
     [25, 10, 10, 5, 1, 1, 1, 1, 1, 1],
     [25, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [25, 10, 5, 5, 5, 5, 1],
     [25, 10, 5, 5, 5, 1, 1, 1, 1, 1, 1],
     [25, 10, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [25, 10, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [25, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [25, 5, 5, 5, 5, 5, 5, 1],
     [25, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1],
     [25, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [25, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [25, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [25, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [25, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 10, 10, 10, 10, 5, 1],
     [10, 10, 10, 10, 10, 1, 1, 1, 1, 1, 1],
     [10, 10, 10, 10, 5, 5, 5, 1],
     [10, 10, 10, 10, 5, 5, 1, 1, 1, 1, 1, 1],
     [10, 10, 10, 10, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 10, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 10, 10, 5, 5, 5, 5, 5, 1],
     [10, 10, 10, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1],
     [10, 10, 10, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 10, 10, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 10, 10, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 10, 5, 5, 5, 5, 5, 5, 5, 1],
     [10, 10, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1],
     [10, 10, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 10, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 10, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 10, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 10, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 5, 5, 5, 5, 5, 5, 5, 5, 5, 1],
     [10, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1],
     [10, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 1],
     [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1],
     [5, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
     ]
    

    Task 2: List Partitioning

    The following partitionIter method takes an integer named pivot and a list of integers named L and partitions the list into two lists:

    1. All the elements in L less than pivot.
    2. All the elements in L greater than or equal to pivot.

    The two resulting lists are returned in a two-element IntListList -- i.e., a list of two integer lists.

        public static IntListList partitionIter (int pivot, IntList L) {
          return partitionTail(pivot, L, IL.empty(), IL.empty());
        }
    
        public static IntListList partitionTail (int pivot, IntList list, 
                                                 IntList lesses, IntList greaters) {
          if (IL.isEmpty(list)) {
            return twoLists(lesses, greaters);
          } else if (IL.head(list) < pivot) {
            return partitionTail(pivot, IL.tail(list), 
                                 IL.prepend(IL.head(list), lesses), greaters);
          } else {
            return partitionTail(pivot, IL.tail(list), 
                                 lesses, IL.prepend(IL.head(list), greaters));
          }
        }
    

    Because the program manipulates both IntList and IntListList objects, it is necessary to distinguish the list operations for these different kinds of lists. As in Task 1, we will use IL. to prefix IntList operations and ILL. to prefix IntListList operations. To make the code more readable, we use the following helper method:

        public static IntListList twoLists (IntList L1, IntList L2) {
          return ILL.prepend(L1, ILL.prepend(L2, ILL.empty()));
        }
    

    Task 2a: Iteration Table

    The partitionTail method is a tail recursive method that specifies an iteration in four state variables named pivot, list, lesses, and greaters. Any iteration can be characterized by how the values of the state variables change over time. Below is a table with four columns, one for each state variable of the iteration described by partitionTail. Each row represents the values of the parameters to a particular invocation of partitionTail.

    pivotlist lessesgreaters
         
         
         
         
         
         
         
         
         

    Suppose that the list A has the printed representation [7,2,3,5,8,6,1]. Fill in the above table to show the parameters passed to successive calls to partitionTail in the computation that begins with the invocation partitionIter(5, A). There are more rows shown here than you need, so you should draw only as many rows as you need to in your table.

    Part 2b: partitionWhile

    It is possible to express any iteration as a while loop. Flesh out the following code skeleton of a partitionWhile method that behaves just like the above partitionIter method except that it uses a while loop rather than tail recursion to express the same iteration as partitionTail.

    public static IntListList partitionWhile (int pivot, IntList L) {
      // Replace this stub
      return ILL.empty();
    }
    

    Notes:

    Task 2c: partitionFor

    The iteration expressed by partitionTail and partitionWhile can also be expressed via a for loop whose index variable is the list state variable. Flesh out the skeleton of the following method so that it expresses the partitioning iteration with a for loop:

    public static IntListList partitionFor (int pivot, IntList L) {
      // Replace this stub
      return ILL.empty();
    }
    

    Recall that a Java while loop has the syntax

    for (init-statement; test-expression; update-statement) {
      body-statements
    }
    

    The above for loop is equivalent to the following while loop:

    init-statement;
    while (test-expression) {
      body-statements;
      update-statement;
    }

    Task 2d: partitionRec

    In the above partitionIter method, elements in the two returned lists are in a relative order opposite to their relative order in the original lists. For instance, partitioning the list [1, 4, 8, 3, 6, 7, 5, 2] about the pivot 6 yields the lists [2, 3, 4, 1] and [7, 6, 8].

    Suppose that we want the resulting lists to have the same relative order as in the original list. If we are provided with an IntList reversal method IL.reverse, we can easily accomplish this by reversing the two lists before gluing them together. That is, we can change the line

    	return twoLists(lesses, greaters);
    
    within partitionTail to be
    	return twoLists(IL.reverse(lesses), IL.reverse(greaters));
    

    An alternative to using IL.reverse to achieve this behavior is to define a non-tail-recursive version of partitionIter that we will call partitionRec. Flesh out the following skeleton of partitionRec, which partitions the elements of a list about the pivot but maintains the relative order of the elements in the resulting lists:

     
        public static IntListList partitionRec (int pivot, IntList L) { 
          if (IL.isEmpty(L)) { 
            return twoLists(IL.empty(), IL.empty()); 
          } else { 
            IntListList subresult = partitionRec(pivot, IL.tail(L)); 
            // replace the following stub:
            return ILL.empty(); 
          } 
        } 
    

    Notes:

    Task 2e: quicksort

    An important use of a partitioning method is a sorting algorithm known as quicksort. Here is the idea behind quicksort:
    To sort the elements of a list, partition the elements of the tail of the list around its head into result lists that we'll call lesses and greaters. Then result of sorting the whole list can be obtained by appending the result of sorting lesses to the result of prepending the head of the list to the result of sorting greaters.

    For example, if the initial list is [5, 2, 8, 3, 6, 7, 1, 4], then partitioning the tail of the list around the head (5) yields:

    	lesses = [4, 1, 3, 2]
    	greaters = [7, 6, 8]
    

    By wishful thinking, sorting lesses will yield [1, 2, 3, 4] and sorting greaters will yield [6, 7, 8]. The result of sorting the original list is the result of appending [1, 2, 3, 4] to the result of prepending 5 to [6, 7, 8].

    Flesh out a method with header public static IntList quicksort (IntList L) that uses this idea to sort the elements of a list. You may use IL.append to append two lists and any of the above partitioning methods to partition a list. The quicksort method is tested by the main method of the Partition class.

    It turns out that quicksort, true to its name, is one of the fastest algorithms for sorting a list. If you take CS230 and CS231, you will learn (among other things) much more about various sorting algorithms and how to compare them in terms of efficiency.


    Task 3: Faces

    In this problem, we will model simple cartoon faces like those shown below:

    Each face is characterized by the following features:

    For example, the following table shows the values for the color (r = red, g = green, and b = blue), happiness (h) and sleepiness (s) of each face in the corresponding position in the figure above:

    r=255, g=0, b=0,
    h=0.0,
    s=0.0
    r=255, g=63, b=0,
    h=0.25,
    s=0.0
    r=255, g=127, b=0,
    h=0.50,
    s=0.0
    r=255, g=191, b=0,
    h=0.75,
    s=0.0
    r=255, g=255, b=0,
    h=1.0,
    s=0.0
    r=255, g=0, b=63,
    h=0.0,
    s=0.25,
    r=255, g=63, b=63,
    h=0.25,
    s=0.25
    r=255, g=127, b=63,
    h=0.50,
    s=0.25
    r=255, g=191, b=63,
    h=0.75,
    s=0.25
    r=255, g=255, b=63,
    h=1.0,
    s=0.25
    r=255, g=0, b=127,
    h=0.0,
    s=0.50
    r=255, g=63, b=127,
    h=0.25,
    s=0.50
    r=255, g=127, b=127,
    h=0.50,
    s=0.50
    r=255, g=191, b=127,
    h=0.75,
    s=0.50
    r=255, g=255, b=127,
    h=1.0,
    s=0.50
    r=255, g=0, b=191,
    h=0.0,
    s=0.75
    r=255, g=63, b=191,
    h=0.25,
    s=0.75
    r=255, g=127, b=191,
    h=0.50,
    s=0.75
    r=255, g=191, b=191,
    h=0.75,
    s=0.75
    r=255, g=255, b=191,
    h=1.0,
    s=0.75
    r=255, g=0, b=255,
    h=0.0,
    s=1.0,
    r=255, g=63, b=255,
    h=0.25,
    s=1.0
    r=255, g=127, b=255,
    h=0.50,
    s=1.0
    r=255, g=191, b=255,
    h=0.75,
    s=1.0
    r=255, g=255, b=255,
    h=1.0,
    s=1.0

    In the following parts, you will be implementing in stages the following drawFace class method within the Face class:

    public static void drawFace (Graphics g, Rectangle r, Color c, double h, double s)
    Using graphics context g, draws a face with color c, happiness h, and sleepiness s in the specified rectangle r.

    Task 3a: Put on a Happy Face

    In this part, you are to begin implementing the drawFace class method. For this part, you should ignore the actual happiness parameter h and sleepiness parameter s and assume that they both have values 1.0. That is, the face you draw should be happy and alert. However, your method should draw the face using the actual color c of the face. When you run the ManyFaces.html applet, the goal is to get the following picture:

    Below is a diagram of a happy face inscribed in the unit square indicating the placement of the eyes, nose, and mouth. You should draw the happy face exactly as depicted in this diagram.

    Notes:

    Task 3b: Sleepy Faces

    In this part, you are to modify the implementation of your drawFace method so that it correctly shows droopy eyelids for sleepy faces, as shown below:

    A face with sleepiness factor s (between 0.0 and 1.0) should have "eyelids" covering a fraction s of the height of the eyes from the top to the bottom. This effect can be achieved as follows:

    Note that, according to its contract, the drawOval() method covers an area that is width + 1 pixels wide and height + 1 pixels tall. In contrast, the the fillOval() method covers an area that is width pixels wide and height pixels tall. Because of this discrepency, to get your picture to "look right" you may need to subtract 1 from the width and height arguments of drawOval().

    Task 3c: Drawing Happiness

    In this part, your goal is to modify the mouth-drawing part of your drawFace method so that it takes into account the happiness of the face. A face with happiness 0.0 should have a line as a mouth, while larger happiness values (up to 1.0) should be drawn as filled half-ovals whose height is proportional to the happiness value.

    For example, here are faces whose happiness value changes from left to right:

    Here is the specification for the mouth that you should implement:

    The above specification can be implemented via a single invocation of the fillArc() method that handles all happiness values between 0.0 and 1.0. The key to getting this to work is to determine the coordinates of the rectangle in which the arc is inscribed as a function of the happiness value. Do not attempt to do this by trial and error! Instead, determine the correct formula on a sheet of paper before you attempt to implement this part!


    Extra Credit Challenge: Create Your Own Picture [up to 5 points]

    This is a completely optional problem. You should only attempt it after completing the rest of the assignment.

    You can use Java graphics as a tool to create fascinating pictures. Here is a chance to be artistically creative and earn some extra credit points at the same time.

    For this challenge, flesh out the paint() method in the MyPicture class within the MyPicture folder to draw whatever picture you imagine. If you like, you can draw more than one by making copies of MyPicture.java where the files (and the contained class) have different names.

    Notes: