Algorithms and OOD (CSC 207 2014F) : Assignments

Assignment 3: Getting Started with Java, Testing, and Objects


Due: 10:30 p.m., Tuesday, 9 September 2014

Summary: You will explore a variety of issues related to Java programming

Purposes: To get you used to programming in Java. To get your brain back in problem-solving mode. To get you used to submitting homework via GitHub. To help you start thinking about objects. To get you accustomed to test-focused development.

Collaboration: You are required to work in a group. We will form groups on the day this assignment is distributed. You may discuss this assignment with anyone, provided you credit such discussions when you submit the assignment.

Wrapper (Prologue): Individually read through this assignment and make sure that you understand what is required. Then use the form available at http://bit.ly/207hw2pro to indicate (a) how long you think this assignment will take and (b) what you think will be the most challenging aspect of this assignment.

Wrapper (Epilogue): When you are done with the assignment, fill out the form available at http://bit.ly/207hw2epi to indicate (a) how long the assignment took, (b) what the most challenging part of the assignment was, and (c) something important you learned from doing the assignment. If you find that the assignment took much less or much more time than you expected, also include (d) a note as to what might have led to that difference.

Submitting: Please put all of your work in a GitHub repository named csc207-hw2. Email the address of that repository to grader-207-01@cs.grinnell.edu. Please use a subject of “CSC207 2014F Assignment 3 (Your Names)”.

Warning: So that this assignment is a learning experience for everyone, we may spend class time publicly critiquing your work.

A Quick Note on Arrays

A few problems in this assignment ask you to work with arrays. Arrays in Java work much like arrays in C except, except that you can find out the length of an array with array.length and you use the following approaches to initialize arrays.

     // Create an array of 10 integer values.
     int[] vals = new int[10];
     // Create an array with particular strings
     String[] profs = { "Davis", "Rebelsky", "Stone", "Walker", "Weiman" };

Assignment

Part A: Java as Imperative Language

Consider the six following static methods.

  • isMultiple, which takes as input two variables, a and b, of type long, and returns true if and only if there is an integer, i, such that a == b*i.
  • isOdd, which takes as input a variable, i, of type int returns true if i is odd and false if i is not odd. In solving this problem, you may not use multiplication, modulus, or division. You also may not use isMultiple.
  • oddSumTo, which takes as input a variable, n, of type int, and returns the sum of all positive odd numbers less than n.
  • isOddProd, which takes as input ints, an array of int values and returns true if any pair of numbers in the array has a product that is odd and false otherwise. Note that you can use ints.length to determine the length of the array.
  • allDistinct, which take as input an array of int values and returns true if no two elements have equal values and false otherwise.
  • reverseInts, which takes as input an array of int values and reverses their order in the same array.

