CS111, Wellesley College, Spring 2003

Problem Set 2

Due: Tuesday, February 18 by 11 pm

About this Problem Set

This problem set is intended to help you understand how Java works and to give you practice using, designing, and writing methods. This problem set consists of a paper-and-pencil problem, two programming problem, and an extra credit programming problem. There is a contest associated with the extra credit problem (please see below) with PRIZES (hint: think Bagels!).

To get the code for this assignment, connect to cs111 download directory via Fetch and download the folder ps2_programs from the directory /cs111d.

Reading

JEM Examples

How to turn in this Problem Set

Save the modified RugWorld.java and FontBuggle.java files in the ps2_programs folder. Submit the entire ps2_programs folder to your drop folder on the cs111 server. Turn in a hardcopy of the JEM diagram from task 1 and your modified Writing2.java, RugWorld.java, FontBuggle.java, and HuggleWorld.java

When submitting your hardcopies, we ask that you turn in only one package of materials. Please staple your files together with a cover page, and submit your hardcopy package by sliding it under the door of Elena's office (E127, in minifocus).

IMPORTANT NOTES:

  1. Pay careful attention to upper and lower case letters in the filenames.
  2. Once you have used Fetch to upload a file to the cs111 server, you should be sure to doublecheck that the file was actually uploaded. You can do this in Fetch by verifying that the file is now listed in your directory. Not only should you check that the file is listed, but you should check that it does not have a size of 0K. If the file isn't listed or if the size for the document is 0K, this means that there was an error in transferring it via Fetch and you must re-upload the document. When transferring a folder, you should check that its contents have been uploaded correctly. That is, you should be sure to check that every single file that you wish to submit has been uploaded correctly. Often times, although not always, you will see a message "Connection Failed" when there is an error in transferring your files.
  3. It is your responsibility to keep a personal back-up of every file that you submit electronically until you have received a grade for the assignment. 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).

Task 1: Java Execution Model

In this part of the homework, you will use the Java Execution Model to draw an Execution Diagram that summarizes the execution of a simple Buggle program. It is important to become familiar with the conventions for drawing Execution Diagrams, since they are an important tool for explaining the behavior of Java programs. In particular, Execution Diagrams explain the meaning of method invocation, parameter passing, local variable declarations, and the this variable. You will be expected to draw an Execution Diagram on Exam 1.

Before continuing with this problem, please study the conventions for drawing execution diagrams (i.e. your notes from lecture and the reading for this problem set).

Your JEM Assignment

Below are the declarations for two classes: a SwapWorld class that is a subclass of BuggleWorld and a SwapBuggle class that is a subclass of Buggle.


public class SwapWorld extends BuggleWorld { public void run () { SwapBuggle bg1 = new SwapBuggle(); SwapBuggle bg2 = new SwapBuggle(); SwapBuggle bg3 = new SwapBuggle(); Point pt1 = new Point(6,3); Point pt2 = new Point(4,5); bg1.setPosition(pt1); bg2.setPosition(pt2); bg3.setPosition(new Point(pt1.x-pt2.x, pt1.y+pt2.y)); bg2.setColor(Color.blue); bg1.setColor(Color.green); bg2.left(); bg3.right(); bg2.swap(bg3); bg3.swap(bg1); } }   class SwapBuggle extends Buggle { public void swap (Buggle bg1) { Point pt1 = this.getPosition(); Point pt2 = bg1.getPosition(); Color c1 = this.getColor(); Color c2 = bg1.getColor(); this.setPosition(pt2); bg1.setPosition(pt1); this.setColor(c2); bg1.setColor(c1); } }

Suppose that Object Land contains an instance of the SwapWorld class that has the reference label SW1. Your assignment is to draw an Execution Diagram for the execution of the statement

SW1.run()

Please be careful. This code is specifically designed to be tricky in a number of places. Be sure to pay attention to the following:


Task 2: Buggle Word Writing using Methods

