(define (append! l1 l2)
  (define (last l)
    (if (null? (cdr l))
        l
        (last (cdr l))))
  (if (null? l1)
      l2
      (sequence (set-cdr! (last l1) l2)
                l1)))


(define (cons x y)
  (define (dispatch m)
    (cond ((eq? m 'car) x)
          ((eq? m 'cdr) y)
          ((eq? m 'set-car) (lambda (in) (set! x in)))
          ((eq? m 'set-cdr) (lambda (in) (set! y in)))
          (else (error "Wrong message!" m))))
  dispatch)
(define (car z) (z 'car))
(define (cdr z) (z 'cdr))
(define (set-car! z new) ((z 'set-car) new))
(define (set-cdr! z new) ((z 'set-cdr) new))


(define (how-many object)
  (define (f l already)
    (cond ((null? l) already)
          ((atom? (car l)) (f (cdr l) already))
          ((memq (car l) already) (f (cdr l) already))
          (else (f (cons (caar l) (cons (cdar l) (cdr l)))
                   (cons (car l) already))))
  (length (f (list object) '())))


(define (minimize1 object)
  (define already '())
  (define (f object)
    (if (atom? object)
        object
        (let ((r (member object already)))
          (if (null? r)
              (let ((new (cons (f (car object)) (f (cdr object)))))
                (set! already (cons new already))
                new)
              (car r)))))
  (f object))


(define (minimize2 object)
  (define (f object already)
    (if (atom? object)
        (cons object already)
        (let ((r (member object already)))
          (if (null? r)
              (let* ((rl (f (car object) already))
                     (rp (f (cdr object) (cdr rl)))
                     (new (cons (car rl) (car rp))))
                (cons new (cons new (cdr rp))))
              (cons (car r) already)))))
  (f object '()))