Old version
This is the CS 112 site as it appeared on May 11, 2018.
Problem Set 2
due by 11:59 p.m. on Tuesday, February 6, 2018
Preliminaries
In your work on this assignment, make sure to abide by the collaboration policies of the course.
If you have questions while working on this assignment, please
come to office hours, post them on Piazza, or email
cs112-staff@cs.bu.edu.
Make sure to submit your work on Apollo, following the procedures found at the end of the assignment.
Part I
40 points total
This part of the assignment consists of a series of short-answer questions. You will be able to check your answers to at least some of these questions in DrJava, but we encourage you to try answering them on your own and convincing yourself of the correctness of your answers before you attempt to test them in DrJava. These questions are similar to ones that could appear on the midterms and final exam, which you will have to take without the use of a computer!
Problem 1: Understanding code that uses an array
8 points total; individual-only
Using folders
Don’t forget that we strongly encourage you to create a separate
folder for each assignment, so that you can more easily keep track
of your work. For example, you could create a folder called ps2
for your work on this assignment, and put all of the files for PS
2 in that folder.
Open up a text editor (e.g., Notepad or TextEdit) and create a
plain-text file named ps2pr1.txt. Put all of your work for
this problem in that file.
-
(3 points) What is the output of the following lines of code?
int[] a = {3, 6, 9, 12, 15}; int[] b = {3, 6, 9, 12, 15}; int[] c = b; c[3] = 10; System.out.println(a[3] + " " + b[3] + " " + c[3]);After giving the output, explain briefly why it makes sense.
-
(3 points) Consider the following static method, which operates on an array of integers:
public static void mystery(int[] arr) { for (int i = 0; i < arr.length / 2; i++) { int n = arr.length - 1 - i; int val = arr[n]; arr[n] = arr[i]; arr[i] = val; // What values do the variables have here, // for each value of the loop variable `i`? } }Consider the following code fragment, which calls this method:
int[] values = {0, 1, 2, 3, 4, 5, 6, 7}; mystery(values);Copy the table shown below into your text file for this problem, and complete it to illustrate the execution of the above method call.
mystery's variables i | n | val | arr ------------------------------------------- - | - | - | {0, 1, 2, 3, 4, 5, 6, 7} 0 | | |We have started the table for you. The first row shows what the array looks like before the start of the
forloop. For each value of the loop variablei, include a row in the table that shows the values of the other variables at the end of the iteration of the loop for that value ofi. Note that you should write the value ofarras an array literal that shows the current contents of the array, even though the variable itself actually holds a reference to the array. -
(2 points) After running the code fragment from part 2, we then execute the following statement:
System.out.println(Arrays.toString(values));
Do we see the original array, or do we see the changes made by the call to the
mystery()method? Explain briefly why your answer makes sense.(Note: If you want to check your answer, you’ll need to import the
java.utilpackage so that you can use theArrays.toString()method.)
Problem 2: Two-dimensional arrays
8 points total; pair-optional
This is one of only two problems in this assignment that you may complete with a partner. See the rules for working with a partner on pair-optional problems for details about how this type of collaboration must be structured.
Open up a text editor (e.g., Notepad or TextEdit) and create a
plain-text file named ps2pr2.txt. Put all of your work for
this problem in that file.
Overview
Two-dimensional arrays in Java are extremely similar to
two-dimensional lists in Python.
In Python, a 2-D list is a list of lists:
grid = [ [2, 4],
[5, 7],
[8, 1] ]
In the same way, a 2-D array in Java is an array of arrays:
int[][] grid = { {2, 4},
{5, 7},
{8, 1} };
(Note: When we declare a variable for a 2-D array, the type of the
elements is followed by two pairs of square brackets: int[][])
Here is a comparison of other key operations for 2-D sequences:
|
operation |
in Python |
in Java |
|---|---|---|
|
determining the number of rows |
|
|
|
determining the number of elements in row r |
|
|
|
determining the number of columns in a rectangular grid/matrix (in which all rows have the same length) |
|
|
|
accessing the element at row r, column c |
|
|
Problems
Assume that you have a variable twoD that refers to a
two-dimensional array of integers. Here is another example of such
an array:
int[][] twoD = { {1, 2, 3},
{4, 5, 6},
{7, 8, 9} };
In your answers below, you may assume that the array is rectangular – i.e., that all rows have the same number of elements.
-
(2 points) Write an assignment statement that replaces the value of 6 in the above array with a value of 12.
-
(3 points) Write a code fragment that prints the values in the leftmost column of the array to which
twoDrefers. Print each value on its own line. For the array above, the following values would be printed:1 4 7
Make your code general enough to work on any two-dimensional array named
twoDthat has at least one value in each row. -
(3 points) Write a code fragment that prints the values in the anti-diagonal of the array to which
twoDrefers – i.e., the values along a diagonal line from the bottom-left corner to the upper-right corner. Print each value on its own line. For the array above, the following values would be printed:7 5 3
Make your code general enough to work on any two-dimensional array in which the dimensions are equal – i.e., the number of rows is the same as the number of columns.
Problem 3: A class that needs your help
12 points total; individual-only
Open up a text editor (e.g., Notepad or TextEdit) and create a
plain-text file named ps2pr3.txt. Put all of your work for
this problem in that file.
Consider the following class, which is intended to serve as a
blueprint for objects that encapsulate two pieces of data: a
person’s name (which should not be allowed to have the special
value null) and the person’s age (which must be non-negative).
public class Participant {
String name;
int age;
}
-
(8 points) This class does not employ appropriate encapsulation. Rewrite it to prevent direct access to the internals of a
Participantobject while allowing indirect access through appropriate methods. Your rewritten version should include:- whatever changes are needed to the field declarations to prevent them from being accessed outside the class
- methods that can be used to obtain the value of each field
(call them
getNameandgetAge) -
methods that can be used to change the value of each field (call them
setNameandsetAge). These methods should ensure thatageis always non-negative, and thatnameis notnull. Attempts to assign an invalid value should produce anIllegalArgumentException, which you can do as follows:throw new IllegalArgumentException();
-
a constructor that initializes the fields of a newly created
Participantobject to the values specified by the parameters of the constructor. Attempts to assign an invalid value should produce anIllegalArgumentException. Take advantage of the error-checking code that is already present in the methods that you defined for changing the values of the fields.
No other methods are required.
-
(4 points) Now imagine that you’re writing client code for your revised
Participantclass – i.e., code in a different class that usesParticipantobjects.Write a single line of client code to accomplish each of the following tasks:
-
Construct a
Participantobject for a person named Tom Brady who is 35 years old, and assign it to a properly declared variable namedqb. -
The Tom Brady (the one who is participating in his 8th Super Bowl this week) is actually 40 years old! Change the age in the
Participantobject that you created in part (a). You should not create a new object; you should change the internals of the existing object.Important: As a result of your changes from part 1, clients no longer have direct access to the fields in a
Participantobject. As a result, you will need to make an appropriate method call to accomplish the change to the age. -
Get the name from the
Participantobject that you created in part (a), and assign it to a properly declared variable namedmvp. Here again, you will need to make an appropriate method call.
-
Problem 4: Static vs. non-static methods
12 points total; 6 points each part; individual-only
Open up a text editor (e.g., Notepad or TextEdit) and create a
plain-text file named ps2pr4.txt. Put all of your work for
this problem in that file.
When designing a blueprint class, we can include both non-static and static methods. A non-static method is required if the method must have access to the fields of a particular called object. However, if a method does not need a called object – i.e., if all of the information that it needs is supplied by its parameters – then we typically make it static. Non-static methods must be called on an object of the class. Static methods may be called on an object of the class, but it is better style to call them using the name of the class instead.
Consider the following simple class, which is a blueprint class
for Grade objects that encapsulate both the number of points earned
(a floating-point number) and a late penalty, if any. The late-penalty
percentage is stored as an integer (e.g., 10 for a 10% late penalty).
public class Grade {
private double points;
private int latePenalty;
public Grade(double pts, int penalty) {
this.points = pts;
this.latePenalty = penalty;
}
// other methods are omitted for the sake of brevity
}
Assume that you are considering adding two methods to this class.
-
The first method is called
addExtraCredit. It takes a floating-point number calledamountand increases the points component of aGradeobject by the specified amount. It does not return anything.- What type of method should
addExtraCreditbe — static or non-static? Explain briefly. - Give an appropriate header for this method. You do not need to define the body of the method.
- Give an example of how you would call this method from
outside the
Gradeclass. If you need aGradeobject to call the method, assume that the variablegrepresents that object, and that the object has already been created.
- What type of method should
-
The second method is called
computePercent. It takes two floating-point numbers – one calledpointsEarnedand another calledpossiblePoints– and it returnspointsEarnedas a percentage ofpossiblePoints. For example, ifpointsEarnedis 30.0 andpossiblePointsis 50.0, the method should return 60.0, because 30.0 is 60 percent of 50.0.- What type of method should
computePercentbe — static or non-static? Explain briefly. - Give an appropriate header for this method. You do not need to define the body of the method.
- Give an example of how you would call this method from
outside the
Gradeclass. If you need aGradeobject to call the method, assume that the variablegrepresents that object.
- What type of method should
Part II
60 points total
Problem 5: Array-processing methods
24 points total; 8 points each part; individual-only
In a class named ArrayMethods, implement each of the methods
described below.
Important guidelines:
-
Your methods must have the exact headers that we have specified, or we won’t be able to test them. Note in particular that the case of the letters matters.
-
If you are asked to write a method that returns a value, make sure that it returns the specified value, rather than printing it.
-
You should not use any Java classes that we have not covered in the lecture notes.
-
Each of your methods should be preceded by a comment that explains what your methods does and what its inputs are. You should also include a comment at the top of the file, similar to the one that we included in
Methods5.javafrom Problem Set 1. -
More generally, use good programming style. Use appropriate indentation, select descriptive variable names, insert blank lines between logical parts of your program, and add comments as necessary to explain what your code does. See the coding conventions for more detail.
-
Write a method with the header
public static void swapAdjacent(int[] values)
that takes a reference to an array of integers
valuesand swaps adjacent pairs of elements:values[0]withvalues[1],values[2]withvalues[3], etc.For example, after implementing this method and compiling your
ArrayMethodsclass, you should see the following when you test the method from the Interactions Pane in DrJava:> int[] a1 = {0, 2, 4, 6, 8, 10}; > ArrayMethods.swapAdjacent(a1); > a1 { 2, 0, 6, 4, 10, 8 }(Note that if you evaluate an array variable in the Interactions Pane, DrJava is nice enough to show you the contents of the array, even though printing that same variable would show something based on the array’s memory address.)
In an odd-length array, the last element should not be moved:
> int[] a2 = {1, 2, 3, 4, 5, 6, 7}; > ArrayMethods.swapAdjacent(a2); > a2 { 2, 1, 4, 3, 6, 5, 7 }Special case: If the parameter is
null, the method should throw anIllegalArgumentException. -
Write a method with the header
public static int[] copyReplace(int[] values, int oldVal, int newVal)
that takes a reference to an array of integers
valuesand two integersoldValandnewVal, and that creates and returns a new array that is a copy of the original array, but in which all occurrences of the valueoldValare replaced with the valuenewVal.Important:
-
You may not use any of the built-in methods for copying an array.
-
Your method must not modify the original array.
Examples:
> int[] a1 = {2, 5, 4, 2, 7, 4, 2}; > int[] a2 = ArrayMethods.copyReplace(a1, 4, 0); > a2 { 2, 5, 0, 2, 7, 0, 2 } > int[] a3 = ArrayMethods.copyReplace(a1, 2, -1); > a3 { -1, 5, 4, -1, 7, 4, -1 } > a1 { 2, 5, 4, 2, 7, 4, 2 }Special case: If the parameter is
null, the method should throw anIllegalArgumentException. -
-
Write a method with the header
public static int maxSorted(int[] values)
that takes a reference to an array of integers and returns the length of the longest sorted sequence of integers in the array. For example:
> int[] a1 = {3, 8, 6, 14, -3, 0, 14, 207, 98, 12}; > ArrayMethods.maxSorted(a1) 4The above call should return
4, because the longest sorted sequence in the array has four values in it (the sequence-3, 0, 14, 207). Note that the sorted sequence could contain duplicates. For example:> int[] a2 = {17, 42, 3, 5, 5, 5, 8, 4, 6, 1, 19}; > ArrayMethods.maxSorted(a2) 5This call should return
5for the length of the sequence3, 5, 5, 5, 8.Special cases:
-
If the parameter is
null, the method should throw anIllegalArgumentException. -
Your method should return
0if passed an empty array (i.e., an array of length 0). -
Your method should return
1if passed an array with one element or an array in which all of the elements are in decreasing order. It should be possible to get a return value of 1 for these cases without needing to explicitly check for them.
-
Problem 6: Our Rectangle class revisited
12 points total; 4 points each part; pair-optional
This is one of only two problems in this assignment that you may complete with a partner. See the rules for working with a partner on pair-optional problems for details about how this type of collaboration must be structured.
This problem asks you to modify an existing blueprint class.
The guidelines from the previous problem also apply here.
Begin by downloading this file:
Rectangle.java, which contains a
version of the Rectangle class that we discussed in lecture. Open
it in DrJava, and add your methods to the class that we have given you
in that file.
-
Add a non-static method named
rotatethat rotates aRectangleobject 90 degrees by swapping its width and height values. For example, if aRectangle‘s dimensions are 10x30, then calling therotatemethod would change its dimensions to 30x10.Because the method should change the internals of the called object, it doesn’t need to – and should not! – return a value.
-
Add a non-static method named
largerThanthat takes anotherRectangleobject and determines if the calledRectangleobject (i.e., the one on which the method is invoked) has a larger area than the otherRectangleobject – returningtrueif the called object has a larger area andfalseotherwise.Special case: If a
nullvalue is passed into the method, it should throw anIllegalArgumentException.Important:
-
For full credit, you should take full advantage of the existing
Rectanglemethods to get the information that you need in this method. Do not reinvent the wheel! -
Make sure that you return a boolean literal (
trueorfalse) and not the string"true"or the string"false".
-
-
Add code to the bottom of the existing
main()method that makes at least two test calls to each of your new methods.-
If the method returns a value, you should assign that value to an appropriately declared variable, and then print the value of that variable.
-
If the method does not return a value, print the
Rectangleobject both before and after each call to that method.
-
Problem 7: A blueprint class for Card objects
24 points; individual-only
In this problem you will create a class called Card that serves as a
blueprint for objects that can be used to represent a single playing
card for a card game called Buno (pronounced B-U-no).
You can think of it as BU’s version of a popular card game whose name
does not begin with B!
The sections below outline the steps that you should take.
The guidelines from Problem 5 also apply here.
-
(0 points) Download
Card.java, and open it in DrJava. This file includes some starter code for the class you will write. Read through this code before continuing — including all of the comments that we have provided.You will note that we have provided two class constants – global variables whose value cannot change. Here is the first one:
public static final int MIN_VALUE = 0;
In general, a class constant is defined near the top of the class, outside of any method. Its definition includes several key components:
-
the keyword
static, which means that the variable belongs to the class as a whole. This distinguishes it from a field, which is a non-static variable that is inside every object of the class. Every object gets its own separate set of the fields, but there is only one copy of astaticvariable, and it is is shared by all objects of the class. -
the keyword
final, which is what makes this variable a constant. The value that we assign to the class constant here is its final value, and we cannot assign a new value to it somewhere else. -
the type declaration, like that of any other variable
-
the variable name, which we capitalize so that it will be obvious that it is a constant
-
the initialization of the variable, which we must do here, because we can’t change a class constant outside of its definition.
We have provided two class constants. Read the accompanying comments to see what they represent.
-
-
(1 point) Add a third class constant for the maximum value that a
Cardcan have, which is 9. -
(5 points) Add a static method called
isValidColor. It should take the name of a color as a parameter, and it should returntrueif the specified color is valid (i.e., if it is one of the colors listed in theCOLORSarray), andfalseotherwise. For example:isValidColor("red")should returntrue, because “red” appears in theCOLORSarrayisValidColor("orange")should returnfalse, because “orange” does not appear in theCOLORSarray.
Notes:
- The case of the letters matters. For example,
isValidColor("Red")should returnfalse, because"Red"begins with an upper-caseR, and the version in theCOLORSarray begins with a lower-caser. - You may not use any built-in methods to determine whether
the color is in the
COLORSarray. Rather, you should write the code needed to process this array and see if the color is present. - In addition, you should not make any assumptions about the
actual values in the
COLORSarray. If we change the set of colors, your method should still work. - This method is a helper method that will be used by one or more of the other methods that you write.
- This method (unlike the others you will write) is static, because it does not need to access the fields in the object. Rather, we pass it all of the information that it needs as a parameter.
-
Define the fields (3 points)
EachCardobject should encapsulate two pieces of state:- the card’s color (a string)
- the card’s value (an integer).
For example, here is what a
Cardobject representing a red 7 would look like in memory:(To simplify matters, we have shown the string “red” inside the field, even though in reality the memory address of the string would be stored.)
For now, you only need to define the fields, making sure to protect them from direct access by client code. In subsequent sections, you will write constructors that assign values to the fields, and that ensure that only valid values are allowed.
-
Implement mutators for the fields (4 points)
Next, add the following mutator methods:-
setColor, which takes aStringrepresenting a color and sets the value of theCardobject’scolorfield to the specified color. Attempts to assign an invalid color should produce anIllegalArgumentException. Take advantage of yourisValidColormethod when checking for invalid colors. -
setValue, which takes an integer and sets the value of theCardobject’svaluefield to the specified number. Attempts to assign an invalid value (one that is outside the range specified by theMIN_VALUEandMAX_VALUEconstants) should produce anIllegalArgumentException.
Make sure that your methods are non-static, because they need access to the fields in the called object. Use the class constants when checking for invalid values.
-
-
Implement a constructor (3 points)
Next, add a constructor that takes a string for theCard‘s color and an integer for theCard‘s value (in that order), and initializes the values of the fields. Your constructor should call the mutators that you defined in part 3 so that you can take advantage of the error-checking code that is already present in those methods. -
Implement accessors for the fields (2 points)
Next, define the following accessor methods:getColor, which returns the string representing theCardobject’s color.getValue, which returns the integer representing theCardobject’s value.
Make sure that your methods are non-static, because they need access to the fields in the called object.
Once you have completed parts 1–6, you can test them using the first client program that we’ve given you. See below for more detail.
-
Define the
toStringmethod (2 points)
Write atoStringmethod that returns aStringrepresentation of theCardobject that can be used when printing it or concatenating it to aString. We discuss this type of method in the lecture notes, and we provide an example in ourRectangleclass. The returnedStringshould be of the formcolor value(e.g.,"blue 3"or"red 10"). -
Define methods for comparing
Cardobjects (4 points)
Finally, define the following two instance methods for comparingCardobjects:-
matches, which takes anotherCardobject as a parameter and returnstrueif the calledCardobject matches the color and/or value of the otherCardobject, andfalseif it doesn’t match either the color or the value. If a value ofnullis passed in for the parameter, the method should returnfalse. -
equals, which takes anotherCardobject as a parameter and determines if it is equivalent to the called object, returningtrueif it is equivalent andfalseif it is not equivalent. TwoCardobjects should be considered equivalent if their color and value are the same. If a value ofnullis passed in for the parameter, the method should returnfalse.
-
Client programs and testing your code
To help you in testing your Card class, we have created two sample
client programs:
Client1.java- should compile after completion of part 6. If it doesn’t, check your method headers.
- tests the methods from parts 2 and 4-6
- expected output is given here
Client2.java- should compile after completion of part 8. Do not open it before then!
- tests the methods from parts 7 and 8
- expected output is given here
Put the client programs in the same folder as your Card.java
file. Make sure not to open the clients until the necessary parts have
been completed.
In addition to using the client programs, we recommend that you perform
additional testing on your own. You can do so in the Interactions Pane,
or by adding code to one of the clients, or by adding a main method to
the Card class.
If you are unable to get a given method to compile, make sure to comment out the body of the method (keeping the method header and possibly a dummy return value) so that we’ll still be able to test your other methods.
Submitting Your Work
You should use Apollo to submit the following files:
- your
ps2pr1.txtfile containing your solutions for Problem 1 - your
ps2pr2.txtfile containing your solutions for Problem 2; if you worked with a partner, make sure that you each submit a copy of your joint work, and that you include comments at the top of the file specifying the name and email of your partner - your
ps2pr3.txtfile containing your solutions for Problem 3 - your
ps2pr4.txtfile containing your solutions for Problem 4 - your
ArrayMethods.javafile file containing your solutions for Problem 5 - your modified
Rectangle.javafile containing your solutions for Problem 6; if you worked with a partner, make sure that you each submit a copy of your joint work, and that you include comments at the top of the file specifying the name and email of your partner - your modified
Card.javafile containing your solutions for Problem 7
Warnings
-
Make sure to use these exact file names, or Apollo will not accept your files. If Apollo reports that a file does not have the correct name, you should rename the file using the name listed in the assignment or on the Apollo upload page.
-
Make sure that you do not try to submit a
.classfile or a file with a~character at the end of its name. -
Before submitting your files, make sure that your BU username is visible at the top of the Apollo page. If you don’t see your username, click the Log out button and login again.
-
If you make any last-minute changes to one of your Java files (e.g., adding additional comments), you should compile and run the file in DrJava after you make the changes to ensure that it still runs correctly. Even seemingly minor changes can cause your code to become unrunnable.
-
If you encounter problems with Apollo, click the Log Out button (if you are already logged in), close your browser, and try again. If possible, you may also want to wait an hour or two before retrying. If you are unable to submit and it is close to the deadline, email your homework before the deadline to
cs112-staff@cs.bu.edu
Here are the steps:
- Login to Apollo, using the link in the left-hand navigation bar. You will need to use your Kerberos user name and password.
- Check to see that your BU username is at the top of the Apollo page. If it isn’t, click the Log out button and login again.
- Find the appropriate problem set section on the main page and click Upload files.
- For each file that you want to submit, find the matching upload section for the file. Make sure that you use the right section for each file. You may upload any number of files at a time.
- Click the Upload button at the bottom of the page.
- Review the upload results. If Apollo reports any issues, return to the upload page by clicking the link at the top of the results page, and try the upload again, per Apollo’s advice.
- Once all of your files have been successfully uploaded, return to the upload page by clicking the link at the top of the results page. The upload page will show you when you uploaded each file, and it will give you a way to view or download the uploaded file. Click on the link for each file so that you can ensure that you submitted the correct file.
Warning
Apollo will automatically close submissions for a given file when its final deadline has passed. We will not accept any file after Apollo has disabled its upload form, so please check your submission carefully following the instructions in Step 7 above.