M
|   | Problem Set 6 Due on Friday 3 November at the start of class | 
The purpose of this problem set is to give you more experience with recursion and writing recursive methods that return values.
In each of these three problems, you are asked to create a Java class from scratch rather than fleshing out the methods of a skeleton class. This will give you practice with creating Java classes.
The code for Tasks 2 and 3 is available in 
the ps06_programs directory in the cs111 download 
directory on the CS server.
There are also three optional extra credit problems.  
In Extra Credit Challenge 1, you can
use recursion to have a turtle draw a diamond pattern and return the
number of diamonds drawn.  In Extra Credit Challenge 2, you can
implement another recursive quilt pattern.  In Extra Credit Challenge
3, you are asked to design your own recursive buggle/turtle/picture
patterns.  The code for the Extra Credit Challenges is available in
the ps06_programs_extra folder in the cs111 download
directory on cs.wellesley.edu.
MyFunctions.java file Part b of Task 1;  
  HarvestWorld.java file from Task 2;  
  MazeCounterWorld.java file from Task 3;  
Staple these together, and submit them at the start of class on the due date.
Save your new MyFunctions.java file
and the modified SierpinskiQuilt.java and
HarvestWorld.java files in the ps06_programs
folder.  Submit the entire ps06_programs folder to your
drop folder on the cs111 server. 
DiamondWorld.java file from Extra Credit Challenge
    1 (if you did this problem) .
  TriQuiltWorld.java file from Extra Credit Challenge
    2 (if you did this problem) .
  MyBuggleWorld.java, MyTurtleWorld.java,
    and/or MyPictureWorld.java files from Extra Credit Challenge
    3 (if you did this problem).
    public static int f (int n) {
	if (n <= 2) {
	    return n;
	} else {
	    return n + f(n/2) + f(n/3);
	}
    }
Part a:
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. 
As an example of such an invocation tree, below is a definition
of a recursive Fibonacci function and a sample invocation tree
for the invocation fib(8):
    public int fib (int n) {
        if (n < 2) {
            return n;
        } else {
            return fib(n-1) + fib(n-2);
        }
    }
Part b:
In DrJava, create a new file named MyFunctions.java
containing a MyFunctions class. Your class should have
three class (i.e., static) methods: 
f from above
fPrint that is just like
f except that it uses System.out.println
to display every time the method is entered and exited. 
It should have a structure similar to the factPrint 
method in Factorial.java and the 
fibPrint method in Fibonacci.java. 
main that permits invoking the above 
two methods in the DrJava Interactions pane using
the MyFunctions application as 
illustrated by the following examples: 
java MyFunctions f 40
java MyFunctions fPrint 30
Your main method should have a structure similar to the 
main methods in 
Factorial.java and Fibonacci.java. 
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 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:
Each 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:  That is the path
that buggles walk on to get from row to row.
Each row is harvested according to the following procedure:
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.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
Harvesterbuggles 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 theHarvesterbuggle 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.
Finally, the Harvester buggle must
count the number of bagels harvested in the field and report that to
her supervisor.
The following two pictures show the state of a field before and after the buggle has harvested it.
|  |  | 
Your task is to write the Harvester class, which will
contain the methods that allow the 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 
below (as usual, you can
download the program files from the download directory).  Each method
must satisfy the specification given. 
In addition to their individual specificaitons, all the methods described below must also meet the following invariant:
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 facingEAST. 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 facingEASTand in the bottom row (the clear path) of the field. Harvesting a row involves the following steps:
- Pick up and count all the bagels in the row
- Put the bagels out to dry in a row starting from the bottom but not including the very bottom row
- Pulling the tarp over the rest of each row by walking to the end of the row and coloring the row black until you've reached the bagels
- Marking the row as fair (no color), good (green), or bad (red) by coloring the first (bottom) square of each row. A row produced a good harvest if there are more bagels than blank spots. A row produced a bad harvest if there are fewer bagels than blank spots.
- Marking the row by dropping the number of blank spots in the bottom square.
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 facingNORTHand 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 facingNORTHand 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 facingNORTHand 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 ifnumberBagelsis greater thannumberSpaces. The current cell is painted red ifnumberBagelsis less thannumberSpaces. The current cell is not painted if thenumberBagelsis equal tonumberSpaces. The buggle also marks the cell with thenumberSpaces(usingdropInt()).
Notes:
Use paintCell() to color cells:
public void paintCell (Color c)
Paints the cell under this buggle with the colorc
Use dropInt() to drop an integer
into a particular cell:
public int dropInt (int n)
Drops the integerninto the cell of this buggle and returns the integer dropped.
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.
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:
 
  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
  ps06_programs.  This applet has
  a parameter window that looks 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 the MazeCounter
  class whose methods direct Maisy to count the number of bagels in
  any maze, annotating the cells with numbers, as shown above.  You
  should put your MazeCounter class definition in the
  MazeCounterWorld.java file in the MazeCounter
  folder of ps06_programs.  Your class should
  contain a defintion for the following method:
  
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.
  
  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 may 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 integerninto the cell of this buggle and returns the integer dropped.
