CS 112
Spring 2024

Problem Set 4

due by 11:59 p.m. on Wednesday, February 21, 2024

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 instructor.

Make sure to follow the instructions outlined at the end of Part I and Part II when submitting your assignment.


Part I

40 points total

Creating the necessary folder

Create a subfolder called ps4 within your cs112 folder, and put all of the files for this assignment in that folder.

Creating the necessary file

Problems in Part I will be completed in a single PDF file. To create it, you should do the following:

  1. Access and make a copy of the template that we have created by clicking on this link and signing into your Google account as needed.

  2. When asked, click on the Make a copy button, which will save a copy of the template file to your Google Drive.

  3. Select File->Rename, and change the name of the file to ps4_partI.

  4. Add your work for the problems from Part I to this file.

  5. Once you have completed all of these problems, choose File->Download->PDF document, and save the PDF file in your ps4 folder. The resulting PDF file (ps4_partI.pdf) is the one that you will submit. See the submission guidelines at the end of Part I.

Problem 1: Understanding and using inheritance

10 points total; individual-only

Imagine that you wanted to capture information about a collection of different types of vehicles (cars, trucks, motorcycles, etc.). To do so, you could use inheritance to create a collection of related classes whose inheritance hierarchy looks like this:

We have provided an implementation of most of these classes in this folder, and we encourage you to review the provided files. They include:

The hierarchy diagram above includes a Limousine class and a MovingVan class, but we have not defined those classes yet.

In the Problem 1 section of your ps4_partI document (see above), answer the following questions:

  1. (1 point) Which of the classes that are shown in the diagram above are a superclass of the Taxi class?

  2. (1 point) Suppose we have a Taxi object that has been assigned to a properly declared variable t. You want to know how many seats are available to fit you and your friends. Is it possible to make the following call?

    t.getNumSeats()
    

    Explain briefly why or why not.

  3. Write a definition for the Limousine class that takes full advantage of inheritance.

    A Limousine object should have all of the same state and behavior as an Automobile object. In addition, it should maintain additional state that keeps track of:

    • whether the limousine has a sun roof (true or false)
    • how many bottles of champagne it can chill (a non-negative integer)
    • Its color (non-empty)

    When a Limousine object is printed, we should see its make, its color, model, and the number of seats available to customers, which is two fewer than the total number of seats. For example, if the Limousine is a white Cadillac XTS-L with a total of 8 seats, printing it should produce the following output:

    White Cadillac XTS-L (seats up to 6 customers)
    

    Note that the output mentions 6 seats, because only 6 of the 8 seats are available for customers.

    In your ps4_partI file, add a definition of this class that includes the following:

    1. (1 point) a class header that sets up the appropriate inheritance

    2. (2 points) whatever new fields are needed to capture the state of a Limousine object. Make sure that you take inheritance into account when deciding which fields to include.

    3. (2 points) a constructor that takes as parameters the make, model, year, and total number of seats, as well as a boolean value indicating whether the limo has a sun roof, an integer indicating how many bottles of champagne it can chill and its color. The constructor should ensure that the object is not put in an invalid state (throwing an exception as needed), and it should take whatever steps are needed to initialize the object.

    4. (3 points) any necessary methods. It should be possible for a client to obtain the value of any of the fields, and to change the value of any field that can be changed in an Automobile object. However, you should assume that the portion of the state specifying whether there is a sun roof, color, and how many champagne bottles can be chilled will never change, and thus mutator methods are not needed for those fields. You also don’t need to define an equals method for this class.

Problem 2: Inheritance and polymorphism

18 points total; 2 points each part; individual-only

Imagine that you have a set of related classes that have been defined using inheritance. Here are the key facts about these classes:

In addition, you should make the following assumptions:

