Computer Science 15-111 (Sections A & B), Spring 2007

Homework #3 (part 2)

  Due:  Mon 29-Jan-2007 at 8pm (online submission).

 

Place the written portions of the following problems in the file “hw3-written.txt” in your online submission of hw3.2.zip.  Remember:  Show your work!

 

1.      The version of WordSearch.java that we wrote in class used an ArrayList<String> as the representation of the board.  This was useful since we did not know ahead of time how many rows to read in (and, hence, how large an array to allocate).  But this also complicated other parts of our code – specifically, accessing characters in the board.  It would be more natural (hence, preferable) to store the board as a two-dimensional array of char’s, as in:
     char[][] board;
Write a program, WordSearch1.java, that does just that.  It still reads in the input using an ArrayList<String>, but then it converts that input to a 2d array of chars once you know the appropriate dimensions to use.  Modify the code to use this representation of a board.  Also, make the printed report nicer by printing human-readable directions (“Up”, “Up-Left”, “Down-Right”, etc) rather than (drow,dcol) when matches are found.   Finally, add a few more well-chosen comments and be sure to generally study the code and understand how every aspect of it works.

2.      Write a program, WrappingWordSearch.java, that is a modification of your WordSearch1.java program.  Here, you should not fail as you run off the board during a match.  Rather, you should wraparound.  So, for example, the following board would contain the words DOG and CAT with wraparound:

O  D  X  C  G
T  X  X  X  X
X  X  X  X  A

DOG at 0,1 heading LEFT
CAT at 0,3 heading UP-RIGHT


3.      Carefully read Appendix A.3 on manipulating bits.  Then confirm each of the following by converting the arguments to signed int’s (32-bit 2’s complement), performing the operation, and converting the answer back into decimal.
 

a.      First we consider bitwise and (&), or (|), xor (^), and not (~):
  (17 & 5)  ==   1
  (17 | 5 ) ==  21
  (17 ^ 5 ) ==  20
  ~17       == -18
  ~17 + 1   == -17
  (we expected this – negation in 2’s complement!)

b.      Ignoring overflow, left-shifting is the same as multiplying by powers of 2 (why?), and right-shifting positive numbers is the same as dividing by powers of 2 (again, why?).  To demonstrate this, confirm the following:
  (-5 << 3) == -40  (which equals -5 * 23)
  (87 >> 4) ==   5  (which equals 87 / 24)

c.      Right-shifting negative numbers, though, whether sign-extended (a >> b) or not (a >>> b), is not the same as dividing by powers of 2.  To demonstrate this, confirm the following:
  (-87 >> 4) == -6  (which does not equal -87 / 24)
  (-87 >>> 4) is positive (and very large!)

d.      As discussed in class, we combine shifting and bitwise operators to get and set bytes from within int’s.  For example, we can obtain the second byte of an int by first shifting 8 bits to the right (thus moving our target bits into the lowest byte) then &’ing against the mask 0xFF to set all the bits except the lowest byte to 0 (how does it do this?).  That is:
     int secondByte = (x >> 8) & 0xFF;
Now, a nibble is half a byte (cute, huh?), or 4 bits.  It is represented by a single hex digit, as in 0xF.  A 32-bit integer contains 4 bytes and so it contains 8 nibbles.  Write an expression (not a statement, just an expression, like the one above for finding the second byte) that uses shifting and &’ing to get the kth nibble (where the least-significant 4 bits are the 0th nibble, the most-significant 4 bits are the 7th nibble, and you can presume k is in [0,7]).  You may use a Java compiler to check your work along with this (not very stylistic) sample code (which, of course, you are expected to fully understand, too!):

public static void main(String[] args) {
  Scanner scanner = new Scanner(System.in);
  String hexDigits = "0123456789ABCDEF";
  int x;
  while (true) {
    System.out.print("Enter an int (or 'quit' to exit): ");
    if (!scanner.hasNextInt()) {
      if (scanner.next().equals("quit")) break;
      else { System.out.println("Huh?"); continue; }
    }
    x = scanner.nextInt();
    // Print the hexadecimal value of x using kth-nibble
    System.out.printf("%d = 0x",x);
    for (int k=7; k>=0; k--) {
      int kthNibbleOfx = (YOUR EXPRESSION GOES HERE);
      if ((kthNibbleOfx < 0) || (kthNibbleOfx > 15))
        System.out.println("\nkthNibbleOfx out of range!");
      else
        System.out.print(hexDigits.charAt(kthNibbleOfx));
    }
    System.out.println();
  }
}


