Exam 3: Final

Solutions and Commentary

Part of the homework for CS:2820, Fall 2017
by Douglas W. Jones
THE UNIVERSITY OF IOWA Department of Computer Science

Grade Distributions

Exam 3

                X
Mean   = 8.65   X
Median = 7.7    X X
                X X       X
          X     X X   X   X
          X   X X X   X   X X
          X   X X X X X   X X X
        X X X X X X X X   X X X   X
        X X X X X X X X X X X X   X   X
 _______X_X_X_X_X_X_X_X_X_X_X_X___X_X_X_______
   0 . 2 . 4 . 6 . 8 . 10. 12. 14. 16. 18. 20

Total Exams 1-3

Mean   = 18.85        X
Median = 17.9         X       X
              X       X   X   X X   X           X
          X   X   X X X   X   X X   X X   X   X X
          X X X X X X X X X   X X   X X   X   X X X   X   X X
 _______X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X___X_X_X_X_X_X_X_X_X_X_X_____X_____
   4 . 6 . 8 . 10. 12. 14. 16. 18. 20. 22. 24. 26. 28. 30. 32. 34. 36. 38

Total Machine Problems 1-6

                                                    X
                                                    X     X
Mean   = 21.38                                      X   X X
Median = 22.9                                       X   X X
                                        X           X   X X
                                        X   X   X   X   X X X
                                X       X X X   X   X X X X X
                X           X X X   X X X X X X X   X X X X X X
 _________X_____X___X___X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_
   0 . 2 . 4 . 6 . 8 . 10. 12. 14. 16. 18. 20. 22. 24. 26. 28. 30

Total Highest 10 of Homeworks 1-12

                                          X
                                          X           X X
Mean   = 21.18                            X     X     X X
Median = 21.4                     X       X X X X X   X X
                                  X       X X X X X   X X X
                              X   X     X X X X X X   X X X
                              X X X   X X X X X X X X X X X X
 _____________X___X___X_______X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X___
   0 . 2 . 4 . 6 . 8 . 10. 12. 14. 16. 18. 20. 22. 24. 26. 28. 30

Total Scores

                                                                   X
Mean   = 61.41                             X                       X X
Median = 60.9                    X   X     X                       X X
                           X   X X X X   X X           X     X X   X X X
                     X     X X X X X X   X X   X X X X X X   X X X X X X
 __X_______X___X_____X_X___X_X_X_X_X_X_X_X_X___X_X_X_X_X_X_X_X_X_X_X_X_X_______X
  16. 20. 24. 28. 32. 36. 40. 44. 48. 52. 56. 60. 64. 68. 72. 76. 80. 84. 88. 92
        |-  -    D    +  +|-  -    C    +  +|-  -    B    +  +|-  -         +  +

