Computer Science 60
Principles of Computer Science


Assignment 8: DP and BSTNode    [100 Points]
Due Tuesday November 5th at 11:59pm

This week's homework is a combination of several ideas we've been examining in CS 60. This assignment includes some programming review (in Prolog and Racket) that includes both the use-it-or-lose-it technique and dynamic programming, an approach that speeds up such implementations -- sometimes remarkably so!

Partners:  This week's problems may be done singly or with pair programming.

Problem 1: Change, Inc.

30 points

You have been hired by Change, Inc., a pioneer in the business of making change. Our motto is "Making positive change throughout the world!". Strictly speaking, the change is only "non-negative" since 0 change is possible, but this was a nuance that the PR folks chose to ignore.

Your job is to write software Change, Inc. that will make change in any given currency system using the smallest number of coins/bills. The currency system might have very odd denominations - for example, Gringotts, a potential customer, uses currency whose values are 1, 29, and 493 knuts, respectively - so the software should not impose limits on what denominations it can handle. This software will be embedded in cash registers and used to inform tellers how to make change optimally - or will simply automate the dispensing of change via robotic change-makers.

You may assume that you have "unlimited" quantities of each coin/bill, and that you may use any combination - including repeats - in making change for a given quantity. Also, you may assume that 1 is always present in the list of denominations -- this ensures that it's always possible to make change for any (nonnegative) target!

Your boss, Professor I. Lai, believes that a simple recursive algorithm for this problem will be fast enough for use in the company's cash registers. Although you are skeptical, Prof. Lai is the boss - at least for the moment.

Thus, first task, therefore, is to test the viability of a purely recursive approach. To that end, Dr. Lai has requested both a Prolog predicate and a Racket function that find the shortest-length list of "coins" that sum to a provided target value.

In the end, you'll create three implementations, one in each of Racket, Prolog, and Java. The first two will use recursion (and will remind you about those languages, we hope!) The Java implementation will use dynamic programming -- and run much more efficiently!



Part 2: The Floyd-Warshall all-pairs shortest-paths algorithm

40 points

You've been hired away from Change, Inc. to work for Google and their new stealth-mode version of their mapping service, named GoogleCpam, and which they claim will "completely reverse" the maps experience! GoogleSpam allows users to estimate the shortest distance among any pair of possible spam-locaitons (nodes) in a map (graph).

In particular, you've been asked to implement the main "smarts" of GoogleSpam, i.e., the Floyd-Warshall all-pairs-shortest-paths algorithm. It reads in a graph from a file as an adjacency matrix, computes the shortest paths between every pair of vertices, and then allows a user to make queries against those results.

map files In the hw8.zip archive, there are a number of different map files, named map0.txt, map1.txt, up to map4.txt. Each contains an adjacency matrix that indicates the edge weights from each node to each node. There are zeros in the top row and top column of each file because all of the cities are indexed from 1, not from 0. The extra zeros are padding so that you can read all of the data from the file directly into your data structure and still start indexing the cities/vertices from 1.

Note that, within the map files, no edge from one vertex to another is represented as -1. This is typically represented as some sort of "infinity" value, and the starter code has a data member INF for that purpose. INF is equal to Integer.Max_VALUE. Be careful, however, Java will allow to add or otherwise use INF as an int, and will simply wrap. Thus, INF + INF yields -2! (You'll need conditionals to make sure to avoid this.)

The cities are indexed from 1, not from 0!    Although 1-indexing is not the norm in computer science, it's very useful here, because it means that the 0-index slice of the Floyd-Warshall table can be the original adjacency matrix. Then the 1-index slice of the Floyd-Warshall table can hold all of the shortest paths using the first vertex (with index 1) as possible intermediate node. The 2-index slice of the FW table can then hold all of the shortest paths using also the next vertex (with index 2) as a possible intermediate node, and so on... Notice that this means that the nth slice of the FW table will hold all of the shortest-path lengths when the algorithm is complete. Note, too, that you will have to make each dimension of size n+1, where n is the number of cities, in order to support indexing from 1 to n!

Here is a brief overview/picture of the included map files:



starter file

The file fw.java contains a little bit of starter code that reads in the first integer from a map file. It also shows how to print a 3d array and has a bit of code to get source and destination vertices from the user via keyboard.

Example results


Here is an example of the completed FW table and, underneath, a few example queries for each of the five maps. In these examples, the paths are printed, but that is the extra-credit portion of this problem -- we'd suggest first getting the shortest-path-distances working, then (if you'd like) returning to work on the paths.

Because some are large, these example results are linked on separate pages:

Warnings/Reminders


  • Since different OSes use different combinations of characaters to indicate newlines, the above examples include all of the data of each map. If our mapfiles are not working, you can create your own by pasting the number of cities and then the adjacency matrix into a new file using a text editor.
  • As you'll recall from our discussion of the Floyd-Warshall algorithm, vertices should be numbered from 1 upwards rather than from 0. Here's why. The algorithm builds a series of tables of path lengths from every src to every dst. The kth "slice" of the table thus represents "the shortest path-length from all src vertices to all dst vertices going through intermediate vertics numbered from 1 to k. By starting at 1, the zeroth table then goes through no intermediate vertices at all, which means it's simply the original graph. By starting vertex-counting at 1, we avoid having a special case for the original graph.
  • Watch out for infinities! INF can be added like any other integer, and it "wraps around" the maximum value an integer can hold, causing surprising results such as INF + INF == -2 ! You'll need special cases to handle infinity appropriately.
  • Extra-credit    For up to +10 points of extra credit, you should also keep track of an array of "parent pointers" and then print out the path from src to dst for each query the user makes. These examples have been included in the sample runs above. How you implement the "parent" table and other details is entirely up to you!
  • Submit your solution in the file called fw.java

    Part 3: BSTNodes...(30 points)

    At this point you've written code for Binary Search Trees (BSTs) in two different languages: Racket & Prolog. Here, we provide a binary-search-tree data structure (class) in Java named BSTNode. For this problem, you should start with this almost-complete BSTNode class and BSTNodeTest class

    BSTNode has much of its basic functionality already provided. This provides both an additional example of how Java creates data structures and it's to allow you to focus on the most algorithmically interesting facets of binary search trees!

    However, in this class, we're doing something unsual for Java. We have based the class BSTNode off of Racket trees. Recall that in Racket we never changed any lists, we only made new lists. So in this BSTNode class we will do the same thing - and NEVER change any BST!

    In this problem you will add the methods insert and delete for the class BSTNode.