(続々)Gaucheで「カブらない数字を4桁だすの」をやる*1

http://d.hatena.ne.jp/n9d/20071120/1195568232

で、shiroさんに教えて頂いたのでもう少しやってみる。

gauche.sequenceを使う方法

>> (begin (use srfi-1) (use gauche.sequence) (take (shuffle (iota 10)) 4))
=> (8 9 5 0)

append-mapを使う方法

やばい、今度は引数の勉強しなきゃいけなくなった。

>> (use util.combinations)(use srfi-27)
=> #<undef>

>> => #<undef>

>> (define permutations2 (lambda (x y) (append-map permutations (combinations x y))))
=> permutations2

>> (let ((a (permutations2 (iota 10) 4))) (list-ref a (random-integer (length a))))
=> (6 2 0 5)

可変引数に対応したバージョンのpermutationsをつくる

>> (use util.combinations)
=> #<undef>
>> (define permutations.super permutations)
=> permutations.super
>> (define permutations (lambda (x . y) (if (null? y) (permutations.super x) (append-map permutations.super (combinations x (car y))))))
=> permutations
>> (permutations '(1 2 3))
=> ((1 2 3) (1 3 2) (2 1 3) (2 3 1) (3 1 2) (3 2 1))
>> (permutations '(1 2 3) 2)
=> ((1 2) (2 1) (1 3) (3 1) (2 3) (3 2))

Gaucheで可変長の引数を扱う。

なるほどな。dorリストつかうのか。

>> ((lambda (x . y) (print x y)) 1) 
1()
=> #<undef>
>> ((lambda (x . y) (print x y)) 1 2)
1(2)
=> #<undef>
>> ((lambda (x . y) (print x y)) 1 2 3)
1(2 3)
=> #<undef>
>> ((lambda (x . y) (if (null? y) "only x" "x and y")) 1)
=> only x
>> ((lambda (x . y) (if (null? y) "only x" "x and y")) 1 2)
=> x and y

Gaucheでクイックソート

リストから任意のものを抜き出すのはrubyだとselectだからと思って探してみると
srfi-1のfilterがそうだった。

>> (define qsort (lambda (x) (if (null? x) () (append (qsort (filter (lambda (y) (< y (car x))) (cdr x))) (list (car x)) (qsort (filter (lambda (y) (>= y (car x))) (cdr x)))))))
=> qsort

>> (qsort '(5 3 2 1 6 4 7 9 3 3))
=> (1 2 3 3 3 4 5 6 7 9)

なんか (list (car x))というのがいただけないな。

GaucheでUNIQ

一つずらしたリストとzipして同じ要素のタプルを削除するフィルターを通す版

更に追記。zipつかうとちょっとだけ富豪な気分
srfi-1のzipは少ない方で作るので (cons () x)がちょっとだけかっこわるい。

>> (define uniq (lambda (x) (unzip1 (filter (lambda (x) (not (eq? (car x) (cadr x)))) (zip x (cons () x))))))
=> uniq
>> (uniq '(1 2 2 2 3 3 2 4))
=> (1 2 3 2 4)

fold-right版

更に追記。fold-rightで再帰の必要性もないってfold-rightが再帰だって(笑

>> (define uniq (lambda (x) (fold-right (lambda (y z) (if (and (not (null? z)) (equal? y (car z))) z (cons y z))) () x)))
=> uniq

>> (uniq '(1 2 2 3 3 3 2 4))
=> (1 2 3 2 4)

再帰

やり直した。cadr使う癖無いもん。

>> (define uniq (lambda (x) (if (null? x) () (if (and (not (null? (cdr x))) (eqv? (car x) (cadr x))) (uniq (cdr x)) (cons (car x) (uniq (cdr x)))))))
=> uniq

>> (uniq '(1 2 2 3 3 4))
=> (1 2 3 4)

なんかエレガンスさなんてどこにもないんだがとりあえず作った。

>> (define uniq (lambda (x . y) (if (null? x) () (if (and (not (null? y)) (eqv? (car x) (car y))) (uniq(cdr x) (car y)) (cons (car x) (uniq (cdr x) (car x))))))) 
=> uniq

>> (uniq '(1 2 2 3 3 4))
=> (1 2 3 4)

>> (uniq '(1 2 2 2 3 3 4))
=> (1 2 3 4)