Answer the following questions in light of the above information about these classes. Before you begin, you may find it helpful to draw an inheritance hierarchy for the classes, although doing so is not required.

  1. (2 points) The information above states that the Zoo class has its own equals() method that overrides the inherited one. Where does the equals() method that Zoo overrides come from? Be as specific as possible, and explain your answer briefly.

  2. (2 points) Implement a constructor for Yoo class. Initialize all the fields in a Yoo object – both the ones that it declares and the ones (if any) that it inherits.

  3. (5 points) Consider the following code fragment:

    Yoo y1 = new Yoo();
    System.out.println(y1.one(10));
    System.out.println(y1.two());
    System.out.println(y1.three(12.5));
    System.out.println(y1.equals(y1));
    System.out.println(y1);
    

    Each of the println statements in this code fragment displays the result of a method call. (This includes the fifth println statement, in which the Java interpreter calls a method on our behalf.) However, it is possible that one or more of these methods calls would fail to compile because the necessary method is neither defined in the Yoo class nor inherited from a superclass of Yoo.

    In section 2-3 of ps4_partI, we have included a table that you should complete with appropriate information about each of these method calls. We have filled in the first row for you, and you should complete the remaining rows.

  4. (3 points) Now imagine that you want to add a non-static method to the Too class. It should be called avg(), it should take no parameters, and it should return the average of all of the integer fields in the called Too object. Add a full definition of that method to section 2-4 of your ps4_partI file. Make sure to take into account the fact that the classes employ proper encapsulation. Make the average as precise as possible.

  5. (6 points) For each of the following assignment statements, indicate whether it would be allowed according to the rules of polymorphism, and explain briefly why or why not.

    1.     Woo w = new Too();

    2.     Zoo z = new Woo();

    3.     Zoo z = new Yoo();

    4.     Too t = new Zoo();

Problem 3: Memory management and the ArrayBag class

12 points total; individual-only

In this problem, you will draw a series of memory diagrams that illustrate the execution of a program that operates on objects of the ArrayBag class from lecture.

Consider the following Java program:

public class ArrayBagTest {
    public static void main(String[] args) {
        ArrayBag b1 = new ArrayBag(3);
        ArrayBag b2 = new ArrayBag(3);
        ArrayBag b3 = b2;

        // part 1: what do things look like when we get here?

        // part 2: what do things look like at the start of
        // this method call?
        b1.add("happy");

        b2.add("valentines");
        b3.add("day");

        // part 3: what do things look like when we get here?

        System.out.println(b1);
        System.out.println(b2);
        System.out.println(b3);
    }
}
  1. In section 3-1 of ps4_partI, we have given you the beginnings of a memory diagram. On the stack (the region of memory where local variables are stored), we have included a frame for the main method. On the heap (the region of memory where objects are stored), we have included the ArrayBag object to which the variable b1 refers and its items array. As usual, we have used arrows to represent the necessary references.

    Complete the provided memory diagram so that it shows what things look like in memory just before the call b1.add("happy").

    To do so, you should:

    • Click on the diagram and then click the Edit link that appears below the diagram.

    • Make whatever changes are needed to the diagram. Below the thick horizontal line, we have given you a set of extra components that you can use as needed by dragging them above the thick line and putting them in the correct position. These components include String objects representing the strings "happy", "valentines" and "day". You may not need all of the provided components.

    • You can also edit any of the values in a field or array by clicking on the corresponding cell and editing the text that is inside the cell.

    • Once you have made all of the necessary changes, click the Save & Close button.

  2. In section 3-2 of ps4_partI, we have given you the beginnings of a memory diagram that you should complete to show what things look like in memory at the start of the execution of b1.add("happy")—just before the first statement of that method is executed.

    Note: To save time, it should be possible to select and copy some of the components of your diagram for 3-1 and paste them into your diagram for 3-2.

  3. In section 3-3 of ps4_partI, we have given you the beginnings of a memory diagram that you should complete to show what things look like in memory after all of the calls to add have returned—just before the print statements execute in main().

    Note: We have included a method frame for add, but it may or not be needed in this diagram; you should delete it if you determine that it would no longer be present in memory.

  4. What would be printed by this program? You may find it helpful to consult the toString method of the ArrayBag class.

Submitting your work for Part I

