(module rle mzscheme
(require (lib "list.ss")
(lib "etc.ss")
(lib "contract.ss")
(planet "comprehensions.ss" ("dyoo" "srfi-alias.plt" 1)))
(define encoding/c? (listof (list/c number? char?)))
(provide/contract [rle-encode (string? . -> . encoding/c?)]
[rle-decode (encoding/c? . -> . string?)])
(define (rle-encode a-string)
(local ((define L (string-length a-string)))
(cond
[(= L 0)
empty]
[else
(let loop ([i 1]
[last-char (string-ref a-string 0)]
[run 1])
(cond
[(= i L)
`((,run ,last-char))]
[else
(local ((define next-char (string-ref a-string i)))
(cond
[(char=? last-char next-char)
(loop (add1 i) last-char (add1 run))]
[else
(cons `(,run ,last-char)
(loop (add1 i) next-char 1))]))]))])))
(define (rle-decode an-encoding)
(string-append-ec (:list n&c an-encoding) (apply make-string n&c))))