2012/03/10

リスト ("*" (2 3 4) (a b) "!" (8 9 0)) から文字列 "*2a!8", "*2a!9", "*2a!0", "*2b!8" ...を作る

2chのLisp Schemeスレに掲題の問題が出てた。
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"

プログラミングGauche

0 件のコメント:

コメントを投稿