Note: There are separate instructions at the end of Part II that you should use when submitting your work for that part of the assignment.

Submit your ps4_partI.pdf file using these steps:

  1. If you still need to create a PDF file, open your ps4_partI file on Google Drive, choose File->Download->PDF document, and save the PDF file in your ps4 folder.

  2. Login to Gradescope by clicking the link in the left-hand navigation bar, and click on the box for CS 112.

  3. Click on the name of the assignment (PS 4: Part I) in the list of assignments on Gradescope. You should see a pop-up window labeled Submit Assignment. (If you don’t see it, click the Submit or Resubmit button at the bottom of the page.)

  4. Choose the Submit PDF option, and then click the Select PDF button and find the PDF file that you created. Then click the Upload PDF button.

  5. You should see a question outline along with thumbnails of the pages from your uploaded PDF. For each question in the outline:

    • Click the title of the question.
    • Click the page(s) on which your work for that question can be found.

    As you do so, click on the magnifying glass icon for each page and doublecheck that the pages that you see contain the work that you want us to grade.

  6. Once you have assigned pages to all of the questions in the question outline, click the Submit button in the lower-right corner of the window. You should see a box saying that your submission was successful.

Important

  • It is your responsibility to ensure that the correct version of every file is on Gradescope before the final deadline. We will not accept any file after the submission window for a given assignment has closed, so please check your submissions carefully using the steps outlined above.

  • If you are unable to access Gradescope and there is enough time to do so, wait an hour or two and then try again. 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


Part II

60 points total

Important

Don’t forget that each of your methods should be preceded by a comment that explains what your method does and what its inputs are. In addition, you should include a comment at the top of each Java file, and you should use good programming style more generally.

In addition, you should continue to follow the other guidelines that we gave you in the prior problem sets.

Problem 4: Set Class: A Custom Data Type to represent a set of integers

35 points total; 2 points each part; individual-only

Overview

In mathematics and computer science, a set is a collection in which order does not matter and there are no duplicates. There are several well-defined operations which can be performed on sets, namely: union, intersection, and difference.

Additionally, when working with sets you often want to know the cardinality of the set, whether or not it is an empty set, and whether one set is a subset of another set.

Example, given two sets A and B:

A = {5,4,3,2,1}
B = {3,2,7,9}
A union B => {5,4,3,2,1,7,9}
A intesection B => {3,2}
A difference B => {5,4,1}
B difference A => {7,9}

{} denotes the empty set

{3,4,5} is a subset of {1,2,3,4,5} because all the elements in the first set exist in the second
{3,4,5,6} is not a subset of {1,2,3,4,5} because the element 6 of the first set is not int the second set

In this problem, you are asked to write a class named Set which will allow us to create an object to represent a Set of integers. Each instance of the class will represent one Set and the integers that make-up the set (i.e. the elements of the set) will be stored in an array of type int. You will also implement as methods all the operations that can be performed on sets.

These are the members that need to be declared in your Set class. The array that stores the elements of the set should be initially created using the default SIZE static variable. However, as elements are added to the set, you can use the resize method (which has been provided) to grow the array to store additional elements.

private static final int DEFAULT_SIZE = 10;   // default (inital) size of set
private int[] set;            // reference to the array which stores the set of integers
private int next;             // index of the next available open position in set

Thus, a Set [2, 3, 7, -3] would be represented as follows:

array-01

and the empty set [] would be represented as:

array-02.png

The member next should be incremented each time a new element is added to the set. The cardinality of the set is represented by member next, and the total number of elements that the set can hold is determined by the length attribute of the array.

The idea is that you can represent a Set of up to set.length integers, and they are stored in the array, without duplicates, in the indices from 0 to next-1.

The Methods of the Set Class

public Set() -- No argument constructor; initialize this set as an
   instance of the empty set.

public Set(int[] arr) -- Initialize the set from the elements passed through
   the array referenced by arr. Note that the array referenced by 
   arr may contain duplicate values, but the array representing the 
   set should not.

   In addiion, the array passed to the constructor can be of an arbitrary length 
   (i.e. it may be larger than DEFAUL_SIZE).