It is possible to use methods to expand the capabilities of the buggle word writing program from problem set 1. For example, using a larger grid, but fewer actual lines of code, a buggle can write the word "JAVA" multiple times, around the perimeter of the grid, as shown below:

Your assignment:

Using methods, create the above grid. The file Writing2.java contains Java code which creates a larger grid and defines a LetterBuggle, a new class of objects which extends the Buggle class. A new LetterBuggle named ellie has also been created for you, along with two LetterBuggle methods; writeName, and writeJ, as shown below:


//write the word "JAVA" around the perimeter of the grid
 
public void run () {
 LetterBuggle ellie = new LetterBuggle();
 ellie.writeName(Color.red, Color.blue, Color.yellow);
 
 // statements which will write the word in various colors around the perimeter of the grid
 
}
 
 
class LetterBuggle extends Buggle {
 
 //write the word "JAVA", in the appropriately colored letters, 
 //by invoking methods with appropriate color parameters for writing the individual letters
 //Note that the J and the V are always the same color, and each A can be a different color from the 
 // color of the J and V.
 public void writeName (Color c1, Color c2, Color c3) {
 
   //fill in with statements which will position this Buggle correctly to start writing
 
 
   this.writeJ(c1);//write the "J" in color c1
 
 
   // fill in with statements which will write the "A V A"  in the correct colors
 
 
 }

 //write the letter "J"
 public void writeJ(Color jcolor) {
         // set the buggle's color to jcolor
            
         this.left(); // face NORTH
	 this.forward(); // draw hook in lower left of "J"

        //the rest of the statements for writing a "J"
     }
		     
		     
     //methods for writing the other letters in the word JAVA
		     
}

Perform the following steps to solve the problem:
  • Add the rest of the code to the writeJ method so that it draws the letter "J". This code should be very similar to the code you used in problem set 1 for that purpose! Assume that when you start to write a letter (other than"V"), the buggle is in the lower left square of a 4x5 grid, facing the direction you are writing in. At the end of the method, make sure that the buggle is placed in the correct position and direction to start the next letter (at the lower left square of the next 4x5 grid, separated by one space from the previous letter, facing the direction of writing).
  • Note that the writeJ(Color jcolor) method takes a Color parameter jcolor. Use this parameter inside the body of writeJ() to set the Color of the Buggle appropriately.
  • Define similar methods (each also with a single Color parameter) to write an "A" and a "V". Note that "V" occupies a 3x5 grid instead of the 4x5 grid occupied by each of the other letters.
  • Add code to the writeName method so that it draws the word "JAVA" by invoking the methods which write the individual letters and using the three color parameters correctly.
  • Add code to the run method so that it draws the word 4 times around the perimeter of the grid, by invoking the writeName method repeatedly. You will need to make sure that you invoke writeName() with the correct 3 color parameters in the right order to match the given picture (above). You will need to come up with a way to turn and change your heading at each corner of the grid.
You must conform to the following rules:
  1. You may not invoke the "setPosition" or "setHeading" methods.
  2. You should use the methods "brushUp" and "brushDown" where appropriate.
  3. Each letter except "V" should fit in a 4x5 grid, and should be separated from the next letter by one blank space.
  4. The letter "V should occupy a 3x5 grid as shown.
  5. Ellie must draw the letters in the appropriate colors. All the colors used in the picture above are Color constants from the Color class. These constants are only used in the run() method. They may not be used anywhere else in your code.
  6. Ellie must end up in the position shown above, facing the correct direction (EAST).
  7. Use methods to solve the problem.

Task 3: The Buggle Bagel Ruggle Company


Important note: Before you begin working the second task, make sure to close the project that you were using for the first task by choosing Close from the File menu to close . Then double-click on the RugWorld.mcp icon to open the second project.

