![]() |
Wellesley College, Summer 2003
Problem Set 5Due: Fri, June 27 by 10 am |
The purpose of this problem set is to give you experience with recursion. Task 1 is a pencil-and-paper problem in which you will draw an execution diagram for a recursive buggle program. In Task 2, you will use recursion in TurtleWorld to generate a self-similar picture. In Task 3, you will use recursion in BuggleWorld to produce quilt designs with bagels. The code for Tasks 2 and 3 is available in the BagelQuiltWorld and SierpinskiWorld subfolders of the ps5_programs folder in the CS111 download directory.
We have including working examples of the solutions to the programming problems in the Test subfolders of the BagelQuiltWorld and SierpinskiWorld folders. It is a good idea to run these programs to get a feel for what we are asking you to do. Your solutions should generate the exact same pictures as the test programs on all parameters, but it need not generate the pictures in the same way.
With the introduction of conditionals and recursion, programming becomes much more challenging than on your first few assignments. It is a good idea to think carefully about how to solve your problems before you sit down at a computer and start writing code. It has been our experience that attempting to solve these sorts of problems while sitting at the computer is a recipe for disaster, because it can easily turn into a frustrating trial-and-error nightmare. Instead, we suggest that you form study groups and talk about solution strategies with your classmates before attempting to write any code. Once you have settled upon a strategy, we suggest that you write your Java code first using pencil and paper and simulate it in your head to check for its correctness. Only as a last step should you type in your code and test it on the computer. As always, while you may discuss problems in English with your classmates, you may not discuss or share the Java code for solving these problems.
Notes, hints, and suggestions for Tasks 2 and 3 are given on a separate page. We want you to have freedom to think about the problem in your own way. Reading the hints page is not required. It's main purpose is to help you think about the problem if you don't know how to get started.
SierpinskWorld.java file from Task 2;
BagelQuiltWorld.java file from Task 3.
Save your modified SierpinskiWorld.java and
BagelQuiltWorld.java files in their respective folders.
Submit the entire ps5_programs folder to your
drop folder on the cs111 server.
The following recursive method is defined for the Recurser
subclass of Buggle:
public void spiral (int n) {
if (n > 0) {
forward(n);
left();
spiral(n - 1);
right();
backward(n);
}
Consider the following run() method in
the RecursionWorld subclass of
BuggleWorld:
public void run () {
Recurser rita = new Recurser();
rita.spiral(3);
}
For this task you are to draw a Java Execution Model
diagram that models the execution of run()
invoked on an instance (call it RW) of
RecursionWorld with a 5x5 grid.
Your JEM diagram should consist of two parts:
RecursionWorld
instance with object reference label RW and a
single Recurser instance with object reference
label R. In order to show how the state of R changes
over time, draw the object R as a table whose columns
are indexed by abstract states s1, s2, etc. that
indicate the values of the index variable for R in a
particular state. The state of R will change every
time it moves or turns. For example, here is such a table for three states
in which the initial state s1 has been fleshed out.
Your table should contain as many state columns as you need
to show all the states of R during the execution.
R s1 s2 s3 ... Position (1,1) Heading EAST Color red BrushDown true
run() returns. Although
Java can discard an execution frame when control returns from it, you
should not discard any frames when drawing your diagram.
In the code section of each execution frame, replace every
expression by its value. Use the notation R@s to denote
a reference to the object R in state s.
For example, in the first execution frame, the statement
rita.spiral(3); should be written as
R@s1.spiral(3);, and in the second execution
frame, the first three lines of code should be:
R@s1.forward(3); R@s2.left(); R@s3.spiral(2);
Here, s2 names the state of the buggle R after it has stepped three units forward and s3 is the state of the buggle after it has turned left from state s2.
You do not need a different state for every different point in
time because the buggle returns to previous states as it backs out
of the spiral. For instance, after executing spiral,
the buggle R should be in state s1 once again.
Let sierpinski(levels, side) be the notation for a Sierpinski gasket with levels levels and side length side. Then a recursive mathematical definition of sierpinski is as follows:
sierpinski(1,100) |
sierpinski(2,100) |
sierpinski(3,100) |
sierpinski(4,100) |
sierpinski(5,100) |
In this problem you will define a Java method that uses a turtle to draw Sierpinski's gasket. To begin this problem, download the SierpinskiWorld folder from the ps5_programs folder in the CS111 download folder. The file SierpinskiWorld.java contains a subclass of Turtle named SierpinskiMaker with a stub for the following method:
// Assume that the turtle's brush state is down.
// Draw a sierpinski gasket specified by levels and side.
// The turtle's position, heading, and color should be invariants of the method.
public void sierpinski (int levels, double side) {
// Put your code here.
}
Flesh out the definition of the sierpinski
method so that it draws the specified Sierpinski gasket and maintains the
turtle's position, heading, and color as invariants. Your method should
use recursion. You may define any auxiliary methods that you deem helpful.
SierpinskiWorld.java includes code that creates an instance of SierpinskiMaker and positions it toward the lower left hand corner of the screen facing east. A gasket whose lower left-hand corner is positioned at this starting point will be automatically centered in the TurtleWorld window.
Recall that the Turtle drawing primitives include the following:
Additionally, there are also versions of fd, bd, lt, and rt that take int parameters, so you can invoke these methods with either an integer or double floating-point value.public void fd (double n) Move the turtle forward n steps. public void bd (double n); Move the turtle backward n steps. public void lt (double angle); Turn the turtle to the left angle degrees. public void rt (double angle); Turn the turtle to the right angle degrees. public void pu (); Raise the turtle's pen up. public void pd (); Lower the turtle's pen down.
You should not need to use any other Turtle primitives other than those listed above. In fact, many solutions use only a subset of the primitives listed above.
Test your definition by specifying levels and side in the parameter
window and then clicking on the Run button in the TurtleWorld window. The
Reset button will clear the screen. Good parameter values are in the ranges
[0 ... 8] for levels and [100 ... 400] for side. If your program hangs,
you may need to "force quit" it by depressing the option, apple, and escape
keys all at the same time.
The Test subfolder of the SierpinskiWorld
folder contains a working version of SierpinskiWorld.html
that you can play with. Your solution should produce the same pictures
as this test applet. It's worth noting that there are many possible ways
to correctly decompose the problem, and the test applet uses only one possible
approach. Thus, while you must produce the same designs as the test applet,
you need not produce the designs in the same way as the test applet.
For instance, for large values of levels, you will see that
the test applet draws the lines of the gasket in a particular order.
While your applet must produce the same final picture, it may draw
the lines a different order.
To help improve sales, Quinton Buggle, the chief quilt designer at Buggle
Bagel Rug, has developed a recursive bagel quilt pattern that can be used
on a rug of any size. Here are examples of his pattern on square rugs with
side lengths 16, 17, 18, and 19:
|
|
|
|
|
|
|
|
|
|
|
|
The fundamental repeated unit in these quilts is a triangle of bagels of size n, where n measures the number of bagels on a side. Here is such a triangle for n = 8:
Given a square rug with dimensions m x m, bagel triangles of size (m/2) are placed at the corners, and then the pattern is repeated in the smaller square bounded by the outer bagels in the center of the rug. Here (m/2) means integer division, as performed by Java. If m is odd, the result is truncated down to the nearest integer. For example, both 6/2 and 7/2 yield 3. Note that if m is even, all border cells of the square are covered with bagels, but if m is odd, the middle cell of each side of the square will not contain a bagel. Quinton has decided that the smallest square that should contain bagels is a 2x2 square. So the pattern is empty when applied to a 1x1 square.
In this problem, you are given a skeleton of the QuiltBuggle class and asked to define the following method in this class:
// Assume that the buggle starts in the lower left-hand corner of a
// square whose side length is side, facing parallel to the bottom side.
// Drops bagels to form quinton's pattern within this square,
// and returns to its initial position and heading.
public void quilt(int side) {
// Put your code here.
}
Your quilt method should work for any integer; it should do nothing for
side lengths <= 1. It should be defined using recursion. You will also need
to define numerous auxiliary methods, many of which themselves will be
recursive.
You should write all your definitions within the QuiltBuggle class, which can be found in the file BagelQuiltWorld.java within the BagelQuilt folder of the ps5_programs folder. You can test your code by running the BagelQuiltWorld.html applet. In addition to the usual BuggleWorld window, this applet displays a parameter window that allows you to change the side length of the BuggleWorld grid. Pressing the Reset button causes the grid to have the side length specified in the parameter window.
The Test subfolder of the BagelQuiltWorld
folder contains a working version of BagelQuiltWorld project
that you can play with. Your solution should produce the same quilt designs
as this test applet. It's worth noting that there are many possible ways
to correctly decompose the problem, and the test applet uses only one possible
approach. Thus, while you must produce the same designs as the test applet,
you need not produce the designs in the same way as the test applet.
For instance, for large values of side, you will see that
the test applet drops the bagels of the quilt in a particular order.
While your applet must produce the same final picture, it may drop
the bagels in a different order.