public Set clone() -- Return an exact copy of this set

   (Hint: Consider how you can use the previous constructor to help.)

public String toString() -- Return a string representation of the set,
   e.g., [2,3,7,-3]  or [] for the empty set; 
   you may not use `Array.toString` to do this, you must build the
   resulting string.

public int cardinality() -- Return the number of elements in this set.

public  boolean isEmpty() -- Return true if this is the empty set has
   no members and false otherwise.

public boolean member(int n) -- Return true if n is in the set and false
   otherwise.

   (Hint: consider how you can use this method to help simplify your
    implementation of other methods.)

public boolean subset(Set S) -- Returns true if this set is a subset of S,
   that is, every member of this set is a member of S, and false
   otherwise.

public boolean equal(Set S) --  Returns true if this set and S have
   exactly the same members.

public void insert(int k) -- If the integer k is a member of the set
   already, do nothing, otherwise, add to the set; if this would cause an
   ArrayOutOfBoundsException, you must grow the array before inserting the new element.

   (Hint: This method is key to correctly implementing many of the other 
   methods without duplicating a lot of code!)

public void delete(int k) -- If the integer k is not a member, do nothing;
   else remove it from the set; you must shift all elements which occur
   after k in the array to the left by one slot.

public void grow() -- resize the array by growing it by the DEFAULT_SIZE.

public Set union(Set S) -- Return a new set consisting of all of the
   elements of this set and S combined (without duplicates). Example:

public Set intersection(Set S) -- Return a new set consisting of the elements
   that are common to both this set and S (without duplicates). Example:

public Set setdifference(Set S) -- Return a new set consistng of all the 
   elements of this set that are not present in S.

Completing your Solution

Begin by downloading the template: Set.java. This template has most of the methods commented out. Begin by implementing the constructors and any other method which may help you correctly insert new elements into the set. You can uncomment each method one at a time as you implement it.

You can also download the file DriverForSet.java which contains a main program that you can use as a guide to incrementally test the methods of your Set class.

Notes and Guidelines:

  • Do not alter the variables that have been declared in the starter file.

  • The methods union, intersection and difference should make and return new sets, and NOT modify the input sets in any way!

  • The methods insert and delete are mutator methods and will modify the set.

  • Look for opportunities to reuse your own code by implementing methods by using other, simpler methods. For example, equals can be implemented simply (one line of code) using two calls to subset, and setdifference is VERY similar to intersection!

  • Use the method descriptions above as a guide to write a comment block before each of the methods.

  • You may add tests to the main method as you develop your code, but remove them before submission.

  • Remove any debugging code in the methods specified above before submission.

  • Do not alter the signature of the methods or they may fail the automatic test.

Problem 5: BigInt: a class for large integers

25 points total; pair-optional

This is the only problem of the 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.

Overview
In Java, the int data type can only represent integers from -2,147,483,648 to 2,147,483,647. This isn’t big enough to store very large numbers. For example, to store the population of Earth (approximately 8 billion as of 2024) or to compute n! for large values of n.

The Java libraries contain a built-in class called BigInteger to handle arbitrarily large integers. In this problem, you will write your own class called BigInt that has a subset of the functionality of the built-in Java class.

Representing integers using an array of digits
Each BigInt object will use an array of integers, where each element of the array represents a single digit of the integer.

We will design the class to handle non-negative integers with up to 20 digits, and thus the array will always have a length of 20.

For example, the integer 57431 would be represented using this array:

{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 7, 4, 3, 1}

Note that:

As another example, the integer for 7.53 billion would be represented using the array

{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 5, 3, 0, 0, 0, 0, 0, 0, 0}

Task 0: Download and review our starter code
Begin by downloading the following starter file: BigInt.java

Open this file in your IDE and review its contents. We have given you:

