CIT 590/591 Assignment 8: Array Operations Fall 2012, David Matuszek
Purposes of this assignment
To get you started with JUnit 4
To give you practice with arrays
To help you understand APIs (Application Programmer Interfaces)
General idea of the assignment
Define a new object type, named Layout. A Layout object is like a one- or two-dimensional array of integers. However, it will be different from an array in a couple of respects: (1) Layouts have a number of operations defined on them that arrays do not have, (2) Layouts are immutable, in the same way that Strings are immutable; once created, they cannot be changed, and (3) Layouts are just objects, so you can't use brackets with them as you can with arrays.
Write a number of methods for manipulating Layouts. Test
all your methods thoroughly with JUnit 4.
There are a lot of methods listed below, but don't worry--they are all
very short, just a couple of for loops each. Most of your
work will be in writing the JUnit tests for them.
Note 1: There is no need for a main method
anywhere in this assignment. You are not writing a program, you are writing
a class that could be used by other programs.
Note 2: You will not be assigned a partner for this program. Please do it
alone.
Constructors
public Layout(int[] array)
Creates a Layout containing the given array.
public Layout(int[][] array)
Creates a Layout containing the given array.
public Layout(int length)
Creates an Layout of length integers, and fills it with the numbers 1 to length.
Example:new Layout(12) returns
1
2
3
4
5
6
7
8
9
10
11
12
Methods
public Layout reverse()
Returns a new Layout whose values are in the reverse order of those in the given Layout.
Example:
3
1
4
1
6
.reverse() returns
6
1
4
1
3
This should also work for two-dimensional Layouts:
Example:
1
2
3
4
5
6
7
8
9
10
11
12
.reverse() returns
4
3
2
1
8
7
6
5
12
11
10
9
public Layout rotateRight()
Returns a new Layout which is "rotated"
a quarter-turn clockwise.
Example:
1
2
3
4
5
6
7
8
9
10
11
12
.rotateRight() returns
9
5
1
10
6
2
11
7
3
12
8
4
public Layout rotateLeft()
Returns a new Layout which is "rotated"
a quarter-turn counterclockwise.
Example:
1
2
3
4
5
6
7
8
9
10
11
12
.rotateLeft() returns
4
8
12
3
7
11
2
6
10
1
5
9
public Layout transpose()
Transposes a Layout of m rows and n columns to form a Layout of n rows and m columns.
The value in location [i][j] of the Layout become the value in
location [j][i] of the new Layout.
Example:
1
2
3
4
5
6
7
8
9
10
11
12
.transpose() returns
1
5
9
2
6
10
3
7
11
4
8
12
public Layout ravel(int n)
Takes a one-dimensional Layout of m × n
numbers and returns a two-dimensional Layout of m rows and
n columns. The first n numbers of the given Layout are
copied into the first row of the new Layout, the second n numbers
into the second row, and so on. This method throws an
IllegalArgumentException if the length of the input Layout
is not evenly divisible by n.
Example:
1
2
3
4
5
6
7
8
9
10
11
12
.ravel(4) returns
1
2
3
4
5
6
7
8
9
10
11
12
public Layout unravel()
Takes a m by n two dimensional Layout and returns
a one-dimensional Layout of size m × n containing the
same numbers. The first n numbers of the new Layout are copied
from the first row of the given Layout, the second n numbers
from the second row, and so on.
Example:
1
2
3
4
5
6
7
8
9
10
11
12
.unravel() returns
1
2
3
4
5
6
7
8
9
10
11
12
public Layout reshape(int n)
Takes a two-dimensional array of r rows and c columns
and reshapes it to have n columns by (r*c)/n rows. This method throws an
IllegalArgumentException if r*c
is not evenly divisible by n.
Example:
1
2
3
4
5
6
7
8
9
10
11
12
.reshape(6) returns
1
2
3
4
5
6
7
8
9
10
11
12
public Layout join(Layout layout)
Adjoins a Layout with n rows and m1 columns to the parameter Layout with n rows and m2 columns, forming a new Layout with n rows and m1+m2 columns. This method throws an IllegalArgumentException if the input Layouts do not have the
same number of rows.
Example:
1
2
3
4
5
6
.join(
10
20
30
40
50
60
70
80
) returns
1
2
3
10
20
30
40
4
5
6
50
60
70
80
public Layout stack(Layout layout)
Forms a new Layout with n rows and m1+m2 columns by putting the recipient Layout with n1 rows and m columns on top of the parameter Layout of n2 rows and m columns. This method throws an IllegalArgumentException if the input Layouts do not have the
same number of columns.
Example:
1
2
3
4
5
6
7
8
.stack(
10
20
30
40
) returns
1
2
3
4
5
6
7
8
10
20
30
40
public int rowCount()
Returns the number of rows in the Layout. For a one-dimensional Layout, this returns 1.
public int columnCount()
Returns the number of columns in the Layout. For a one-dimensional Layout, this is the number of values in the Layout.
public Layout rows(int firstRow, int lastRow)
Returns a new Layout containing values from row firstRow to row lastRow, inclusive, of the recipient Layout.
Example:
1
2
3
4
5
6
7
8
9
10
11
12
.rows(1, 2) returns
5
6
7
8
9
10
11
12
public Layout columns(int firstColumn, int lastColumn)
Returns a new Layout containing values from column firstColumn to column lastColumn, inclusive, of the recipient Layout.
Example:
1
2
3
4
5
6
7
8
9
10
11
12
.columns(1, 2) returns
2
3
6
7
10
11
public Layout slice(int firstRow, int lastRow, int firstColumn, int lastColumn)
Returns a new Layout containing values from the given portion of the recipient Layout.
Example:
1
2
3
4
5
6
7
8
9
10
11
12
.columns(1, 2, 2, 3) returns
7
8
11
12
public Layout replace(Layout layout, int row, int column)
Returns a new Layout in which the parameter layout replaces the values of the recipient Layout, starting at the given row and column. This method throws an IllegalArgumentException if the parameter Layout would go beyond the bounds of the recipient layout.
Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
.replace(
55
66
77
88
99
100
, 1, 2) returns
1
2
3
4
5
6
7
55
66
77
11
12
88
99
100
16
17
18
19
20
@Override
public boolean equals(Object that)
Returns true if and only if this Layout contains an array of the same shape and containing the same values as that Layout.
public int[] toArray1D()
Returns a one-dimensional array of the values in the recipient Layout. If the Layout is two-dimensional, it is first unraveled.
public int[][] toArray2D()
Returns a two-dimensional array of the values in the recipient Layout. If the Layout is one-dimensional, the result will be an array containing, as its single element, a one-dimensional array.
public int at(int row, int column)
Returns the integer at the given row and column.
How to do this assignment
You can save yourself quite a bit of typing if you follow these steps:
In Eclipse, create the project, the package, and the class.
Write each of the methods as stubs--that is, write the
headers, but just have each method return null.
Use Eclipse to create a JUnit 4 (not 3) test class; go through the
steps carefully, so you don't miss the part where Eclipse creates
stubs for all your test methods.
Next, repeat the following steps:
Fill in the tests for one of the methods.
Choose a method that does not depend on other methods that haven't yet been written or tested. It should be either completely independent of other methods, or depend only on well-tested methods.
Run JUnit to make sure that your new test fails.
Now write the method to handle the simplest case, replacing the stub code.
Run JUnit to test whether your new method is correct.
Debug as necessary. (Remember, it's possible that the test itself,
rather than the method being tested, is wrong.)
Refactor (clean up) the code as much as possible, and retest to ensure you haven't introduced new errors.
If the method is correct but incomplete (needs to handle more cases), return to step 1 and write a test for another case.
Do the above for each of the methods, until you are thoroughly familiar
with the pattern.
Things to remember
In your JUnit test class, you have to import the class being tested.
Because all your methods are static, you can say import static layout.Layout.*;
With this kind of import, you can call your methods directly,
as for example myLayout.ravel(5).
With a "normal" (nonstatic) import, you would have to
say Layout.myLayout.ravel(5).
If your test class is in the same package as the class being tested, you do not need to import it.
In
your JUnit test class, declare the
variables as instance variables of the class, but assign them
their initial values in the setUp method.
JUnit has an assertArrayEquals(expected array, actual result)
method.
JUnit tests are intended to find anything that could be wrong
with your methods, not to "prove" that they are correct. As
you write them, you are the prosecuting attorney, trying to expose any
flaws in the defendant's (the method's) story. For example, do the methods
handle zero-length arrays correctly?
In Java, all arrays are one-dimensional. A so-called "two-dimensional" array is actually a one-dimensional array, each of whose elements are one-dimensional arrays; each element is a row of the two-dimensional array.
You can construct test cases more easily if you use array initialization.
For example, int[] oneD = new int[] { 1, 2, 3, 4, 5 };
and int[][] twoD = new int[][] { { 1, 2, 3 },
{
4, 5, 6 } };
Structure of the assignment
Project name: Layout
Package name: layout
Class name: Layout
Method signatures: Exactly as given above.
Provide JUnit tests for: All required methods.
Provide Javadoc documentation for all classes and methods, except JUnit
tests.
Document JUnit tests if they are complex or do something non-obvious
Name to use for Blackboard: Layout
Grading
My JUnit tests will be applied to your methods. They will test everything that I can
think of that your methods might possibly get wrong.
Your JUnit tests will be applied to my methods. There will be errors in some of the
methods, which I expect your JUnit tests to find.
In order for this to work, you must use the method signatures exactly as listed.
(Check the course web page later, in case I have to correct anything.) If your
methods can't be called from my JUnit tests, or vice versa, that will cost you
significant points.