Alternatively, to be on the safe side (i.e. to make sure that you are not running the code from the previous task instead of the new one), you might want to quit CodeWarrior entirely and reopen it for the new project. To do this

  1. quit CodeWarrior (File -> Quit),
  2. quit the Applet Runner by selecting Apple Applet Runner from the menu of active applications in the upper right corner of the screen, then choosing Quit from the File menu,
  3. double-click on the RugWorld.mcp icon to open the second project

The buggles from Problem Set 1, becky, bobby, bertie, billy and benny, had the foresight to copyright their Buggle Olympic Symbol. As a result, they made a killing on the use of the logo for Buggle Olympics memorabilia and merchandise. So, they decided to invest in a rug-making enterprise: The Buggle Bagel Ruggle Company, which designs and weaves rugs made by dropping bagels in interesting ways on a BuggleWorld grid.

Here is an example of a rug they created:

The buggles are great designers, but, unfortunately, they don't know much about manufacturing. It takes so long to hand-drop the bagels individually that it's impossible to make any money. Luckily for them, there is a way to automate the production of the rugs. As it turns out, the design shown above can be produced using just 4 different 3x3 grids of bagel patterns:

pattern 1

pattern 2

pattern 3

pattern 4
The rug itself is created by placing these patterns side by side to tile the entire rug. The rug, divided into 3x3 grids (outlined in black lines), is shown below:

The rug pattern includes a lot of repetitive patterns. This means that there are many opportunities for using methods to generate the pattern efficiently. Your task is to write the code which will create the rug pattern shown above in the most efficient manner you can think of. The code for this problem is contained in the RugWorld folder. The file RugWorld.java contains the initial set-up for creating the rug shown above. becky, bobby, bertie, benny and billy have hired a RugBuggle (another new class of objects which extends the Buggle class) named weaver to produce the rugs. You should add your code to this file, but you should not remove any existing code.

You must observe the following constraints:

  • You can not modify any of the code in the run method.
  • You should use a single RugBuggle for the entire rug (weaver, who has already been created in the file).
  • You may not, and do not need to, use the setPosition() or setHeading() methods. You can use any of the other Buggle methods.
  • You should draw the colors and bagels exactly as shown in the rug.
  • The buggle must finish in the same place it started, facing the same direction (i.e. EAST).
  • You must create the rug pattern by using the 4 3x3 patterns shown above.
  • The buggle must start in the bottom left corner of each pattern (as shown above) facing EAST. The buggle must finish in position to start the next pattern element as shown below:

  •  

     
     




  • You must name the method that generates each of the four patterns above as pattern1, pattern2, pattern3, and pattern4, respectively. Each pattern should take two Color parameters. The first color is the color represented in black, and the second color is the color represented in yellow in the above pictures. Name your parameters c1 and c2. For example, the skeleton for the pattern1 method should look like this:
  • public void pattern1 (Color c1, Color c2) {
      // add code here
    }
  • You must also define the following methods:
    • makeRug: this method creates the entire rug; it has no parameters.

    •  

       
       
       
       
       
       
       

    • outerRing: this method draws the outer ring; it has no parameters. It should have two Color variables. Name your variables c1 and c2. c1 represents the outer color of the border (blue in this rug) and c2 represents the inner color of the border (red in this rug). A snapshot of the outerRing is shown below:

    •  

       
       





    • innerPattern: this method draws the inner pattern which is repeated twice in the rug as shown below:

    •  

       
       






      This method should take two Color parameters named c1 and c2. c1 will represent the areas colored in black above and c2 will represent the areas colored in yellow above. Note that the actual rug uses the colors cyan and pink in one instantiation of the pattern and green and orange in the other instantiation of the pattern.
       
       

    • innerRing: this method draws the border of the inner pattern. This method should also have two Color parameters. Follow the naming conventions as given for the other methods.

    •  

       
       



    • innerRow: this method draws the pattern in the center of the innerPattern. This method should have two Color parameters.

    •  

       
       



    • centerRow: this method draws the pattern in the center of the rug. This method should also have two Color parameters.
    The six methods above must meet the invariant that the buggle must start and finish in the same cell, facing the same direction. You must assume that the buggle starts in the bottom left corner of each pattern (as shown above) facing EAST and should finish that way.