Solutions and Commentary

  1. Background: Several recent homework assignments involved this code:
    public class Lazy {
        public static interface Int {
            int eval();
        }
        public static Int add( Int i, Int j ) { return ()->i.eval() + j.eval(); }
        public static Int term( int i ) { return ()->i; }
        ... and onward ...
    

    In the above context, consider this declaration:

        Int i = add( add( term( 1 ), term( 2 )), add( term( 3 ), term( 4 ) ) );
    

    Calling i.eval() returns a value of 10 by traversing a binary tree. In the following, we need names for the anonymous classes involved in this. Call the first class AddC, call the second TermC.

    a) What is the class of the tree's leaf nodes? (0.5 points)         __TermC____________________

    2/3 got this. 1/20 earned partial credit for Term instead of TermC. The most popular wrong answer was AddC. Only 1 or 2 gave other answers.

    b) What is the class of the tree's internal nodes? (0.5 points)   __AddC_____________________

    2/3 got this. 1/20 earned partial credit for Add instead of AddC. The most popular wrong answer was TermC. Only 1 or 2 gave other answers.

    c) What fields of the internal nodes hold the handles of (pointers to) their children in the tree? (1 point)

    __AddC.i and AddC.j, implicitly made copies of the parameters i and j__
    
    _______________________________________________________________________
    

    Nobody noted that these were copies of the parameters. 1/3 earned good partial credit for saying the parameters i and j. 1/7 had a larger penalty for mentioning i and j in some larger somewhat garbled context. 1/14 similarly mentioned unnamed parameters. The remainder earned no credit.

    d) Which method in this code is recursive? (Be careful, several methods in this code have the same name, do not give an ambiguous answer.) (0.5 points)

    __AddC.eval____________________________________________________________
    
    _______________________________________________________________________
    

    1/10 earned full credit. Another 1/10 earned partial credit for saying Int.eval, which is ambiguous because there are two implementations of the interface. The remainder earned no credit, mostly by saying that add was recursive.

    The argument that add is recursive is clearly wrong! The code of the add method consists of just one statement, a return statement, and that returns the value of a λ expression, the body of which is merely the definition of a method of the anonymous class we've named AddC for the sake of this discussion.

    e) Some of the classes discussed above can be thought of as part of a class hierarchy. What are the subclasses in this hierarchy? (0.5 points)

    __AddC and TermC_______________________________________________________
    

    1/2 got this right. 1/10 earned partial credit, typically by mentioning only one or the other class. Among the remainder who earned no credit, the most popular answers involved method names, not class names.

    f) What are they subclasses of? (0.5 points)                             __Int______________________

    Almost 1/3 got this. There was no partial credit. By far the majority of the remainder said Lazy.

    Giving the answer Lazy implies confusing the idea of a class hierarchy with the notion of inner classes and nesting.

  2. A quick question: If a field of an object is declared to be final, where can its value be assigned? (0.5 points)
    __In a constructor or in the definition itself_________________________
    

    1/7 got this. Almost 1/3 forgot to mention assignment as part of the declaration, while 1/7 forgot to mention constructors. A small amount of partial credit was given to the 1/10 who said "only once." The most popular wrong answers were "anywhere" and "in the same class."

  3. Background: Consider the statement i = i + 1; in the context of the the declaration Integer i, keeping in mind the intValue() method.

    a) Rewrite the statement eliminating the implicit conversion between built-in types and objects. (1 point)

    __i = new Integer( i.intValue() + 1 );_________________________________
    
    _______________________________________________________________________
    

    1/14 did well. 1/7 suffered a modest penalty for inventing i.setValue() to set an Integer to an int value, forgetting that Integers are immutable and don't have a setter method. An additional 2/7 earned half credit for forgetting to do any conversion from int to Integer. 1/10 were penalized for inventing a non-object-oriented Integer.intValue(i) instead of the object-oriented i.intValue() method that fits the standard pattern for getter methods in Java.

    4/10 earned no credit. Among these, two groups stood out, one, about 1/20, went wild with λ notation. An equal number tried to give a method definition, although there was no consensus on what method to define, and the problem clearly did not ask for one.

    b) What is this conversion called? (0.5 points)                         __autoboxing and unboxing_

    Over 1/3 gave good answers. There was no partial credit. Among those earning no credit, the two most popular were conversion (1/7), casting (1/10) and lazy increment (1/7). Other strange answers given by 1 or 2 each included polymorphism, recursion, encapsulation, and other words apparently drawn at random from the word cloud describing this course.

  4. Background: If i is a Java iterator, there are 3 basic operations: i.hasNext() tests to see if there is a next element in the sequence, i.next() gets the next element in sequence, and i.forEachRemaining(x) applies x to each remaining element of the sequence. The parameter x must implement a functional interface called Consumer, where x.accept(p) takes one element of the iterated sequence as the parameter p.

    a) Write the default code for forEachRemaining in terms of the methods documented above. The method body fits in 1 well formatted line of code. (1 point)

    void forEachRemaining( Consumer x ) {
    
        __while (this.hasNext()) x.accept( this.next() );__________________
    
        ___________________________________________________________________
    
        ___________________________________________________________________
    }
    

    1/7 got this. An additional 1/7 earned only a small penalty for replacing this with i in an otherwise good solution. Another 1/7 made this error and added other errors. Major errors that still earned partial credit included forgetting the while loop (1/7), a missing or completely nonsensical loop body (over 1/7). Simple syntax errors such as missing parentheses (1/10) also led to small deductions.

    Almost 2/7 earned no credit. Among these, 1/7 gave answers involving λ notation.

    This was not a memorizaiton problem where I expected anyone to have seen the implementation of forEachRemaining() in advance. I expected most students to have never noticed it in the documentation for class Iterator. The problem was designed to test the ability of students when faced with just enough documentation to invent how it works and how to use it.

    b) Rewrite for (Element i: myList) { otherList.AddFirst( i ); } using a while loop, as discussed in class. (1 point)

    __Iterator <Element> it = myList.iterator();___________________________
    
    __while (it.hasNext()) {_______________________________________________
    
    ______otherlist.AddFirst( it.next() );_________________________________
    
    __}____________________________________________________________________
    
    _______________________________________________________________________
    

    2/7 did well. 1/5 earned no credit. Among those earning partial credit, 1/5 tried to use myList as if it was an Iterator, or for a smaller penalty, 1/7 tried to use new Iterator(). 2/7 forgot parentheses for a minor penalty, and a few others had notation difficulties.

    A few students opted to try for an integer loop control variable. Of those earning partial credit for this, a significant fraction tried to write myList[i] instead of the object-oriented myList.get(i) that is normative Java.

    This was a "seconc chance" question, re-asking a question that had caused difficulty on exam 1. Students were warned in advance that such second chance questions would be offered for things that caused difficulty on one of the midterms.

    c) Rewrite for (Element i: myList) { otherList.AddFirst( i ); } using forEachRemaining instead of a while loop. This can be done in one long line if you write small, but it fits better in 3 lines. (1 point)

    __myList.iterator().forEachRemaining(__________________________________
    
    ______( Element i ) -> otherList.addFirst( i )_________________________
    
    __);___________________________________________________________________
    
    _______________________________________________________________________
    

    1/7 got this. Among those earning partial credit, almost 2/7 had difficulty constructing the iterator required, frequently trying to use new. 1/7 had difficulty with the λ expression, and as usual, about 1/10 had parentheses or other syntax problems.

    about 1/2 earned no credit. 1/7 used a for or a while loop instead of or in addition to a call to forEachRemaining(), but the remainder of the wrong answers were impossible to classify, frequently amounting to the Java equivalent of word salad.

    Like part a, this was intended to test the student's ability to grapple with a part of Java they'd never seen before after being given just enough information.

    d) Rewriting for (int i: myList) { sum = sum + i; } using the transformation from part c would lead the Java compiler to complain. What is the problem? (0.5 points)

    __Whatever sum is, it is definitely not final or effectively final_____
    
    _______________________________________________________________________
    

    About 2/7 got this. There was no partial credit. Among the wrong answers, many noticed things that were not related to applying the transformation from using a for loop iterating over a collection to using a call to forEachElement(). Questions about whether sum was properly declared or initialized remain the same before and after the transformation, as do questions about whether i should be boxed as in Integer instead of an int.

  5. Background: Which one or more of the following choices for string comparison would you use if ...
    1)   s == "this"
    2)   "this".equals(s)
    3)   s.equals("this")

    a) ... you want an exception thrown if s is null? (0.5 points)               __3__________________

    2/3 got this; among those earning partial credit, 1/10 also listed 1 and 1/10 also listed 2 (neither of which ever throw exceptions).

    b) ... you want the comparison to give false if s is null? (0.5 points)   __2___(also 1)_______

    Again about 2/3 got this. Among those earning partial credit, close to 2/10 just listed 1. Among those earning no credit, 3 was popular (it always throws an exception if s is null).

    c) ... you know that s is definitely not null? (0.5 points)                       __2 or 3___(also 1)__

    About 1/2 got this. Half the class failed to list 2, 2/7 failed to list 3, everyone got at least some credit because nobody left it blank.

    d) ... you care about the object's identity, not its value? (0.5 points)     __1__________________

    5/7 got this. 1/10 got partial credit for also adding either 2 or 3. Among the remainder, most listed either 2 or 3.

    All of the parts of this question were there to offer a second chance on a problem from the first midterm.

  6. Background: In MP5, the posted solution sometimes scheduled gate output-change events where those events caused no output change when they discovered that a later input change had cancelled the output change the event had been intended to cause. Instead of simulating events that do nothing, it would seem better to un-schedule any events when the simulator discovers that they will not be needed. In the logic simulator, this means that the gate-input-change event-service routine for gates would need to remember the most recent output-change event in order to be able to cancel it.

    Java's class PriorityQueue supports a method remove(o) that searches the queue for the object o and removes it from the queue.

    A copy of class Simulator from the posted solution to MP5 is attached at the end of this exam.

    a) The header to the schedule() method in the simulation framework must be changed to allow previously scheduled events to be un-scheduled. Give the new header for schedule (not the body). (0.5 points)

    __public static event schedule( ... )__________________________________
    

    1/14 got this. A few earned partial credit for eliminating void but not indicating the return class.

    Among those earning no credit, over 2/7 added an Event as a parameter, intending that the newly scheduled event replace this event. Unfortunately, they provided no way for the caller to learn the identity of an event. Also, 2/10 eliminated static for no obvious reason. Others added Gate or boolean parameters.

    b) You'd also have to add one line to the body of the schedule() method. Give that line and say where it goes. (0.5 points)

    __return e; // at the end______________________________________________
    

    1/14 got this. In many other cases, the proposed logic completely destroyed the character of class Simulator as a general purpose utility class that has no knowledge of the classes used in the simulation model.

    c) The declaration of class Event would also have to change. How? (0.5 points)

    __Make it public (or at least, not private)____________________________
    

    About 1/3 got this. It is a fairly obvious requirement if schedule() is going to return an Event or take one as a parameter.

    A few proposed making it non static, demonstrating that, for some students, the keyword static still remains a mystery.

    d) Write the code for the new unSchedule(Event e) in class Simulation. (1 point)

    __public static void unschedule( Event e ) {___________________________
    
    ______eventSet.remove( e );____________________________________________
    
    __}____________________________________________________________________
    
    _______________________________________________________________________
    
    _______________________________________________________________________
    

    About 2/7 got this. Among those earning partial credit, almost 2/10 forgot the keyword static, 1/10 forgot the return type void, and a few more made small errors. A very few earned half credit with code that included complex features that, miraculously, would not have prevented it from functioning.

    Among wrong answers, 2/10 made removal conditional on strange things, and 1/7 invented complex iterative or recursive algorithms to do the search that remove(o) already does.

  7. Background: You could run your Java program with the following shell command:
    java Logic testfile > thisfile 2> thatfile
    

    a) System.err.println( "x" ); outputs to what file? (0.5 points)     __thatfile_______

    5/7 got this right.

    b) System.out.println( "x" ); outputs to what file? (0.5 points)     __thisfile_______

    5/7 got this right. A few earned partial credit with answers such as outfile or standard output.

    This was a second-chance question covering material from midterm 1.

  8. Background: Here is a quotation from a makefile that was discussed in class
    html: classes $(JavaSourceFiles)
    	javadoc @classes
    

    a) What make command would use this? (0.5 points)     __make html____________________

    4/10 got this. There was little partial credit. Most of the wrong answers fit no broad patterns, but 1/10 gave either make classes or make javadoc.

    b) What shell command could it run? (0.5 points)           __javadoc @classes_____________

    about 1/6 got this, and a comparable number just gave javadoc (the shell command without its arguments) for partial credit. Again, most wrong answers fit no broad patterns, but about 1/14 gave either make html or make javadoc.

    c) What files does this make command tell you that the shell command depends on? (1 point)

    __classes plus all the files listed in the variable JavaSourceFiles____
    
    _______________________________________________________________________
    

    almost 1/4 got this. 3/7 got partial credit by saying "Java source files", many in a way that was ambiguous about whether it referred to the make variable or to all of the actual Java source files. In addition, 1/10 got partial credit for classes alone.

  9. Background: Suppose you began a Java class declaration with final abstract class.

    a) Java forbids this. Explain why, on a first reading, such a declaration seems pointless. (1 point)

    __i) final classes cannot have subclasses and__________________________
    
    __ii) abstract classes are primarily used as the basis for subclasses__
    

    3/7 got this. 1/10 earned half credit for listing only one or the other of the two clauses. A few more got partial credit for vague or confusing wording.

    b) If Java didn't forbid this, what fields of such a class could still be useful as parts of a larger program? (1 point)

    __static fields (and methods)__________________________________________
    
    _______________________________________________________________________
    

    1/7 got this. There was little partial credit. Among those earning no credit, the most popular answers were public fields, final fields and private fields.

  10. Background: Consider a simulation program containing the following line of code that depends on the attached version of class Simulation:
    Simulator.schedule( someTime, (float t)->anObject.someMethod( t ) );
    

    Under some circumstances, we can rewrite this as a direct call to

    anObject.someMethod( someTime );
    

    a) This rewrite is only possible for some values of someTime. Which values? (0.5 points)

    __someTime must be now, not a future time______________________________
    
    __(at the very minimum, it must be before any other event)_____________
    

    Over 2/7 got this, and only 1 earned partial credit.

    b) If anObject.someMethod( someTime ) has side effects, the rewrite might still be possible if what holds for those side effects ... (0.5 points)

    __... do not change variables used by later code in the current event__
    
    _______________________________________________________________________
    

    Only a few got this and a few more got partial credit. Wrong answers were very difficult to classify.

    c) If the call to schedule was not the last line of a simulation event service method this rewrite might still be possible if those later lines ... (0.5 points)

    __... do not change any variables on which someMethod() depends________
    
    _______________________________________________________________________
    

    1/14 got this, and there was no partial credit.

 


