Review Sheet for the second Midterm Exam

This review sheet is intended to help you study for the second midterm exam. It is not intended to be an exhaustive list of everything we've covered, but it should help you identify the "big ideas". Note that the midterm will cover all topics we've seen so far, including those that we covered before midterm 1.  However, emphasis will be placed on topics since the last exam (i.e., at least 75% of the points will be for topics since the last exam).

You should also review your lecture notes and the solutions to your homework problems.  The lecture "quizzes" are especially useful in helping you study for the exam.

You may bring to the exam a 8.5 by 11 sheet with your own writing (only) on both sides.

Study Topics

Since the last exam (more emphasis)

Object-oriented Programming in Python

Abstract Data Types (ADT's), Data Structures

Searching, Sorting (and other algorithms) and Big-O

(Simple) Logic Programming in Prolog

From the last exam (less emphasis)

Foundations of functional programming with Racket!

Parsing and Evaluating a Language

Program Design

Data Structures and Algorithms

Digital Logic and Computer Architecture

Assembly Language Programming

Some Practice Problems (coming soon...)

WARNING: This list of practice problems does not nearly cover the entire space of material you will be asked to know for the exam.  We provide it simply as an additional source in  your preparations (under the "something is better than nothing" principle).  THE BEST WAY TO PREPARE FOR THE EXAM IS TO REDO IN CLASS "QUIZ" PROBLEMS AND HOMEWORK PROBLEMS.  You should go on to the problems below only once you are sure you can do all the problems from classes and homeworks.  Also review the practice problems on the last review sheet.
  1. The Tree of Python!

    You've been hired by Millisoft, a major software company. Your first job is to write a class called BasicDictionary that supports the dictionary abstract data type operations of insert and find. The insert method takes a reference to an object and inserts it into the dictionary. The dictionary will be implemented as a binary search tree (but not a fancy one like an AVL tree or a B-Tree). More on that in a moment!

    The objects that are being inserted and found might be anything, but it is assumed that there is some ordering of the objects. For example, if the objects are numbers, the ordering could be numerical order. If the objects are strings, the ordering might be alphabetical ordering. If the objects are canned meat products, the ordering might be the order in which the products were made. In general they will be objects made from some class that is expected to have a class method called lessThan that is expected to take as input two of these objects, o1 and o2 and return a boolean: It will return True if o1 is less than o2 in this particular ordering and it will be False otherwise. For example, you could invoke this function by calling o1.lessThan(o1, o2) to compare objects o1 and o2.  As the developer of the BasicDictionary class, you don't need to worry about how the lessThan method works, you can just assume that you are dealing with a class that has this method available.

    Your job is to give an implementation of the BasicDictionary class using a binary search tree implementation. Below is the starter code with comments. Just implement the insert method, not the find method.



    class TreeNode(object):  

    def __init__(self, data):
    self.data = data
    self.lessChild = None
    self.greaterChild = None

    class BasicDictionary(object):

    def __init__(self):
    self.root = None # root is a reference to the root of the tree

    def insert(self, data):
    # Fill in code here.



  2. Tree Pruning Now, Millisoft would like you to build a new class called Dictionary that extends the BasicDictionary class and also has a delete method that takes an input an object and deletes it from the tree. You may assume that the object is in the tree. Write the code for Dictionary using inheritance. NOTE: This problem is a tiny bit bigger than what we might ask on an exam, but it's a good practice problem nonetheless!
  3. Objects and References in Python

    Consider the following class definitions.

    class Person(object):

        def __init__(self, name):

            self.name = name

        def isAsleep( self, hr ):

            return 22 < hr or 7 > hr

        def __repr__(self):

            return self.name

        def status( self, hr ):

            if self.isAsleep( hr ):

                print "Now offline: " + self

            else:

                print "Now online: " + this



    class Student(Person):

        def __init__(self, name, units):

            super(Student, self).__init__(name)

            self.units = units

        def isAsleep( self, hr ):

            return 2 < hr and 8 > hr

        def __repr__(self):

            result = super(Student, self).__repr__()

            return result + " units: " + str(self.units)



    class Mudder(Student):
        # add a dorm data member
        def __init__( self, name, units, dorm ):
            super(Mudder, self).__init__(name, units)
            self.dorm = dorm

        def isAsleep( self, hr ):
            return False

        def __repr__(self):
            result = super(Student, self).__repr__()
            return result + " dorm: " + str(self.dorm)


    What will the following code print?  Will it produce any errors at run time?

    # p is a person
    def doStuff(p):
        s = Student( "Sally", 17 )
        p.name = s.name
        p = s
        return p

    def main():

        M = Mudder( "Zach", 42, "Olin" )
       
        P = doStuff( M );

        print P

        print M  

  4.   Consider the following Racket functions:

    (define (flatten L)
      (if (null? L)
          L
          (append (first L) (flatten (rest L)))))


    (define (flatten2 L)
      (flatten2-help L '()))

    (define (flatten2-help L ans)
      (if (null? L)
          ans
          (flatten2-help (rest L) (append ans (first L)))))

    Assume they will only be run on a-lists (i.e., lists of pairs).  Let N be the length of the input list.