We will group all of these in a class we call PartA. (How's that for creative naming?)

0. Write a class, PartA which contains stub versions of each method. A stub method is a really simple implementation that may not do what is advertised, but returns a value so that we can still compile the code and use it during development. For example, you might start with the follwoing.

public class PartA
{
  /**
   * Determine if a is a multiple of b.
   */
  public static boolean isMultiple(long a, long b)
  {
    // STUB
    return true;
  } // isMultiple(long, long)
} // class PartA

1. Write a class, TestPartA, which contains six methods, each of which tests one of the methods above. When creating this class in Eclipse, use New > JUnit Test Case Your tests should use the assertEquals(String message, type expected, type actual) method. For example, you might start with the following.

public class TestPartA
{
  @Test
  void test_isOdd(void) 
    throws Exception
  {
    assertEquals("negative even", false, PartA.isOdd(-4));
    // Integer.MAX_VALUE is 2^31 - 1, which is odd
    assertEquals("MAX_VALUE", true, PartA.isOdd(Integer.MAX_VALUE));
    ...
  } // test_isOdd

  @Test
  void test_reverseInts(void)
    throws Exception
  {
    assertArrayEquals(new int[] {}, 
                      PartA.reverseInts(new int[] {}));
    assertArrayEquals(new int[] { 1 }, 
                      PartA.reverseInts(new int[] { 1 }));
    assertArrayEquals(new int[] { 1, 2 }, 
                      PartA.reverseInts(new int[] { 2, 1 }));
    ...
  } // test_reverseInts
} // class TestPartA

2. Implement all of the methods in PartA.

Part B: Averaging

The following method has at least one subtle bug. Identify and correct that bug.

public class PartB {
  /**
   * Compute the average of two integers.  Rounds toward zero if the
   * average is not a whole number.
   */
  public static int average(int left, int right) 
  {
    return ((left + right) / 2);
  } // average(int,int)
} // class PartB

Hint: The algorithm works correctly for most pairs numbers. It only fails to compute the correct value for certain pairs of numbers. So think about what some special cases might be.

Part C: Designing Objects

When designing objects, a good first step is to consider what natural operations are associated with the object. Traditionally, we consider three kinds of operations:

  • Observers extract information from an object, but do not modify the object. For example, an might have an observer that extracts the value of a counter object.
  • Mutators modify objects. For example, we might have a mutator that increments the value of a counter object.
  • Constructors build new objects. For example, we are likely to want a constructor that creates a new counter object.

Some methods do more than one thing. For example, an object that represents an idea might have a method that creates a derivative idea. Such a method is a constructor, because it creates a new idea. But it's also likely to mutate our original idea (at the very least, by creating a link to the derivative).

Your goal in this problem is to reflect on the objects we might use in programming Ushahidi in Java.

First visit the class Ushahidi site at http://ushahidi1.grinnell.edu/sandbox. Explore a bit to understand the basic capabilities of Ushahidi. Submit a report on the site. Since it's a site for our use, you can do what you want for the submission. However, please be polite in what you write.

Suppose we want to represent the primary information for Ushahidi (at least the incidents). Sketch the classes you would use and the fields and methods you would include in each class. You may choose to write Java code with stub methods or you can put everything in a big comment.

Here's a sample stub method.

  /**
   * Get the name of the owner of this resource.
   */
  public String getOwnerName()
  {
    return "Casey Smith";
  } // getOwnerName()

When you need to return an object in a stub method, the easiest thing is to return the value null. (Okay, that may make other code break; but right now we're just trying to describe goals.)

  /**
   * Get the owner of this resource.
   */
  public UshahidiUser getOwner()
  {
    return null;
  } // getOwner()

Here's a comment that provides the same information as these two stub methods. The advantage of the comment is that we don't have to worry about getting the Java right for the compiler.

/*
   Method:      getOwnerName
   Type:        Observer
   Purpose:     Get the name of the owner of this resource.
   Parameters:  [none]
   Produces:    name, a String

   Method:      getOwner
   Type:        Observer
   Purpose:     Get the owner of this resource
   Parameters:  [none]
   Produces:    owner, an UshahidiUser
 */

Note that the object is implicit for methods associated with that object. Hence, you need not specify the object you are working with.

Part D: The Name Game

You may be familiar with a classic algorithm by Shirley Ellis entitled The Name Game. Ms. Ellis describes this algorithms for developing phrases based on her colleague's names as follows:

Come on everybody! 
I say now let's play a game 
I betcha I can make a rhyme out of anybody's name 
The first letter of the name, I treat it like it wasn't there 
But a B or an F or an M will appear 
And then I say bo add a B then I say the name and Bonana fanna and a fo 
And then I say the name again with an F very plain 
and a fee fy and a mo 
And then I say the name again with an M this time 
and there isn't any name that I can't rhyme.

She also gives us a number of examples:

Shirley! 
Shirley, Shirley bo Birley Bonana fanna fo Firley 
Fee fy mo Mirley, Shirley!

Lincoln! 
Lincoln, Lincoln bo Bincoln Bonana fanna fo Fincoln 
Fee fy mo Mincoln, Lincoln!

Write a method, nameGame, that takes as input a string and returns a string that contains a verse of the form Ms. Ellis suggests. Your method need not function correctly with names that begin with vowels, although you must handle situations in which the name begins with multiple consonants (as in the case of “Shirley”).

You need not write test cases for this procedure! A few simple experiments should suffice.

Citations

The six methods in part A are adapted from an assignment by Jerod Weinman. Prof. Weinman in turn adapted those from section 1.0 of M. T. Goodrich and R. T. Tamassia's Data Structures & Algorithms in Java, 4/e (Wiley, 2005).

The Name Game problem stems from a laboratory on strings that I wrote in the distant past.

Ms. Ellis's text is taken from the jacket of a copy of her LP, The Name Game. For those of you who don't know what an LP is, LP is short for “Long-Playing record” and it's a circular slab of vinyl about 12" in diameter that contains an encoding of sounds..