# CS3110 Fall 2009 Prelim 2 November 17, 2009

Solutions

Instructions

Write your name and Cornell netid above. There are 6 questions on 8 numbered pages. Check now that you have all the pages. Write your answers in the boxes provided. Use the back of the pages for workspace. Ambiguous answers will be considered incorrect. The exam is closed book and closed notes except for the handouts provided. Do not begin until instructed. You have 90 minutes. Good luck!

1 Score Grader /18

2 /24

3 /8

4 /5

5 /15

6 /30

Σ /100

November 17, 2009

CS3110 Prelim 2

Page 1 of 8

1. (18 points) Determine the type and value of each of the following expressions as they would be printed by the interpreter. # let (s, t) = ([1; 2; 3], [4; 5; 6]);; val s : int list = [1; 2; 3] val t : int list = [4; 5; 6] # [s] @ [t];; - : int list list = [[1; 2; 3]; [4; 5; 6]] (a) # t :: [s];; - : int list list = [[4; 5; 6]; [1; 2; 3]] (b) # List.map (fun z -> z :: s) t;; - : int list list = [[4; 1; 2; 3]; [5; 1; 2; 3]; [6; 1; 2; 3]] (c) # List.map (fun z -> List.map (fun w -> w - z) s) t;; - : int list list = [[-3; -2; -1]; [-4; -3; -2]; [-5; -4; -3]] (d) # let t = List.tl s in let s = List.hd t in s;; - : int = 2 (e) # let x = ref 2 in let f y = x := !x + y in f !x;; - : unit = () (f) # [[[]]];; - : ’a list list list = [[[]]]

November 17, 2009

CS3110 Prelim 2

Page 2 of 8

2. (24 points) Supply a value for zardoz that causes the entire expression to evaluate to 42. If impossible, say so and explain why. Example: let zardoz = (42, 43) in fst zardoz

(a) let zardoz = fun -> fun in zardoz zardoz zardoz

-> 42

(b) let zardoz = fun -> 42 in List.hd (List.tl (List.map zardoz [zardoz; zardoz]))

(c) let zardoz = (=) 42 in if zardoz 42 && not (zardoz 43) then 42 else 43

(d) let zardoz = 14 in List.fold left (+) zardoz [zardoz; zardoz]

(e) let zardoz = let x = ref 42 in fun () -> let y = !x in decr x; y in if zardoz () = 42 then zardoz () + 1 else 43

(f) let zardoz = fun x -> x ("42", int of string) in try failwith (zardoz fst) with Failure "42" -> (zardoz snd (zardoz fst))

November 17, 2009

CS3110 Prelim 2

Page 3 of 8

3. (8 points) Consider the following data abstraction for Booleans and its implementation. module type BOOL = sig (* A "boolean" is a Boolean with the usual operations. *) type boolean val true_ : boolean val false_ : boolean val and_ : boolean -> boolean -> boolean val or_ : boolean -> boolean -> boolean val not_ : boolean -> boolean end module Boolean : BOOL = struct type boolean = int let true_ = 1 let false_ = 0 let and_ x y = x * y let or_ x y = x + y let not_ x = if x <> 0 then 0 else 1 end Recall that the abstraction function AF is a partial function from concrete values to the abstract values they represent, and the representation invariant RI is a property that determines which concrete values represent an abstract value. (a) What is the abstraction function for this implementation? AF(0) = false , AF(x) = true for x > 0) (b) What is the representation invariant maintained by this implementation? x≥0

November 17, 2009

CS3110 Prelim 2

Page 4 of 8

4. (5 points) Consider the following concurrent program. let x = Mutex.create () let c = Condition.create () let g () = Mutex.lock x; print_endline "Vasilis"; Condition.signal c; print_endline "Jerzy"; Mutex.unlock x; print_endline "Dane" let f () = Mutex.lock x; ignore (Thread.create g ()); print_endline "Dexter"; Condition.wait c x; print_endline "Gabriel"; Mutex.unlock x; print_endline "Andrew" Suppose a thread executes f(). Check the sequences that could be printed. 2 Dexter Vasilis Gabriel Jerzy Andrew Dane x 2 Dexter Vasilis Jerzy Gabriel Dane Andrew 2 Vasilis Dexter Jerzy Dane Gabriel Andrew x 2 Dexter Vasilis Jerzy Dane Gabriel Andrew x 2 Dexter Vasilis Jerzy Gabriel Andrew Dane

November 17, 2009

CS3110 Prelim 2

Page 5 of 8

5. (15 points) Here is a simulation of a double-ended queue (deque) with three stacks. Call the stacks Stack1, Stack2, and Stack3. The stack operations are push and pop. The deque operations are push-front, pop-front, push-back, and pop-back. Stack1 will simulate the front of the deque. Stack2 will simulate the back of the deque. Stack3 is just used for transferring data between Stack1 and Stack2 in the correct order. The deque operations are simulated as follows. • push-front: Push the element onto Stack1. • push-back: Push the element onto Stack2. • pop-front: If Stack1 is nonempty, pop the top element oﬀ Stack1. Otherwise, transfer half the elements on Stack2 to Stack3 (raising an exception if Stack2 is empty—there is nothing to pop), transfer the other half of the elements on Stack2 to Stack1, then transfer the elements from Stack3 back to Stack2. Then pop the top element from Stack1. • pop-back: The same, switching the roles of Stack1 and Stack2. Give an analysis showing that each of the four deque operations can be performed in constant amortized time. (Hint. Use the physicist’s method with the potential function Φ(n1 , n2 ) = n1 + n2 + 3 · |n1 − n2 |, where n1 and n2 are the number of 2 elements on Stack1 and Stack2, respectively.)

