# 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.

; 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)
(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

\$
```