Assignment 4: Stacking Queues

Overview

The fourth assignment is about stacks and deques. In Part A you’ll use a stack to create a simple Calculator application using the stack implementation in Java Collections.In Part B you’ll be testing a flawed Deque implementation that we will be providing to you, with the goal of determining what mistakes the implementer made

Package Setup

Files you will be editing are marked with an asterisk (*).

hw4-student.zip
--
exceptions/
    EmptyException.java
    IndexException.java
    ExampleException.java
    LengthException.java
hw4/
    Deque226.java
    Assignment4.jar
    Calc.java *
    tests/
        FlawedDeque226Test.java *

These provided files should compile as is. Notice that we have separated the JUnit test files into a subdirectory to make command-line compilation easier. You can compile everything in exceptions from the command line by running javac -Xlint:all exceptions/*.java. Compiling the hw4 java files will be similar: javac -Xlint:all hw4/*java. Then you can compile and run the junit files from the same directory using our aliases:

This structure will hopefully circumvent many of the command-line compilation problems people were having with hw3. However, it will make life more difficult for jGrasp people. In jGrasp, your test files and source code are supposed to be in the same folder. You can carefully get around this problem:


Part A: RPN Calculator

Your first task is to implement a basic RPN calculator that supports integer operands like 1, 64738, and -42as well as the (binary) integer operators +, -, *, /, and %. RPN is the same as post-fix arithmetic expression notation that we discussed in class. The stack underlying your implementation should be the one provided by Java Collections, the documentation for which can be found here. Your program should be called Calc and work as follows:

Examples

Here are two examples for interacting with Calc that will hopefully help you understand what you’re trying to achieve. First a “slow” example:

> java hw4.Calc
?
[]
10
?
[10]
20 30
?
[10, 20, 30]
*
?
[10, 600]
+
?
[610]
.
610
?
[]
!
>

Here > is the shell prompt. After starting the program, the first command was ? to print the stack (which is empty at this point, hence [] is the output). Then the user typed 10 followed by ? and we see that the stack now holds that number: [10]. Now the user typed two numbers 20 30 in sequence before hitting return. When we check the stack now using ? we get the answer [10, 20, 30] so obviously the “top” of the stack is to the right. Then we see the * operator being typed, which will pop and multiply the top two numbers, pushing the result onto the stack. We use ? again to check the result: [10, 600]. This is followed by the + operator, which will add the top two numbers. Again we check with ? and get [610] as we’d expect. The . command pops and prints the value 610. The ? command then displays an empty stack, and finally the user typed the ! command to quit, returning us to the shell. Here’s the same example, done “fast” this time:

> java hw4.Calc
? 10 ? 20 30 ? * ? + ? . ? !
[]
[10]
[10 20, 30]
[10, 600]
[610]
610
[]
>

As you can see, if the entire sequence of integers, operators, and commands is entered on a single line, they are all executed in order. It’s like having our own little programming language! Finally, here’s an example for the two error conditions described below:

> java hw4.Calc
1 2 blah 1.0 3 ?
ERROR: bad token
ERROR: bad token
[1, 2, 3]
+ + ?
[6]
+ + ?
ERROR: Not enough arguments.
ERROR: Not enough arguments.
[6]
!
>

Note in particular that blah and 1.0 lead to error messages but are otherwise ignored (the program doesn’t stop); same for the two + operations when the stack only has a single element (the program doesn’t even modify the stack in that case).

Implementation Details

Most of these details explain how to use a Stack to evaluation a post-fix expression, similar to the example we worked through in class. More details regarding the special operations are also included.

Note that there are a number of error conditions that your program must deal with gracefully for full credit. We’ll give you two examples for free, you’ll have to figure out any further error conditions for yourself:

Of course this means that you’ll have to print error messages to the user. Error messages must be printed to standard error (System.err) and not to standard out! (Of course, the regular input and output is done through standard in and standard out as usual.) Furthermore, all error messages must start with the string ERROR:, be exactly one line, and be followed by a newline!**

Discussion

In your README, document all error conditions you determined and why they are error conditions. Do this by including the inputs that you used to test your program and what error conditions they exposed.

Hints

> java hw4.Calc 10 5 - . !

and

> java hw4.Calc 5 10 - . !

to be different! More generally, if the stake state is [a, b] and we want to apply the operator op, it should be equivalent to evaluating a op b in infix notation. Take a look at the RPN wiki page for more examples.

Part B: Testing Deques

Your second task is to write comprehensive testing for a flawed deque implementation FlawedDequeImpl.class that we have provided you, with the intention of finding all the bugs and mistakes it contains. Note that we will not be saying how many bugs In particular, we are supplying you with a compiled Java executable that has no attached Java source files, so you are only able to interact with the implementation as a black box. For reference, we also provide the Deque226.java interface that our implementation implements.

Testing

You are going to develop a JUnit 4 tests for your FlawedDeque226 class. We provide the skeleton code to get you started in test/FlawedDeque226Test.java. Note that all we really care to test is that an FlawedDeque226 is a correct implementation of the Deque226 interface, and that you detect times when it fails to live up to that expectation.

To run against the implementation in the Jar file, simply import it as a library! This can be done in IntelliJ via File -> Project Structure -> Libraries -> + -> /path/to/jar.

Discussion

In your README, please give a list of the flaws you uncovered in our implementation and list the JUint 4 tests that uncovered each flaw. For each flaw you identify, please share an educated guess as to what is the mistake that led to the flaw. Also, please discuss the process with which you determined what tests to write? What made this process more difficult?

Hints


Deliverables

The files you have // TODO items in are listed explicitly below:

Calc.java
tests/FlawedDeque226Test.java

You need to submit all of these files to the autograder along with a README. You can upload them individually or in a zip file. If you upload them in a zip file make sure they are all at the top level, you cannot have any extra directories or else the autograder won’t be able to find them. This even applies to the test file - do not submit it in a tests subdirectory!

Make sure the code you hand in does not produce any extraneous debugging output. If you have commented out lines of code that no longer serve any purpose you should remove them.

README

You must hand in the source code and a README file. The README file can be plain text (README with no extension), or markdown (README.md). In your README be sure to answer the discussion questions posed in this description. You should discuss your solution as a whole and let the staff know anything important. If you are going to be using late days on an assignment, we ask that you note it in your README.

If you want to learn markdown formatting, here is a good starting point.

Submitting to Gradescope

Once you are ready to submit your files, go to the assignment 4 page for Gradescope and click submit. Note that you can resubmit any time up until the deadline. Only your most recent submission will be graded. Please refer to course policies as far as policies regarding late days and penalties.

After you submit, the autograder will run and you will get feedback on your functionality and how you performed on our test cases. Some test cases are “hidden” from you so you won’t actually know your final score on the test cases until after grades are released. We also include your checkstyle score as a test case.

If you see the “Autograder Failed to Execute” message, then either your submission did not compile at all or there was a packaging error. Please see the Gradescope Submission Notes in Piazza Resources for help debugging why your submission is not working.

You do not need to fully implement each file before you submit, but you’ll probably fail the test cases for the parts of the assignment you haven’t done yet. Also note that only the files with // TODO items in them will be used. You cannot modify any of the provided interface files as the autograder will overwrite any changes you made with the original provided file.


Grading

For reference, here is a short explanation of the grading criteria; some of the criteria don’t apply to all problems, and not all of the criteria are used on all assignments.

Packaging refers to the proper organization of the stuff you hand in, following both the guidelines for Deliverables above as well as the general submission instructions for assignments.

Style refers to Java programming style, including things like consistent indentation, appropriate identifier names, useful comments, suitable javadoc documentation, etc. Many aspects of this are enforced automatically by Checkstyle when run with the provided configuration file.

Testing refers to proper unit tests for all of the data structure classes you developed for this assignment, using the JUnit 4 framework as introduced in lecture. Make sure you test all parts of the implementation that you can think of and all exception conditions that are relevant.

Performance refers to how fast/with how little memory your program can produce the required results compared to other submissions.

Functionality refers to your programs being able to do what they should according to the specification given above; if the specification is ambiguous and you had to make a certain choice, defend that choice in your README file.

If your submission does not compile, you will not receive any of the autograded-points for that assignment. It is always better to submit code that at least compiles. You will get freebie points just for compiling.

If your programs have unnecessary warnings when using javac -Xlint:all you will be penalized 10% functionality per failed part. (You are also unable to use the @SuppressWarnings annotation - we use it just to filter our accepted warnings from yours.)

If your programs fail because of an unexpected exception, you will be penalized 10% functionality per failed part. (You are not allowed to just wrap your whole program in to a universal try-catch.)