Q1: 10 points Q2: 15 points Q3: 15 points Q4: 15 points Q5: 15 points Q6: 10 points Q7: 20 points Total: 100 points
Dog
class:
public class Dog {
private String name;
private int age;
public Dog (String newName, int newAge) {
name = newName;
age = newAge;}
public String getName {return name;}
public void setName (String newName) {name = newName;}
public int getAge ( ) {return age;}
public void setAge (int newAge) {age = newAge;}
public boolean equals (Dog other) {
if (!this.name.equals(other.name)) return false;
return (this.age == other.age);}}
Several questions use these generic interfaces from DJW:
public interface QueueInterface<T> {
T dequeue( );
boolean isEmpty( );}
public interface BoundedQueueInterface<T> extends QueueInterface<T> {
void enqueue (T element);
boolean isFull( );}
public interface UnboundedQueueInterface<T> extends QueueInterface<T> {
void enqueue (T element);}
Question 7 uses this generic interface from DJW:
public interface ListInterface<T> {
int size( ); // number of elements in the list
void add (T element); // put "element" into the list
boolean contains (T element); // is "element" in the list?
boolean remove (T element); // returns whether element was there
T get (T element); // returns item equal to
// "element" or returns null
String toString( ); // returns string describing list
void reset( ); // sets current position to beginning
T getNext( ); // returns item at current position,
// advances current position
}
The recursive method computes n! by multiplying n by (n-1)!, the
latter computed by a recursive call. The iterative method sets x = 1 and
then does x *= i for all i from 1 to n, using a for
loop.
LLNode<T>
and the class DLLNode<T>
LLNode<T> is a node for a singly linked list with a link pointer. DLLNode<T>
is a node for a doubly linked list that also has a back pointer. Both have info
fields of type T.
A serializable class has objects that can be written directly to a file by a
writeObject
method, and read back with readObject
. An unserializable class'
objects must be converted to strings or primitives before being written to a file,
and this output must be parsed when read back.
A synchronized method cannot overlap execution with another version of the same method in another thread. It locks variables down until it is finished. An unsychronized method could overlap in this way, both threads modifying the same variables, possibly with unintended consequences.
A sorted list always has it elements in ascending order according to the compareTo
method in the elements' class. An unsorted list can have its elements in any order
and need not have comparable elements. The add
method in an unsorted list, for
example, puts the new element in the right place according to the order.
markBlobs
method,
which was recursive and thus implicitly used a stack. Could we
have done this job instead with a non-recursive method using
queues? Explain how we could or why we could not.
Yes, we could if we set up a queue as int he centrality test of Project #4, and marked every node as visited when it went onto the queue. We will mark every node on the continent by the time the queue is empty. We could then give the marked nodes the correct continent label.
X
in a
MapGrid
object, which was the distance from
X
to the farthest square on X
's
continent. How could you use a similar queue-based method to
determine the number of squares on X
's
continent?
Make sure that no square can go on the queue more than once. Then count the squares as they come off the queue. Since we put every square of the continent on the queue exactly once each, we get the number of squares in our counter when the queue is empty. Note that since there is no time we are sure that all the squares are on the queue, we can't just get the size of the queue at any time -- we must count them going on or going off.
When a customer is dequeued for a server, we need to determine whether they gave
up before reaching the front of the queue. If they were in the queue for k seconds,
they had k/10 chances to give up. We create a Random object, ask it for k/10 numbers
using nextInt(100)
, and see whether any of those numbers are 0. If so, we don't serve
the customer and move on -- if not we serve the customer.
Dog
class from above is present.
Include a brief justification of your answer.
// give the return value of recurse (3, 3)
public int recurse (int j, int k) {
if ((j == 0) && (k == 0))
return 7;
if (j == 0) return (1 + recurse (0, k - 1));
return recurse (j - 1, k + 1);}
By successive substitution we get recurse (3,3) = recurse (2, 4) = recurse (1, 5) = recurse (0, 6) =
1 + recurse (0, 5) = 2 + recurse (0, 4) = … = 6 + recurse (0, 0) = 6 + 7 = 13
.
Dog cardie = new Dog("Cardie", 5);
Dog duncan = new Dog("Duncan", 3);
LLNode<Dog> list = new LLNode<Dog>(null);
LLNode<Dog> cNode = new LLNode<Dog>(cardie);
LLNode<Dog> dNode = new LLNode<Dog>(duncan);
list.setLink(cNode);
cNode.setLink(dNode);
dNode.setLink(list);
list.setLink(list.getLink( ).getLink( ));
cNode.setLink(dNode.getLink( ));
dNode.setLink(dNode.getLink( ).getLink( ));
LLNode<Dog> cur = cNode;
for (int i = 0; i < 4; i++)
cur = cur.getLink( );
System.out.println (cur.getInfo( ).getName( ));
Lines 3-5 create three nodes L, C, and D. Lines 6-8 set them up
L --> C --> D --> L. Line 9 makes L point to D. Line 10 makes C point to L.
Line 11 makes D point to itself. So we have C --> L --> D --> D and the for loop
sets cur
to D, so what is printed is "Duncan"
.
QueueInterface<String> q = new ArrayQueue<String> ( );
QueueInterface<String> r = new ArrayQueue<String> ( );
q.enqueue ("Cardie");
r.enqueue ("Duncan");
q.enqueue ("Biscuit");
r.enqueue ("Ace");
for (int i = 0; i < 3; i++) {
String first = q.dequeue( );
String second = r.dequeue( );
if (first.compareTo(second) < 0) {
q.enqueue (first);
r.enqueue (second);}
else {
r.enqueue (first);
q.enqueue (second);}}
while (!q.isEmpty( ))
System.out.println (q.dequeue( ));
Start with q = CB, r = DA. Each of the three passes through the loop takes
the two front elements off the queues and puts them back with the smaller element
in q. So the first move makes q = BC, r = AD, the second makes q = CA, r = DB, and
the third makes q = AB, r = BD. We print "Ace"
and "Cardie"
on separate lines.
public class DogPound {
public DogPound ( ) {
ListInterface<Dog> list = new ArrayUnsortedList<Dog> ( );}
public static void main (String [ ] args) {
Dog cardie = new Dog("Cardie", 5);
list.add (cardie);
System.out.println (list);}}
This won't compile because the variable list
is not declared in the main method,
either as a local variable or an instance variable. (It is declared in the
constructor and thus dies when the constructor finishes.)
public int multiply (int j, int k) {
// precondition: j and k are positive or 0
// postcondition: return value is j * k
if (k == 0)
return 0;
if (j == 1)
return k;
return (k + multiply (j - 1, k);}
The intended error is that if this method is called with j = 0 and k > 0, it will never reach a base case and thus never return a result, violating the postcondition even though the precondition is true. There is also an unintended error, a missing right paren in the last line.
Dog cardie = new Dog("Cardie", 5);
Dog duncan = new Dog("Duncan", 3);
LLNode<Dog> list = new LLNode<Dog>(null);
LLNode<Dog> cNode = new LLNode<Dog>(cardie);
LLNode<Dog> dNode = new LLNode<Dog>(duncan);
cNode.setLink(list);
dNode.setLink(cNode);
list = dNode;
LLNode cur = list;
while (cur.getInfo( ) != null) {
int totalAge += cur.getInfo( ).getAge( );
cur = cur.getLink( );}
System.out.println (totalAge);
The intended error is that the variable totalAge
is declared inside the while
loop and used outside it -- the code will not compile. There is also an unintended
error in that on line 9 cur
should be declared as LLNode<Dog>
instead of just
LLNode
-- this would also cause it not to compile. Many of you thought there was
an error causing the while loop not to terminate, but there isn't. Saying list =
dNode
just moves the pointer list
. It doesn't affect the node with the null
info field, which is still linked from cNode
and is still found by the while loop.
BoundedQueueInterface<String> q = new ArrayQueue<String> (3*N);
BoundedQueueInterface<String> r = new ArrayQueue<String> (3*N);
for (int i = 0; i < N;, i++)
q.enqueue("Cardie");
boolean flag = false;
while (!q.isEmpty( )) {
if (flag)
r.enqueue (q.dequeue( ));
else r.enqueue ("Duncan");
flag = !flag;}
The queue q is filled with N elements which are eventually taken off, but we only take an element off of q every other time through the loop. (By the end of the code r will have "Cardie" N times and "Duncan" N times, alternating.) But only O(1) operations are done each time an element comes off of q, so the while loop is O(N), and everything else is O(1) or O(N), so the whole fragment is O(N).
BoundedQueueInterface<String> q = new ArrayQueue<String> (N);
BoundedQueueInterface<String> r = new ArrayQueue<String> (N);
for (int i = 0; i < N;, i++)
q.enqueue("Cardie");
while (!q.isEmpty( )) {
while (!q.isEmpty( ))
r.enqueue(q.dequeue( ));
r.dequeue( );
while (!r.isEmpty( ))
q.enqueue(r.dequeue( ));}
The inner loop shifts all the elements from q to r, then shifts all but one of the elements back. So q, which starts with N elements, will have N, N-1, N-2, etc., on successive trips through the outer loop. So the outer loop will execute N times, and the inner loop takes O(N), so we have O(N2) total time.
UnboundedQueueInterface<String> q = new LinkedQueue<String> ( );
UnboundedQueueInterface<String> r = new LinkedQueue<String> ( );
q.enqueue("Cardie");
for (int i = 0; i < N; i++) {
while (!q.isEmpty( )) {
r.enqueue(q.dequeue( ));
r.enqueue("Duncan");}
while (!r.isEmpty( ))
q.enqueue (r.dequeue( ));}
The two while loops take the contents of q, shift them to r with a new element after each one, then shift the result back to q. Thus the size of q doubles each time through the outer loop, going from 1 to 2 to 4 and so on to reach 2N after the N executions of the outer loop. The time of the inner loop is proportional to the number of elements of q at the start. So the total time is O(1 + 2 + … + 2N) = O(2N).
Remember that you had a Board class whose objects have 9 by 9
arrays of numbers, with 0's representing unassigned cells. To
make things simple and uniform for this question, we will revise
the Board
class to have the following methods,
which you may assume to be already written:
public int getEntry (int row, int col)
// returns array entry from that row and column
public Board move (int row, int col, int value)
// returns a new Board with entry at that row and column
// changed to "value"
public boolean isBad ( )
// returns true if calling Board has a positive number
// twice in any row, column, or box
Write a method public Board solution ( )
to be
added to the Board
class. This method should
return null
if the Board
is not
solvable (if it is not possible to replace the zeros with
positive numbers to get a valid completed puzzle). If there is
a solution, the method should return the first one in
lexicographic order (just as SudokuSolver
did in
Project #2).
Your strategy should be to move toward a solution by finding
the first unassigned cell, trying all nine possible digits in
that position, and for each one using a recursive call to see
whether there is a solution. There are two base cases for your
recursion -- one where you know that no solution is possible and
one where you know that the curerent Board
is the solution.
public Board solution ( ) {
if (isBad( )) return null; // calling board is bad, no solution
int row, col;
for (row = 0; row < 9; row++)
for (col = 0; col < 9; col++)
if (getEntry(row, col) == 0) break;
// now (row, col) is the first location with a 0 in the calling board
if (row == 9) return this; // calling board is the desired solution
for (int val = 1; val <= 9; val++) {
Board b = move (row, col, val);
if (b.solution( ) != null) return b.solution( );}
return false; // no entry for (row, col) led to a solution
}
int
),
a Person
object representing the owner, and a
Dog
object representing the dog to be licensed.
Write the header and field declarations of the License
class.
You may assume that you have standard getters and setters for each
field,
and a constructor that takes a parameter to set each field.
But if you need this class to have any other methods, you must write
them.
You also need to write a class LicenseDatabase
such
that a
LicenseDatabase
object stores a set of
License
objects in a sorted list, where the objects are sorted by license
number.
You will need to make sure that there are never two licenses with the
same license number in the list. Thus you must write the
equals
and compareTo
methods for License
that will make this work.
LicenseDatabase
will have the following methods:
public boolean addNewLicense (int number, Person owner, Dog d)
// adds new license with given data to database,
// unless another license with that number is there
// return value tells whether the addition was successful
public boolean removeLicense (int number)
// removes license with that number if it is there
// return value tells whether the removal had any effect
public License findDog (Dog d)
// returns the first License object with d.equals (dog) if any,
// otherwise returns null
The code base at the beginning of the exam has the
ListInterface
interface from DJW, and you may assume that the class
ArraySortedList
implements this interface with the intended behavior for a sorted
list.
The code base also has the Dog
class from the first exam
(with an equals
method added), and you may assume that
there is a Person
class that also has an equals
method implemented.
Remember that DJW lists do not use iterator objects, but get the same
functionality with reset
and
getNext
. If getNext
is called when the current position is at the end, it goes to the beginning.
public class License implements Comparable<License> {
int number;
Person owner;
Dog d;
// getters and setters, constructor
public boolean equals (License other) {
return (this.getNumber( ) == other.getNumber( );}
public int compareTo (License other) {
int ours = this.getNumber( );
int theirs = other.getNumber( );
if (ours < theirs) return -1;
if (ours == theirs) return 0;
return 1;}}
public class LicenseDatabase {
public ListInterface<License> list;
public LicenseDatabase( ) {
list = new ArraySortedList<License> ( );}
public boolean addNew License (int number, Person owner, Dog d) {
License lic = new License (number, owner, d);
if (list.contains(lic)) return false;
list.add (lic);
return true;}
public boolean removeLicense (int target) {
list.reset( );
for (int i = 0; i < list.size( ); i++) {
License entry = list.getNext( );
if (entry.getNumber( ) == target) {
list.remove (entry);
return true;}
return false;}
public License findDog (Dog d) {
list.reset( );
for (int i = 0; i < list.size( ); i++) {
License entry = list.getNext( );
if (entry.getDog( ).equals(d))
return entry;
return null;}}
Last modified 1 January 2013