2004 CS2102 Exam #1A   Answers are in Red

Q0. [0 points] The Dilbert Zone

wpe46C.jpg (22678 bytes)

Q1. [12 points] This question tests your basic knowledge of the Java for statement. When the following method executes, what are the final values of x and y printed out? [At the underlined statement, you must show the intermediate values for x and y, otherwise you only get 1/2 credit].

Answers: I expected students to tell me the value of x,y immediately before the statement executed (but I was willing to accept answers that were consistent with 'just after'). Here are the results. note that the values that are output ARE NOT the same as the last two entries. This question tested (a) understanding of the way in which a for loop executes; (b) integer division; (c) the knowledge that the advance statement (y--) within a for loop happens after the body executes and BEFORE the condition is evaluated.

public void f() {
  int x = 5;
  int y = x;
 
  for (x = 6; y < x; y--) {
     x = x/2 + y;
  }
  System.out.println (x + "," + y);
}
x 6 8 8 7 5 3 1 -1 -2            
y 5 4 3 2 1 0 -1 -2 -3            


Final Values of x,y printed out:
-4, -4

Q2. [20 points] There are at least five logical errors in the following code that compiles successfully. The code is supposed to print “(100,100) is inside: false” but it instead prints out "(100,100) is inside: true". Circle the errors and suggest changes to make it work. You may suggest new lines of code to add, or suggest lines of code to remove.

Answer:

  1. The initial coordinates to Square (20, 40, 90, 120) are not, in fact, square. Should likely have said 90,110 as the last two values.
  2. Defining unit as x-x2 creates a negative value, if indeed the user passes in (x,y) and (x2,y2) as the upper left and lower right coordinates
  3. Two errors: The statements (x = x) and (y = y) have no effect. Why? because they refer to the value of the parameter 'x' within the constructor, even though it is clear that the person who wrote the constructor intended the value of the parameter 'x' to be copied into the value of the instance variable 'x'. This is called 'shadowing'.
  4. Two errors: Assuming that unit is a positive value, then the conditional check '(u-unit >= x)' should have said '(u-unit <= x)' (the same is true for 'v-unit >= y').
public class Square {
  /** Upper left corner point. */
  int x;
  int y;
   
  /** Width and height of square. */
  int unit;

  /** Construct Square from upper
   * left (x,y) and lower right (x2,y2). */
  public Square (int x, int y, int x2, int y2) {
    // compute constants for Square.
    x = x;
    y = y;
    unit = x-x2;
  }

  /** Determine if point is contained
   * within Square (even on an edge). */    
  public boolean inside (int u, int v) {
    return (x <= u) && (u-unit >= x) && 
           (y <= v) && (v-unit >= y);
  }
}
public class Exam {
  public static void main (String []ss) {
    // Create the Square
    Square sq = new Square (20, 40, 
                            90, 120); 

    // see if point is inside.
    System.out.println ("(100,100) is inside: " + sq.inside(100,100));
  }
}

Q3. [18 points] Given the following code, fill in the stack frame diagram on the right with the appropriate references, either static or point to this. For all variables and parameters include values or references as appropriate. Show objects on the heap as well. Note that the program is stopped at the underlined code. 

public class Q2 {
  int top;
  int val;

  public Q2 (int x) {
    top = x;
    val = 0;
  }

  public void process (int [] ar) {
    if (ar[top] > val) {
     val = ar[top];
    }
  }

  public static void main (String []args) {
    Q2 q = new Q2(2);
    int [] ar = new int {1,2,3,4,5,6};
    q.process (ar);
}

stack_example.jpg (12503 bytes)

 

Q4. [24 points] This question tests your knowledge of procedural abstractions. The authors of the book introduce the following concept regarding the properties of procedures and their implementation.

    Minimality
-- one specification is more minimal than another if it contains fewer constraints on allowable behavior.

You are given the following three specifications for a method 'void f(int []ar)'.

Specification A REQUIRES: ar != null
MODIFIES: ar
EFFECTS: ar contains descending order of ints
Specification B REQUIRES: ar != null
MODIFIES: ar
EFFECTS: rearranges the elements of ar to be a random
         permutation of ar.
Specification C REQUIRES: ar != null
MODIFIES: ar
EFFECTS: rearranges the elements of ar into descending order.

a) [8 points] Is SpecB more minimal than SpecA? Explain your answer [otherwise you only get 1/2 credit]
b) [8 points] Is SpecC more minimal than SpecA? Explain your answer [otherwise you only get 1/2 credit]
c) [8 points] Which Specification does the following implementation match most clearly. Explain your answer [otherwise you only get 1/2 credit]

