Graphic by Keith Ohlfs |
Problem Set 9
|
[CS111 Home Page] [Syllabus] [Students] [Lecture Notes] [Assignments] [Programs] [Documentation] [Software Installation] [FAQ] [CS Dept.] [CWIS]
The purpose of this problem set is to give you experience with lists of lists (Task 1) and with graphical user interfaces (Task 2). In Task 2, you will also get experience writing a complete program almost entirely from scratch.
Homework Problems :
Turn in only one package of hardcopy materials. Staple your files together with the cover page, and submit your hardcopy package by placing it in the box outside of Stanzi's office (SCI E106).
Reminders
Lists of lists are useful data structures for holding lists of possibilities. For example, as seen in lecture and lab, we can use them to hold the list of all permutations and subsequences of a list of numbers.
In this problem, we will use lists of lists to represent all the possible ways of making change for a given amount of money using an unlimited number of coins from a given list of denominations. You may assume that the amount of money is a non-negative integer, and that the list of coin denominations is a list of distinct positive integers ordered in decreasing order. When making change for the given amount, you may use any number of "copies" of the coins in the denomination list.
In the resulting list of lists, each element (which we shall call a change list) should be a list of coin values sorted in order of decreasing value whose sum is the given amount of money. These change lists should be ordered in reverse lexicographic order (i.e., reverse dictionary order). That is, change lists with a larger first coin come before change lists with a smaller first coin. If two change lists have the same first coin, the one with the largest second coin goes first. And so on.
Here are a few simple examples:
Amount of money |
Denominations |
Ways to Make Change |
---|---|---|
5 |
[5,1] |
[[5], [1,1,1,1,1] ] 1 nickel or 5 pennies |
16 |
[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] ] |
|
|
|
|
|
[[10, 10, 1], [10, 5, 5, 1], [10, 5, 1, 1, 1, 1, 1, 1], [10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [5, 5, 5, 5, 1], [5, 5, 5, 1, 1, 1, 1, 1, 1], [5, 5, 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] ] |
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 denominations provided in descending order of value. To
do this, you will flesh out the makeChange()
method in
the ChangeMaker.java
file within the ChangeMaker
folder of ps9_programs. The contract for
the method is as follows:
public
static
IntListList makeChange (
int
amount, IntList coins)
Assume that amount is a non-negative integer and that coins is a list of distinct positive integers in descending order. Returns a list of all possible change lists, where a change list is a list of denominations taken from coins (potentially with duplicates) whose sum is amount. The denominations in a change list should be in descending order. The change lists themselves should be ordered in reverse lexicographic order.
makeChange
involves working with
IntList and IntListList lists, we can no longer just
use list methods and operators without the class name because Java
won't know which method we want (i.e. do we want the one that
applies to the IntList or the IntListList class?).
Instead, we must specify the name of the class with the method
(e.g. IntList.prepend
or
IntListList.prepend
). However, specifying the full
name of the class makes the code harder to read so we have
provided you with the following "shortcut" way to refer to IntList
and IntListList methods and operators for doing this problem.
|
|
IL.empty IL.prepend IL.head IL.tail IL.isEmpty IL.length IL.append IL.postpend |
ILL.empty ILL.prepend ILL.head ILL.tail ILL.isEmpty ILL.length ILL.append ILL.postpend |
public static IntListList mapPrepend (int n, IntListList L) { if (ILL.isEmpty(L)) { return L; } else { return ILL.prepend (IL.prepend(n, ILL.head(L)), mapPrepend(n, ILL.tail(L))); } }
Correct Test Case Answers
---------------------------------------------------- There are 2 ways to make change for 5 cents using [10, 5, 1]: [[5], [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 9 ways to make change for 21 cents using [25, 10, 5, 1]: [[10, 10, 1], [10, 5, 5, 1], [10, 5, 1, 1, 1, 1, 1, 1], [10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [5, 5, 5, 5, 1], [5, 5, 5, 1, 1, 1, 1, 1, 1], [5, 5, 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] ] ---------------------------------------------------- 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] ] ---------------------------------------------------- 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]: [ ] ----------------------------------------------------
This problem involves a simple game in which a player guesses the red, green, and blue components of a randomly chosen color. The game is played using an applet whose initial appearance is as follows:
The applet has the following parts:
Pressing the New Game button starts a new game. Starting a new game zeroes out the three text fields and displays a randomly chosen color on the canvas, which we will refer to as the secret color. It also displays the message "Press Guess to make a guess; Hint for a hint." in the message line.
The goal of the game is to guess the RGB (Red/Green/Blue) components of the secret color. Recall that RGB components are numbers between 0 and 255. A guess is entered by typing numbers into the three text fields and pressing the Guess button. Here is the result of a first guess:
Whenever a guess is made, the canvas is changed to show a rectangular "ring" with the guessed color. In this example, the guessed color is a light purple while the secret color is a darker purple. The area outside the ring and the the "hole" inside the ring both show the secret color. Showing secret color both outside and inside makes it easier to compare the guessed color to the secret one. The "thickness" of the ring segments are one-fifth the size of the canvas in each dimension.
Since it is surprisingly difficult to get the colors to match, a "hint" option is provided. Pressing the Hint button indicates for each color component whether it needs to be made larger, smaller, or kept the same. (In this respect, the game is like the classical game of Hi/Lo, except that it is played with three secret numbers at once.) As with guesses, hints are numbered. For example, pressing the Hint button in our running game yields.
Play continues with the player making more guesses and optionally choosing to see hints. Below are some snapshots from a running game.
As indicated by the last of the above pictures, the differences between the guessed color and the secret color can be so small as to be almost undetectable by the human eye. Human vision is not the only problem; some computer screens/and or color mapping software don't accurately display all subtle color differences. In this case, the hint information is extremely helpful for getting the "correct" answer!
When the correct RGB value has been guessed, the message line displays a message indicating this fact, along with the number of guesses and hints that were used in the process.
Using binary search in conjunction with hints, it is possible to guess the components of any secret color in no more than 8 guesses. But you can achieve this result even if you don't see the secret color! With enough practice, you can do better than 8 guesses if you use the feedback provided by the color in the canvas. (If there is sufficient interest, we can hold a contest to see who can reliably guess colors with the fewest number of guesses.)
In some cases, a player may just want to surrender and be shown the answer. To do this, the player presses the I Give Up! button. Here is the result of doing this in a different game:
The Guess, Hint, and I Give Up buttons only work when there is a game in progress. Pressing these buttons when one game has finished but a new one has not yet begun (by pressing the New Game button) results in the following error message in the message line:
Your task is to implement the "Guess the Color" game described above. You will be writing the program almost entirely from scratch. All you are given is a rather empty skeleton file GuessTheColor.java, which you must flesh out to have the appearance and behavior of the applet described above. Here are some notes/hints on how to proceed:
// Returns a randomly chosen integer between LO and HI, inclusive, // with approximately uniform distribution. private int intBetween (int lo, int hi) { return lo + (int) (Math.random() * (hi + 1 - lo)); }
The Guess the Color game can be improved in many ways. Below are some improvements you might want to implement for extra credit. Feel free to extend the game in other ways you find interesting.
To submit extra credit, create a copy of the GuessTheColor folder named ExtraCredit that contains all of your modified code. For your softcopy, upload your ExtraCredit folder to the ps9 drop folder. For your hardcopy submission, submit (1) a description of what modificiations you made to the program and (2) your final version of GuessTheColor.java.