Partial answer key for final exam in CS U370, fall 2003. These were the most difficult questions, plus the programming questions. Except where noted, the most popular answers were correct. 56 students took the test. The low score was 56, the median was 80, and the high was 94. The arithmetic mean was 77.8, and the sample deviation was 10.3. For each alternative answer to a multiple choice question, the percentage of students who chose that answer is shown in square brackets to the right of the answer. (These percentages may not add up to 100% because not all questions were answered, and because of rounding.) For other questions, the percentage of credit that was earned by students is shown in square brackets following the question. 3. In Java, which of the following evaluates to a reference value? ____ A. 2.5 * 50 [ 2%] ____ B. 18 != 19 [ 7%] ____ C. new int[12] [ 64%] ____ D. System.out.println() [ 4%] ____ E. "abc".equals("def") [ 23%] [Note: the correct answer to question 6 is B.] 6. With regard to reuse, Alan Perlis observed that ____ A. Smart data structures and dumb code work a lot better than the other way around. [ 45%] ____ B. It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures. [30%] ____ C. Programming languages are your enemies, but compilers are your friends. ____ D. When you have eliminated the impossible, whatever remains, however improbable, must be the truth. ____ E. There are two kinds of large software systems: those that evolved from small systems and those that don't work. [ 25%] [Note: the correct answer to question 10 is E.] 10. The instructor believes that any object-oriented programming language worthy of the name must include ____ A. static methods [ 5%] ____ B. contravariant subtyping [ 4%] ____ C. abstract classes [ 11%] ____ D. parametric polymorphism [ 39%] ____ E. automatic garbage collection [ 41%] 11. Java's current lack of support for parametric polymorphism ____ A. is one of the things that makes Java better than C++. [ 2%] ____ B. is a consequence of Java's single inheritance. [ 36%] ____ C. makes the Java Collections framework less useful. [ 46%] ____ D. is helpful when writing a stream tokenizer. [ 12%] ____ E. reduces the number of casts in Java programs. [ 4%] 13. Function objects are most likely to be used with ____ A. the Visitor pattern [ 45%] ____ B. the Factory pattern [ 18%] ____ C. the Singleton pattern [ 2%] ____ D. the Wrapper/Adapter pattern [ 23%] ____ E. the Iterator pattern [ 12%] The next two questions involve the following code, which is part of a solution to the last programming assignment in this course. public class WordCounter { // Given the name of a text file, prints its most common words. public static void listWords (String filename) { listWords (new StringIterator (filename)); } // Given text in a StringBuffer, prints its most common words. public static void listWords (StringBuffer sb) { listWords (new StringIterator (sb)); } // Given a StringIterator that generates words, // prints the words that are generated most frequently. private static void listWords (StringIterator sit) { ... } ... } 23. The structure of the above code, in which the two public methods call the same private method, is an example of ____ A. the Visitor pattern [ 4%] ____ B. the Factory pattern [ 30%] ____ C. software reuse [ 64%] ____ D. XML schema ____ E. the CRC model [ 2%] 26. [10 points] Write Java code for a reversePrint predicate that, given a StringIterator as in the last programming assignment, prints the generated strings in reverse order. For example, the first string generated by the iterator is to be printed last, and the last generated string is to be printed first. You may assume that all classes in java.util have been imported. [ 71%] // There are a zillion correct answers to this. (Literally;) // Here are two answers of the kind I was expecting. void reversePrint (StringIterator sit) { // Push the words onto a stack. Stack stk = new Stack(); while (sit.hasNext()) { stk.push (sit.next()); } // Print them in reverse order. while (! stk.empty()) { System.out.println (stk.pop()); } } void reversePrint (StringIterator sit) { // Accumulate the strings into a list. List strings = new ArrayList (); while (sit.hasNext()) { strings.add (sit.next()); } // Reverse the list. Collections.reverse (strings); // Print the list. for (Iterator it = strings.iterator(); it.hasNext(); ) { System.out.println (it.next()); } } // It is of course possible to do this without using a Collection, // but only one student did that successfully, using code like this. void reversePrint (StringIterator sit) { while (sit.hasNext()) { // Read the next string. String s = sit.next(); // Print the remaining strings. reversePrint (sit); // Then print this string. System.out.println (s); } } // Common mistakes included: // // Printing the strings in forward instead of reverse order. // Use of StringIterator methods that don't actually exist. // Use of Collection methods that don't actually exist. // Improper use of Collection methods. (In particular, none // of the students who attempted to use the previous() // method did so correctly.) // Storing the strings into an array of some fixed size. // Two-pass algorithms that use the StringIterator to compute // the size of an array, and then try to use the exhausted // StringIterator to generate the strings. // Thinking that a StringIterator can be cloned by assignments // of the form StringIterator sit2 = sit; 27. [10 points] Write Java code for an allDistinct predicate that, given a StringIterator as in the last programming assignment, returns true if all of the String values that are generated by the iterator are distinct (where two String values are considered distinct if they are not equal in the sense defined by the equals method), and returns false otherwise. You may assume that all classes in java.util have been imported. [ 73%] // See the instructor's comments on question 26. boolean allDistinct (StringIterator sit) { // Enter each word into a set. Set s = new HashSet(); while (sit.hasNext()) { // If it's already there, then we've found a duplicate. if (! s.add (sit.next())) return false; } // If we don't find any duplicates, then there aren't any. return true; }