Important guidelines

  1. You may not add any additional fields to the BigInt class.

  2. You may not use any variables of type long, any of Java’s built-in classes for numbers (Long, BigInteger, etc.), or any of Java’s built-in collection classes (e.g., ArrayList).

Task 1: Add your first of several custom constructors

public BigInt(int[] arr)

It should use the contents of the array that is passed in as the basis of the new BigInt object. For example, we should be able to create a BigInt for 57431 as follows:

int[] arr = {5, 7, 4, 3, 1};
BigInt val = new BigInt(arr);

Suggested approach:

Important: Make sure that the digits field references a new array of length MAX_SIZE. You should not make it refer to the array that is passed in.

Task 2: Add two methods useful for testing

Once these two methods are defined, you can—and should!—uncomment the first few tests in the main method, and run the class to confirm that you get the correct results.

Task 3: Add the remaining methods
After adding a given method, uncomment the corresponding unit tests in the main method to test it.

The following accessor method is needed by the autograder:

Note: In general, it is not good practice to return a reference to an array as arrays are mutable and therefore can be changed. You do not want external code to be able to alter the contents of an array that is private to an object.

Algorithms
The algorithms for manipulating these big integers are simply computational versions of the procedures that we would use to add, compare, or multiply integers “on paper”.

For example, to add two arrays of digits, we must go from right to left (i.e. least significant digit to most significant digit) adding the digits and keeping track of the carry. For example, to add 57339 to 4598, the process looks something like this:

carry:           1   0   1   1     
            -----------------------+
       ...   0 | 5 | 7 | 3 | 3 | 9 |
            -----------------------+
            -----------------------+
       ...   0 | 0 | 4 | 5 | 9 | 8 |
            -----------------------+
            -----------------------+
sum:   ...   0 | 6 | 1 | 9 | 3 | 7 |
            -----------------------+

Note that addition will result in overflow (creating a number with more than 20 digits) if you need to add the digits in position 0 of the two arrays and if their sum plus any incoming carry value produces a value that is greater than or equal to 10.

We encourage you to:

Submitting your work for Part II

Note: There are separate instructions at the end of Part I that you should use when submitting your work for that part of the assignment.

You should submit only the following files:

Make sure that you do not try to submit a .class file or a file with a ~ character at the end of its name.

Here are the steps:

  1. Login to Gradescope as needed by clicking the link in the left-hand navigation bar, and then click on the box for CS 112.

  2. Click on the name of the assignment (PS 4: Part II) in the list of assignments. You should see a pop-up window with a box labeled DRAG & DROP. (If you don’t see it, click the Submit or Resubmit button at the bottom of the page.)

  3. Add your files to the box labeled DRAG & DROP. You can either drag and drop the files from their folder into the box, or you can click on the box itself and browse for the files.

  4. Click the Upload button.

  5. You should see a box saying that your submission was successful. Click the (x) button to close that box.

  6. The Autograder will perform some tests on your files. Once it is done, check the results to ensure that the tests were passed. If one or more of the tests did not pass, the name of that test will be in red, and there should be a message describing the failure. Based on those messages, make any necessary changes. Feel free to ask a staff member for help.

    Note: You will not see a complete Autograder score when you submit. That is because additional tests for at least some of the problems will be run later, after the final deadline for the submission has passed. For such problems, it is important to realize that passing all of the initial tests does not necessarily mean that you will ultimately get full credit on the problem. You should always run your own tests to convince yourself that the logic of your solutions is correct.

  7. If needed, use the Resubmit button at the bottom of the page to resubmit your work. Important: Every time that you make a submission, you should submit all of the files for that Gradescope assignment, even if some of them have not changed since your last submission.

  8. Near the top of the page, click on the box labeled Code. Then click on the name of each file to view its contents. Check to make sure that the files contain the code that you want us to grade.

Important

  • It is your responsibility to ensure that the correct version of every file is on Gradescope before the final deadline. We will not accept any file after the submission window for a given assignment has closed, so please check your submissions carefully using the steps outlined above.

  • If you are unable to access Gradescope and there is enough time to do so, wait an hour or two and then try again. 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