Midterm Exam

Midterm Exam



Important notes:
  1. Do not start until you are instructed to do so!
  2. You will have 70 minutes once the proctor says to start.
  3. You will have brief additional time after we stop to scan and submit your solutions.

  4. Just before the exam...
    1. Have a fully-charged smartphone and laptop, and still plug both in if possible
    2. Log into Gradescope on your phone
    3. Change the screen timeout setting on your phone to never, so your screen doesn't go black if you don't interact with your screen for a while.
      • iPhones: Settings / Display & Brightness / Auto-Lock / Never
      • Android: Settings / Display / Screen timeout / 10 minutes (or the maximum amount of time)
    4. Turn on Do Not Disturb (or otherwise turn off all notifications).
    5. Position your webcam so we can see:
      • Your desk
      • The paper you are working on
      • Your writing utensil(s)
      • Both of your hands
      • Your phone

  5. During the exam:
    1. You may not ask questions during the exam.
      • If you are unsure how to interpret a problem, take your best guess.
      • If you feel a question is unfair because you could not ask a question about it, please email the instructor after the exam and describe your concern. (We are working hard to make the questions extra clear this year, but we want to know when we fail.)
    2. You may not touch your laptop or webcam.
      • This includes muting yourself at any point; the proctors may mute you though.
    3. All of these must be visible at all times:
      • Your desk
      • The paper you are working on
      • Your writing utensil(s)
      • Both of your hands
      • Your phone, with the exam webpage
    4. For any major tech fails (laptop or internet stops working, etc.):
      1. Stop taking the exam
      2. Email the instructor (rileyrd@cmu.edu) right away explaining the issue.
      3. Scan your progress so far to a PDF.
      4. Email that PDF to the instructor.
      5. We will reply soon to set up a 1-on-1 oral exam with the course faculty.

  6. After the exam:
    1. Follow all proctor instructions on how to end the exam.
    2. If you finish early, wait patiently until the end of the exam. (Note: Don't use your phone...)
    3. Keep everything in view (as noted above) until the proctor calls "time".
    4. When instructed, use your phone to scan your exam and submit the PDF to Gradescope.
    5. After submitting to Gradescope, hold your phone up to the webcam to show the receipt.
    6. Even then, remain in exam mode until the proctor calls "all clear"

1. Short Answer

Answer each of the following in just a few words.

Part A [2 pts]

What are getters and setters and why do we use them?

Part B [2 pts]

What is the largest, signed value that can be stored in a 4-byte integer? You do not need to reduce your answer. Be certain to show your work, and also very clearly circle your answer!

Part C [2 pts]

What does it mean when you get a NullPointerException?

Part D [4 pts]

What does the following code print?

Be certain to show your work, and also very clearly circle your answer!

public class IncrementorExercise {
    public static void main(String[] args) {
        int e = 2;
        int f = 4;
        int g = ++f - --e;

        System.out.println(++f + e-- + --g);
        System.out.println(e);
        System.out.println(f);
        System.out.println(g++);
    }
}

2. Short Code

Write the code for the following methods. You do not need to rewrite the method prototypes, simply write the body code.

Part A [5 pts]

/**
 * Given an array, print all of the odd numbers in the
 * array and return how many numbers in the array are
 * divisible by 5.
 * 
 * @param arr The array of integers to check
 * @return The number of integers in arr that are
 *         divisible by 5.
 */
public int numChecker(int[] arr) {
    // Your code here
}

Part B [5 pts]

/**
 * Convert an ArrayList to an array. The returned array
 * should contain all of the items from the ArrayList,
 * in **reverse** order.
 * 
 * @param theList The ArrayList to convert to a reversed
 *                array
 * @return The converted array
 */
public String[] reversedArray(ArrayList<String> theList) {
    // Your code here
}

3. Big-Oh [15 pts]

Determine the big-oh runtime of each of the following, in terms of N, the length of array arr. Circle your final answer for each.

Part A

public static boolean func1(int[] arr, int i, int j) {
    if (arr[i] == arr[j]) {
        return false;
    }
    return true;
}

Part B

public static int func2(int[] arr) {
    int b[] = { 3, 5, 7, 11, 13, 17 };
    int cnt = 0;
    for (int i = 0; i < arr.length; i++) {
        for (int j = 0; j < b.length; j++) {
            if (arr[i] % b[j] == 0) {
                cnt++;
            }
        }
    }
    return cnt;
}

Part C

public static void func3(int[] arr, int n) {
    for (int i = 0; i < arr.length; i++) {
        if (arr[i] == n) {
            arr[i]++;
        }
    }
}

4. Linked List Memory Diagram [20 pts]

Consider the following code snippet that creates a linked list. You may assume that the ListNode class exists and was defined as in class.

ListNode<Integer> head = null;
ListNode<Integer> tmp = null;
ListNode<Integer> other = null;

head = new ListNode<Integer>(10);
// Stop and draw Diagram A.

other = head;
tmp = new ListNode<Integer>(6);
tmp.next = head;
head = tmp;
// Stop and draw Diagram B.

other.next = new ListNode<Integer>(7);
// Stop and draw Diagram C.

tmp = new ListNode<Integer>(8);
tmp.next = other.next;
other.next = tmp;
// Stop and draw Diagram D.

tmp.next.next = head;
other.next = null;
head = tmp;
// Stop and draw Diagram E.

Draw the state of the linked list at each of the commented lines of code. The linked list is defined as starting at head.

The first one is drawn for you:

Draw the remaining four diagrams: Diagram B, Diagram C, Diagram D, and Diagram E.

Be sure to label each picture clearly with which Diagram it is.


5. Meeting Class [20 pts]

Consider the following code for the meeting class. The testing code in main includes comments containing the expected output.

public class Meeting {
    // A list of people invited to the meeting
    private ArrayList<String> invitees;
    // The date of the meeting
    private String date;

    // You should not require any additional instance variables.

    /**
     * A basic constructor.
     * 
     * @param date The date of the new meeting
     */
    public Meeting(String date) {
        // Your code will go here for Part A
    }

    /**
     * Add an invitee to the meeting. If an invitee is
     * already part of the invitee list, then do not add
     * them again.
     * 
     * @param email The email address of the invitee
     * @return true if the invitee was added to the meeting
     *         and false otherwise
     */
    public boolean addInvitee(String email) {
        // Your code will go here for Part B
    }

    /**
     * Get the number of people invited to the meeting
     * 
     * @return The number of invitees
     */
    public int numInvitees() {
        // Your code will go here for Part C
    }

    /**
     * Load invitees from a file. The file will contain
     * email addresses, one per line. If an invitee is
     * already part of the invitee list, then do not add
     * them again.
     * 
     * @param filename The filename to load the invitees
     *                 from.
     */
    public void loadInvitees(String filename) {
        // Your code will go here for Part D
    }

    /**
     * A basic toString.
     */
    public String toString() {
        String ret = "Meeting [ " + this.date + " ] [ ";
        for (String s : this.invitees) {
            ret += s + " ";
        }
        ret += "]";
        return ret;
    }

    /* Testing code.  The expected output is contained in comments
     * after the line in question. 
     */
    public static void main(String[] args) {
        Meeting m = new Meeting("Oct 1, 2020");
        System.out.println(m);
        // Meeting [ Oct 1, 2020 ] [ ]

        boolean ret = m.addInvitee("rileyrd@cmu.edu");
        System.out.println(ret);
        // true
        System.out.println(m);
        // Meeting [ Oct 1, 2020 ] [ rileyrd@cmu.edu ]

        m.loadInvitees("people.txt");
        System.out.println(m);
        // Meeting [ Oct 1, 2020 ] [ rileyrd@cmu.edu joe@fakemail.com bob@fakemail.com ]

        ret = m.addInvitee("bob@fakemail.com");
        System.out.println(ret);
        // false
        System.out.println(m);
        // Meeting [ Oct 1, 2020 ] [ rileyrd@cmu.edu joe@fakemail.com bob@fakemail.com ]

        System.out.println(m.numInvitees());
        // 3
    }
}

The file, people.txt contains the following:

joe@fakemail.com
bob@fakemail.com
rileyrd@cmu.edu

Part A

Write the code for the constructor. You do no need to rewrite the method prototype, as long as your label your answer with “Part A”.

Part B

Write the code for addInvitee. You do no need to rewrite the method prototype, as long as your label your answer with “Part B”.

Part C

Write the code for numInvitees. You do no need to rewrite the method prototype, as long as your label your answer with “Part C”.

Part D

Write the code for loadInvitees. You do no need to rewrite the method prototype, as long as your label your answer with “Part D”.


6. Inheritance [15 pts]

This problem builds on the previous problem. If your Meeting solution does not work, that is fine: It is still possible to receive full points on this problem by just pretending that your Meeting class does work properly.

A CMUZoomMeeting is-a Meeting, but it is one that only users with @andrew.cmu.edu email addresses can be invited to. It also has a Zoom meeting id.

Here is some testcode for the CMUZoomMeeting class. It includes comments containing the expected output.

Meeting m = new CMUZoomMeeting("Oct 2, 2020", "123-456-1234");
System.out.println(m);
// Meeting [ Oct 2, 2020 ] [ ] [ 123-456-1234 ]

boolean ret = m.addInvitee("jsmith@andrew.cmu.edu");
System.out.println(ret);
// true
System.out.println(m);
// Meeting [ Oct 2, 2020 ] [ jsmith@andrew.cmu.edu ] [ 123-456-1234 ]

ret = m.addInvitee("jsmith@fakemail.com");
System.out.println(ret);
// false
System.out.println(m);
// Meeting [ Oct 2, 2020 ] [ jsmith@andrew.cmu.edu ] [ 123-456-1234 ] 

ret = m.addInvitee("ahmed@andrew.cmu.edu");
System.out.println(ret);
// true
System.out.println(m);
// Meeting [ Oct 2, 2020 ] [ jsmith@andrew.cmu.edu ahmed@andrew.cmu.edu ] [ 123-456-1234 ] 

ret = m.addInvitee("jsmith@andrew.cmu.edu");
System.out.println(ret);
// false
System.out.println(m);
// Meeting [ Oct 2, 2020 ] [ jsmith@andrew.cmu.edu ahmed@andrew.cmu.edu ] [ 123-456-1234 ]

System.out.println(m.numInvitees());
// 2

Write the CMUZoomMeeting class. For full credit, you must properly make use of inheritance, including avoiding unnecessary code duplication.


7. Bug Hunting [10 pts]

Consider the following buggy code that raises an exception when executed:

public class MagicList {
    // An array to store Strings
    private String[] arr;
    // The total number of strings actually stored in arr
    private int numItems;

    public MagicList() {
        this.arr = new String[2];
        this.numItems = 0;
    }

    public void append(String val) {
        // Enlarge arr if needed.
        if (this.numItems == arr.length) {
            String[] newArr = new String[arr.length * 2];
            for (int i = 0; i < arr.length; i++) {
                newArr[i] = arr[i];
            }
            String[] arr = newArr;
        }
        // Add the new item to arr
        this.arr[this.numItems++] = val;  // This is line 22
    }

    public static void main(String[] args) {
        MagicList myList = new MagicList();
        myList.append("Hi");
        myList.append("there");
        myList.append("Bob"); // This is line 29
    }
}

When executed, this code raises the following exception:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2
    at MagicList.append(MagicList.java:22)
    at MagicList.main(MagicList.java:29)

A. Identify and describe the bug that is causing the exception.

B. Fix the buggy code so that it functions properly.

You do not need to rewrite the entire class, simply specify the exact changes that need to be made.


Extra Credit – Code Tracing [5 pts]

Note: Do not work on this problem unless you are done with all the others. This one can be a real time sink.

Consider the following three classes:

public class ExtraCreditA {
    private int a;
    private int b;

    public ExtraCreditA(int a, int b) {
        this.a = b;
        this.b = a;
    }

    public int getA() {
        return this.a;
    }

    public int getB() {
        return this.b;
    }

    public double getRatio() {
        int ret = this.a / this.b;
        return ret;
    }
}
public class ExtraCreditB extends ExtraCreditA {

    public ExtraCreditB(int a, int b) {
        super(a + 5, b - 3);
    }

    public int getA() {
        return super.getA() - 5;
    }

    public int getB() {
        return super.getB() + 3;
    }

    public double getRatio() {
        return (getA() + 1.0) / getB();
    }
}
public class ExtraCreditC extends ExtraCreditB {

    public ExtraCreditC(int b, int a) {
        super(a + 1, b + 5);
    }

    public double getRatio() {
        return (getB() + 0.0) / getA();
    }

    public static void main(String[] args) {
        ArrayList<ExtraCreditA> theList = new ArrayList<ExtraCreditA>();
        theList.add(new ExtraCreditA(3, 10));
        theList.add(new ExtraCreditB(7, 12));
        theList.add(new ExtraCreditC(9, 15));

        for (ExtraCreditA tmp : theList) {
            System.out.println(tmp.getRatio());
        }
    }
}

Assuming that the main method of ExtraCreditC is executed, what is the output of this program?