[Instructions] [Search] [Current] [Syllabus] [Links] [Handouts] [Project] [Outlines] [Labs] [More Labs] [Assignments] [Quizzes] [Exams] [Examples] [Book] [Tutorial] [API]
Distributed: Friday, November 19, 1999
Due: 10 a.m., Monday, December 6, 1999
No extensions!
This page may be found online at
http://www.math.grin.edu/~rebelsky/Courses/CS152/99F/Exams/exam.03.html.
Code files:
ALTester.java
AssociationList.java
BinarySearchable.java
BinarySearcher.java
Comparator.java
CursoredList.java
CursoredLinkedList.java
Dictionary.java
IncomparableException.java
Node.java
Pair.java
SimpleOutput.java
There are four problems on the exam, each with an equivalent point value (25 points). Note that the different questions are not necessarily of the same complexity or length.
This examination is open book, open notes, open mind, open computer, open Web. Feel free to use any and all resources available to you except for other people and for exam and homework solutions. As always, you are expected to turn in your own work. If you find ideas in a book or on the Web, be sure to cite them appropriately. Do not use exam or homework solutions you find on the Web.
This is a take-home examination. It is likely to take you about four hours. You may use any time or times you deem appropriate to complete the exam, provided you return it to me by the due date. No late exams will be accepted. I will make a solution key available soon after the exam.
Because different students may be taking the exam at different times, you are not permitted to discuss the exam with anyone until after I have returned it. If you must say something about the exam, you are allowed to say ``This is definitely the hardest exam I have ever taken.'' You may also summarize these policies.
Answer all of your questions electronically. That is, you must write all of your answers on the computer and print them out. You should also email me a copy of your exam (a plain text file, please). If you include a note about the time spent on each problem, I will give you three points of extra credit. Please put your answers in the same order that the problems appear in.
I will give partial credit for partially correct answers. You ensure the best possible grade for yourself by highlighting your answer and including a clear set of work that you used to derive the answer.
I may not be available at the time you take the exam. If you feel that a question is badly worded or impossible to answer, note the problem you have observed and attempt to reword the question in such a way that it is answerable. If it's a reasonable hour (before 10 p.m. and after 8 a.m.), feel free to try to call me in the office (269-4410) or at home (236-7445).
I will also reserve time at the start of classes next week to discuss any general questions you have on the exam.
Write a new class, ListComparator, that compares pairs of
cursored lists. In both your equals and
lessThan methods, You should first verify that the
parameters are, in fact, CursoredLists and throw an
exception if they are not.
You should write working code for this problem.
As you've seen, many of our data structures come from sets of functions we need for particular tasks. Consider the problem of binary search. What methods do we need for binary search to work? I'd suggest that there are four
Once we have those methods, we can write binary search as follows:
import Comparator;
/**
* An object that knows how to search.
*
* @author Samuel A. Rebelsky
* @version 1.0 of November 1999
*/
public class BinarySearcher {
/**
* Search for an object u sing binary search.
*/
public boolean binarySearch(BinarySearchable stuff,
Object findMe,
Comparator compare)
throws Exception
{
if (stuff.isEmpty())
return false;
else if (compare.equals(findMe, stuff.middle()))
return true;
else if (compare.lessThan(findMe, stuff.middle()))
return binarySearch(stuff.smaller(), findMe, compare);
else
return binarySearch(stuff.larger(), findMe, compare);
} // binarySearch(BinarySearchable, Object, Comparator)
} // BinarySearcher
As this suggests, we need a BinarySearchable interface
in order to use binary search.
/**
* Collections of objects amenable to search with binary search.
*
* @author Samuel A. Rebelsky
* @version 1.0 of November 1999
*/
public interface BinarySearchable
{
/**
* Get the ``middle'' key in the collection.
* Pre: The collection is nonempty.
* Post: Returns some designated element in the collection.
*/
public Object middle();
/**
* Get elements in the collection that are smaller than the
* middle element.
* Pre: The collection is nonempty.
* Pre: The collection has not been modified since the last call
* to middle.
* Post: Returns the smaller elements.
*/
public BinarySearchable smaller();
/**
* Get elements in the collection that are larger than the
* middle element.
* Pre: The collection is nonempty.
* Pre: The collection has not been modified since the last call
* to middle.
* Post: Returns the larger elements.
*/
public BinarySearchable larger();
/**
* Determine if the collection is empty.
*/
public boolean isEmpty();
} // BinarySearchable
Sketch an implementation of BinarySearchable using
sorted arrays. Each method should be O(1). Here's the start of the class.
/**
* An implementation of BinarySearchable using an array
* along with bounds that determine the portion of the array
* under consideration. An attempt to turn some of the trickiness
* in array-based binary search into something more general.
*
* At any point, we care only about the subarray of contents given
* by lowerBound .. upperBound.
*
* @author Samuel A. Rebelsky
* @author Your Name Here
*/
public class ProblemB
implements BinarySearchable
{
// +--------+--------------------------------------------------
// | Fields |
// +--------+
/** The array under consideration. */
private Object[] contents;
/** The lower bound of the subarray under consideration. */
private int lowerBound;
/** The upper bound of the subarray under consideration. */
private int upperBound;
// +--------------+--------------------------------------------
// | Constructors |
// +--------------+
// +---------+-------------------------------------------------
// | Methods |
// +---------+
} // Problem B
You need not write working code for this problem; simply convince me that you have the basic idea.
In our discussion of dictionaries, we decided that we could
use association lists to implement dictionaries. Here's
part of an association list class. Note that CursoredLinkedList
is an implementation of the CursoredList class
like the one you prepared for assignment 4. You can use mine, or you
can use your own.
import CursoredLinkedList;
import Pair;
/**
* A simple implementation of dictionaries, using a list of
* key/value pairs.
*
* @author Samuel A. Rebelsky
* @author Your Name Here
*/
public class AssociationList
implements Dictionary
{
// +--------+--------------------------------------------------
// | Fields |
// +--------+
/** The pairs in the dictionary. */
private CursoredLinkedList pairs;
// +--------------+--------------------------------------------
// | Constructors |
// +--------------+
/** Create a new association list. */
public AssociationList() {
this.pairs = new CursoredLinkedList();
// Because the find method skips the starting node,
// we make sure the association list begins with an
// unused pair. It should always have this pair at the
// front.
pairs.addToFront(new Pair("FRONT",""));
} // AssociationList()
// +---------+-------------------------------------------------
// | Methods |
// +---------+
/**
* Populate the association list with some sample pairs.
* Intended primarily for testing.
*/
public void populate() {
pairs.addToEnd(new Pair("Joshua Vickery", "Undecided"));
pairs.addToEnd(new Pair("Sierra Soleil", "Philosophy"));
pairs.addToEnd(new Pair("Kate Ducey", "Theatre"));
pairs.addToEnd(new Pair("Wanlin Liu", "Economics"));
} // populate()
/**
* Get the value associated with a key. See the interface
* for more information.
*/
public Object get(Object key)
throws Exception
{
try {
// Find the first pair with the appropriate key.
pairs.front();
pairs.find(new Pair(key, null));
// If we got this far, find succeeded.
return ((Pair) pairs.getCurrent()).getValue();
}
// Whoops! Not found
catch (Exception e) {
throw new Exception(key.toString() + " not found");
}
} // get(Object)
/**
* Set the value associated with a particular key. See the
* interface for more information.
*/
public void put(Object key, Object value)
throws Exception
{
// STUB
} // put(Object,Object)
/**
* Convert to a string.
*/
public String toString() {
String result = "";
pairs.front();
try {
while (true) {
Pair p = (Pair) pairs.getCurrent();
result = result + p + " ";
pairs.advance();
}
}
catch (Exception e) {
// Hit the end of the list.
}
return result;
} // toString
} // AssociationList
Write and test the accompanying put method. Note that
you should make sure that the list does not have two pairs with the
same key.
Here is a class that might help you test your method.
import AssociationList;
import SimpleOutput;
/**
* Test association lists. Takes advantage of some prior knowledge
* about the magical "populate" method.
*
* @author Samuel A. Rebelsky
* @version 1.0 of November 1999
*/
public class ALTester {
// +--------+--------------------------------------------------
// | Fields |
// +--------+
/** The association list we're testing. */
AssociationList testme;
/** Something to generate output with. */
SimpleOutput out;
// +--------------+--------------------------------------------
// | Constructors |
// +--------------+
public ALTester() {
// Prepare to generate output.
out = new SimpleOutput();
// Set up the associatoin list.
testme = new AssociationList();
// Set up a sample set of key/value pairs for testing.
testme.populate();
// Look up a few names that are already there. We check all
// of them so that we hit all the positions.
lookup("Joshua Vickery");
lookup("Sierra Soleil");
lookup("Kate Ducey");
lookup("Wanlin Liu");
// Capitalization should matter.
lookup("joshua vickery");
// Here's a name that's not there.
lookup("sam rebelsky");
// Add it.
add("sam rebelsky", "CS");
// Now it should be there.
lookup("sam rebelsky");
// Change Josh
add("Joshua Vickery", "CS");
lookup("Joshua Vickery");
out.println("Final list: " + testme.toString());
} // ALTester()
// +---------+-------------------------------------------------
// | Methods |
// +---------+
/** Look up a name in the association list. */
public void lookup(Object key) {
out.print("Looking up '" + key + "': ");
try {
out.println(testme.get(key));
}
catch (Exception e) {
out.println("FAILED");
}
} // lookup(Object)
/** Add a key/value pair to the list. */
public void add(Object key, Object value) {
out.print("Adding key: '" + key + "', value: '" + value + "' ...");
try {
testme.put(key,value);
out.println("OK");
}
catch (Exception e) {
out.println("FAILED");
}
} // add(Object,Object)
// +------+----------------------------------------------------
// | Main |
// +------+
/** Test away. */
public static void main(String[] args) {
new ALTester();
} // main(String[])
} // class ALTester
You should write working code for this problem.
As you may have discovered in your work on assignment 4, it is often helpful to have more than one cursor on a list. The same is true for trees. Consider our basic interface for cursored trees.
/**
* A simple way of looking a trees. Uses a cursor to support
* retrieval of information in the tree.
*
* @author Samuel A. Rebelsky
* @version 1.0 of November 1999
*/
public interface CursoredTree {
// +-----------+-----------------------------------------------
// | Modifiers |
// +-----------+
/**
* Set the value stored in the root of the tree.
* Pre: (none)
* Post: The root of the tree now contains newRoot.
* The tree is nonempty.
*/
public void setRoot(Object newRoot);
/**
* Set one of the children of the current node (given by the
* cursor). Children are numbered from 0 to numChildren-1.
* Pre: The cursor is at a known location.
* Post: The number of children is at least childNum-1.
* The childNum'th child contains newChild.
*/
public void setChild(Object newChild, int childNum);
/**
* Clear the subtree starting at the current node.
* Pre: The cursor is at a known location.
* Post: The cursor is at the parent of the current location
* (as long as the cursor was not at the root).
* There is now a "hole" where the subtree was.
*/
public void clear();
// +-----------------+-----------------------------------------
// | Cursor Movement |
// +-----------------+
/**
* Move the cursor to the root of the tree.
* Pre: (none)
* Post: The cursor is at the root of the tree.
*/
public void root();
/**
* Move the cursor up one level in the tree.
* Pre: The cursor is not at the root of the tree.
* Post: The cursor is at the parent of the current node.
*/
public void parent();
/**
* Move the cursor down to a child.
* Pre: The current node has at least childNum-1 children.
* Post: The cursor is on the node representing the specified child.
*/
public void child(int childNum);
// +-----------+-----------------------------------------------
// | Accessors |
// +-----------+
/**
* Get the value associated with the current node.
* Pre: There is a current node.
* Post: Returns the value associated with the current node.
*/
public Object getValue();
/**
* Get the number of children of the current node.
* Pre: There is a current node.
* Post: Returns the number of children associated with the current node.
*/
public int getNumChildren();
} // interface CursoredTree
Write a new pair of interfaces, MultiCursoredTree and
TreeCursor to support multiple cursors on the same tree.
You'll need to think about how the two interfaces will interact.
Although you cannot specify constructors in an interface, include a
note as to the expected form of any constructors for the two classes.
Since you're only writing interfaces, you won't write ``working'' code. However, you should make sure that your interfaces compile correctly.
Prior to 18 November 1999
18 November 1999
[Instructions] [Search] [Current] [Syllabus] [Links] [Handouts] [Project] [Outlines] [Labs] [More Labs] [Assignments] [Quizzes] [Exams] [Examples] [Book] [Tutorial] [API]
Disclaimer Often, these pages were created "on the fly" with little, if any, proofreading. Any or all of the information on the pages may be incorrect. Please contact me if you notice errors.
This page may be found at http://www.math.grin.edu/~rebelsky/Courses/CS152/99F/Exams/exam.03.html
Source text last modified Mon Nov 22 08:43:09 1999.
This page generated on Mon Nov 22 08:48:41 1999 by Siteweaver. Validate this page's HTML.
Contact our webmaster at rebelsky@grinnell.edu