compact-number-list
higepon さんの d:id:higepon:20080925:1222326246 をやってみました。
こういう問題です。
整列済みの number のリストがある。
'(1 3 4 5 6 12 13 15)このようなリストで数が連続している部分は '(1 2 3) -> '(1 . 3) のように両端のみを書くような記法を導入する。
最初の例のリストであれば以下のようになる。
'(1 (3 . 6) (12 . 13) 15)このようなリストの変換をするコードを書きたい。
http://d.hatena.ne.jp/higepon/20080925/1222326246
で、わたしの書いたコードがこちら。
(use srfi-1) (define (compact-number-list lst) (define (consec? a b) (if (pair? a) (= (+ (cdr a) 1) b) (= (+ a 1) b))) (define (update-range a b) (if (pair? a) (cons (car a) b) (cons a b))) (let loop ((result (list (car lst))) (rest (cdr lst))) (if (null? rest) (reverse result) (let ((prev (car result)) (now (car rest))) (loop (if (consec? prev now) (cons (update-range prev now) (cdr result)) (cons now result)) (cdr rest)))))) (define (expand-compacted-list lst) (append-map (lambda (x) (if (pair? x) (iota (- (cdr x) (car x) (- 1)) (car x)) (list x))) lst)) (compact-number-list '(1 3 4 5 6 12 13 15)) (expand-compacted-list (compact-number-list '(1 3 4 5 6 12 13 15)))
流れは higepon さんのと同じですが、if を loop の中に入れて、苦し紛れながらもスッキリさせてみました。
逆の expand もやってみましたけど、こちらは瞬殺。