Exam 2: Midterm

Solutions and Commentary

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

Grade Distributions

Exam II

Mean = 3.77       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_X_X_X_X_X_X_X_X___X_____
   0 . 1 . 2 . 3 . 4 . 5 . 6 . 7 . 8 . 9 . 10

Exams I and II

Mean =   10.26          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_X_X_X_X_X_X_X_X_X_____
   0 . 2 . 4 . 6 . 8 . 10. 12. 14. 16. 18. 20

Machine Problems 1 to 4

                                        X
                                        X
                                      X X
                                      X X
                                      X X
Mean   = 14.65            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_X_
   0 . 2 . 4 . 6 . 8 . 10. 12. 14. 16. 18. 20

Homeworks 1 to 9

                                        X       X
                                        X       X X
Mean   = 17.29          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_X_X_X_X__
   0 . 2 . 4 . 6 . 8 . 10. 12. 14. 16. 18. 20. 22. 24. 26. 

Total Scores

                                          X
                                      X   X           X X
Mean   = 41.45                  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_X_X_X_X_X___
   0 . 4 . 8 . 12. 16. 20. 24. 28. 32. 36. 40. 44. 48. 52. 56. 60. 64
Grades?    |      D      |      C      |      B      |      A      |

Exam II Solutions and Commentary

  1. Background: The following pattern was proposed in the posted solution to Homework 7 for matching floating point numbers: \d+\.\d*|\.\d+

    Later, in the posted solution to MP4, we used this:

    Pattern numb = Pattern.compile( "[0-9]+\\.?[0-9]*|\\.[0-9]+|" );
    

    a) In the first pattern, we used \., but later, we used "\\.". Why? (0.5 points)

    ___Java String literals containing \ require it to be quoted as \\_____
    
    _______________________________________________________________________
    

    3/16 got this, 1/4 earned partial credit. The most popular wrong answer, given by 3/16, was that the problem had something to do with the difference between [0-9] on the one hand and \d on the other hand; these are exactly equivalent.

    b) In the first, we used \. while later, we used \\.?. The question mark suffix makes the previous pattern element optional. Give some example strings that the later pattern matches that the first does not. (0.5 points)

    ___1___123___12345___(integers without decimal points)_________________
    
    _______________________________________________________________________
    

    Over 1/2 got this, and there was very little partial credit. The most popular wrong answers, given by 3/16, were 0.5 and .5 (with varying numbers of various digits); both variants of the first pattern will match 0.5, but neither variant matches .5.

    c) The first pattern has just two alternatives. The second pattern has three. What is the third alternative and why does it matter in the nextFloat() method? (1 point)

    ___The empty string.  We need this in case there is no next float._____
    
    _______________________________________________________________________
    

    Amost 5/16 got this. 3/16 mentioned optional values without explicitly stating what the pattern matched, while another 1/8 understood that it matched the empty string but did not see why this was useful. Among those with outright wrong answers, most did not appear to understand that there were 3 alternative separated by vertical bars in the second pattern, but only two alternatives in the first pattern.

  2. Background: Consider this Java interface:
    interface A {
            void m1( int i );
            void m2( float j, float k );
    }
    

    A question: Can this interface be used as the basis of a lambda expression? Explain briefly? (1 point)

    ___No, because it has two methods and lambda can only define one.______
    
    _______________________________________________________________________
    

    almost 5/16 got this. A further 3/16 just said no, without giving a good reason.

  3. In the solution to MP4 posted on line, this awkward code was used: followed this pattern:
    Float delay = ScanSupport.nextFloat( sc );
    if (delay != delay) {
    

    A question: How is it possible that (delay != delay) could be true? (0.5 points)

    ___If delay is NaN because Java NaN's are never equal._________________
    

    Almost 1/4 gave correct answers. An equal number earned partial credit with answers that appeared intended to talk about NaNs but did not appear aware of the correct terminology. For less partial credit, 1/8 talked about the reason for the if statement, saying things like "if there is no next float" without addressing how the strange comparison result could possibly be true. Many who gave wrong answers suggested, preposterously, that the two mentions of delay might somehow refer to different variables or, even more preposterously, that one might refer to the value now and the other, somehow, to the value sometime in the past. Nothing in any programming language we have studied supports either of these hypotheses.

  4. Here is code for a key method of class StopLight in the road network simulator, minus comments:
    private void lightChangeEvent( float time ) {
            lightDir = lightDir + 1;
            if (lightDir >= incomingSize) lightDir = 0;
            if ((!waiting[lightDir].isEmpty()) && (!occupied)) {
                    Vehicle v = waiting[lightDir].remove();
                    Simulation.schedule(
                            time + traversalTime,
                            (float t)-> this.departureEvent( t, v )
                    );
            }
            Simulation.schedule(
                    time + greenTime + yellowTime,
                    (float t) -> lightChangeEvent( t )
            );
    }
    

    a) Every call to the lightChangeEvent() method in the entire program was done via a lambda expression identical to the one used above. lightChangeEvent() is not declared as static. What object is it operating on? (0.5 points)

    ___this___That is, this StopLight Intersection.________________________
    

    3/8 got this correct. For partial credit, almost 1/8 were vague about which intersection, saying things like "some intersection" or "some stoplight".

    b) There is an error in the above code! When the light changes and a vehicle is launched into the intersection, the intersection is not marked as occupied. Where should occupied=true be added to the code to correct this error? (0.5 points)

    ___Anywhere in the if statement, but at the end is easier to read._____
    

    Over 5/8 got this right. There was no partial credit. The most popular wrong answer was to add the code after the second if statement; a total of 3/16 suggested putting the code outside of any if statement, so it was not conditional on injecting a vehicle into the intersection. A surprising 1/16 wanted to insert the new code into one of the parameter lists for a call to schedule().

    c) Suppose we replaced the first lambda expression above with this, assuming that Java lets us do it:

    (float t) -> this.departureEvent( time + traversalTime, v )
    

    Would this change the behavior of the simulation? If so, how? (1 point)

    ___There would be no change____________________________________________
    
    _______________________________________________________________________
    

    Just over 1/4 got this right. There was very little partial credit. A surprising number of wrong answers asserted that time+traversalTime evaluated in the lambda expression would give a different result from evaluating it outside the lambda expression -- because of a difference in the value of time. Others asserted that failing to use the parameter t to the lambda expression would cause difficulty, despite the fact that declaring a variable or parameter and then not using it is fairly common.

    d) In fact, Java will not allow the above change because of a restriction on references to non-local variables within lambda expressions. What does it complain about? (0.5 points)

    ___traversalTime is not final__________________________________________
    
    _______________________________________________________________________
    

    Just over 1/4 got this. Among those earing partial credit, an almost equal number said that the problem was that traversalTime is not local (that doesn't matter, finality matters). About 1/10 said that the problem was with traversalTime without giving a clear indication of what was wrong with it. Among outright wrong answers, a surprising number said that the problem was with time, despite the fact that time and v have similar (but not identical) locality.

  5. Background: In the posted solution to Homework 8, code was given for minGate.inputChange(). This was modified in the posted solution to Machine Problem 4, where most of that code was moved into the parent class, Gate. Here is that code:
    protected abstract int logicValue();
    
    public void inputChangeEvent( float time, int oldv, int newv ) {
            inputCounts[oldv]--;
            inputCounts[newv]++;
            final int newOut = logicValue();
            if (output != newOut) {
                    final int old = output;
                    Simulation.schedule(
                            time + delay,
                            (float t) -> outputChangeEvent( t, old, newOut )
                    );
                    output = newOut;
            }
    };
    
    a) Would it make sense to mark any other declarations in this code as final? Which ones? (1 point)
    ___time, oldv and newv can all be declared to be final_________________
    

    Just under 1/16 gave the expected answer, and a similar number listed just time for partial credit. Another 1/16 earned partial credit for suggesting, correctly, that inputChangeEvent() could be final.

    Less credit was offered for the assertion that everything that must be declared final already is final. This is true, but misleading; the keyword final is not there just for dealing with error messages that say that something must be declared final, it is also there to explicitly state that something cannot be redefined.

    Partial credit was also given for those who suggested that inputCounts could be final. Yes, the binding of this array name to a specific array should not vary, but note, the problem asked about "declarations in this code", and inputCounts is declared elsewhere.

    Among wrong answers, the most popular, with just over 3/16, was to suggest that output should be final. First, it is not declared here (see above), and second, if you look at how the code works, you'd note that output changes every time the output of a gate changes -- so it cannot be final. The other popular answer, given by 3/16, was an undecorated no. A shocking 1/16 suggested that logicValue() could be declared to be an abstract final method.

    b) Where do actual implementations of logicValue() get declared? (1 point)

    ___In subclasses of gate_______________________________________________
    
    _______________________________________________________________________
    

    Over 1/4 got this. There was little partial credit. Among wrong answers, almost 1/4 said that it is implemented at the point of call, evidently confusing the fundamental concepts of implementation and evaluation.

    c) When the method outputChangeEvent() is called it takes three parameters. Where does it get the value of t from? (1 point)

    ___t comes to the lambda expression when an Action is triggered________
    
    ___by triggering an event in Simulation.run; that got its time_________
    
    ___when the event was scheduled._______________________________________
    

    Only 1/16 did well. There was lots of partial credit for subsets of this, but very little credit was given for the 1/8 who said simply time+delay; that oversimplifies a complicated process. 1/8 got no credit.

    d) When the method outputChangeEvent() It gets the value of old and newOut from the local variables of a call to inputChangeEvent(). What makes this difficult? (1 point)

    ___inputChangeEvent() returns long before outputChangeEvent() is called
    
    ___so it would seem that the local variables should be long gone.______
    
    _______________________________________________________________________
    

    1/20 got this. Partial credit was given for the few who said that old and newOut are "hard to access" by the time the call is made or that copies must be made without a metion of why. A bit less credit was given for the 1/16 who said that the values may change by the time of the call.

    Among wrong answers, a large number focused on Java's requirement that variables mentioned in lambda expressions be final or effectively final; all of the required variables in the code meet this requirement, but among students suggesting this, not one explained why this is required or hinted at what difficulties it posed; if anything, it was discussed as a gratutious requirement imposed by the compiler for the sole purpose of making life hard for the programmer.

    Many students wrote about normal problems you might have with any program, for example, that there are some references to non-local variables. Others found issues that had nothing to do with old and newOut.