uncoupling lists


Write a function that accepts a list and returns a copy of the list with couples (successive pairs of equal elements) removed.

 $ cat dc.rkt  
 #lang racket 
  
  
 (define (decouple l) 
  
   ; Return a copy of the given list with all adjacent pairs of equal elements 
   ; removed. 
    
   ; This code is ridiculous.  The problem has an elegant one-pass solution.   
  
   (define (dc done pending decoupled reversals) 
  
     (if (null? pending) 
  
       (if decoupled 
         (dc '() done #f (+ reversals 1)) 
         (if (odd? reversals) (reverse done) done)) 
  
       (let ((e (car pending)) 
            (next-pending (cdr pending))) 
  
         (cond 
  
           ((null? next-pending) 
              (let ((done (cons e done))) 
                (if decoupled 
                  (dc '() done #f (+ reversals 1)) 
                  (if (odd? reversals) (reverse done) done)))) 
  
           ((eq? e (car next-pending)) 
            (dc done (cdr next-pending) #t reversals)) 
  
           (#t 
            (dc (cons e done) next-pending decoupled reversals)))))) 
  
   (dc '() l #f 1)) 
  
  
 (require rackunit) 
  
 (check-equal? (decouple '(red blue green green blue red yellow)) '(yellow)) 
 (check-equal? (decouple '(red red red)) '(red)) 
 (check-equal? (decouple '(red red)) '()) 
 (check-equal? (decouple '(red)) '(red)) 
 (check-equal? (decouple '(red red blue blue)) '()) 
 (check-equal? (decouple '(red red blue green green)) '(blue)) 
  
 (check-equal? (decouple '()) '()) 
 (check-equal? (decouple '(1)) '(1)) 
 (check-equal? (decouple '(1 1)) '()) 
 (check-equal? (decouple '(1 1 1)) '(1)) 
 (check-equal? (decouple '(1 1 1 1)) '()) 
 (check-equal? (decouple '(1 2 2 1)) '()) 
 (check-equal? (decouple '(a 1 1 b)) '(a b)) 
 (check-equal? (decouple '(a b 1 1 b c)) '(a c)) 
 (check-equal? (decouple '(a 1 1 1 b 1 1 b 1 c)) '(a c)) 
  
 $ racket dc.rkt  
  
 $