235 :デフォルトの名無しさん:2012/03/09(金) 15:21:07.33 Allegro Common Lisp (ACL) の試用版を使っています (list "*" '(2 3 4) '(a b) "!" '(8 9 0)) こういう文字列とリストからなるリストをもとに *2a!8 *2a!9 *2a!0 *2b!8 *2b!9 *2b!0 *3a!8 ... と続くものを出力したいです(文字列とリストは0回以上ランダムに表れます) リストについては命令型言語でいうところの for (...) for (...) のような処理をすることになりそうですが どこから手をつければよいかわかりません おそらくmapcarを使ってリストを作り直す必要があります? どうすればよいですかこの問題って、対象のリスト
(list "*" '(2 3 4) '(a b) "!" '(8 9 0))の文字列も要素一個の集合ってことにして
(list '("*") '(2 3 4) '(a b) '("!") '(8 9 0))であると見なして、集合の集合と考えちゃう。するとこれらの集合に対してSQLで言うところのcross joinの結果を出せばいいんじゃないかという気がする。調べてみたらcross joinってデカルト積って言うんですって。そこで、デカルト積を出すにはどうしたらいいのかなーと探してみたらgaucheのutil.combinationsにcartesian-productってのが組み込みであった。
ちょっとズルい気もするけど、それっぽい結果になった。gaucheで書きました。
(use util.combinations) (let* ((ls (list "*" '(2 3 4) '(a b) "!" '(8 9 0))) (ls (map (^x (if (list? x) x (list x))) ls))) (for-each (^s (write s)(newline)) (map (apply$ string-append) (map (map$ x->string) (cartesian-product ls))))) ;; "*2a!8" ;; "*2a!9" ;; "*2a!0" ;; "*2b!8" ;; "*2b!9" ;; "*2b!0" ;; "*3a!8" ;; "*3a!9" ;; "*3a!0" ;; "*3b!8" ;; "*3b!9" ;; "*3b!0" ;; "*4a!8" ;; "*4a!9" ;; "*4a!0" ;; "*4b!8" ;; "*4b!9" ;; "*4b!0"
追記
せっかくなのでちょっと見やすく(use util.combinations) (define (print-list ls) (for-each (^s (write s)(newline)) ls)) (define (list->set-of-set ls) (map (^x (if (list? x) x (list x))) ls)) (define (cartesian-product-string set-of-set) (map (apply$ string-append) (map (map$ x->string) (cartesian-product set-of-set)))) (define (main ls) (print-list (cartesian-product-string (list->set-of-set ls)))) (main (list "*" '(2 3 4) '(a b) "!" '(8 9 0))) ;; "*2a!8" ;; "*2a!9" ;; "*2a!0" ;; "*2b!8" ;; "*2b!9" ;; "*2b!0" ;; "*3a!8" ;; "*3a!9" ;; "*3a!0" ;; "*3b!8" ;; "*3b!9" ;; "*3b!0" ;; "*4a!8" ;; "*4a!9" ;; "*4a!0" ;; "*4b!8" ;; "*4b!9" ;; "*4b!0"
0 件のコメント:
コメントを投稿