Computer Science 15-100 (Sections T & U), Spring 2008
Homework 5
Due:  Fri 15-Feb-2008 at 10:00am (online submission) and at recitation (physical copy)
(no late submissions accepted).



  1. Write a program, Hw5Graphics.java, that draws four graphics at once, each occupying one quadrant of the window, as such:




    Note:  collectively, the four graphics must fill the entire window, even as the window is being resized by the user (without regard to what happens when the window gets too small to properly render the flags), with each graphic occupying 1/4th of the window. This week you should continue to color-match, rather just using built-in colors.

    Also:  you must use "for" loops when appropriate.  This includes a separate "for" loop for each of the following (and perhaps others, too!):
         * The diagonal pattern of 7 full and 2 half stars in Bosnia and Herzegovina's flag (larger image)
         * The 14 red-and-white stripes in Malaysia's flag (larger image)
         * The 13 red-and-white stripes in the US flag (larger image)
         * The pattern of 50 stars in the US flag
         * The many-toothed pattern (with 9 white points) in Qatar's flag (larger image)
         * The makeStar method that is described below (for both the 5-pointed and 14-pointed stars)

    To do this, you will write additional static paint methods, one for each quadrant of the window, like this:

      public static void paintBosniaAndHerzegovinaFlag(Graphics page, int left, int top, int width, int height) {
           // your code here!
      }

      public static void paintMalaysiaFlag(Graphics page, int left, int top, int width, int height) {
           // your code here!
      }

      public static void paintUSFlag(Graphics page, int left, int top, int width, int height) {
           // your code here!
      }

      public static void paintQatarFlag(Graphics page, int left, int top, int width, int height) {
           // your code here!
      }

    Note that the "width" and "height" in these signatures represent the bounding regions for the given flag, and not the width and height of the entire window!  The main paint method will just call these paint methods, providing appropriate arguments to place the flags in the appropriate quadrant of the window, so your paint code will look like this:

      public void paint(Graphics page) {
           int width = getWidth();
           int height = getHeight();
           paintBosniaAndHerzegovinaFlag(page, 0, 0, width/2, height/2);  // top-left quadrant
           paintMalaysiaFlag(....);  // you fill in the parameters
           paintUSFlag(....);        // ditto
           paintQatarFlag(....);     // ditto
      }

    Additionally, you must write one more static method that makes an n-pointed star with exactly this signature:

      public static Polygon makeStar(int nPoints, int cx, int cy, int r1, int r2) {
      }

    This method will create and return a new Polygon that represents a star with "nPoints" points, centered at the location (cx,cy), with an outer radius of "r1" and an inner radius of "r2".  You must use this method to create the 5-pointed stars in Bosnia and Herzegovina's flag and the US flag, and you must also use this same method to create the 14-pointed star in Malaysia's flag.

    Note:  Do not use the Polygon.translate method this time -- instead, make repeated calls to makeStar, one for each star in each flag.

     

  2. In your program Hw5.java, write a method with this signature:
      public static boolean isPrime(int n) {
      }

    This method takes a (possibly negative!) integer "n", and returns true if that integer is a prime number and false otherwise.  Note that 2 is the smallest prime number.  For full credit, you must add these efficiencies:  first, check if it is divisible by 2, and if so, handle that case separately.  Otherwise, only check the odd factors between 3 and the square root of n (recalling, as we discussed in class, that if a number is not prime, then it must have a factor that is no greater than its square root).  Be careful about the boundary cases (should you round the square root or truncate it?  Should you go up to and including the square root, or up to and excluding it?).

    Also, to test this method, write another method with this signature:
      public static void testIsPrime() {
      }


    In this method, you should add some tests to verify that your isPrime method works.  To do this, you will write yet another method, which we will call "verify" (this is very similar to the "assert" mechanism, new to Java 1.5, in case you are interested).  Here is the "verify" method, in its entirety:
      public static void verify(boolean test) {
         if (test == false) throw new RuntimeException("Failed test!");
      }

    The "verify" method takes a boolean value, which should be true, and if it is false, simply throws an exception.  This is very useful, because you can then look at the stack trace that the exception prints out to see exactly where your test failed.  Do not forget that step!  To emphasize it, here it is again in bold:

    When your program throws an exception, carefully look at the stack trace to see exactly on what line number the error occurred!

    Now, returning to your "testIsPrime" method, you should add a variety of test cases to help verify that your method works.  Here are a couple written for you:
      public static void testIsPrime() {
         verify(isPrime(1) == false);
         verify(isPrime(2) == true);
         System.out.println("isPrime passed all tests!");
      }


    Note that the last line (declaring success) will only execute if none of the tests fail (because a failed test will throw an exception and thus end your program).  You should add a good variety of test cases, at least handling all of the "boundary conditions" (which we will discuss in class).  Your grade depends in part on the quality (more than the quantity) of your test cases!

    Finally, write one last method for this part, with this signature:
      public static void interactivelyTestIsPrime() {
      }


    This method will repeatedly read in a number, halting when then user enters a negative number, and will use the isPrime method to print out whether or not the given number is prime.  The method should work exactly like this (where user input is underlined):
      Enter an integer (<0 to exit): 3
      3 is prime.

      Enter an integer (<0 to exit): 1
      1 is not prime.

      Enter an integer (<0 to exit): -14
      Goodbye!

    Now, to test this method, you probably want to call it from your main method, though that is just for your testing purposes.  Note that your main method for the Hw5.java program will not actually be tested by us, and can include whatever code you want.

    Hint:  for your interactivelyTestIsPrime method, you should use an infinite loop -- "while (true)" -- and inside that loop, if the user enters a negative number, you should include a "break" statement, like this:
         while (true) {
              // load variable "x" with the value to test
             if (x < 0) {
                  break;   // user entered a negative #, so break out of the enclosing while loop
            }
            // test if "x" is prime and print out the result
         }


     
  3. In your program Hw5.java, write a method with this signature:
      public static int nthPrime(int n) {
      }

    This method takes a (possibly negative!) integer "n", and if n is positive, returns the nth prime number, otherwise (n is non-positive) returning -1.  Note that 2 is the smallest prime number, so a call to nthPrime(1) returns 2, a call to nthPrime(2) returns 3, a call to nthPrime(3) returns 5, and so on.  As should be clear, you must use your isPrime method from above.
    Hint:  you will want to use a "while" loop here, starting a counter at 2 and increasing it by 1 on each pass, checking if that counter is prime, and if so, adding one to the number of primes seen so far, and looping while the number of primes seen so far is less than n.  Like this:
         while (primes < n) {
              // add one to the counter
              // check if the counter is prime
              // if the counter is prime, increment the "primes" count
         }


    Also, to test this method, write another method with this signature:
      public static void testNthPrime() {
      }


    In this method, you should again use the "verify" method and add some tests to verify that your nthPrime method works.

    Finally, write one last method for this part, with this signature:
      public static void interactivelyTestNthPrime() {
      }


    This method will repeatedly read in a number, halting when then user enters a non-positive number, and will use the nthPrime method to print out the nth prime.  The method should work exactly like this (where user input is underlined):
      Enter an integer (<=0 to exit): 3
      Prime number #3 is 5.

      Enter an integer (<=0 to exit): 1
      Prime number #1 is 2.

      Enter an integer (<=0 to exit): -14
      Goodbye!

    Again, to test this method, you probably want to call it from your main method, though that is just for your testing purposes.  Note that your main method for the Hw5.java program will not actually be tested by us, and can include whatever code you want.

     
  4. The last step in the previous problem printed the results in a stilted manner.  Rather than saying "The 3rd prime number is 5", it says "Prime number #3 is 5".  We did that because, well, it was easier.  Here, we'll take on the problem of properly printing out an ordinal integer (that's what these are called) with its appropriate suffix.

    To do this,in your program Hw5.java, write a method with this signature:
      public static String toOrdinalString(int n) {
      }

    This method takes a (possibly negative!) integer "n", and if n is non-negative, returns a string with the ordinal number and its appropriate suffix, otherwise (n is negative) returning the "null" string.  Here are some sample calls and return values:
         toOrdinalString(-1) returns null
         toOrdinalString(0) returns "0th"
         toOrdinalString(1) returns "1st"
         toOrdinalString(2) returns "2nd"
         toOrdinalString(3) returns "3rd"
         toOrdinalString(4) returns "4th"
         All values from 4 to 20 use "th" as their suffix.  For example, toOrdinalString(11) returns "11th"
         After 20, you determine the suffix according to the ones digit, so:
         toOrdinalString(21) returns "21st"
         toOrdinalString(1043) returns "1043rd"

    Also, to test this method, write another method with this signature:
      public static void testToOrdinalString() {
      }


    In this method, you should again use the "verify" method and add some tests to verify that your toOrdinalString method works.

    Finally, write one last method for this part, with this signature:
      public static void interactivelyTestToOrdinalString() {
      }


    This method will repeatedly read in a number, halting when then user enters a non-positive number, and will use the toOrdinalString method and nthPrime method to print out the nth prime.  The method should work exactly like this (where user input is underlined):
      Enter an integer (<=0 to exit): 3
      The 3rd prime number is 5.

      Enter an integer (<=0 to exit): 1
      The 1st prime number is 2.

      Enter an integer (<=0 to exit): -14
      Goodbye!

    Again, to test this method, you probably want to call it from your main method, though that is just for your testing purposes.  Note that your main method for the Hw5.java program will not actually be tested by us, and can include whatever code you want.
     

Carpe diem!