Exam 3: Final

Comments and Solutions

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

Grade Distributions

Several students did almost no work during the semester except for taking the exams. Two students did not even take the final and are not included in any of the following statistics. Since exams cannot reasonably test many of the subjects this course teaches, most notably, the ability to write large programs, the score distribution for this course was worked twice. This is reflected in the following histograms and statistical measures.

In the histograms, X marks are used for students who turned in at least 6 of the 12 homework assignments and at least 4 of the 6 machine problems. M marks indicate students who did not meet this standard.

The first score given for each statistical measure is the score including all registered students who took the final exam. Following this, in parentheses, is the score excluding those marked M in the histograms.

Exam III

Mean   = 9.59 (10.01)
Median = 9.5  (9.8)

                  M     X
                  X     X
              M   X     X
            M M   X     X
            X X M X   X X   X
            X X X X   X X   X
            X X X X   X X   X       X
          M 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 I to III

Mean   = 19.51 (20.13)
Median = 18.1  (18.5)
                            X
                X           X
              M X X       M X
              X X X M X X X X     X         X X               X
        M M   X X X X X X X X X X X     X X X X X             X
 _______X_X_M_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X___X___X___X___
   6 . 8 . 10. 12. 14. 16. 18. 20. 22. 24. 26. 28. 30. 32. 34. 36

Machine Problems 1-6

                                                X
                                                X
                                                X     X
Mean   = 20.38 (21.70)                          X     X
Median = 22.1  (22.6)                           X     X
                                        X   X   X X   X X X
                                        X   X   X X   X X X X
              M   X     M   X M     X   X X X   X X X X X X X X
 ___________M_M___X_M___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

Homeworks 1-12 (top 10 of 12)

                                                    X
                                                    X
Mean   = 22.59 (23.50)                      M X     X X
Median = 23.8  (24.3)                       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
                      M         M   M     X X X X X X X X X X
 _____________________M_M_____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 and Grade Distribution

Mean   = 62.48 (65.33)          X           X X
Median = 62.3  (64.7)         X X   X       X X                 X
                              X X   X     X X X X             X X
                M     M X     X X X X X X X X X X           X X X
 _______M_M_M___M_____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_____
   24. 28. 32. 36. 40. 44. 48. 52. 56. 60. 64. 68. 72. 76. 80. 84. 88. 92. 96
          F      |- -   D   + +|- -   C   + +|- -   B   + +|- -   A   + +|

