mark shroyer, dot com: this is where I keep my things

Site Navigation


My solutions to "ANSI Common Lisp": Chapter 2

Exercise 1

  1. The two inner function calls, (- 5 1) and (+ 3 7), are evaluated. Next, their values are used as arguments to the outer function call, yielding a result of 14.
  2. The inner function (+ 2 3) is evaluated and passed to list, which returns the list (1 5).
  3. The predicate (listp 1) evaluates to nil, so the second expression in the if block, (+ 3 4), is evaluated to 7. This value is returned by the if block.
  4. list’s arguments are evaluated and their values stored in a list. The first argument evaluates to nil, as (listp 3) is false; the second argument evaluates to 3. Thus, the entire expression evaluates to (nil 3).

Exercise 2

  1. (cons 'a '(b c))
  2. (cons 'a (cons 'b '(c)))
  3. (cons 'a (cons 'b (cons 'c nil)))

Exercise 3

(defun fourth-element (list)
  (car (cdr (cdr (cdr list)))))

Exercise 4

(defun greater-of-two (a b)
  (if (> a b) a b))

Exercise 5

  1. enigma is a function on lists. It returns t for non-nil lists which contain at least one nil element, and nil on all other lists.
  2. mystery returns the index of the first occurrence of x within the list y, if it is present within the list, or nil otherwise. The and function is used to prevent (+ z 1) from being evaluated in the case that z is nil; this statement works as such because and returns the value of its last argument if the whole expression evaluates to a truth value.

Exercise 6

  1. cdr
  2. or
  3. apply

Exercise 7

(defun contains-list? (list)
  (if (null list)
      nil
      (if (listp (car list))
          (car list)
          (contains-list? (cdr list)))))

Exercise 8

  1. Iterative version:

    (defun print-dots-iterative (n)
      (do ((i 1 (+ i 1))) ((> i n))
        (format t "."))
      (format t "~%"))
    

    Recursive version:

    (defun print-dots-recursive (n)
      (if (> n 0)
          (progn
            (format t ".")
            (print-dots-recursive (- n 1)))
          (format t "~%")))
  2. Iterative version:

    (defun count-a-iterative (list)
      (let ((n 0))
        (dolist (ele list n)
                (if (eql ele 'a)
                    (setf n (+ n 1))))))
    

    Recursive version:

    (defun count-a-recursive (list)
      (if list
          (let ((rest (count-a-recursive (cdr list))))
            (if (eql (car list) 'a)
                (+ rest 1)
                rest))
          0))
    

Exercise 9

  1. The program would work as written if remove stored the modified list in the original variable. However, remove is a non-destructive function. The original version of summit could be rewritten correctly as follows:

    (defun summit (lst)
      (apply #'+ (remove nil lst)))
    
  2. The problem is that this recursive incarnation of summit does not test for the base case which occurs at the end of the list (where the cdr is nil), and so it will recurse until the stack fills up. A corrected version:

    (defun summit (lst)
      (let ((x (car lst)))
        (if (cdr lst)
            (if (null x)
                (summit (cdr lst))
                (+ x (summit (cdr lst))))
            (if (null x) 0 x))))
    

0 Comments

Leave a comment