Finally, study the code in PixelImages.java (which we covered briefly in class) which uses bit operations to get and set bytes within an ARGB (Alpha-Red-Green-Blue) integer.  You are responsible for that code, too!

4.      To further help you in your study of bit manipulations, here is a program, BitQuiz.java, that generates problems using random arguments and randomly-chosen operators from { &, |, ^, ~, <<, >>, >>> }.  First, compile the code and use it to practice (since you do need to know how to do bit manipulations by hand!).  Then, study the code itself, since you are responsible for all of it.  Answer the following questions:

a.      What does random.nextInt(n) return?

b.      Why can’t we use a switch statement to select the operator in the “eval()” method?   That is, what is wrong with this code:
switch (operator) {
   case "&":  return (arg1 & arg2);
   case "|":  return (arg1 | arg2);

   // ... //
   default:   System.out.println("oops"); return 0;
}

c.      Why do we need the “+ 1” in this code:
int arg1 = min + (random.nextInt(max - min + 1));

d.      Consider the line:
   int result = (byte)eval(arg1,operator,arg2);
Give specific values for arg1, operator, and arg2 where the value of result would differ if the cast to byte were not present.

5.      In class, we briefly reviewed code to display pixels.  Here is an updated version of that code:  PixelImages.java.  First, compile and run the code.  Then, study the code itself, since you are responsible for the first half of the file.  Answer the following questions:

a.      Read Sections 6.1 and 6.2 then, in just a few words, briefly describe an advantage of declaring FadeType as an enum, rather than declaring each enum element as a static int, such as:
    public static int HORIZONTAL_FADE = 1;
    public static int VERTICAL_FADE = 2;
   


b.      Note that this code uses (x,y) notation which is typical for graphics rather than the (row,col) notation which is typical for matrices (even though both use 2d arrays!).  For example, we used (row,col) notation in WordSearch.java.  Confusing these two approaches is quite common and leads to many errors.  In (row,col), the first dimension is the vertical dimension (rows go up-and-down), whereas in (x,y) the first dimension is clearly the horizontal direction.  Either way, for most programming tasks, we conventionally place (0,0) in the top left (unlike graphing in math, where it is usually in the lower left).  There is nothing to submit for this part of the question, just be sure you understand it.

c.      Write the following method:
public static void fillCircle(int[][] pixels,
                              int cx, int cy, int radius,
                              int alpha,
                              int red, int green, int blue)

This method should fill in a circle of the given color centered at (cx,cy) with the given radius.  While it is possible to do this with trigonometry, there is an easier way.  Just iterate over the pixels in the enclosing square, as in fillRect, and for each point (x,y) simply check if the distance from that point to (cx,cy) is less than or equal to the radius.  If so, fill the pixel in, otherwise skip it.  Test your method by adding a filled yellow circle with radius 50 placed against the lower-right corner of the picture.  (Note:  yellow is red + green with no blue.)

d.      Write the following method:
public static void removeRed(int[][] pixels,
                             int left, int top,
                             int width, int height)

This method removes all the red from the pixels in the given rectangle (that is, sets the red component of the ARGB to 0x0), leaving the alpha, blue, and green unmodified.  Note that there are methods in the code to get the color components (alpha, red, green, blue) at a given pixel.  Demonstrate your code works by calling removeRed on the left half of the yellow circle drawn above, and seeing that half turn green (since yellow is red plus green, removing red leaves just green).

6.      BONUS:  This is optional but strongly encouraged.  Unlike extra credit which is factored in at the end of the semester, bonus is factored immediately into your grade on this assignment (thus allowing scores over 100).  But, again, it is entirely optional, and not doing the bonus will in no way detract from your score.

a.      [2.5 pts] Modify the fadeValue() method so that it supports a RADIAL_FADE, where value0 is the value at the center and value1 is the value at the edges of the rectangle.  To make this easier, it is ok to assume that the rectangular is a square, and to use the smaller rectangular dimension as the square’s side.  Then, find the distance from (x,y) to the center, and divide this by the radius.  That is the fraction of the fade that should occur, right?  Anyhow, test your method by adding a 75x75 square, radially fading from blue to red, in the top-right corner of the picture.

b.      [2.5 pts] Add a method fillOval which works like fillRect but instead fills in only the oval that fits inside the enclosing rectangle.  In a clear and concise comment at the head of your method, explain the math behind your approach.