![]() Graphic by Keith Ohlfs |
Problem Set 6
|
[CS111 Home Page] [Syllabus] [Assignments] [Documentation] [FAQ] [CS Dept.] [CWIS]
The purpose of this problem set is to give you more experience with recursion and writing recursive methods that return values. Task 1 is a pencil-and-paper problem in which you will draw an invocation tree for a recursive function. In Task 2, you will use recursion in PictureWorld to generate a recursively structured quilt. In Task 3, you will use recursion in BuggleWorld to implement the elaborate buggle bagel-harvesting ritual. The code for Tasks 2 and 3 is available in the ps6_programs folder in the cs111 download directory on nike.
There are also two optional extra credit problems. In Extra Credit Challenge 1, you can use recursion to have buggles count the number of bagels in a maze. In Extra Credit Challenge 2, you are asked to design your own recursive buggle/turtle/picture patterns. The code for the Extra Credit Challenges is available in the ps6_programs_extra folder in the cs111 download directory on nike.
Patchwork.java
file from Task 2;
HarvestWorld.java
file from Task 3.
MazeCounterWorld.java
file
from Extra Credit Challenge 1 (this part is completely optional).
MyBuggleWorld.java
,
MyTurtleWorld.java
,
and/or MyPictureWorld.java
files from Extra Credit Challenge 2
(this part is completely optional).
Save the modified Patchwork.java
and
HarvestWorld.java
files in the ps6_programs
folder. Submit the entire ps6_programs
folder to your
drop folder on the cs111 server.
If you complete any of the extra credit problems,
submit the entire ps6_programs_extra
folder to your
drop folder on the cs111 server.
public static int f (int n) { if (n <= 2) { return n; } else { return n + f(n/2) + f(n/3); } }Draw an invocation tree that summarizes the execution of the class method invocation
f(30)
.
Each node of the execution tree should have the
form f(arg):result
,
where arg
is the integer that
is the argument of the invocation of f
and
result
is the result of the invocation.
Keep in mind that dividing two integers in Java always returns an integer result. For example, (15/2) returns 7, (5/2) returns 2, and (5/3) returns 1.
Your goal in this problem is to write a recursive method that draws the following Picture in PictureWorld:
This picture is specified by the following method in the file Patchwork.java within the folder Patchwork:
In this problem, you are to write a recursive definition of the following method:
public Picture patchwork(int levels, Color c1, Color c2, Color c3, Color c4)
Returns a picture of the above pictured staircase pattern nested levels levels deep, using colors c1, c2, c3, and c4
To see the picture created by patchwork(n, Color.red, Color.yellow, Color.blue, Color.green) for values of n between 0 and 6, experiment with the test applet Patchwork.java within the Test subfolder of the Patchwork folder. Select patchQuiltn from the pulldown menu in the applet, where n ranges from 0 to 6.
Important Notes:
Your final definition for patchwork
should be very short. You should be able to write
the definition in a handful of lines without defining any auxiliary
methods of your own. However, you can use any of the methods
in the PictureWorld
contract,
as well as any of the
following auxiliary methods, which we have provided for you:
public Picture patch(Color c) Return a picture that consists of a solid patch of color c public Picture fourPics(p1, p2, p3, p4) Return a picture that consists of four pictures p1, p2, p3 and p4, with p1 in the upper left corner, p2 in the upper right corner, p3 in the lower left corner and p4 in the lower right corner.
Note: Please read this entire
problem carefully. Simply generating the correct final pattern is not
enough to get full credit. Each specified method must behave as
described below. Bagels in BuggleWorld grow in fields (you knew
that, didn't you?). Twice a year the Each Each row is harvested according to the
following procedure: The buggle stacks the bagels in a row near
the path (starting from the second cell up) so that they will be
able to dry (dried bagels are the best and keep fresh all year
long). The rest of the field needs to be covered
with tarp (black) which preserves the field from bad weather
during the non-growing season. The tarp is at the far end of the
row (i.e. at the top of the BuggleWorld grid). The buggle needs to
go to the end of the row and pull the tarp up to the point where
the bagels are stacked. The buggle should count the number of
empty spaces left in each row (spaces covered by the
tarp). While the Finally, the The following two pictures show the state of a
field before and after the buggle has harvested it. Your task is to write the methods that will
make the
In addition to their specificaitons,
all the methods described below must also meet
the following invariant:
Notes: Use Use Test your methods by executing the
HarvestWorld.html
applet. When you first load the applet, the BuggleWorld grid is
empty. Hit Reset to generate a bagel field. Every time you
Run this applet, the number of bagels reported by the
Harvester
buggle will appear in the cyan box within the parameter frame
window. A working applet can be found in the
test subfolder
of the HarvestWorld
folder. You should experiment with this test applet to better
understand the behavior of Harvester
buggles. Hint: It may be easier to write the methods in
the reverse order from the order listed above. That is, you might
want to start by writing the markRow() method.
This is a completely optional problem. You should only attempt
it after completing the required parts of the assignment.
Before starting this problem, you should read over the
notes on the PathfinderWorld example.
Maisy Buggle comes from a long line of maze-navigating buggles.
But unlike other buggles, she is not satisifed with stopping when she
finds the first bagel in a maze. She wants to explore the world and
find out how many bagels there are in the entire maze! For instance,
suppose Maisy starts at "home" (facing eastward at point (1,1)) in
the following maze:
Task 3: Harvest World
Harvester
buggles
go out and harvest bagels so that buggles in BuggleWorld will have
bagels to eat and play with throughout the year. Bagels are the most
important commodity in BuggleWorld. Therefore, their harvesting
procedure is quite complex and elaborate. It is described
below:Harvester
is assigned a field
of bagels to harvest. The buggle does not know the width or height of
the bagel field. The buggle starts in the bottom left corner of the
field and harvests bagels one row at a time (a row is a vertical
column on the BuggleWorld grid). It doesn't matter if the buggle
chooses to harvest the closest row first and work down to the end of
the field or to walk to the end of the field and harvest rows on the
way back to the beginning. Note that there are no bagels planted in
the bottom horizontal row of the field. Instead, that is the path
that buggles walk on to get from row to row.The buggle harvests the bagels in the
row by picking them up and counting them. It doesn't matter if the
buggle picks up bagels on the way to the end of the row or picks
them up coming back from the end.
Harvester
buggles do
all the work, their supervisors want to be able to quickly look at
the field and see how it did. It's a bit difficult to see the
entire field, so the Harvester
buggle must mark each
row indicating whether or not the row did well. Bad rows (fewer
bagels than blank spaces) are marked red and will get more
fertilizer and attention in the next growing season. Good rows
(more bagels than blank spaces) are marked green. Fair rows (same
number of bagels as blank spaces) are left uncolored. Each row is
also tagged with the number of empty spaces (i.e. spaces covered
with black tarp). See the pictures below for
clarification.Harvester
buggle must
count the number of bagels harvested in the field and report that to
her supervisor.
Harvester
buggle do its job. You are free to
write any auxiliary methods needed. At a minimum, you must
define the following methods for the Harvester
class.
The complete specifications for each method are given in
HarvestWorld.java
(as usual, you can download the program files from the download
directory). Each method must satisfy the specification in the
code file. The descriptions below are intended to supplement and
clarify the specifications in the code file.
The buggle's state (position, heading, color, and brush state) will
not be changed by execution of this method. Assumes the buggle's
brush is initially up.
public int
harvestField()
This method assumes that the buggle is starting in the lower left
corner of a field facing EAST. When this method is invoked, the
buggle will harvest the field of bagels to its front and left (up to
the walls in front of and to the left of the buggle) and return the
number of bagels harvested in this field.public int
harvestRow()
When this method is invoked, the buggle will harvest the row of
bagels to its left (i.e. the vertical column above the
buggle). The number of bagels harvested in this row is returned. This
method should be invoked when the buggle is facing EAST and in the
bottom row (the clear path) of the field.public int
harvestBagels()
When this method is invoked, the buggle will pick up all the bagels
between it and the wall and return the number of bagels picked up.
This method should be invoked when the buggle is facing NORTH and in
the bottom row (the clear path) of the field.public void
stackBagels(
int
numberBagels)
When this method is invoked, the buggle will create a stack of the
specified number of bagels in front of itself. This method
assumes that there will always be at least enough space in front of
the buggle for the bagel stack. This method should be invoked when
the buggle is facing NORTH and in the bottom row (the clear path) of
the field.public int
pullTarp()
When this method is invoked, the buggle should draw a black line
from the wall in front of the buggle to the current
cell in front of the buggle (i.e. do not color the cell the
buggle is on when the method is invoked). This method returns the
number of cells colored. This method should be invoked when the
buggle is facing NORTH and at the end of its bagel stack (i.e. right
where the tarp should start).public void
markRow(
int
numberBagels,
int
numberSpaces)
This method paints the current cell green if numberBagels is greater
than numberSpaces. The current cell is painted red if numberBagels is
less than numberSpaces. The current cell is not painted if the
numberBagels is equal to numberSpaces. The buggle also marks the cell
with the numberSpaces (using dropInt());paintCell
to color cells:
public void
paintCell (Color c)
Paints the cell under this buggle with the color
cdropInt
to drop an integer
into a particular cell:
public int
dropInt (int n)
Drops the integer n into the current cell and
returns the integer dropped.
Extra Credit Challenge 1: MazeCounter
Using the same maze-navigating strategy followed by the PathFinder buggle described in the the PathfinderWorld notes, Maisy can traverse the entire maze and determine that it contains 17 bagels. Suppose that, after exploring the submaze accessible from a given cell, Maisy writes in the cell the number of bagels in that submaze. Then after she returns to her home position, the maze would be annotated as follows.
Note that the number in each cell is the number of bagels to the left, right, in front of, and under Maisy when she is in a cell (assuming she is facing the direction in which she entered the cell).
To get a better sense for how the above numbers are generated, you should experiment with the test applet MazeCounterWorld.html within the Test subfolder of the MazeCounter folder of ps5_programs. This applet has a parameter window that look like this:
The numbers in yellow control the side length of the maze and the number of bagels placed randomly in the maze. If you change these and press the Reset button, a new maze will be created with these parameters. The cyan-colored box labelled result is where Maisy writes the total number of bagels in the maze when she returns home. For example, after Maisy has explored the maze depicted above, the parameter window changes to:
Before proceeding with this problem, you should play with the test applet and study the above pictures until you understand how the numbers for each cell are determined.
Maisy is a member of the MazeCounter class of buggles. Your goal in this problem is to define a collection of methods in the MazeCounter class that direct Maisy to count the number of bagels in any maze, also annotating the cells with numbers, as shown above. You should flesh out the skeleton of the MazeCounter class in the MazeCounter folder of ps5_programs. This skeleton contains a "stub" version of a method with the following contract.
public int countBagels()
Counts the number of bagels to the left, right, in front of, and under this buggle.Drops this number in the cell under this buggle, and then returns it.Leaves the state of this buggle unchanged.
You should replace the stub with a method that works. As part of your solution, you should define any auxiliary methods that you find helpful. It is strongly recommended that you use a decomposition similar to the one used in for the PathFinder buggle. Your solution should work for any maze size and any number of bagels. (Warning: do not attempt to place more bagels in the maze than there are grid cells. This situation is not handled gracefully, and will cause your machine to crash.)
In order to drop an integer in a cell, you will need to invoke the following Buggle primitive:
public int dropInt (int n)
"Drops" the integer n in the cell of this buggle. The cell shows the most recently dropped integer. This method returns the integer that was dropped.
This is a completely optional problem. You should only attempt it after completing the rest of the assignment.
We have seen that fascinating recursive patterns can be created in BuggleWorld, TurtleWorld, and PictureWorld. In this problem, we ask you to create your own recursive patterns in one or more of these worlds.
Start with the folders MyBuggleWorld
,
MyTurtleWorld
, and
MyPictureWorld
in the
ps6_problems_extra
folder.
Feel free to define any methods you desire to create
your patterns.
Some notes: