# Solutions to Second Midterm Exam

### Directions:

• Answer the problems on the exam pages.
• There are seven problems for 100 total points. Actual scale is A=82, C=54.
• If you need extra space use the back of a page.
• No books, notes, calculators, or collaboration.

```  Q1: 10 points
Q2: 15 points
Q3: 15 points
Q4: 15 points
Q5: 15 points
Q6: 10 points
Q7: 20 points
Total: 100 points
```

• The following code base was provided on a separate sheet at the exam:

``````
public class Dog {
private String name;
private int age;
// public get and set methods, two-parameter constructor

public class SledDog extends Dog {
private String breed = "Husky";
// public get and set methods, three-parameter constructor

public class LinearNode {
private T element;
private LinearNode next;
// public get and set methods, zero-parameter and one-parameter constructors
}

public class DogTeam {
private int size;
// public get and set methods, zero-parameter constructor
public SledDog removeLead ( ) {...}
public void switchLastTwo ( ) {...}
public SledDog removeYoungest ( ) {...}
public int countHuskies ( ) {...}
}

// block of code to be run before other code fragments:

Dog ace = new Dog("Ace", 6);
Dog biscuit = new Dog("Biscuit", 1);
Dog cardie = new Dog("Cardie", 3);
Dog duncan = new Dog("Duncan", 1);
SledDog balto = new SledDog("Balto", 92, "Husky");
SledDog king = new SledDog("King", 73, "Husky");
SledDog buck = new SledDog("Buck", 108, "Mixed");

// back to class definitions

public class Cell {
private int x;
private int y;
private boolean isOpen;
// public get and set methods, two- and three-parameter constructors
}

public class SCell extends Cell {
private boolean seen;
// public get and set methods, constructors

public class QCell extends SCell {
private int distance;
private QCell parent;
// public get and set methods, constructors

``````

Remember that the Maze class is a two-dimensional array of ```SCell ``` objects in Project #2 and of `QCell` objects in Project #4. It has public methods `isPath` and `path`. For Question #7 here, we are givingit an additional public method ``` getCell (int x, int y)``` that returns the cell in position (x, y).

Here is a picture of a 3 by 3 hexagonal grid, ready for a game of Hex as defined in Question #7:

``````
|        RED
|       _       _
_/ \_   _/ \_   _/ \_   _/
/     \ /     \ /     \ /
| 0, 0  | 1, 0  | 2, 0  |
|       |       |       |
_/ \_   _/ \_   _/ \_   _/
/     \ /     \ /     \ /    BLUE
| 0, 1  | 1, 1  | 2, 1  |
|       |       |       |
BLUE  _/ \_   _/ \_   _/ \_   _/
/     \ /     \ /     \ /
| 0, 2  | 1, 2  | 2, 2  |
|       |       |       |
_/ \_   _/ \_   _/ \_   _/ \_
/     \ /     \ /     \ /     \
RED

``````

• Question 1 -- Java Concepts (20): Briefly explain the difference between the two concepts in each pair (2 points each):

• (a) stack and queue

Stacks and queues are both linear data structures giving only limited access to their elements. Stacks support a push operation, adding an element, and a pop operation that removes and returns the last element added. Queues support an enqueue operation, adding an element, and a dequeue operation that removes and returns the element that has been in the queue the longest.

• (b) `enqueue` (in `QueueADT`, in L&C) and `add` (in `Queue`, in `java.util`)

These operations both add a new element to the queue. The `add` operation returns a boolean telling whether the add succeeded -- the `enqueue` operation is void. I was strict about taking off a point if you did not say this about the return point.

• (c) `LinearNode` and linear list

A linear node is an object that holds a content element and a pointer to another linear node. A linear list is a linear data structure containing elements -- it can be built out of linear nodes but could also be implemented with an array.

• (d) `LinearNode<T>` and `LinearNode<SledDog>`

`LinearNode<T>` is the first line of a declaration of the generic class `LinearNode` -- here `T` is a type variable that may be used in the code of the declaration. When the generic class is actually used, the T must be replaced by an actual type, such as `SledDog` in the second example. When this happens, a new class is defined, for example `LinearNode<SledDog>`, by replacing every T in the declaration with the supplied type, in this case `SledDog`.

• (e) depth-first search and breadth-first search

Both are general search techiques, which we employed in Projects #2 and #4 respectively to search a maze. In DFS the elements in the process of being investigated are placed on a stack, so that when an element is finished it is popped and we continue processing its predecessor on the stack. In BFS these elements are placed on a queue, so that the distance-1 neighbors of the source are checked, then the distance-2 neighbors, and so on. BFS this first discovers a path with the minumum number of edges in it.

• Question 2 -- Software Engineering (15): Briefly discuss how you would make the following modifications to the code for the specified program, with specific reference to the code (5 points each):

• (a) Modify the `DropoutStack` class so that there is a new method called `dropped( )`, which returns an array full of all the elements that have been dropped by the calling stack since it was created.

We add a new instance field to the class, a data structure that will contain all the dropped elements. This could be a stack, queue, `ArrayList`, or other list, or an array that we resize ourselves as needed, but it must be able to contain all the dropped elements. We change the push method so that when we drop an element, we add it to this data structure. When the method `dropped` is called, we create an array out of the data structure and return it.

• (b) Modify the classes of Project #4 so that the user can specify a cell z and a positive `int` value k and get back an array containing all the cells, if any, at distance exactly k from z.

As in part (a), we need an expandable data structure to hold all the elements at distance k, which we can then convert into an array and return. The most efficient way to find all the distance-k elements is to run a variant of the path method of Project #4, without a destination node, and stop when the first cell at distance k comes off the queue. At that time the queue will contain exactly the elements at distance k, and we know how many there are.

A less efficient but acceptable way to assemble the list is to run the original path method for the given source and every possible (open) cell as destination, placing the cell into the holding structure if the distance from the source is exactly k.

• (c) Recall that L&C's key cipher program had a fixed key and code to encrypt and decrypt one particular message with that key. Modify their program so that the user can specify the key (as a sequence of ```char ``` values) and be able to encrypt or decrypt arbitrary messages.

We first adapt L&C's encrypt and decrypt methods so that the key and message are each parameters to the method instead of instance fields of the calling object. We then give the user a way to specify the key and message, by a method that gets the input directly or through a constructor. I took off two points from anyone who didn't note that the message, as well as the key, need to be specifiable by the user.

• Question 3 -- Tracing Code (15): Determine the output value of the following blocks of code. In each case, assume that the class and variable definitions above are in force when this code is run. Include a brief justification of your answer.

• (a)
``````
DropoutStack<Dog> d = new DropoutStack<Dog>( ) // recall default capacity is 3
d.push (ace);
Dog dog1 = d.peek( );
d.push (duncan);
Dog dog2 = d.pop( );
d.push (cardie);
d.push (ace);
if (dog1 = d.peek( )) d.pop( );
d.resize (5);
System.out.println (d.size( ));
``````

Before the if statement there are three dogs on the stack with Ace on the top -- the dropout stack never drops out in this example. Since `dog1` and the top element of the stack are both the object `ace` created in the code base, the `d.pop( )` operation is run and we are left with Cardie and Ace on the stack. The `resize` operation does not change the number of elements on the stack, so `size` is still equal to 2, and the output is "2".

• (b)
``````
// new method in DogTeam class
public void reorder ( ) {
DogTeam temp = new DogTeam( );
while (!isEmpty( ))

// then run this code
DogTeam team = new DogTeam( );
for (int i = 0; i < 4; i++) {
team.reorder ( );
for (int j = 0; j < 6; j++)
System.out.println (team.countHuskies( ));
``````

The `reorder` method in fact reverses the order of the dogs in the team without adding or subtracting any dogs. (Note that assigning the lead node of one DogTeam as the lead node of another changes the second DogTeam to equal the first, even though no other pointers are changed.)

We begin with a team containing only King. Then four times we successively add Balto, reverse the team, and add Buck. The first time this gives us (Buck, King, Balto), the second gives us (Buck, Balto, King, Buck, Balto), the third gives us (Buck, Balto, Buck, King, Balto, Buck, Balto), and the fourth gives us (Buck, Balto, Buck, Balto, King, Buck, Balto, Buck, Balto) for a total of nine dogs. The next for loop removes the first six of these dogs, leaving us with (Balto, Buck, Balto). Since Balto is a husky and Buck is not (all SledDogs are originally set to be huskies by default but this can be overridden in the constructor or later), the output is "2".

• (c)
``````
String [ ] init = {"1111", "1001", "1001", "1111"};
Maze m = new Maze (4, 4, init); // this is a project #4 Maze
QCell [ ] path1 = m.path (0, 0, 3, 3);
System.out.println (path1.length);
``````

There are two shortest paths from (0, 0) to (3, 3), and the BFS in the path method will return one of them. These paths have "length 6" and the distance from source to destination is 6, but the path array `path1` has seven nodes in it because it has both the first and last node. So the output is "7".

• Question 4 -- Finding Errors (15): Each of the following code segments has a specific error that either prevents it from compiling, will cause an exception if it is run, or will cause it to produce a clearly unintended output. Find the error and explain what will happen (5 points each):

• (a) (A new method in the `DogTeam` class:)

``````
public boolean containsHusky( ) {
boolean done = false;
while (!done) {
if (current.getElement( ).getBreed( ).equals ("Husky"))
done = true;
current = current.getNext( );}
return done;}
``````

If this method is called from a DogTeam that contains no huskies (including the case of an empty team), the while loop will continue to the end of the team and throw a `NullPointerException` when `current` becomes null and we try to apply its `getNext` method. This is not an "infinite loop", as some of you claimed.

• (b) A new class. (Note: This code turns out to have two errors due to the author's mistake -- full credit was given for finding and describing the outcome of either one.)

``````
public class DogTeamDriver {
public static void main (String [ ] args) {
DogTeam team = new DogTeam( );
for (int i = 0; i < 6; i++)
for (int j = 0; j < 3; j++) {
team.getElement.setBreed ("Cairn Terrier");
temp = temp.getNext( );}
System.out.println (team.countHuskies( ));}}
``````

There are actually three errors in this class, only one of which I deliberately put there. (Of course I gave full credit for any of the three.) My intended error was the missing parentheses on the method call `getElement`, which would make the class fail to compile. Many of you noted that the instance field `leadNode` of `DogTeam` is private, and thus cannot be referenced in the `DogTeamDriver` class -- this would also make this class fail to compile. (It would be ok to use the field if it were public, however.) Finally, the class references the `SledDog` variable `balto`, which is defined in the code base. But since this declaration does not occur within the code for `DogTeamDriver`, the reference to `balto` will also cause the class to not compile.

• (c) (using L&C's code base)

``````
StackADT<Dog> s = new ArrayStack<Dog>( );
DogTeam team = new DogTeam( );
for (int i = 0; i < 4; i++)
s.push (new SledDog("Dog" + i, 3, "Dachshund"));
while (!s.isEmpty( ))
System.out.println (team.countHuskies( ));
``````

This is a subtle error -- many of you were suspicious of the use of both Dog and SledDog variables in the same code fragments, but only some of those people pointed out the actual error. Since the class `SledDog` extends `Dog`, a `SledDog` is-a `Dog`, and there is no reason that a `SledDog` object cannot be pushed onto a stack of Dogs. The problem comes when we pop one of these dogs off of the stack, and try to add it to the DogTeam. Although this dog would always be a SledDog if we could run this code, the compiler does not know this because it came out of a stack of Dogs. So the code fragment will not compile.

• Question 5 -- Timing Analysis (15): Give the big-O running time of each method in terms of n, the number of inputs. Include a brief justification of your answer. In each case we use L&C's code base. (5 points each)

• (a) (Recall that `LinkedQueue`, like all of L&C's collection interfaces, has a `toString` method that returns a description of every element in the collection.) B:)

``````
for (int i = 0; i < n; i++)
q.enqueue (cardie);
while (!q.isEmpty( )) {
System.out.println (q);
q.dequeue( );}
``````

Despite the note given during the exam, most of you did not notice that the next-to-last line takes O(n) time to execute, since printing `q` really means printing the string `q.toString( )`. This string is of length O(n) because it contains the toString output for each element of the queue.

Since this line occurs within a while loop that executes n times, the total time is O(n2) -- the length of the string is actually O(k) where k is the number of elements then in the queue, but we know that 1 + 2 + 3 + ... + n is O(n2). The other parts of the code take only O(n) time, so the O(n2) dominates.

• (b) Describe (in English or pseudocode) a method to be added to the `LinkedQueue` class that takes parameter `k` and returns (but does not remove) the `k`'th element in the calling queue, if there is one. Analyze the worst-case running time of your method in terms of n, the number of elements in the queue.

``````
public T getElementK (int k) {
if (k >= size( )) return null;
LinearNode<T> current = front;
for (int i = 0; i < k; i++)
current = current.getNext( );
return current.getElement( );}
``````

This is clearly O(n) in the worst case as it does O(k) iterations of a loop that does O(1) work, and k might be as large as n, the size of the queue. I did not deduct points for algorithms that threw exceptions when k was too big.

• (c) Here is a method to be added to `LinkedStack`. Analyze its worst-case running time in terms of n, the number of elements in the stack.

``````
public void reverse( ) {
if (isEmpty( )) return;
while (size( ) > 1) {
LinearNode<T> curr = top.getNext( );
LinearNode<T> prev = top;
while (curr.getNext( ) != null) {
curr = curr.getNext( );
prev = prev.getNext( );}
prev.setNext(null);
curr.setNext(temp.top);
temp.top = curr;
temp.size++;
size--;}
top.setNext(temp.top);
size += temp.size;}
``````

Though of course you shouldn't assume so from the name, this method actually does reverse the order of elements of the stack. It repeatedly finds the last element of the stack, removes it, and pushes it onto the temporary stack. Once it has done this for all but one element of the original stack (the element that was originally last), it appends the temporary stack to the original one.

The outer while loop executes n - 1 times, and the inner one runs down the entire current stack and does O(1) work for each element it passes. Again we have a sum 1 + 2 + ... + (n - 1), which is a total of O(n2).

• Question 6 -- Short Code Writing (10): Write an instance method called ```public void feedTeam( )``` to be added to the `DogTeam` class. Assume that the `SledDog` class has a method ```public boolean feed( )``` which has some side effect on the calling `SledDog` and returns `true` if the calling dog is "full" and `false` if it is not. (We do not ask the dogs directly whether they want more food.)

Your method should put the dogs of the colling team in a queue and call the `feed` method for each in turn, adding each dog to the back of the queue if it is not yet full. Your method should not terminate until all dogs are full -- do not worry about the case where some dog remains hungry indefinitely.

``````
public void feedTeam ( ) {
QueueADT<SledDog> q = new ArrayDeque<SledDog>( );
while (current != null) {
q.enqueue (current.getElement( ));
current = current.getNext( );}
while (!q.isempty( )) {
if (q.first( ).feed( ))
q.dequeue( );
else q.enqueue (q,dequeue( ));}}
``````

• Question 7 -- Long Code Writing (20): The game of Hex is played on an n by n grid of hexagonal cells like the 3 by 3 grid shown with the code base above. In a hexagonal grid, every cell has siz neighbors because you can move northwest or southeast as well as north, south, east, or west. By a simple variant of what you did on Question 2b of the first midterm, we can alter the Maze class so that the moves method looks at the hexagonal neighbors.

The game works like this. Initially all cells are unowned. Red and Blue alternate moves, with Red moving first. A move consists of making a previously unowned cell belong to the player moving. The winner is the first player to make a path, of cells that they own, between the two sides of the grid that they own -- north and south for Red, east and west for Blue.

Your task is the implement this game using the Maze class from either Project #2 or Project #4 (the differences are unimportant.) You may asssume that the Maze class has been altered to give a hexagonal grid, but you may not change the Maze class otherwise. (But the Maze class has a method `public QCell getCell (int x, int y)` which returns the cell in position (x, y).)

Remember that the two-parameter constructor for Maze makes every cell open. You may find it useful to run this, then use for loops and `getCell(i, j).setIsOpen (false)` to make every cell closed.

You also get a `Position` class, where a `Position` object has `int` fields `x` and `y`, methods `getX`, `setX`, `getY`, `setY`, and a two-parameter constructor.

You will get input from the players by two methods `getRedMove` and `getBlueMove`, each of which return a `Position` object and have no parameters. (I did not say this clearly enough on the test paper, but my intention was that you should not write these methods, but assume that they are given to you and treat them with black boxes.) Don't worry about excpetions that might be thrown by these two methods -- it is ok if they crash your program.

You should write a class `HexGame` so that a HexGame object allows the two players to play one game of Hex. Use one or more Maze objects to store the state of the game. When it is Red's move, you should call `getRedMove` as many times as needed to get a valid `Position` (in the grid and unowned) and then update your Maze objects to reflect the Red move. It then becomes Blue's turn, and you get and process a valid Blue move the same way. The game should continue until one player has won -- it turns out the draws in this game are impossible. Announce invalid moves and the end of the game on via `System.out.println`.

Here is a good way to get started. Before you have necessarily decided how to store the state of the game, assume that you have methods `isValidRedMove`, `isValidBlueMove`, `processRedMove`, `processBlueMove`, `hasRedWon`, and `hasBlueWon` already written. You will get substantial partial credit for writing a main method of `HexGame` that calls on these methods. Then you can decide on the representation and write these six methods.

Finally, the easiest way to code `hasRedWon` and `hasBlueWon` is inefficient, in that these methods make O(n2) calls to the `isPath` method of `Maze`, when it is possible to make only O(1) calls. You can get up to 16 of the 20 points for this problem for this inefficient implementation. You can get full credit for coding the inefficient implementation, then describing clearly in English how to fiex it to get only O(1) calls. (Of course you can also get full credit for coding the efficient version immediately.)

``````
public class HexGameDriver {
public static void main (String [ ] args) {
// takes width and height from command line
HexGame h = new HexGame (args[0], args[1]);
h.play( );}}

public class HexGame {
private int w, h;
private Maze redMaze, blueMaze;

public HexGame (int width, int height) {
w = width; h = height;
redMaze = new Maze (w, h);
blueMaze = new Maze (w, h);
for (int i = 0; i < w; i++)
for (int j = 0; j < h; j++) {
redMaze.getCell(i, j).setIsOpen (false);
blueMaze.getCell(i, j).setIsOpen (false);}}

public void play ( ) {
while (!hasRedWon( ) && !hasBlueWon( )) {
Position move = getRedMove( );
while (!isValidRedMove (move)) {
System.out.println ("Invalid move for Red, try again:");
move = getRedMove( );}
processRedMove (move);
if (hasRedWon( )) break;
move = getBlueMove( );
while (!isValidBlueMove (move)) {
System.out.println ("Invalid move for Blue, try again:");
move = getBlueMove( );}
processBlueMove (move);}
if (hasRedWon( ))
System.out.println ("Red has won!");
else System.out.println ("Blue has won!");}

public boolean isValidRedMove (Position move) {
int x = move.getX( );
int y = move.getY( );
if ((x < 0) || (x >= w) || (y < 0) || (y >= h))
return false;
if (redMaze.getCell(x, y).getIsOpen( )) return false;
if (blueMaze.getCell(x, y).getIsOpen( )) return false;
return true;

public boolean isValidBlueMove (Position move) {
return isValidRedMove (move);}

public void processRedMove (Position move) {
redMaze.getCell(x, y).setIsOpen (true);}

public void processBlueMove (Position move) {
blueMaze.getCell(x, y).setIsOpen (true);}

public boolean hasRedWon ( ) {
for (int i = 0; i < w; i++)
for (int j = 0; j < w; j++)
if (redMaze.isPath (i, 0, j, h - 1)) return true;
return false;}

public boolean hasBlueWon ( ) {
for (int i = 0; i < h; i++)
for (int j = 0; j < h; j++)
if (redMaze.isPath (0, i, w - 1, j)) return true;
return false;}}
``````

This version uses O(n2) calls to `isPath` to test for a winner on an n by n grid. A trick to reduce this to O(1) calls is as follows. Make `redMaze` a Maze of height h + 2 instead of h, and make the top and bottom rows open. Similarly, make `blueMaze` a Maze of width w + 2 instead of w, and make the left and right rows all open. Then we can ask just whether there is a path from any particular cell on one end to any particular cell on the other, and this will be true if and only if there is any path across in the original HexGame.