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 $