This homework introduces Java, a language designed for creating and using data structures. The first part is to implement an OpenList data structure, which is a list of the type Scheme uses for programs and data. The OpenList "shows off" Java's data-structuring capabilities without sacrificing the generality of Scheme. There is also a Scheme "unit-calculator" application, which will lead to a Java version (next week).
You will want to submit your two files
This assignment uses material through Chapter 5 in the text, though the material needed to handle this assignment will be presented in class also.
There are many, many environments in which you might write Java code. Because CS 60 seeks to get at the fundamentals of computation (and not focus on a particular toolset like Eclipse, JCreator, Visual Studio, NetBeans, etc.) our default setup will use Java from the command line (similar to Python).
If you have a favorite environment, you're welcome to use it, but please be sure that you are submitting the plain-text .java files so that we will be able to compile and run them!
Setup on the Mac Type javac -version at the command line in the Terminal application; it should already be built-in. We are using version 1.5.0_11, though 1.4 might well be good enough, too.
Setup on the PC (Windows) You might have java, but might _not_ have java software development kit (JDK) which includes the compiler. To find out, look for the folder C:\Program Files\Java\jdk1.5.0_11\ - the jre folder, which stands for java runtime environment can run software but can not compile it and so is not sufficient. If you don't have the JDK, download it from the references page.
Installation should be straightforward. After installing the JDK, you will want to set up your "path" so that you can simply type javac at the command line to compile. To do this, click the Start Menu and go through the following steps:
- Control Panel
- System
- "Advanced" Tab
- "Environment Variables" button at bottom
- Under "System variables," scroll to
- "Path" and select it
- click "Edit"
- a one-line textbox will appear
- go to the right-hand end and paste the following:
;C:\Program Files\Java\jdk1.5.0_11\bin
Then enter and click on OK a couple of times to finish.
The semicolon is the windows path separator. That's why
it's at the start. After the semicolon is the
path to the java compiler (javac) as well as some
other tools.
To check that it's working, open a cmd window and type javac -version. You should see javac 1.5.0_11 and then lots of additional lines.
OK, but the command java to actually run the programs isn't
working!
This may or may not be happening to you (it depends on earlier interactions of your
computer with Java, some of which you might not have realized because it gets used
behind the scenes in lots of web-browsing situations).
However, if javac, the compiler, is working, but java is not working (be sure you're typing java CLASSNAME without the .class extension!), then it's almost certainly the so-called "classpath". The classpath is where Java looks for the classes whose main method it will run. You need to have the current directory in your classpath, and this is done by setting the CLASSPATH environment variable. Here's what to do (almost identical to augmenting the Path environment variable, above:
- Control Panel
- System
- "Advanced" Tab
- "Environment Variables" button at bottom
- Under "System variables," scroll to
- "CLASSPATH" and select it IF PRESENT
- click "Edit"
- a one-line textbox will appear
- go to the right-hand end and paste the following:
;.
Then enter and click on OK a couple of times to finish.
- if CLASSPATH was NOT PRESENT
- click "New" (in the lower, "System variables" part of the window)
- name the new variable CLASSPATH
- enter the value
.
Then click on OK a couple of times to finish.
You'll have to start a new command-line window to have the changes take effect. Within
a command-line window, you can view the values of all the environment variables with
the set command. (You can change them with the same command - type help
set for more.)
Working remotely at the CS lab You can login remotely to your CS lab account by using a secure shell login program. A very popular one that you can download for free is named Putty.
Again, you may use your favorite text editor. A free editor that has worked well on any OS is JEdit. For some people, the development release has installed more readily than the "stable" release. A much faster (to load) editor is Crimson Editor, but it is for Windows only. Regardless of your specific editor, do be sure to use a text editor, not a word processor - word processors (like Microsoft Word) insert invisible control characters into their documents that will interfere with writing and compiling code.
Unlike Scheme and Python, running Java source code is a two-step process.
From within the directory containing the code, you need to first compile the code. This converts it from source (what you wrote) to byte code (which will get executed). For example, if your source file is named OpenList.java you would type
prompt> javac OpenList.javaThe compiler may catch errors - in that case, go to the topmost error, read the message, and go back to the source code to fix the problem. Once the code compiles without error, if you list the contents of the directory, there will now be a file named OpenList.class - this file holds the byte code. There will be one .class file for each class in your original source-code file. To actually run your program, you then type
prompt> java OpenListwhere you may replace OpenList with any class name that has a main method. This will then start the main method of that class.
70 points
This problem is meant to introduce the implementation of data structures in Java. In addition, it is a chance to either introduce yourself (or review) what Java looks like and how java code is structured. If you haven't used Java before, you may need to review a bit about the language. In particular, there is a starting point for your OpenList.java file on the top-level assignments page. Also, there are on-line references and tutorials available from the references page.)
Write a java class named OpenList that implements an (open) linked list data structure. Since the goal of this problem is to transition from Scheme to Java, you will be implementing lists in the same way Scheme does. In fact, this problem is, essentially, the first step in writing the Scheme programming language in Java. Open lists are not modified in the computer's memory (so that there is no worry about side effects) -- instead, each function returns a newly created list (or whatever data is appropriate).
Write your class in a file called OpenList.java. You should start with the OpenList.java file located at the top-level assignments page.
The main method of this OpenList.java contains a couple of tests. You might want to try out the file to begin with and read over the code in order to get a sense of what Java is doing (and how it's organized).
Testing your code! Just as with your Scheme programming, you should test each of your methods as you write it. To do this, add tests to your OpenList class's main method that exercise each of your methods. It's much easier to make small syntactic errors in Java than in Scheme (all those semicolons!) Be sure to try out base cases, as well as recursive ones!
Reminder Again, the command
% javac OpenList.java
will create a file named OpenList.class in your directory.
After that, running
% java OpenList
will execute the code in the main method of
the OpenList class.
First, in your OpenList class, you will want to indicate the data that constitute a list. There are two nonstatic data members (first and rest) and one static data member (emptyList) in an OpenList:
private Object first;
private OpenList rest;
public static OpenList emptyList = new OpenList(null, null);
These are the only data members you will need in
your list implementation. You may use others, if you
would like -- in fact, there is considerable leeway
in how you want to implement OpenList. However,
it has to have all of the methods indicated below, and
they need to behave as specified!
Notice that because the data member named first is of type Object, this OpenList implementation will be able to create lists of any Java Objects. Everything in Java is an Object except the types int, double, float, boolean, byte, char, and long. We will use only Strings and OpenLists for this assignment. The next problem, on the other hand, will put your OpenList class to work... .
In Java and other object-oriented languages, functions that are members of a class are often called methods.
So, in your OpenList class, implement the following methods:
This toString method is a nonstatic method that returns a String representation of the invoking list. A static version isn't needed. The toString method is used internally by Java whenever your code adds a String to an OpenList, e.g., in code like this:
OpenList L = OpenList.list("Hello","World");
System.out.println("List L is " + L);
This code should output
List L is ["Hello", "World"]
String m1 = "mudd";
String m2 = "mit";
if ( m2.compareTo(m1) < 0 ) ... // this test will evaluate to true
Basically, if compareTo is less than zero, then this is
before the input argument in the dictionary.
Object s = new String("I'm a string.");
if ( s instanceof String ) ... // this test will evaluate to true
if ( s instanceof OpenList ) ... // this test will evaluate to false
No static version is required. Remarkably, Java's compiler checks if an instanceof
expression can possibly be true - the code won't compile if it can't! In this case,
s is of type Object, which could be a String or a OpenList.
(The compiler doesn't actually read the code, it just checks the types....)
This problem asks you to write a Scheme function, convert, which implements a "unit-calculator" application. A complete application will be able to convert any unit quantity to any compatible quantity by using an association list of known conversions. Incompatible conversions will result in a set of extra units "left over."
For example, the following call is asking "how would you convert from 1 mph (mile per
hour) to 1 meter per second?" The third input argument to convert, named db
is a "database" of unit conversions. This "database" is simply an associate list.
This result is indicating that 1 mile-per-hour == 0.447032 * 1 meter-per-second.
> (convert '(1 ("mile") ("hour")) '(1 ("meter") ("second")) db)
(0.447032 () ())
Here is an example with some units left over, because it's not possible to
convert miles-per-hour to feet:
This time the result is showing that 1 mile-per-hour == 1.46666 feet-per-second.
> (convert '(1 ("mile") ("hour")) '(1 ("foot") ()) db)
(1.466666 () ("second"))
Since there were no time units in the denominator and there should have been, the result shows the basic (irreduceable) time units there.
Basic units are simply those which do not appear on the left-hand side of the association list.
In both of these examples, only the first few significant figures have been shown.
As these examples suggest, your convert function needs only to
handle multiplicative conversions - it will not handle more complicated
conversions, such as the one from Fahrenheit to
Celsius.
Here are the key representations used in Unicalc:
(1.0 ("mile") ("hour")) represents 1 mile per hour
(2.5 ("meter") ("second" "second")) represents 1 meter per second squared
(60.0 ( ) ("second")) represents 60 hertz
(3.14 ( ) ( )) represents about pi radians
To summarize, a Quantity list is a list of three elements: the
first is the quantity (a floating point number), the second is a list of
units in the numerator, and the third is the list of units in the
denominator. Empty lists are required when no units are present.
Note You may assume that the lists of
units within the numerator and within the denominator, if any,
are initially in alphabetical order.
Your code needs to make sure this property is maintained!
(define small-db
'(
("foot" (12.0 ("inch") ()))
("inch" (2.54 ("cm") ()))
("hertz" (1.0 () ("second")))
("mile" (5280.0 ("foot") ()))
("coulomb" (1.0 ("ampere" "second") ()))
("cm" (0.01 ("meter") ()))
("hour" (60.0 ("minute") ()))
("minute" (60.0 ("second") ()))
)
)
Each line in the database is thus a list of two elements -- the first element is a string
that names some unit and the second element is a Quantity List that is
equivalent to that named unit.Not every unit is defined in terms of others in the database. Some are intentionally left undefined. We'll call the latter basic units. In the above example, ampere, meter, and second are basic units.
A database does not need to contain conversions for everything to everything; that would tend to make it very large and maintenance would be error-prone. Instead, all conversions done by Unicalc are derived from basic ones in the database.
Individual functions You are welcome to decompose this unit-calculator into smaller functions on your own. If you do so, we will simply test your convert function. However, you are also welcome to write the functions described on this page, which will lead you to a full implementation of the unit-calculator. If you use this decomposition, we will grade each function separately.