Exam Solutions

  1. Background: Consider this code from a variation on class Simulator from MP5:
    public interface Action {
        void trigger( float time );
    }
    
    private static class Event {
        public final float time;
        public final Action act;
        public Event( float t, Action a ) {
            time = t;
            act = a;
        }
    }
    
    static void schedule( float time, Action act ) {
        eventSet.add( new Event( time, act ) );
    }
    

    a) The fields of the private inner class Event are public. Where are these fields visible? (1 point)

    ____Everywhere in class Simulator______________________________________
    
    _______________________________________________________________________
    

    About 1/5 got this and 1/5 earned no credit. The most common answer earning partial credit was "throughout class event".

    b) In the context of the above code, can a programmer legally write new Event() (without parameters) elsewhere in class Simulator? Why or why not? (1 point)

    ____No, there is no implicit constructor if an explicit one is given___
    
    ____Also, implicit constructors don't work for final fields____________
    

    Almost 1/2 got this, while 1/5 earned no credit. The most common answers earning partial credit focused their explanations on the static and private attributes (these are irrelevant). The most common wrong answer asserted that the initializer Event() is always avaialble because it is implicitly declared.

    c) To what class does the second argument of the following call belong?
      Simulator.schedule( 0.0f, (float t) -> printHeaders() );
    (1 point)

    ____An anonymous subclass of Action____________________________________
    
    _______________________________________________________________________
    

    Almost 1/4 got this. As many earned no credit. The most common errors earning partial credit were to assert that the argument was of class Action (not a subclass), or that it was an anonymous subclass of something else. Wrong answers were evenly divided between classes Event, Simulator, SimulationOutput and λ-expression.

  2. Background: Consider this code, an abridged version of part of class SimulationOutput from the posted solution to MP5:
    static void setOutput( Scanner sc ) {
        interval = ScanSupport.nextFloat( sc, ()->"interval error" );
        timeRemaining = ScanSupport.nextFloat( sc, ()->"duration error" );
        Simulator.schedule( 0.0f, (float t) -> printHeaders() );    /*a*/
        Simulator.schedule( interval, (float t) -> printState(t) ); /*b*/
    }
    static void printHeaders() {
        for( Neuron neu: NeuronNetwork.neurons) {
            int t = (5 <= neu.name.length()) ? 5 : neu.name.length();
            String n = neu.name.substring( 0, t );
            System.out.append( n );
            System.out.append( "      ".substring( 0, 6 - n.length()) );
        }
        System.out.println();
    }
    

    a) Why does setOutput schedule printHeaders instead of calling it directly from setOutput? (1 point)

    ____This defers it until the neuron network is fully built_____________
    
    _______________________________________________________________________
    
    _______________________________________________________________________
    

    Almost 1/3 got this, just over 1/3 earned no credit. The most common answer earning partial credit involved questions of the simulated time at which the headers are printed when all that really matters is that the headers are printed after all neuron names are known and before any simulation output.

    b) In the code above, the value t in this λ expression (float t)->printHeaders() is never used. Why can't we use ()->printHeaders() instead? (1 point)

    ____The action trigger interface requires a parameter__________________
    
    _______________________________________________________________________
    
    _______________________________________________________________________
    

    Almost 1/2 got this, and as many earned no credit. The most common answer earning partial credit involved arguments about the need for a parameter in the simulation class. This names the wrong class but seems to focus on the right issue!

    c) Suppose that we delete the line of code marked /*a*/ and add this line to class SimulationOutput:
       static boolean needHeader=true;
    Give the code needed to call printHeaders from within printState so that the behavior of the complete program is unchanged. (1 point)

    ____if (needHeader) { // goes at the start of printState_______________
    
    ________Simulator.schedule( 0.0f, (float t) -> printHeaders() );____
    
    ________needHeader = false;____________________________________________
    
    ____}__________________________________________________________________
    

    Almost 2/5 got this. 1/4 earned no credit. The errors made by those earning partial credit were to use a λ expression to call printHeaders() (this is not a harmless error, it breaks the code!), and forgetting to reset needHeader.

    d) Instead of the change in part c), suppose we move the line of code marked /*b*/ into the body of printHeaders (but outside the for loop). How would this change the behavior of the program? (1 point)

    ____There would be no change___________________________________________
    
    _______________________________________________________________________
    

    Almost 2/5 got this, the remainder earned no credit, offering a wide variety of proposed and often dire consequences of making this change.

  3. Background: Consider this code from a variation on class Simulator from MP5:
    private static final PriorityQueue <Event> eventSet
    = new PriorityQueue <Event> (
        (Event e1, Event e2) -> Float.compare( e1.time, e2.time )
    );
    

    a) eventSet is declared final. What does this prevent? (1 point)

    ____It prevents assigning a different priority queue to it_____________
    
    _______________________________________________________________________
    
    _______________________________________________________________________
    

    Almost 1/6 got this, and an equal number gave ambiguous answers that earned partial credit. Of the remainder who earned no credit, the majority made it very clear that they thought that the queue or even the items in the queue became immutable as a result.

    b) When is the λ expression that is passed here evaluated? (1 point)

    ____Every time two events are compared to determine their order________
    
    _______________________________________________________________________
    
    _______________________________________________________________________
    

    1/12 gave good answers, while 2/5 earned no credit. The majority of the partial credit went to those who asserted that the comparisons were done when items were inserted in the queue -- the truth is, you can build priority queues that do all the comparisons at dequeue time, and the Java class uses a heap algorithm that does comparisons on both enqueue and dequeue. The most popular wrong answer involved doing the comparisons when the queue is created.

  4. Background: The Java standard library makes extensive use of generics, for example, in class PriorityQueue. There is an alternative commonly used in the C++ library; in Java terms, class PriorityQueue has a public inner class Queueable with a public field, a float called key. The queue holds objects of class Queueable, ordered by the values of the key field; typically, users use subclasses of Queueable for the objects they enqueue.

    a) Give an appropriate declaration for eventSet using this alternative implementation of class PriorityQueue. (1 point)

    ___________PriorityQueue eventSet = new PriorityQueue();_______________
    
    _______________________________________________________________________
    

    1/30 gave good answers, while 1/10 earned partial credit. Among the latter, the common error was to make the priority queue generic on class Event, while the whole point of the question was to present an alternative to the use of generics. Note that attributes such as public, final or static were ignored in grading this question.

    b) In the spirit of the code given with problem 1, give an appropriate declaration for class Event for use with this alternative priority queue. (3 points)

    ____class Event extends PriorityQueue.queueable {______________________
    
    ________Action act;____________________________________________________
    
    ________Event( float t, Action a ) {___________________________________
    
    ____________key = t; // super( t ) was also accepted here______________
    
    ____________act = a;___________________________________________________
    
    ________}______________________________________________________________
    
    ____}__________________________________________________________________
    
    _______________________________________________________________________
    
    _______________________________________________________________________
    
    _______________________________________________________________________
    

    1/5 got this. About as many earned no credit. Among those earning partial credit, omitting the extends queueable was bar far the most common error. Including an explicit key field in class event was half as common, and many added an explicit time field in addition to key without noting that this was redundant. Forgetting to initialize key was also common, as was adding a field containing a Queueable.

  5. Background: Java allows variables to be declared with various combinations of the keywords protected, final and private.

    a) One of the above keywords is in a different category from the others. Which? (1 point)

    ____final (the others have to do with field visibility)________________
    

    Almost 2/3 got this. There was no partial credit.

    b) Given a working Java program, if you deleted all instances of the above three keywords, what is the worst case effort you would have to make in order to repair the program so it still worked. (1 point)

    ____Because private and protected fields become visible, some _________
    
    ____variables may need to be renamed___________________________________
    
    _______________________________________________________________________
    

    1/5 got this, 1/3 earned no credit. Partial credit went to those who were certain it would work with no changes, or who suggested it would still work but we might have to make unneeded checks for finality or inappropriate access. Among those earning no credit, many suggested the need to add elaborate code to enforce finality or visibility rules, not understanding that every variable that was declared final will be effectively final in the new version, and if a variable was not visible in some context, we know that the existing code does not reference it (except where there are name conflicts).

  6. Background: The posted solution to MP6 contains a fleshed out version of this code from class SimulationOutput:
    static void printState( float time ) {
    
        // code to print the neuron states goes here
    
        Simulator.schedule(
            new Simulator.Event( time + interval ) {
                void trigger() { printState( time ); }
            }
        );
    }
    

    a) To what class does the object created by new above belong? (1 point)

    ____an anonymous subclass of Simulator.event___________________________
    

    1/5 got this. About 2/5 earned partial credit, forgetting to say it was an anonymous subclass. Among those earning no credit, the vast majority said it was in class Simulator.

    b) In the expression time+interval above, where is time declared? (1 point)

    ____in the parameter list of PrintState________________________________
    

    Almost 2/3 got this, while almost 1/3 earned no credit. Among those earning no credit, many gave the context of use of time, that is, as a parameter to the initializer Simulation.event instead of the point of declaration.

    c) In the expression printState(time) above, where is time declared? (1 point)

    ____as a field of class Simulator.Event________________________________
    

    1/4 got this while 2/5 earned no credit. Among those earning partial credit, most said that it was declared in the constructor for class Simulator.Event; this seems to involve confusing declaration with initialization. Among those earning no credit, many gave the context of use of time, that is, as a parameter to the printState method instead of the point of declaration.

    d) Explain how the concept of a simulation process applies here. (1 point)

    ____each time printState is called, it schedules a future______________
    
    ____call to printState_________________________________________________
    

    About 1/4 got this. Almost 1/2 earned no credit. Among those earning no credit, the most common error was to confuse the process of discrete event simulation with the idea of a process as a sequence of events each of which causes the next.

    e) Suppose Java didn't have the keyword static or any of its associated behavior. Could we still make the simulator produce output? How? (Do not write code. Answers that do not fit in the space provided will be ingored.) (1 point)

    ____Yes, we could create an instance of class SimulationOutput_________
    
    ____and then reference what were static fields relative to this________
    
    ____instance___________________________________________________________
    

    About 1/5 got this, almost as many earned no credit. Partial credit was given for just saying yes, with something wrong to explain how. Some were penalized for suggesting creating new instances each time a field was needed. Among the serious problems some students had was confusing the static and private attributes. These are totally unrelated in their effect.