Helpful Hints:
  • The paintCell(Color c) method can be used to paint the cell under the buggle a certain color without having to move the buggle. For example,

  • sara.paintCell(Color.gray);
    will paint the cell under sara gray. sara's brush state is not changed by the invocation of the paintCell method.
  • The RugBuggle's brush is initially up before making the rug.
  • You can temporarily modify the run method to test out small parts of your code. Comment out the invocation of makeRug and add what you want to test. Remember that you can comment out a line of code by adding // (two slashes) before that line of code.
  • The row patterns are created by alternating patterns 3 and 4 like so (pattern3--pattern4--pattern3):

     
  • You should feel free to add as many more methods as you see fit. There are many more opportunities for creating methods in this problem.


Extra Credit Task 4: HuggleWorld

Also see the contest conditions below!

Background

The Story

Fontaine Buggle is very impressed by the creative work of her cousins at the Buggle Bagel Ruggle Company. But she thinks that buggles can use their considerable talents to do more than just drop bagels in interesting patterns.

Inspired by the buggle writing problem of Problem Set 1 (remember "Java"?), Fontaine wants buggles to be able to write words using letters of any color drawn in rectangles of arbitrary size and orientation. As a simple example of what can be done with this capability, Fontaine designs the following Valentine card:

Valentine Figure

The card uses the seven letters 'C', 'd', 'G', 'H', 'I', 'P', and 'U'. Note that the 'U' appearing in "CUPId" and "HUG" has the same basic shape even though it is written in rectangles of different sizes (a 5x5 rectangle in the case of the 'U' in "CUPId" and a 7x17 rectangle int the case of the 'U' in "HUG").

Letter Methods and their Contracts

Fontaine recognizes that methods can be used to capture the similarity in shape while abstracting over the color and rectangle size. She defines a new FontBuggle class that is a subclass of Buggle extended with methods that draw the seven letters of the Valentine card. For example, the FontBuggle class has a method for drawing the letter 'U' according to the following contract:

public void U (Color col, int width, int height);

Assume the initial brush state of this buggle is down. Consider the width by height rectangle such that this buggle is in the lower left hand corner facing along the width edge. Executing this method causes this buggle to draw the letter 'U' inscribed in the rectangle, as shown below. The heading of the buggle should not change, but its final position should be width + 1 cells in front of its original position, its final color should be col, and its final brush state should be down.

Fontaine defines similar methods for the other six letters, whose contracts are the same as that for U() except for the shape inscribed in the rectangle. The shapes drawn by the C(), d(), G(), H(), I(), and P() methods are depicted below:

Java Arithmetic

The dimensions in the above pictures are given in terms of Java integer arithmetic. Java integer arithmetic is pretty much what you would expect except that division of two integers always yields the integer that results by truncating (not rounding) the decimal portion of the exact result. For example:

n

n/2

n/3

n/4

5

2

1

1

6

3

2

1

7

3

2

1

8

4

2

2

9

4

3

2

The following equations are also always true (both in Java arithmetic and traditional arithmetic):

1 + (n/2) = (n + 2)/2

1 + ((n - 1)/2) = (n + 1)/2

The reason that we prefer the left-hand side versions to the right-hand side versions in the above diagram is that the left-hand side versions turn out to be more useful when drawing the letters with buggles. (See the note on fencepost errors in the tasks section, below.)

You should also convince yourself that in Java integer arithmetic, the following equation is always true (this equation is not true for traditional arithmetic!):

n = 1 + ((n - 1)/2) + (n/2)

Stringing Letters Together

The final position and heading of a FontBuggle after drawing a letter is designed to facilitate stringing letters together to form words. If the FontBuggle is asked to draw a new letter, both letters will be on the same "baseline", and there will be one cell of space between the previous letter and the new one. For example, consider the following method for drawing the word "CUP":

