CS365 Final Solutions -- Spring 2015


The correct answers are highlighted by bold-facing them.

  1. (5 points) This question refers to the MVC model. For each of following task descriptions, indicate the class that should implement that task (if the answer is "Model class" put the lette A next to the task description):
    1. Model class
    2. Observer (Listener/View) interface
    3. View class
    4. Controller class
    5. Glue class

    1. D Provides event handling

    2. E Sets up the application and establish connections between all the application's components.

    3. B Specifies the API that the model should use for notifying the views of changes to the model

    4. C Pictorially presents the application's state information to the user

    5. A Stores the application's state information

  2. Why is it important to override the getPreferredSize method in a custom painted panel or component?

    1. The default preferred size method does not erase the previous image in the panel/component and hence you will get ghosting. Thus you need to override the getPreferredSize method and explicitly erase the previous image.
    2. The default preferred size of a panel or component is very small and hence will cause the panel/component to be drawn smaller than one expects. Thus you need to override the getPreferredSize method and provide the actual size at which you want the panel/component drawn.
    3. The default preferred size method sets the layout to be a border layout, which is incompatible with the layout manager needed for custom painting. Hence you need to override the getPreferredSize method to provide an appropriate layout manager for custom painting.
    4. The default preferred size method specifies that the panel/component will be as large as the screen and hence the panel/component will cover more screen real estate than one expects. Thus you need to override the getPreferredSize method and provide the actual size at which you want the panel/component drawn.

  3. What is the purpose of a Java event adapter class, such as the MouseAdapter class?

    1. To provide a mechanism for mapping events from unrecognized devices, such as a pen, to events recognized by the OS, such as a mouse click event.
    2. To allow code written in the Java Swing toolkit to be retrofitted on top of code written in the Java AWT toolkit.
    3. To convert primitive events, such as mouse and keyboard events, that are too low-level for application event handlers to manage, to application-level events, such as action and change events, that are at the appropriate level for application event handlers to manage.
    4. To provide a default set of implementations for the methods required by the event's listener interface.

  4. What is the correct way to write a loop in Python that computes the sum of the numbers from 1 to 10?

    1. sum = 0
      for i from 1 to 10:
          sum = sum + i
      
      
    2. sum = 0
      for (i = 1; i <= 10; i++):
          sum = sum + i
      
    3. sum = 0
      for i in range(1, 11):
          sum = sum + i
      
    4. sum = 0
      for i = 1 to 10 by 1:
          sum = sum + i
      
  5. Suppose I want to write a loop to determine if the value in the variable target is in the list L. If target is in L, then I want to set the variable x to target's index location in L. If target is not in L, then I want to append target to L and set x to target's index location in L. Which of the following fragments of code most elegantly accomplishes this task? By elegant I mean uses features of Python designed for this task.

    1. for i, v in enumerate(L):
        if v == target:
            x = i
            break
      else:
        L.append(target)
        x = i+1
      
    2. for i, v in enumerate(L):
          if v == target:
              x = i
              break
      if i > len(L):
          L.append(target)
          x = i
      
    3. i = 0
      for v in L:
          if v == target:
              break
          else:
              i = i + 1
      if i > len(L):
          L.append(target)
      x = i
      
    4. i = 0
      for v in L while v != target:
          i = i + 1
      break: x = i
      else:
          L.append(target)
          x = i + 1
      

  6. (8 points) Which of the following features typically distinguish scripting languages from traditional, compiled languages such as C or C++?

    1. built-in language syntax for data types for lists and hash tables
    2. strong access protections for object-oriented programming
    3. interpreted execution
    4. support for high-level string manipulation, including pattern-matching constructs
    5. efficient execution of programs
    6. concise, compact syntax that allows programmers to quickly write small but powerful programs
    7. declaration of typed variables and static type checking of statements that use these variables
    8. Use of pointers to simplify the implementation of linked structures

  7. Suppose I want to compute a list that contains the pairwise smallest elements from two lists a and b. For example, if a is [5, 10, 15, 20, 25] and b is [3, 12, 10, 100, 30] then the result list should be [3, 10, 10, 20, 25]. What is the most elegant way to write this operation in a recent version of Python, such as 2.7. By elegant I mean the most compact way to write the computation.
    1. c = []
      for v1, v2 in zip(a, b):
          if v1 < v2:
              c.append(v1)
          else:
              c.append(v2)
      
    2. c = reduce(lambda x,y: x if x < y else y, a, b)
    3. c = map(lambda x,y: x if x < y else y, a, b)
    4. c = filter(lambda x,y: x if x < y else y, a, b)

  8. (4 points) Suppose I have tuples of the form (firstname, lastname, age) and I wish to sort the tuples into ascending order by lastname, then firstname, and lastly age. Which of the following expression will successfully return a sorted list of such tuples? Check all correct expressions and assume any necessary functions have been imported from the proper modules.
    1. sorted(a, key=itemgetter(1,0,2))
    2. sorted(a, key=attrgetter(1,0,2))
    3. sorted(a, key = lambda t: (t[1], t[0], t[2]))
    4. sorted(a, key = (1, 0, 2))
    5. sorted(a, key = lambda t: (t[1], t[0], t[2]), reverse=True)
    6. sorted(a, key=(a[1], a[0], a[2]))

  9. (5 points) In which of the following ways does a Python class differ from a C++ class?
    1. A Python class is an object whose structure/values you can modify at run-time, whereas a C++ class is not a modifiable run-time object.
    2. Python classes may have multiple base classes whereas a C++ class may have only a single base class.
    3. Python classes may have only one constructor whereas a C++ class may have multiple constructors.
    4. A Python class may have attributes dynamically added to or deleted from it whereas the set of instance variables in a C++ class is fixed (i.e., you may change their values but you cannot add a new instance variable or delete an instance variable at runtime).
    5. Python methods are non-virtual by default whereas C++ methods are virtual by default
    6. Python classes have no enforceable access protection (i.e., everything is public).
    7. Python methods must explicitly declare a pointer to their object (e.g. one named self) whereas in C++ the pointer is automatically declared with the name "this"
    8. Python classes are introduced with the keyword 'module' rather than 'class'

  10. In a functional programming language, applicative evaluation order means that:
    1. arguments to functions are lazily evaluated using function caching
    2. arguments to functions are all evaluated before the function itself is called
    3. arguments are passed unevaluated to a function and evaluated only when their value is needed by an expression
    4. arguments are evaluated in right-to-left order rather than left-to-right order

  11. Consider the following function definition:
    (define sumList (lambda (L)
        (letrec ((sumListHelper (lambda (L sumThusFar)
            (cond
                ((null? L) sumThusFar)
                (#t (sumListHelper (cdr L) (+ (car L) sumThusFar)))))))
          (sumListHelper L 0))))
    
    Which function construction technique has been used to create this function?
    1. tail recursion
    2. inductive construction
    3. head recursion
    4. deductive construction

  12. (6 points) Which of the following features distinguish functional programming from imperative programming?
    1. Iteration
    2. First class functions that can be computed and assigned as values
    3. Implicit, parametric polymorphism
    4. Mutable state
    5. Garbage collection
    6. Powerful list-handling facilities
    7. Fully general aggregate structures that permit nested initialization
    8. Side effects
    9. Static scoping
    10. Structured function returns that allow any type of aggregate, including functions, to be returned from a function
  13. Why is it so efficient to write functions using tail recursion?
    1. It allows the compiler to simplify the recursion so that the function only uses the base cases and hence avoids using multiple function calls
    2. It allows the compiler to re-use the stack frame for the function and hence avoid multiple function calls
    3. It allows the compiler to unroll the function into a linear sequence of in-line statements, thus eliminating multiple function calls.
    4. It allows the compiler to convert the function to an iteration over lists and thus eliminate multiple function calls

  14. (6 points) In Java which of the following synchronization techniques can be used to prevent race conditions (as opposed to enforcing happens before relationships)?
    1. join
    2. volatile variables
    3. atomic variables
    4. wait
    5. synchronized methods
    6. synchronized statements
    7. fork
    8. sleep

  15. The following Java and C keyword forces any changes made to a variable to be immediately forced to memory, as opposed to being cached in a register:

    1. force
    2. volatile
    3. atomic
    4. synchronize

  16. In Java how can a client program detect when the server has shutdown or crashed?
    1. The client socket's isConnected method returns false
    2. The client socket's isClosed method returns false
    3. The client socket's input stream returns a null value
    4. The client socket's output stream throws an I/O exception

  17. The following term refers to a situation in which two threads cannot make progress because they are each waiting on the other to release a lock.
    1. deadlock
    2. livelock
    3. starvation
    4. jamming

  18. (4 points) What are two advantages that Java's mutex locks have over the object locks used by synchronized methods and synchronized statements?

    1. They allow finer grained synchronization by allowing an object to contain two or more locks.
    2. They are reentrant, thus allowing a thread to call other methods which also require the lock
    3. They allow threads to back out of acquiring locks that are currently held by other threads, thus helping avoid deadlock
    4. They provide an option that allows a lock to be given to the longest waiting thread, thus avoiding starvation.

  19. What is the advantage of a synchronized Collection class?
    1. It provides a fail-fast action if two threads attempt a concurrent modification on the object
    2. It provide a guarantee of atomicity for various types of non-primitive operations, such as insert, delete, and get operations on an object (i.e., another thread cannot access/modify the object until the operation finishes).
    3. It provides a local copy of the object to each thread and then synchronizes updates to all local copies so that each thread has a memory consistent view of the object
    4. It distributes the execution of the object's methods across multiple threads, thus allowing parallel accesses.

  20. (6 points--Model-View-Controller (MVC) model) Behold the following Java pseudo-code for displaying and updating a slider. The color swatch in the middle (the black rectangle) can be updated by either moving one of the three sliders in the left panel or selecting one of the color chips in the right panel.

    class rgbSliders extends JPanel {
        rgbSliders() {
            create 3 sliders for red, green, and blue
            create an event listener for each of the three sliders that performs
                 the following actions
                 -- inform ColorModel that the slider's value has changed (i.e.,
                      call changeBlue, changeRed, or changeGreen)
                 -- repaint the rgbSliders panel
        }
        notifyChange(newColor) {
            update the three sliders to reflect the new color
            repaint the rgbSliders panel
        }
    }
    
    class ColorChips extends JPanel {
        ColorChips() {
            create color chips for several different colors
            create an event listener that performs the following actions
               when one of the color chips is selected
                 --notify the model about the color of the selected color chip
                    (i.e., call changeColor)
                 --deselect the previous color chip, if necessary
                 --call the repaint method on the color chip panel
        }
        notifyChange(newColor) {
            --select the color chip that represents the new color
            --deselect the previous color chip, if necessary
            --repaint the view
        }
    class ColorModel extends JPanel {
        Color currentColor = Color.RED
    
        ColorModel() {
            create and draw a color swatch rectangle that displays the currentColor
        }
    
        changeColor(newColor) {
            currentColor = newColor
            redraw the color swatch rectangle so that it displays the new color
            call rgbSliders' notifyChange method
        }
    
        changeBlue(newBlue) {
            change currentColor so that it reflects the newBlue value
            redraw the color swatch rectangle so that it displays the new color
            call ColorChips notifyChange method
        }
    
        changeRed(newRed) { // do same thing as changeBlue except for Red }
        changeGreen(newGreen) { // do same thing as changeBlue except for Green }
    }
    
    class Glue { 
            Glue() {
            create a JFrame object using BorderLayout
            create an instance of ColorModel and add this instance to the JFrame
                 in the appropriate region
            create an instance of rgbSliders, passing it a pointer to ColorModel,
                 and add this instance to the JFrame in the appropriate region
            create an instance of ColorChips, passing it a pointer to ColorModel,
                 and add this instance to the JFrame in the appropriate region
            pack the JFrame and display it
        }
    
        static public void Main(String args[]) {
            new Glue();
        }
    }
    
    This pseudo-code abstracts away a great many details about creating the appropriate widgets, laying them out, and repainting them, so please do not worry about the details. From a broader perspective, the design of this class violates the MVC model in multiple ways. From the following list, select all the ways in which this design violates the MVC model as it is typically implemented in practice (hint--there are three correct answers):

    1. The model is responsible for drawing some of the graphics rather than delegating that responsibility to the views
    2. The names of the views are hard-coded in the model rather than notifying views of changes through a pre-determined API
    3. The event listeners (i.e., controllers) should be placed in separate classes from their views
    4. The views are aware of other views
    5. The event listener (i.e., controller) for the ColorChips view changes some of its graphics pre-maturely rather than waiting for the model to accept the changed color and handling the change to the graphics in its notifyChange method
    6. The rgbSlider and ColorChips views maintain model information rather than letting the model store the information and retrieving it as needed
    7. The Glue class is not correctly implemented in the sense that if it is executed as shown, then the interface shown in the figure will not get displayed properly

    Here is an explanation of why each answer is either correct or incorrect:

    1. The model is drawing the color swatch, but in the MVC model, the views draw the graphics, not the model. Hence the model violates the MVC model.

    2. The model specifically calls the rgbSliders and colorChips NotifyChange methods rather than iterating through a list of views and calling their NotifyChange methods. This hardcoding means that as additional views are added to the interface, the model will have to be modified to accommodate these additional views. If the model had been properly set up so that views registered with it and it iterated through a list of views to notify them of changes, then when another view is added to the application, the model would not have to be modified.

    3. The problem asked about how the MVC model is implemented in practice and in practice the controllers are bundled with their views and therefore it is not problematic that the controllers were bundled with their views in this problem.

    4. The views are not aware of each other (i.e., there are no hard coded reference to other views in any of the view classes).

    5. A controller should not modify any unnecessary graphics and should instead allow the change methods make necessary changes to the graphics. However, the ColorChips controller is trying to unselect a color chip, which should not happen if the model decides to reject the change.

    6. The view classes don't have any instance variables that are storing model information. It is true that the change methods set values in the sliders or color chips, but that is required to get them to display properly. Overall, the view classes are not storing unnecessary model information.

    7. If the Glue class is executed as shown, the interface will appear correctly because the model class will draw the color swatch (the model should not be doing so, but that does not change the fact that the interface will appear correctly).

  21. (10 points--Python) Write a Python function named topSalaries that given a list of people's names, returns a sorted list in ascending order of the top n salaries among the people. The function takes three parameters--a dictionary of people where the key is the person's name and the value is their salary, a list of the people's names in which we are interested, and the number n of salaries to return. For example, if there are 20 people on the list and n is 5, then your function should find the top 5 earners among these 20 people and return a list of their salaries in sorted, ascending order. For example, [30000, 40000, 50000, 100000, 150000]. You may assume that every person on the list is in the dictionary. You may not assume that every person in the dictionary is on the list. For example, the dictionary might contain the names of all of a company's employees and the names on the list might be the names of the company's executives.
    def topSalaries(salaryDict, people, numSalaries):
      salaries = []
      for p in people:
        salaries.append(salaryDict[p])
      salaries.sort()
      return salaries[-numSalaries:]
    
    There were a number of common problems with this problem:
    1. Iterating through the entire dictionary, which might have thousands of entries, rather than through the person list, which might only have a handful of entries
    2. Trying to sort a dictionary--horribly inefficient and the sort method returns a list of keys, not a list of key/value pairs as most of you assumed. Also many of you did not use a legitimate key function when trying to sort a dictionary.
    3. Returning salaries from the front of a sorted list rather than the back
    4. Checking to see if a person was in the dictionary--the problem statement guaranteed that each person in the list was in the dictionary.
    5. Not using a splice, like [:-n] to return items from the list
    6. Not using a dictionary properly--many answers iterated thru the dictionary trying to find the person rather than just accessing the person directly using peopleDict[name]

  22. (12 points--Java Concurrency) The following class handles blog posts from different clients:
    public class BlogDistributer {
        class BlogPost {
    	public String userName;
    	public String post;
        }
    
        List blog = new ArrayList();
        List mirrorSites = new ArrayList();
    
        public void postBlog(String name, String blogEntry) {
    	BlogPost newPost = new BlogPost();
    	newPost.userName = name;
    	newPost.post = blogEntry;
    	blog.add(newPost);
    
    	String post = name + ": " + blogEntry;
    	PrintWriter out;
    	for (Socket s: mirrorSites) {
    	    out = new PrintWriter(s.getOutputStream(), true);
    	    out.println(post);
    	}
        }
    
        // adds a socket for a mirror site so we can post blogs to it
        public void addMirrorSite(Socket s) { ... }
        public BlogDistributer() { ... }
    }
    
    
    A single instance of this class will exist on the blog server and the blog server will have threads that serve each client. When a client posts a message, its thread on the server side will call postBlog in order to both save the blog and have it posted to the mirror sites (the sites that have agreed to hold copies of our blog). The following questions only concern the postBlog method. Do not concern yourself with the addMirrorSites method. Also assume that we do not care in which order blog posts get distributed to mirror sites (i.e., even if two blog posts arrive in the order "bvz" and "jplank" we don't care if they go out to the mirror sites in the order "jplank" and "bvz"). None of your answers should exceed 3 sentences.
    1. What type of problem might be experienced by postBlog (I want the specific name given to the problem and the cause of the problem)?

      This code causes a race condition when adding entries to the blog list since multiple blog threads might try to simultaneously access the list.

    2. How can the problem be fixed? Don't give me code. A simple explanation will suffice.

      I accepted a number of different answers, all of which revolve about synchronization:

      1. Use a synchronized(blog) statement to protect the blog.add call, with the blog being the lock we need to acquire.
      2. Make postBlog be a synchronized method. I deducted 1 point for this answer because the only statement that needs to be protected is the add call and we don't want to lock out other threads while we distribute the blog to the mirror sites (remember that the problem statement indicated that we do not care in which order the blog posts are posted to the mirror site and therefore this part of the code does not need to be protected).
      3. Change from an ArrayList to a thread-safe data structure, such as a Vector.
      4. Create a new class for the blog list object which contains a synchronized method for add.
      5. Use locks to protect the blog list object. I deducted a point for this answer because it is too low-level and buggy. You have to remember to both acquire and relinquish the locks, whereas if you use Java's high level synchronized method or synchronized statement, they will automatically acquire/relinquish the locks.
    3. Would the situation change if the BlogPost object were added to a hash table where the blogger's name was the key and the post were the value? Assume that the hash table uses separate chaining (i.e., if multiple keys hash to the same bucket, they are added to a list)? Why or why not?

      There is still a potential race condition if two blogger's names hash to the same bucket, because then we will still be in the situation of trying to add two blogs simultaneously to the same list. You need to make sure that you use a synchronized add method in this case, or else use a hash table that is thread safe.

    4. Would the situation change if each blogger had a unique id between 0 and 100 and the object with the blogger's name and post were added to a list in the array that is indexed on the blogger's id? Why or why not? The list would be a list of that blogger's post and we would also add a parameter to postBlog that contained the blogger's unique id.

      You no longer have a race condition because blogs from two different bloggers always go to different parts of the array and hence there is no contention between bloggers. If your answer indicated that there could still be a race condition between two blogs from the same blogger, I gave you some partial credit, but there is in fact no race condition because all blog posts from the same blogger are handled by the same blog thread and this thread reads blog posts serially from the socket. Thus before it can read the second blog post, it must have already added the first blog post to the array. I also gave you full credit if you pointed out that while the insertion does not cause contention, there could be a contention issue between a reader and a writer of these lists. Here are a few comments on the answers:

      1. Several of you focused on the mirror sites as a race condition even though the problem statement explicitly said not to worry about the addMirrorSite method and that we did not care if posts went to the mirror site out of order. Additionally, some of your answers said that writes could be pre-empted, but they can't be--they're atomic and therefore there is no problem with race conditions on the mirror sites.
      2. Some of you answered that mutex locks were the way to fix the problem with a blog. While correct, this is a low level solution appropriate to C, but not to Java. Java provides higher level language features such as synchronized statements and methods that should be used instead. Locks require that you remember to unlock them, which can lead to buggy code, whereas the synchronized statements and methods will automatically acquire and release locks.
      3. Some of you assumed that hash tables are thread safe in Java but they're not. If you look at the class description, they must be dropped into a concurrent object in order to be thread safe. Your answer needed to address the problem of bucket collisions to get full credit.
      4. Some of you assumed that users could have the same name, but any sane blog system will enforce unique user names. How many sites have you registered on that allow you to have the same user name as someone else?
      5. I accepted answers for arrays that said that a user could be logged in to two different threads and could post simultaneous blogs, but that is not really going to happen in the real world. It is quite easy to prevent a user from being logged on more than once.

      Many of you provided answers that were either not specific enough or did not really address the core problem. To help you with answering essay questions in the future, I have provided a few of the answers I saw along with an explanation of why I did not like it.

      1. Answers to part (a):

        • Bad answer: A race condition. Multiple users may submit to blog post at the same time.

          What is wrong: This answer does not tell me why the race condition occurs. Sure multiple users may submit to blog post at the same time but if it is properly implemented, that is not a problem. The problem is that it is not properly implemented because the blog list is not synchronized and therefore the add method can cause corruption problems.

        • Bad answer: postBlog could have a race condition.

          What is wrong: The problem specifies that you give both the name of the problem and the cause of the problem.

        • Bad answer: Race condition. A client thread can call it, stop executing, another client starts and finishes and control returns to the first one for example. The memory may no longer contain the correct info (it gets trashed/overwritten).

          What is wrong: What memory gets trashed/overwritten? You need to be specific about where the problem is occurring. This answer does not specify if the problem lies with the string newPost, with the blog list, or with the mirror sites. The problem is with multiple contention for the blog list.

      2. Bad answer for "how can the problem be fixed" (part b): You can use a lock around the blog object.

        What is wrong: That may be true but locks do not make the best use of Java's language features. Java specifically provides a synchronized statement for this purpose and it will result in simpler, less buggy code than if you try to lock/unlock the blog object explicitly. Let Java do the work for you!

      3. Bad answer for hash table (part c): No, you would still have issues accessing the table if another thread was accessing it.

        What is wrong: This answer does not tell me what issue there will be if the table has another thread accessing it so I cannot evaluate whether you know what the issue is. The issue is that if two users hash to the same bucket, then they will try to add their posts to the same list and since the list is not synchronized, you still have a race condition.

      4. Bad answer for an array (part d): Yes, this will eliminate the race condition. It could not be possible for a blogger to post multiple blogs in the same instant. What is wrong: The statement that a blogger cannot post multiple blogs in the same instant is true, but that does not explain why the race condition is eliminated. The race condition is eliminated because posts from different users will go to different lists in the array and hence there will not be any list contention.

        This answer does not allow me to assess whether or not you know what specific issue is causing the problem or whether you're just taking a stab at an answer. You need to specifically tell me that two users could hash to the same bucket, and since the buckets use lists to handle collisions, you could still have a race condition on a list if two users collide.

  23. (10 points--Functional Programming) Using Scheme, write a function named map that takes a function and a list as parameters and applies the function to each element of the list. It should return a list which represents the results of the function applied to each element of the list (you may not, of course, use Scheme's built-in map function). For example:
    (map (lambda (x) (+ x 30)) '(3 6 10))
    
    should return
    (33 36 40)
    
    Some requirements for your answer:
    1. It must handle empty lists
    2. It may not use iteration or side-effects.
    3. It may use either the inductive construction technique or the tail recursive construction technique.

    Inductive Construction

    (define map (lambda (fct aList)
    	(if (null? aList)
    	    aList
    	    (cons (fct (car aList)) (map fct (cdr aList)))
    	)
    ))
    
    Tail Recursive Construction:
    (define tailMap (lambda (fct aList)
            (letrec ((maphelper (lambda (fct aList resultList)
                      (cond
                        ((null? aList) (reverse resultList))
                        (#t (maphelper fct (cdr aList)
                                       (cons (fct (car aList)) resultList))))
                    )))
              (maphelper fct aList '()))))
    

    There were a number of common problems:

    1. Forgetting to use lambda to define a function. I made it a point in class to say that while our dialect of Scheme allows you to use (define (map fct L) ...), it is not standard and that I wanted you to get used to using lambda. This was a 1 point deduction.

    2. Copying the map function from somewhere on the internet and not reading the problem statement. The problem specified a single list so you made it overly complicated by handling multiple lists. You needed to show that you understood Scheme well enough to simplify the function so that it handled a single list. This was a 3 point deduction.

    3. Interchanging the order of arguments to cons. The correct way to write cons is:
      	(cons element list)
      
      not
      	(cons list element)
      
    4. Using append to try to add a single element to a list. Append appends 2 or more lists--it does not work with single elements