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
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:
package hw4.tests;
to package hw4;
package hw4.tests;
as originally given.package hw4.tests;
before submitting.Your first task is to implement a basic RPN calculator that supports integer operands like 1
, 64738
, and -42
as 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:
?
to request that the current state of the stack be displayed (based on toString),.
to pop the top value off the stack and display only that value,!
to exit the program.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).
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.
Stack
to hold intermediate results and then repeatedly accept input from the user.?
(that’s a question mark), you print the current state of the stack using its toString()
method followed by a newline..
(that’s a dot or full-stop), you pop the top element off the stack and print only that value, followed by a newline.!
(that’s an exclamation mark or bang), you exit the program, regardless of the state of the stack.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:
blah
(or anything else that doesn’t make sense for a calculator as specified above) your program should make it clear that it can’t do anything helpful with that input; but it should not stop at that point.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!**
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.
> 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.
!
is not absolutely required in order to stop the program.int
./
stands for integer division (DIV) and %
stands for integer remainder.%
to work just as the %
operation in Java. Some languages have different conventions for this (in regards to dealing with negative numbers, since remainder and modulo differ when dealing with negatives), but for this assignment %
is the Java remainder operator.Unique
programs, Calc
should never terminate with an exception. If it does (if our test cases trigger some sort of exception like an EmptyException
), you will be penalized.Stack
implementations for Integer
objects yet still do arithmetic like we would on regular int
variables.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.
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
.
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?
expected
parameter of the @Test
annotation. One of the example tests we give you shows how to do this properly.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.
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.
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.
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.
public
, protected
, and private
appropriately, etc.). Simple, clean, readable code is what you should be aiming for.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.)