#-(and) "

P08 (**) Eliminate consecutive duplicates of list elements.
    If a list contains repeated elements they should be replaced with a single copy of the element. The order of the elements should not be changed.

    Example:
    * (compress '(a a a a b c c a a d e e e e))
    (A B C A D E)

"

;; Nice recursive solution:

(defun compress (list)
  (labels ((compress-run (item list)
             (cond ((null list)              (list item))
                   ((eql item (first list))  (compress-run item (rest list)))
                   (t                        (cons item (compress-run (first list) (rest list)))))))
   (cond
     ((null list)          list)
     ((null (rest list))   list)
     (t                    (compress-run (first list) (rest list))))))


;; Iterative solution:

(defun compress (list)
  (cond
    ((null list)          list)
    ((null (rest list))   list)
    (t  (loop
           :with result = '()
           :with item = (first list)
           :for other :in (rest list)
           :do (unless (eql item other)
                 (push item result)
                 (setf item other))
           :finally (push item result) (return (nreverse result))))))



;; Smartass solution, using Common Lisp reduce:

(defun compress (list)
  (reduce (lambda (item result)
            (cond
              ((endp result)             (list item))
              ((eql (first result) item) result)
              (t                         (cons item result))))
          list
          :from-end t
          :initial-value '()))


;; Without :from-end, we need a reverse, and notice the order of the
;; arguments to the function:

(defun compress (list)
  (nreverse (reduce (lambda (result item)
                      (cond
                        ((endp result)             (list item))
                        ((eql (first result) item) result)
                        (t                         (cons item result))))
                    list
                    :initial-value '())))


;;;; THE END ;;;;
ViewGit