What follows was attached as a last page. Students were instructed to tear it off for use as scratch paper and reference material.


/** Framework for discrete event simulation
 */
class Simulator {

    /** interface used to allow lambda expressions passed to schedule method
     *  This is a functional interface.
     *  Typically, it will be used from lambda expressions passed to the
     *  schedule method.
     */
    public interface Action {
        /** trigger the action
	 *  @param time gives the time at which the action is triggered
	 */
	void trigger( float time );
    }

    private static class Event {
	public float time;	// time of the event
	public Action act;	// the action to perform
    }

    private static PriorityQueue <Event> eventSet
	= new PriorityQueue <Event> (
	    (Event e1, Event e2) -> Float.compare( e1.time, e2.time )
	);

    /** schedule one new event
     *  @param time when an event will occur
     *  @param act the action that will be triggered at that time
     *  Typically, this is called as follows:
     *  <pre>
     *  Simulator.schedule( someTime, (float time)->aMethodCall( time ... ) );
     *  </pre>
     */
    public static void schedule( float time, Action act ) {
	Event e = new Event();
	e.time = time;
	e.act = act;
	eventSet.add( e );
    }

    /** main loop that runs the simulation
     *  This must be called after all initial events are scheduled.
     */
    public static void run() {
	while (!eventSet.isEmpty()) {
	    Event e = eventSet.remove();
	    e.act.trigger( e.time );
	}
    }
}