Answer: Some observations: (1) Specification A says nothing about the relationship between the values of ar before the method is called and the values that are left in ar after the method is called. A function that satisfies this specification simply overwrites the actual contents of the array with values {0, -1, -2, -3, -4, ...} for the entire size of the array. (2) While Specification B states that the array simply be a random permutation (i.e., shuffle) of existing elements within the array, specification C declares that the integers must be sorted in descending value.

Now, given these observations:
(a) Specification B is not more minimal than Specification A. Functions that conform to Specification B are restricted to only modify the 'ar' array to contain a permutation of the original elements; functions that conform to Specification A are only restricted by the requirement that the numbers that ultimately appear in ar are in descending order.
(b) Specification C is not more minimal than Specification A. Specification C is deterministic in that it can return only a single result given input array 'ar', namely, the original array sorted in descending order. Specification A (again) has much fewer constraints on the allowed behavior of the functions that conform to the Specification.
(c) If you look at the code below, the function f() can be best called 'randomSort'. It randomly selects items from the array, swaps them, and checks to see if the array has been sorted into descending order. Thus this code most closely conforms to Specification C [even though there is a random permutation, the final result is restricted as with Specification C; also, while Specification A also produces descending integers, they may have nothing to do with input parameters, thus we select Specification C as the best one.

public void f(int []ar) {
  boolean b = true;
  while (b) {
    int r1 = selectRandom(0,ar.length-1);  // randomly select from 0,1,...,ar.length-1
    int r2 = selectRandom(0,ar.length-1);  // randomly select from 0,1,...,ar.length-1
   
    int tmp = ar[r1]; ar[r1] = ar[r2]; ar[r2] = tmp;   // swap ar[r1] with ar[r2]
    b = false;
    for (int i = 0; i < ar.length-1; i++) {
      if (ar[i] < ar[i+1]) {
        b = true;
        break;
      }
    }
  }
}

Aside: For the curious, what is the performance of this random sort? Well, given that it is non-deterministic, the following values should be taken as only a single data point, not reflecting the total time to sort arbitrary arrays. All time is in milliseconds and performed on a ~400 Mhz machine. Naturally, one would not want to use this algorithm to sort! note how it took about 1 Hour to sort 8 elements at random.

SIZE InsertionSort RandomSort
2 0 0
3 0 0
4 0 8,223
5 0 95
6 0 495
7 1 498
8 0 3,604,632

Q5. [2 points] Fill in the following Dilbert cartoon. Extra points if I fall out of my chair laughing.

e1.jpg (24238 bytes)

Q6. [24 Points] This question test your knowledge of how to manipulate object references. Assume that you are given the following LinkedList class and a companion Node class.

LinkedList Node
public class LinkedList {
  // first element
  Node head;

  public LinkedList () {
    head = null;
  }

  public void insert (int i) { ... }

}

 

public class Node {
  // Value
  int value;

  // next
  Node next;

  // constructor
  public Node (int i) {
    value = i;
    next = null;
  }
}

Assume that the other methods (not shown here) of LinkedList properly build up a linear LinkedList of Node objects.

(a) [10 points] Write the specification for a method 'void remove(int i)' for the LinkedList class which removes the first Node from the LinkedList whose value is i.
(b) [14 points] Write the Java implementation for this specification.

/**
* Remove from the LinkedList any Node whose int value is
* equal to target.
*    MODIFIES: this
*    EFFECTS:  Ensures that LinkedList contains no Node
*              whose int value is 'target'.
*/
public void remove (int target) {
   // handle empty list case. Done immediately, so return.
   if (head == null) {
      return;
   }

   // if 'target' is the head of the LinkedList, simply
   // redirect to second. Note: this may result in an
   // empty list.
   if (head.value == target) {
     head = head.next;
     return;
   }

   // find if we are already in the list. We must work
   // to keep track of the pointers
   Node current = head;      // known NOT to be 'target'
   Node nextOne = head.next; // next one to check

   while (nextOne != null) {
     // if we have found our entry in the linked list,
     // then link around and return.
     if (nextOne.value == target) {
       current.next = nextOne.next;
       return;
     }
   
     // update pointers
     current = nextOne;
     nextOne = nextOne.next;
   }

   // if we get here, then we are not in the list!
}