In this problem, your job is to use recursion to draw diamond-based pictures in TurtleWorld, as shown below. The diamonds are just squares turned on end at a 45-degree angle.
| 
 | |||||
| 
 | |||||
| 
 | 
 | ||||
| 
 | 
 | ||||
| 
 | 
 | 
 | 
 | 
 | 
 | 
| 
 diamonds = 8 | 
 diamonds = 5 | 
 diamonds = 4 | 
 diamonds = 3 | 
 diamonds = 2 | 
 diamonds = 1 | 
Diana is a DiamondMaker, a special breed of turtles
  that draw these kinds of patterns based on the side length of the
  largest diamond.  Her initial position is at the bottom corner of the
  largest diamond in each picture; her initial heading is east.  The
  diamond touching the largest diamond to the right has 2/3 the side
  length of the largest diamond.  The diamond touching the largest
  diamond to the left has 1/3 the side length of the largest
  diamond.  This pattern is repeated for each new diamond drawn.  The
  new diamond on the right is now viewed in a new orientation where
  the top of the new diamond is 90 degrees in a clockwise direction
  from the larger diamond it touches.  Therefore, the "right" of this
  new diamond points "south" and the left of this new diamond points
  "north".  The new diamond on the left is now viewed in a new
  orientation where the top of this new diamond is 90 degrees in a
  counterclockwise direction from the larger diamond it
  touches.  Therefore, the "right" of this new diamond points to the
  "north" and the "left" of this new diamond points to the
  "south".  Each new diamond repeats the pattern of drawing a smaller
  diamond on its right and a smaller diamond on its left, if
  possible. 
Unlike other recursive turtles we have studied, Diana draws a
  pattern whose depth of recursion is not controlled by an explicit
  levels parameter.  Instead, it is
  controlled by the fact that Diana refuses to draw any line that is
  less than 5 units long.  For instance, in the picture where the
  largest diamond has a side length of 9,  Diana draws the smaller
  easterly diamond because its side length is (2/3)*9 = 6, which is
  greater than 5, but she does not draw the westerly diamond because
  its side length would be (1/3)*9 = 3, which is less than 5.
In addition to drawing the diamonds, Diana keeps track of the total number of diamonds she has drawn in the pattern. This number is indicated for each of the sample pictures above.
Your task in this problem is to implement the
  DiamondMaker class which must define the following
  instance method:
public int diamonds (double side)
Draws the recursive diamond pattern described above where the side length of the largest diamond isside. Returns the number of diamonds drawn. Draws no diamond whose side length is less than 5 units long. This method meets the invariant that the turtle's state (position, heading, color, pen state) is not changed by execution of the method.
Notes:
DiamondWorld.java,
     which is in the DiamondWorld folder of the
     ps06_programs_extra directory. 
 length is a double value, you
     can calculate 2/3 of length by (2*length)/3 or
     (2.0/3.0)*length.  However, the expression
     (2/3)*length will not work, since the integer
     division (2/3) yields 0.
  DiamondWorld.html applet.
   Test
    subdirectory of the DiamondWorld directory.  You should
    experiment with this test applet to better understand the behavior
    of DiamondMaker buggles.
triQuilt()
| triQuilt(black, cyan, 1) | triQuilt(black, cyan, 2) | 
| triQuilt(black,cyan,3) | triQuilt(black,cyan,4) | 
 Your goal in this pattern is to define a triQuilt method that
  creates the above pictures for any given colors and levels:
To complete this problem, put your definition of thepublic Picture triQuilt (Color c1, Color c2, int n)
Assume that n >= 1. Returns one of Gilda's quilts that is constructed out of triangles filled with colorsc1andc2. The parameterncontrols the nesting level of the patterns used in the quilt.
triQuilt() method
in the TriQuiltWorld.java file in the TriQuilt folder
in ps06_programs_extra.  You will want to define several auxiliary
methods as well.  Study the patterns in the example quilts above carefully to
determine what auxiliary methods you need.
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 ps06_problems_extra directory.
  Feel free to define any methods you desire to create your patterns.
Some notes: