- Answer the problems on the exam pages.
- There are seven problems for 100 total points. Likely scale is A=88, C=64.
- 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

Here is a code base from previous assignments, that is assumed to be available throughout 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<T> {
private T element;
private LinearNode<T> next;
// public get and set methods, zero-parameter and one-parameter constructors
}
public class DogTeam {
private LinearNode<SledDog> leadNode;
private int size;
// public get and set methods, zero-parameter constructor
public void addToLead (SledDog newLead) {…}
public SledDog removeLead ( ) {…}
public void switchLastTwo ( ) {…}
public SledDog removeYoungest ( ) {…}
public int countHuskies ( ) {…}
}
Code 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 = newSledDog ("Buck", 108, "Mixed");
Some useful API information for L&C's code base:
public interface ListADT<T> extends Iterable<T> {
public T removeFirst( );
public T removeLast( );
public T remove (T element);
public T first( );
public T last( );
public boolean contains (T target);
public boolean isEmpty( );
public int size( );
public Iterator<T> iterator( );
public String toString( );}
public interface OrderedListADT<T> extends ListADT<T> {
public void add (T element);}
public interface UnorderedListADT<T> {
public void addToFront (T element);
public void addToRear (T element);
public void addAfter (T element, T target);}
// Note: For this exam is is assumed that the class ArrayList implements UnorderedListADT
public class SortingandSearching {
public static <T extends Comparable<? super T >> boolean
linearSearch (T [ ] data, int min, int max, T target) {...}
public static <T extends Comparable<? super T >> boolean
binarySearch (T [ ] data, int min, int max, T target) {...}
public static <T extends Comparable<? super T >> void
selectionSort (T [ ] data) {...}
public static <T extends Comparable<? super T >> void
quickSort (T [ ] data, int min, int max) {...}
public static <T extends Comparable<? super T >> void
mergeSort (T [ ] data, int min, int max) {...}}
```

**Question 1: Java Concepts**Briefly explain the difference between the two concepts in each pair (2 points each).- a) selection sort and insertion sort
Selection sort repeatedly finds the smallest element in the list, removes it, and places it at the tail of a new list. Insertion sort repeatedly takes a new element and inserts it into an ordered list, so that the new list remains sorted. Both take O(n

^{2}) time on array-based structures. - b)
`add`

(in an ordered list) and`addAfter`

(in an unordered list)The one-parameter

`add`

method places the new element in its appropriate place in the calling ordered list. The two-parameter`addAfter`

method places the new element immediately after the target element in the calling unordered list, and throws an exception if the target element is not already there. - c)
`Cloneable`

and`Serializable`

Both are interfaces extended by the

`List`

interface in`java.util`

--`Cloneable`

is a signal to the runtime system that the`clone`

method of the`Object`

class, which creates a deep copy of the calling object, is supported. (If you said that a`Cloneable`

had to have the`clone`

method I gave full credit.) Hardly anyone remembered`Serializable`

, which is an indication that objects of the calling type may be written to and read from files. - d)
`ArrayList`

(in L&C) and`java.util.ArrayList`

Both are array-based implementations of lists that resize their arrays as necessary to deal with inserted elements. But the

`java.util`

class is an**indexed**list -- it has methods to access elements based on their current position in the array, such as`get(i)`

and`set(i)`

. They also have different names for many methods -- in general, the`java.util`

class has far more methods. - e)
`Iterable`

and`Iterator`

Both are interfaces dealing with iterators, auxiliary objects that give all the elements of a collection when repeatedly asked. Iterator classes normally implement the Iterator interface, which requires the methods

`hasNext`

,`next`

, and`remove`

, though this last method is often not supported. The`Iterable`

interface is normally implemented by the class that*has*the iterator -- it requires the method`iterator`

which returns an iterator object attached to the calling collection.

- a) selection sort and insertion sort
**Question 2: Software Engineering**-- Briefly discuss how you would make the following modifications to the code for specified programs, with specific reference to the code (5 points each):- a) Suppose I want to know, in the course of a test of a solution
to Project #6, how many total comparisons of
`SledDog`

objects occurred. Describe (in English) what code I should add to what methods and classes.The most natural thing would be to add a

*static*int field to either the`SledDog`

or`DogTeam`

classes, that would be initialized at 0 and incremented by the`compareTo`

method of`SledDog`

whenever it was called. We would need methods to retrieve and to reset this counter. It would be possible to have an instance field on each`SledDog`

or on each`DogTeam`

counting how many comparisons it had been involved in. To get the total from this we would have to add the numbers for every dog or for every team, dividing by two if the comparison is counted for both its arguments. - b) Modify a solution to Project #5 to change the "tax rate" on
spoons brought into a town from 5% (rounded up) to 10% (rounded up).
There are various ways to do the calculation of the spoons brought into the town, based on the number of spoons at the preceding place. All of these have a parameter 0.05 for the tax rate in the Project #5 solution, and we simply change that parameter to 0.10 to get the new tax rate.

- c) Suppose that in a simulation of the Towers of Hanoi
problem, I want to represent each disk by an object and keep track,
through the simulation, of which disks are on which pins. What new
data structures should I use, and how would the
`moveOneDisk`

method modify these data structures?The disks are added to and removed from a pin at only one end, so the simplest idea would be to keep the disk objects on three stacks. The

`moveOneDisk`

method would pop a disk from one stack and push it onto another. Either in that method or elsewhere, there would have to be a check that the disk pushed was smaller than the top disk on that stack, if any.

- a) Suppose I want to know, in the course of a test of a solution
to Project #6, how many total comparisons of
**Question 3: Tracing Code**-- indicate the output of each code fragment (5 points each)- a)
`UnorderedListADT<Dog> pack = new ArrayList<Dog>( ); pack.addToFront (duncan); pack.addAfter (cardie, duncan); pack.addToRear (biscuit); Dog x = pack.remove (duncan); Dog y = pack.removeLast( ); pack.addToFront (x); pack.addAfter (y, cardie); System.out.println (pack.last( ).getName( );`

The list goes from empty to (D) to (D, C) to (D, C, B) to (C, B) (x set to D) to (C) (y set to B) to (D, C) to (D, C, B). The return value is B so the string printed is

**"Biscuit"**. - b)
`public static int fred (int n) { if (n == 0) return 1; else return ginger (n) + fred (n-1);} public static int ginger (int n) { if (n == 0) return 0; else return ginger (n-1) + fred (n-1);} System.out.println (fred(3));`

As with Fibonacci numbers, the best way to compute the values of F(i) and G(i) is bottom up: G(0) = 0, F(0) = 1, G(1) = 0 + 1 = 1, F(1) = 1 + 1 = 2, G(2) = 1 + 2 = 3, F(2) = 2 + 3 = 5, G(3) = 3 + 5 = 8, and finally F(3) = 5 + 8 =

**13**. Clearly these functions are a*lot*like the Fibonacci numbers. - c)
`public static int netCaps (String input) { if (input.equals ("")) return 0; char first = input.charAt(0); // first letter String rest = input.substring(1); // all but first letter if ('A' <= first && first <= 'Z') return netCaps (rest) + 1; return netCaps (rest) - 1;} System.out.println (netCaps ("i Can HaZ chEEzburGer?");`

The function recurses repeatedly on all but the first letter of the string, until it reaches the base case of the empty string. As it finishes each substring, it adds one for every capital letter and subtracts one for every character that is not a capital letter. Since the given string has six capitals and sixteen non-capitals (counting the spaces and the question mark), the output is

**-10**.

- a)
**Question 4: Finding Errors**-- indicate whether the code fails to compile, throws an exception on reasonable input, or has clearly unintended output (5 points each):- a)
`public int abbott (int n) { if (n == 0) return n; else return abbott (n-1) + costello (n);} public int costello (int n) { if (n == 0) return 1; else return abbott (n) + costello (n-1);} System.out.println (abbott (2) + costello (3));`

This is an example of an ungrounded indirect recursion. The computation begins by trying to evaluate A(2), which is A(1) + C(2), which is A(0) + C(1) + C(2), which is C(1) + C(2), which is A(1) + C(0) + C(2), and so forth -- the call to A(1) produces a call to C(1) which produces another call to A(1), which will call C(1), so that the calls never reach a base case. The computation will not terminate normally but will have a runtime error when the method stack overflows.

- b)
`// uses L&C code base, usual dogs are defined as above ArrayList<Dog< kennel = new ArrayList<Dog>( ); kennel.addToFront (cardie); DogTeam redSox = new DogTeam( ); redSox.addToLead (balto); kennel.addAfter (king, cardie); kennel.removeFirst ( ); redSox.addToLead (kennel.removeFirst( )); if (kennel.isEmpty( )) System.out.println ("No more dogs"); else System.out.println (kennel.first( ).getName( ));`

This is the same error that was on the second midterm -- in line 7, the object returned by the method call

`kennel.removeFirst( )`

has type`Dog`

, although the actual object in the run of this code fragment happens to be`king`

who is a`SledDog`

. The compiler will not let the output of this call be the argument of the call`redSox.addToLead( )`

, which must be a`SledDog`

, because it cannot guarantee that it is of that type. - c)
`public class Group<T extends Comparable<T>> { private T[ ] members; private int size; public Group (int capacity) { members = new T[capacity]; size = 0;} public T getMember (int i) {return members[i];} public void setMember (int i, T newElem) { if (members[i] == null && newElem != null) size++; if (members[i] != null && newElem == null) size--; members[i] = newElem;} // more methods public int compareTo (Group other) { if (this.size < other.size) return -1; if (this.size == other.size) return 0; return 1;}}`

In line 5, this code attempts to create an array of a generic type, which is not allowed -- we must create an array of objects and cast it into the type

`T[ ]`

. This will not compile.This class has a

`compareTo`

method without implementing the`Comparable`

interface -- this is unusual but not an error. The base type`T`

of this collection class is restricted to be an ordered type, but the comparison operator on the collections does not use this.

- a)
**Question 5: Timing Analysis**Indicate the big-O worst case running time of each method or code fragment in terms of n. Include a brief justification of your answer. In each case we use L&C's code base. (5 points each)- a)
`public static int twotoThe (int n) { if (n <= 0) return 1; return twoToThe (n-1) + twoToThe (n-1);}`

The original call with parameter n leads to two separate calls with parameter n-1, then four calls with parameter n-2, eight with parameter n-3, and so on to have 2

^{i}calls with parameter n-i for each number i until i = n, when we have 2^{n}calls to the base case with parameter 0. Each of these calls takes O(1) time and the total number of them is 2^{n}+ 2^{n-1}+ ... + 1 = 2^{n+1}- 1. Thus the total time is**O(2**.^{n}) - b)
`public static int foo (int n) { int x = 0; y = n; for (int i = 0; i < n; i++) { y = y/2; if (y <= 1) break; for (int j = 0; j < n; j++) x += (y * i + j);} return x;}`

This looks like two nested loops each executing n times, with an O(1) body, which would be O(n

^{2}) time. But the outer loop only executes log n times, because the variable y is halved each time through and the loop is broken when y reaches 1. We have O(log n) times through the outer loop, each involving O(n) times through the inner loop, for a total time of**O(n log n)**. - c)
`// uses L&C's binarySearch method, goes in L&C's SortingAndSearching class // "n" is the combined length of the two input arrays public static <T extends Comparable <? super T>> boolean sameElements (T [ ] one, T [ ] two) { boolean soFar = true; for (int i = 0; i < one.length; i++) if (!binarySearch (two, 0, two.length - 1; one[i])) soFar = false; for (int j = 0; j < two.length; j++) if (!binarySearch (one, 0, one.length - 1; two[j])) soFar = false; return soFar;}`

