This homework is due at 11:59PM on Wednesday, November 6. Submit your solutions in a single file using the COMP 50 Handin button on DrRacket; the homework is the abstract homework.

All the exercises should be done using the Intermediate Student Language.

This homework is challenging, which is why you have extra time for it. I recommend that you find a study partner or a TA and that you work some of the finger exercises. If you post a finger exercise to Piazza, I will do my best to give you feedback.

Finger exercises

From the first edition, I recommend these finger exercises:

And also these exercises:

Problems to submit

Using local to contain costs

  1. Copy the solution to pascal-nums from the templates homework. Try these expressions in the Interactions window:

    > (time (pascal-nums 17))
    > (time (pascal-nums 18))
    > (time (pascal-nums 19))

    Now use local to change the running time. You will be reducing the running time from exponential (2N) to quadratic (N2). Try these expressions in the Interactions window:

    > (time (pascal-nums 17)))
    > (time (pascal-nums 18)))
    > (time (pascal-nums 19)))
    > (time (second (pascal-nums 100)))
    > (time (second (pascal-nums 200)))
    > (time (second (pascal-nums 300)))

    Finally, I give you a 3000-millisecond time limit. Staying within that limit, please measure how long a list you can compute with the fast version of pascal-nums.1

    Submit the fast version of pascal-nums, along with the outcome of your measurement.

Using abstraction to eliminate repetitious code

  1. On the mutual-reference homework, you wrote three different functions to determine nesting depth of ordered lists, nesting depth of unordered lists, and nesting depth of all lists. Using the abstraction and simplification techniques from Section 21 (Designing Abstractions from Examples), define a single function that can replace these functions, possibly with the addition of a few helper functions.

Parametric data definitions

  1. The function condense turns lists of lists of things into lists of things. Here are some functional examples:

    (check-expect (condense '((1 2) (3 4 5) () (6 7)))
                  '(1 2 3 4 5 6 7))
    (check-expect (condense '(("Dear") ("Mr" "Ramsey") ("your" "frog" "died")))
                  '("Dear" "Mr" "Ramsey" "your" "frog" "died"))

    Using the parametric data definition for lists, write a signature, purpose statement, and header for condense.

  2. Here is a self-referential data definition:

    A number-bst (binary search tree of numbers) is either:

    • false

    • A structure

      (make-node left key value right)

      where key is a string, value is a number, left is a number-bst in which all keys are less than this key, and right is a number-bst in which all keys are greater than this key.

    An image-bst (binary search tree of images) is either:

    • false

    • A structure

      (make-node left key value right)

      where key is a string, value is an image, left is a image-bst in which all keys are less than this key, and right is a image-bst in which all keys are greater than this key.

    In both data definitions, “less” and ’greater" are determined by string<?; they basically amount to alphabetical order. If you want to understand the details, you can experiment with DrRacket’s Interactions window.

    This problem has three parts:

    1. Generalizing from the two example definitions above, write a parametric data definition for binary-search trees that can be used to store any given class of value.

    2. The “search” in a binary-search tree comes from a function that is given a binary-search tree and a string key. The function searches for a node containing that key, and if it finds such a node, it returns the node’s value. If it does not find the node, it returns false.

      Using your parametric data definition from the previous problem, write the signature, purpose statement, and header for a function that searches binary-search trees. The signature must have one or more type variables.

    3. Using the design recipe for self-referential data, finish the design of the function for searching in a binary-search tree (from the previous problem). Make sure that your test cases use the function with different types of values.

    This problem is similar to the search on the apocalyptic railway, but it is significantly easier.

  3. Here are two parametric data definitions:

    A (2Dpoint X) is a structure

    (make-point x y value)

    where x and y are numbers and value is an X.

    A (2Dtree X) is one of the following:

    • A (2Dpoint X)

    • A structure

      (make-v-boundary left x right),

      where

      • x is a number,
      • left is a (2Dtree X) in which every point has an x coordinate at most x, and
      • right is a (2Dtree X) in which every point has an x coordinate at least x
    • A structure

      (make-h-boundary above y below),

      where

      • y is a number,
      • above is a (2Dtree X) in which every point has an y coordinate at most y, and
      • below is a (2Dtree X) in which every point has an y coordinate at least y

    Here is an image derived from a data example made using make-v-boundary:
    A v-boundary example

    And here is an image derived from a data example made using make-h-boundary:
    An h-boundary example

    This problem has two parts:

    1. Based on the simple maps used for the templates homework, write data examples for (2Dtree string). A list of towns appears at the end of the problem, but you need not include every town.

    2. Define a function nearest-point which is given the (x, y) coordinates of a “target” and is also given a (2Dtree X). The function returns the (2Dpoint X) within the tree that is closest (in ordinary Euclidean distance) to the target.

      Your function must avoid searching on the far side of a boundary unless such a search is necessary. To figure out when a far-side search is necessary, use the table you made for the templates homework (or my solution).

    The second part of this problem presents a major design challenge. To help you meet this challenge, here are some observations about templates, conditionals, helper functions, and testing:

    To help you create data examples and test cases, here is a list of all the towns from the maps used in the templates homework:

    (list
     (make-point 11 29 "A")
     (make-point 85 194 "B")
     (make-point 176 185 "C")
     (make-point 58 102 "D")
     (make-point 260 225 "E")
     (make-point 244 118 "F")
     (make-point 199 91 "G")
     (make-point 64 48 "H")
     (make-point 24 62 "I")
     (make-point 116 31 "J")
     (make-point 136 153 "K")
     (make-point 155 277 "L"))

    Once you have a good template, I don’t expect the code itself to give you much trouble, but if at any point you get stuck, here are some useful questions. You should base your answers on the results for the map examples on the templates homework.

Karma problem

There is one karma problem. It uses the following data definition:

The problem is to define a function that is given a bounding-box and a (2Dtree string) and returns an image of that portion of the tree which lies within the bounding box. The image should include not only the points but also the horizontal and vertical lines marking boundaries.


  1. When your program is finished with lists, DrRacket recycles the memory to make new lists. The recycling costs are accounted for as “GC time”, and they vary. When measuring what you can do in 3000ms, assume the worst possible scenario about how much time is spent recycling.

  2. Untested code shows as red text on a black background.