We have Φ(0, 0) = 0 and Φ(n1 , n2 ) ≥ 0 for n1 , n2 ≥ 0, which implies that the actual time is bounded by the amortized time for any sequence of operations. The amortized time for the operation at time t is ct + ϕt+1 − ϕt , where ct is the actual time and ϕt is the value of the potential function at time t. We wish to show that this is bounded by a constant. The actual time of push-front, push-back, pop-front when Stack1 is nonempty, and pop-back when Stack2 is nonempty is constant, and the potential changes by only a constant amount, so the amortized time is O(1) in these cases. For pop-front when Stack1 is empty, the actual cost is 3n2 /2 + 1. The potential before the operation is Φ(0, n2 ) = 5n2 /2 and after the operation is Φ(n2 /2, n2 /2) = n2 , so the amortized complexity is 3n2 /2 + 1 + n2 − 5n2 /2 = 1, which is O(1). The argument for the remaining case, pop-back when Stack2 is empty, is symmetric.

November 17, 2009

CS3110 Prelim 2

Page 6 of 8

6. (30 points) AVL trees were the ﬁrst balanced tree scheme. An AVL tree is a binary search tree such that each node has either 0, 1, or 2 children; there is a datum of type ’a associated with each node; and the tree satisﬁes the AVL invariant: For every node x, the diﬀerence in height between the left subtree of x and the right subtree of x is at most 1. (Recall that the height of a tree rooted at y is the number of edges in a longest path from y to a leaf. For the purposes of this deﬁnition, if x has no left subtree, we deﬁne the height of its left subtree to be −1, and similarly for right.) Here are minimum-size AVL trees of height 0, 1, 2, and 3 with nodes numbered in inorder: 1 1 1 1 (a) (5 points) Write a recurrence for N (m), the number of nodes in a minimumsize AVL tree of height m. (Hint: If an AVL tree is of height m ≥ 2 and minimum size, what must the heights and sizes of its subtrees be?)

N (0) = 1 N (1) = 2 N (m) = N (m − 1) + N (m − 2) + 1 for m ≥ 2

2 2

3 4 2 3 4

5 7 6

November 17, 2009

CS3110 Prelim 2

Page 7 of 8

(b) (15 points) Recall the Fibonacci sequence m : 0 1 2 3 4 5 6 7 8 9 ... F (m) : 1 1 2 3 5 8 13 21 34 55 . . . deﬁned by the recurrence F (0) = F (1) = 1 and F (m) = F (m − 1) + F (m − 2) for m ≥ 2. Find a relationship between N and F , and prove by induction using your recurrence from part (a) that this relationship is correct.

For all m, N (m) = F (m + 2) − 1. Basis: N (0) = 1 = F (2) − 1 and N (1) = 2 = F (3) − 1. Induction step: For m ≥ 2, N (m) = N (m − 1) + N (m − 2) + 1 = F (m + 1) − 1 + F (m) − 1 + 1 = F (m + 2) − 1 by the recurrence (a) by the (strong) induction hypothesis by the Fibonacci recurrence and arithmetic.

√ (c) (5 points) We showed in class that F (m) is Θ(ϕm ), where ϕ = (1 + 5)/2 ≈ 1.618 · · · . Using this fact and the result of part (b), argue that AVL trees are balanced; that is, the height of an AVL tree with n nodes is O(log n).

Since F (m) is Ω(ϕm ), there exists a c > 0 such that for all but ﬁnitely many m, N (m) = F (m + 2) − 1 ≥ F (m) ≥ c · ϕm . As N (m) is the minimum size of an AVL tree of height m, any AVL tree with n nodes and height m satisﬁes n ≥ N (m). Combining this with the above inequality and taking logs, we have m log ϕ + log c ≤ log n, therefore m is O(log n).

November 17, 2009

CS3110 Prelim 2

Page 8 of 8

(d) (5 points) Immediately after an insertion or a deletion, the resulting binary tree may violate the AVL invariant, but the invariant can be reestablished by at most two applications of the operations rotate left and/or rotate right: y

rotate right

x y A B C

x C A B

rotate left

**Write OCaml programs to perform these two operations, assuming the type declaration
**

type ’a avl = Node of ’a * ’a avl option * ’a avl option

for AVL trees. A leaf is a node of the form Node (x, None, None). Your code should raise Invalid argument if the operation does not apply.

let rotate left (t : ’a avl) : ’a avl = match t with Node (x, a, Some (Node (y, b, c))) -> Node (y, Some (Node (x, a, b)), c) | -> raise (Invalid argument "Bad left rotate")

let rotate right (t : ’a avl) : ’a avl = match t with Node (y, Some (Node (x, a, b)), c) -> Node (x, a, Some (Node (y, b, c))) | -> raise (Invalid argument "Bad right rotate")

End of Exam