Sample Final Questions CS 2010 Fall 2003 - - - - - - - - - - - - - - - - - - - - - - - - - Answers are between dashed lines, like this. - - - - - - - - - - - - - - - - - - - - - - - - - A radar center must track flying objects. Every flying object has a position, which is expressed as three numbers for latitude, longitude, and altitude. Known objects also have an identifying string, while unknown objects have no identifier. Provide a data definition (suitable for use with Scheme) for radar-tracked flying objects. - - - - - - - - - - - - - - - - - - - - - - - - - ;; A FO is either ;; - (make-identified string num num num) ;; - (make-ufo num num num) (define-struct identified (id lat long alt)) (define-struct ufo (lat long alt)) - - - - - - - - - - - - - - - - - - - - - - - - - ---------------------------------------- Provide a Java version of your data definition for radar-tracked flying objects. - - - - - - - - - - - - - - - - - - - - - - - - - abstract class FO { double lat; double lng; double alt; } class Identified extends FO { String id; ... } class UFO extends FO { ... } - - - - - - - - - - - - - - - - - - - - - - - - - ---------------------------------------- A data definition: ; A blue is either ; - (make-small num num) ; - (make-medium num blue) (define-struct small (x y)) (define-struct medium (w z)) Provide enough examples to cover each case of data definition. - - - - - - - - - - - - - - - - - - - - - - - - - (make-small 12 89) (make-medium 87 (make-small 1 2)) - - - - - - - - - - - - - - - - - - - - - - - - - ---------------------------------------- Provide a Scheme template for the above data definition - - - - - - - - - - - - - - - - - - - - - - - - - (define (func-for-blue b) (cond [(small? b) .. (small-x b) .... (small-y b) ...] [(medium? b) ... (medium-w b) .... (func-for-blue (medium-z b)) ...])) - - - - - - - - - - - - - - - - - - - - - - - - - ---------------------------------------- Translate the preceding data definition to Java, and include template methods. You can omit class constructors. - - - - - - - - - - - - - - - - - - - - - - - - - abstract class Blue { abstract ... method(...); } class Small extends Blue { int x; int y; ... method(..) { this.x ... this.y ... } } class Medium extends Blue { int w; Blue z; ... method(...) { ... this.w ... this.z.method(...) ... } } - - - - - - - - - - - - - - - - - - - - - - - - - ---------------------------------------- Translate your Scheme examples to Java examples. - - - - - - - - - - - - - - - - - - - - - - - - - new Small(12, 89) new Medium(87, new Small(1, 2)) - - - - - - - - - - - - - - - - - - - - - - - - - ---------------------------------------- Suppose we add a new variant to blue: ; A blue is either ; ... ; - (make-large blue blue num) ... (define-struct large (p q r)) Explain breifly but completely how the Scheme template changes. - - - - - - - - - - - - - - - - - - - - - - - - - Add a condition whose question is (large? b) and add a recursive call for the firt two pieces (large-p b) and (large-q b), and also extract (large-r b) - - - - - - - - - - - - - - - - - - - - - - - - - ---------------------------------------- Here's a new data definition: ; A purple is either ; - num ; - (make-light purple) ; - (make-heavy purple purple) (define light (next)) (define heavy (left right)) Here's a broken function: ; purple-nums : purple -> list-of-num ; Returns a list of all numbers in p (define (purple-nums p) (cond [(light? p) (purple-nums (light-next p))] [else (cond [(number? (heavy-left p)) (cons (heavy-left p) (purple-nums (heavy-right p)))] [else (cons (purple-nums p) (purple-nums (heavy-right p)))])])) Because the implementation fails to follow the data definition in two essential ways, "purple-nums" doesn't work. - What are the two ways in which the function is broken? - - - - - - - - - - - - - - - - - - - - - - - - - - no num case at the top "cond" - no recursive call on (heavy-left p) in the last case - - - - - - - - - - - - - - - - - - - - - - - - - - Provide two example purples, one to expose each problem: - - - - - - - - - - - - - - - - - - - - - - - - - 7 (make-heavy (make-light 8) 10) - - - - - - - - - - - - - - - - - - - - - - - - - ---------------------------------------- The following Java code implements the same data structure and function: // Assume a NList class for lists of numbers: abstract class NList { ... abstract NList scaleNums(int factor); } class NEmpty extends NList { NEmpty() {} ... } class NCons extends NList { NCons(int first, NList rest) { ...} ... } abstract class Purple { // Sums all of the numbers in this purple abstract NList nums(); } class NumPurple extends Purple { int n; NumPurple(int n) { this.n = n; } NList nums() { return this.n; } } class LightPurple extends Purple { private Purple next; LightPurple(Purple next) { this.next = next; } NList nums() { return this.next.nums(); } } class HeavyPurple extends Purple { Purple left; Purple right; HeavyPurple(Purple left, Purple right) { this.left = left; this.right = right; } NList nums() { return new NCons(this.left.nums(), this.right.nums()); } } - The code has two contract violations (so that it will not execute at all). What are the two problems? - - - - - - - - - - - - - - - - - - - - - - - - - a. NumPurple's nums() returns a num instead of a NList b. HeavryPurple's nums() conses a NList instead of a num - - - - - - - - - - - - - - - - - - - - - - - - - - Suggest a way to fix the contract violations and also make the method meet its purpose. - - - - - - - - - - - - - - - - - - - - - - - - - a. new NCons(this.n, new NEmpty()) b. need append in NList: NList append(NList l); and use it: return this.left.nums().append(this.right.nums()); - - - - - - - - - - - - - - - - - - - - - - - - - ---------------------------------------- Extend the LightPurple class to implement ScaleLightPurple: - A ScaleLightPurple has a Purple (like all LightPurples) but also an integer that scales all of the ints in the next purple. - Clearly, the ScaleLightPurple class must override the nums() method. Note that the next field in LightPurple is private. - Include also a setScale() method in ScaleLightPurple for setting the scale of the purple. The setScale() method changes the purple, rather than producing a new purple (so it returns void). - - - - - - - - - - - - - - - - - - - - - - - - - class ScaleLightPurple extends LightPurple { int scale; ScaleLightPurple(Purple next, int scale) { super(next); this.scale = scale; } NList nums() { return super.nums().scale(this.scale); } void setScale(int s) { this.scale = s; } } - - - - - - - - - - - - - - - - - - - - - - - - - ---------------------------------------- Purple p1 = new ScaleLightPurple(new NumPurple(12), 2); ScaleLightPurple p2 = p1; p1.setScale(1); p2.setScale(3); p2.nums() The contracts don't match in this code. In what two places must a cast be inserted to make the contracts match? - - - - - - - - - - - - - - - - - - - - - - - - - In decl p2 = p1: p2 = (ScaleLightPurple)p1; In p1.setScale: ((ScaleLightPurple)p1).setScale(1); - - - - - - - - - - - - - - - - - - - - - - - - - What is the result of the last expression? - - - - - - - - - - - - - - - - - - - - - - - - - new Cons(36, new Empty()) - - - - - - - - - - - - - - - - - - - - - - - - - ---------------------------------------- Suppose that we drop ScaleLightPurple, but we add a Combiner interface declaration to the above program and a combine method as follows: interface Combiner { Object combine(int n, Object o); } abstract class Purple { ... abstract Object combineNums(Combiner c, Object base); } class NumPurple extends Purple { ... Object combine(Combiner c, Object base) { return c.combine(this.n, base); } } class LightPurple extends Purple { ... Object combine(Combiner c, Object base) { return this.next.combine(c, base); } } class HeavyPurple extends Purple { ... Object combine(Combiner c, Object base) { this.left.combine(c, this.right.combine(c, base)); } } Note that, given class Conser implements Combiner { Object combine(int n, Object l) { return new NCons(n, (NList)l); } } then for any Purple p, p.combine(new Conser(), new NEmpty()) is the same as p.nums() Define a class MaxFinder that implements Combiner for finding the maximum positive integer in a Purple (or 0 if the Purple contains no positive integers). Use class Integer { int i; Integer(int i) { this.i = i; } int intValue() { return this.i; } } and the result of p.combine(new MaxFinder(), new Integer(0)) should be an instance of Integer. - - - - - - - - - - - - - - - - - - - - - - - - - class MaxFinder implement Combiner { Object combine(int n, Object o) { if (n > ((Integer)o).intValue()) return new Integer(n); else return o; } } - - - - - - - - - - - - - - - - - - - - - - - - -