public void CUP () {
  C(Color.blue, 3, 5);
  U(Color.green, 8, 3);
  P(Color.red, 4, 12);
}

Invoking the CUP() method on a FontBuggle causes it to draw the following letters:

Buggle Jumping

Since letters do not always directly follow one another, it is useful to have the following jump() method, which changes the relative position of a FontBuggle by fwd units in the forward direction and lft units to its left. (Either number may be 0 or negative.)

	public void jump (int fwd, int lft) {
	  brushUp();
	  forward(fwd);
	  left();
	  forward(lft);
	  right();
	  brushDown();
	 }

Because the parameters to jump() are relative to the buggle's current position and heading, the method works regardless of the buggle's initial state. After jumping, it is often desirable to turn the buggle; the following three methods abstract over the three possible ways of turning:

	 public void jumpAndTurnLeft (int fwd, int lft) {
	   jump(fwd,lft);
	   left();
	 }
	 
	 public void jumpAndTurnRight (int fwd, int lft) {
	   jump(fwd,lft);
	   right();
	 }
	 
	 public void jumpAndTurn180 (int fwd, int lft) {
	   jumpAndTurnLeft(fwd,lft);
	   left();
	 }

As an example of buggle jumping, consider the following method:

	public void fourCUPs () {
	  CUP();
	  jumpAndTurnLeft(4, 0);
	  CUP();
	  jumpAndTurnLeft(4, 0);
	  CUP();
	  jumpAndTurnLeft(4, 0);
	  CUP();
	  jumpAndTurnLeft(4, 0);
	}

Invoking fourCups() on a FontBuggle at position (3,3) facing eastward yields the following picture:

fourCUPs Figure

As another example of buggle jumping, consider the following testFont() method that draws the C(), d(), G(), H(), I(), P(), and U() shapes for 5x5, 4x4, 3x5, 4x4, and 4x3 rectangles for both the east and north buggle orientations:

	public void testFont() {
	  testSizes();
	  jumpAndTurnLeft(27,0);
	  testSizes();
	}
	
	public void testSizes() {
	  testLetters(5,5);
	  jump(-42,6);
	  testLetters(4,5);
	  jump(-35,6);
	  testLetters(3,5);
	  jump(-28,6);
	  testLetters(5,4);
	  jump(-42,5);
	  testLetters(5,3);
	  jump(-42,4);
	}
	
	public void testLetters(int w, int h) {
	  C(Color.red, w, h);
	  d(Color.green, w, h);
	  G(Color.black, w, h);
	  H(Color.blue, w, h);
	  I(Color.yellow, w, h);
	  P(Color.magenta, w, h);
	  U(Color.cyan, w, h);
	}

Executing testFont() should yield the following result:

FontTest Figure


Your Tasks

Your tasks in the problem are to define the following eight FontBuggle methods:

  • The seven letter-drawing methods C(), d(), G(), H(), I(), P(), and U().
  • A valentine() method that draws Fontaine's Valentine card design in a 51x51 grid, as depicted at the beginning of this problem.

You should begin the problem by downloading the HuggleWorld folder from the CS111 download folder. This folder has a file FontBuggle.java that contains skeletons of the eight methods you should define, as well as the jump(), jumpAndTurnLeft(), jumpAndTurnRight(), and jumpAndTurn180() methods described above.

The HuggleWorld folder also contains three .html for testing your methods:

  • After you have defined the C(), U(), and P() methods, run the CupWorld.html applet. This should yield the fourCUPs figure depicted above.
  • After you have defined all seven letter methods, run the FontTestWorld.html applet. This should yield the FontTest figure depicted above.
  • After you have defined all seven letter methods and the valentine() method, run the HuggleWorld.html applet. This should yield Fontaine's Valentine card design.
Note that the applets depend on the letter methods and do not work correctly until all the letter methods are written.

