sequence ranges


Replace consecutive runs with the equivalent ranges in integer sequences.

 $ cat srg.rkt  
 #lang racket 
 (require rackunit) 
  
  
 (define (srg seq) 
  
   ; Return a copy of the given integer list.  Non-trivial ranges in the 
   ; given list are compressed into a pair, the car of which is the first 
   ; integer in the range and the cdr is the last integer in the range. 
  
  
   (define (add-range s e seq) 
  
     ; Prepend the given range to the given list.  If the range is trivial 
     ; (that is, s = e), it is added as the single element s; otherwise the 
     ; range is added as the pair (s . e). 
      
     (cons (if (= s e) s (cons s e)) seq)) 
    
  
   (if (null? seq) 
     seq 
     (let ((e (car seq))) 
       (let loop ((start e) (end e) (old-seq (cdr seq)) (new-seq '())) 
         (if (null? old-seq) 
           (reverse (add-range start end new-seq)) 
           (let ((e (car old-seq)) 
                 (new-old-seq (cdr old-seq))) 
             (if (= (+ end 1) e) 
               (loop start e new-old-seq new-seq) 
               (loop e e new-old-seq (add-range start end new-seq))))))))) 
  
  
 (check-equal? (srg '()) '()) 
 (check-equal? (srg '(1)) '(1)) 
 (check-equal? (srg '(1 2)) '((1 . 2))) 
 (check-equal? (srg '(1 2 3)) '((1 . 3))) 
 (check-equal? (srg '(1 2 3 5)) '((1 . 3) 5)) 
 (check-equal? (srg '(-1 1 2 3 5)) '(-1 (1 . 3) 5)) 
 (check-equal? (srg '(-1 1 2 3 5 7 8 9)) '(-1 (1 . 3) 5 (7 . 9))) 
 (check-equal? 
   (srg '(-5 -4 -3 -1 1 2 3 5 7 8 9)) '((-5 . -3) -1 (1 . 3) 5 (7 . 9))) 
 (check-equal? 
   (srg '(0 1 2 7 21 22 108 109)) '((0 . 2) 7 (21 . 22) (108 . 109))) 
  
 $ mzscheme srg.rkt  
  
 $