CS 3323 Topics in Programming Languages


Lisp Assignment 3, Fall 1999
Due September 29, 1999

For this assignment, your Lisp should not have any iterative constructs (such as prog, do, etc.) but all iteration should be done with recursion. Inside functions you should not make use of setf or setq.

  1. A common mistake involving recursion takes the following form: Suppose we want to write our own version of the Lisp function if. We might try this as follows:
         > (defun our-if (condition then-action else-action)
             (cond (condition then-action) (t else-action)))
         OUR-IF
         > (our-if (< 4 5) 'yes 'no)
         YES
         > (our-if (> 4 5) 'yes 'no)
         NO
    
    our-if seems to work. But what might happen if we use our-if inside a recursive definition? For example, suppose we wrote factorial in terms of our-if:
         > (defun factorial (n)
             (our-if (zerop n) 1 (* n (factorial (1- n)))))
         FACTORIAL
         > (factorial 5)
    
    What happens in this case? Why? [This question was taken from your text, Common Lispcraft by R. Wilensky. It is a rather tricky question. Please don't just run to someone else, but think about is carefully yourself.]

  2. Write a ``super'' reverse function srev which reverses all lists that occur in an S-expression at any level. Thus (srev '((a b (c d)) e (f g))) should yield ((g f) e ((d c) b a)). [Hint: This is similar to the previous reverse1, except for additional recursion.]

  3. Write a function insert1 which takes its first integer argument and inserts it at the correct place in its second argument, a list of integers sorted in increasing order, so that (insert1 3 '(1 4 6 6 7)) produces (1 3 4 6 6 7). [insert1 only works for sorted lists.]

  4. Use insert to write a function sort1 which sorts a list of integers into increasing order. [We are done if the list is nil. Otherwise insert the car of the list into the sorted cdr.]

  5. Write a function that prints an S-expression in dotted pair notation. [Hint: This is easy if you think recursively. The idea is to write one or more recursive Lisp functions with various calls to print functions in them, including perhaps princ or prin1. In addition to printing, your function should just return nil. If your function is called printdot, then it should do the following:
    > (printdot ())
    NIL
    NIL
    > (printdot 'a)
    A
    NIL
    > (printdot '(a))
    (A . NIL)
    NIL
    > (printdot '(a b c))
    (A . (B . (C . NIL)))
    NIL
    > (printdot '(a . (b . (c . nil))))
    (A . (B . (C . NIL)))
    NIL
    > (printdot '(a (b c (d e) (g) (h i))))
    (A . ((B . (C . ((D . (E . NIL)) . ((G . NIL) . ((H . (I . NIL))
      . NIL))))) . NIL))
    NIL
    
    Notice that the function is returning nil after printing.]

  6. Suppose we represent a matrix in Lisp as a list of lists. For example, ((a b) (c d)) would represent a 2-by-2 matrix whose first row contains the elements a and b, and whose second row has the elments c and d. Write a function that takes a matrix as input, and outputs its transpose. For example, (transpose '((a b) (c d))) returns ((A C) (B D)), and (transpose '((a b c) (d e f) (g h i))) returns ((A D G) (B E H) (C F I)). [The solution should also work for non-square matrices. Hint: Write a function make-car-list that will take the car of each sublist and make a list of these, so that (make-car-list '((a b c d) (e f g h) (i j k l))) would return (A E I). Then write a function drop-cars that will drop off the car of each sublist and make a list of these, so that (drop-cars '((a b c d) (e f g h) (i j k l))) would return ((B C D) (F G H) (J K L)). Finally, transpose should cons the cars onto the result of transpose on the lists with cars dropped.]

  7. Try to use the mapcar function in the problem above.


Revision Date: 9/16/99