Each of the loops executes n times, and the times of the two loops add because they are not nested. Within each loop is a call to

`binarySearch`

on an interval of length n, which takes O(log n) time. So the total time is**O(n log n)**.

- a)
**Question 6: Short Code Writing**(10 points)In Lecture #25 we mentioned Counting Sort, another algoirthm to sort an array that takes O(n

^{2}) time. The idea is that if the n elements of the array are distinct, we can compare each element x to the other n - 1 elements in the array, and thus determine exactly how many elements in the array are less than x.Write a generic method

`public static <T extends Comparable<? super T>> T [ ] countingSort (T [ ] input)`

that returns an array that is a sorted copy of the array input. Your method should not change the input array at all. The declaration in angle brackets allows you to assume that

`T`

has a`compareTo`

that we use to define the proper order on its elements.`public static <T extends Comparable <? super T>> T[ ] countingSort (T[ ] input) { T[ ] output = (T[ ]) new Object[input.length]; // cast is required for (int i = 0; i < input.length; i++) { int lesser = 0; for (int j = 0; j < input.length; j++) if (input[j].compareTo (input[i]) < 0) lesser++; output[lesser] = input[i];} return output;}`

I deducted two points for forgetting the cast operation in creating the generic array. Many people tested the output of

`compareTo`

for equality with 1 rather than being greater than 0 (or similarly for -1 and less than 0). While all the`compareTo`

methods we have seen or built have output -1, 0, or 1, the spec for the method only says that the output must be less than, equal to, or greater than 0 according to the relation of the elements. I did not deduct any points for this error.**Question 7: Long Code Writing**(20 points)A

**subteam**of a`DogTeam`

object x is a`DogTeam`

that contains a subset of the dogs in x, in the same order as they occur in x. For example, if x contains dogs a, b, and c, there are eight subteams of x: the empty team (written [ ]), [a], [b], [c], [a, b], [a, c], [b, c], and [a, b, c].The following is a recursive definition of the set of subteams of x. If x has no dogs in it, there is exactly one subteam which also has no dogs in it. Otherwise, let d be the lead dog of x and let y be the team made from x by removing d. Then the subteams of x consist of the subteams of y, plus every team that is made from a subteam of y by adding the dog d to it at the lead.

Write a recursive method

`public DogTeam[ ] listSubteams( )`

to be included in the`DogTeam`

class. If this method is called by a`DogTeam`

object with k dogs in it, it should return an array consisting of all the 2^{k}possible subteams of x. You are not required to list the subteams in any particular order, but ther is an order that is most natural for the recursive definition. Assume that you have a static method`int twoToThe (int k)`

that will return the number 2^{k}when given input k.Make sure that your method has no side effects on the calling

`DogTeam`

object.If you find it convenient, you may assume that you have the

`iterator`

method from Project #6, and the corresponding iterator class, available to use in your code.

```
public DogTeam[ ] listSubteams ( ) {
DogTeam [ ] output = new DogTeam (twoToThe(size)); // no cast, not generic
if (isEmpty( )) {
output[0] = new DogTeam( ); // we return array of one empty team
return output;}
DogTeam temp = clone( ); // clone method using given methods is below
SledDog lead = temp.removeLead( );
DogTeam[ ] half = temp.listSubTeams( ); // array of 2^{size - 1} teams
for (int i = 0; i < half.length; i++) {
output[i] = half[i];
half[i].addToLead(lead);
output[i + half.length] = half[i];}
return output;}
public DogTeam clone( ) { // uses iterator from Project #6
DogTeam ret = new DogTeam( );
DogTeam temp = new DogTeam( );
for (dog : this) temp = addToLead (dog); // temp is this backwards
for (dog : temp) ret.addToLead (dog); // ret is now clone of this
return ret;}
```

Last modified 19 November 2011