Hints/Notes:

  • For every FontBuggle method, you should assume that the brush state of the buggle is down when the method is called and when the method returns.
  • You should define any auxiliary methods that you find helpful.
  • Although you could define every letter method from scratch, it is recommended that you take advantage of the similarities between the letter shapes. For instance, a 'U' is a rotated 'C'. There are many other similarities between the letter shapes that can simplify their definitions!
  • Think carefully about your arithmetic when implementing the seven letter specifications pictured above. In particular, the discrete nature of buggles makes it very easy to introduce "fencepost errors" in which the buggle's position is off by one.

    For instance, suppose you want a buggle to draw the 'I' shape starting in the lower left-hand corner of the rectangle facing along the width. Then even though the base of the 'I' up to and including the stem is specified to be 1 + ((width - 1)/2) cells wide, the buggle should only go forward ((width - 1)/2) steps to draw half the base of the 'I' before turning left to draw the stem of the 'I'. The reason that no "1 +" is needed is that the initial cell occupied by the buggle should not be included in the number of forward steps. This is why all the "half" distances in the letter specifications have a "1 + " at the beginning: so it will be easy for you to subtract off the 1 in your code.
  • Because the trail drawn by buggle does not include the very last cell, you may find it helpful to sometimes use the public void paintCell (Color c) method, which paints the cell under the buggle with color c regardless of the buggle's color. Invoking this method does not change the color of the buggle.


Contest (Everyone should read the following!)

One advantage of methods is that they can be used to significantly shrink the size of a program, as measured by the number of lines of Java code. For the HuggleWorld program, we are having a contest to see how small you can make your FontBuggle class and still have it work correctly. The name of the winner(s) will be announced in the online conference and posted on the class web page! And the lucky winner(s) will receive gift certificates to Bruegger's Bagels ($10 for first prize and $5 for second). Buggles eat bagels!!

Traditionally, program size is measured by the number of lines in the program. Because this metric is very sensitive to the way you format your program (commenting, use of whitespace, placement of squiggly brackets, etc.), we will use a way of measuring the size of a Java program that is insensitive to formatting factors. In particular, we define the following two notions:

  1. The size of a method is one more than the number of statements in the body of the method. The extra one counts the "declaration header" of the method as a statement.
  2. The size of a class is the sum of the sizes of all the methods in the class.

For instance, the size of the jump() method described above is 7, while the three methods jumpAndTurnRight(), jumpAndTurnLeft(), and jumpAndTurn180() each have size 3. So these four methods contribue 16 to the size of the FontBuggle class.

To enter the contest, all you need do is calculate the size of your FontBuggle class and write it on your problem set cover sheet.

We would like to point out that, while making your program shorter is fun and may be a helpful exercise, in general it should not be your goal to make a program shorter. Shorter programs often lack clarity, and since programs are written not only for machines to execute, but also for humans to read, clarity is a far more important goal!

Some rules/hints:

  • You must include any auxiliary methods that you use in your size.
  • If you do not use some of the jump methods, you should not include them in your size.
  • You are not allowed to use any auxiliary classes. All the methods you define must be in the FontBuggle class.
  • Taking advantage of the similarity of shapes between letters is a good way to reduce program size.
  • Although introducing methods often increases the clarity of a program, some methods introduced to optimize the size of FontBuggle may make the class harder to understand rather than easier. If this is the case, you may want to write two versions of the FontBuggle class: a "clear" one to be graded as Problem 3, and a "small" one to be used for the contest. If you submit two versions of FontBuggle, clearly label which is for which purpose.
  • Although optimizing the size of your program is a fun challenge, you should be aware that, in practice, programmers are rarely concerned about making their source programs as small as possible. They are typically more concerned with optimizing the following characterisics of the program:
    • How large is the program after it is compiled?
    • How much time does the program require to run?
    • How much space does the program require in order to run?

    To learn much more about measuring the time and space resources required to run a program, you should take CS230 (Data Structures) and CS231 (Algorithms).