2016-04-24 4 views
1

私はリストの2つのリストを取得し、それらのリストのデカルト積を返す次の関数を書こうとしています。Scheme - map内のfoldrを使ってfoldr procにマップの繰り返しから与えられた現在の要素を使用させる

;; Signature: mix-rows(rows1 rows2) 
;; Purpose: returns a list of rows of the cartesian product of both rows 
;; Type: [ List(Row) * List(Row) -> List(Row) ] 
;; Tests: 
;; (mix-rows (list '(10 11) '(20 21)) (list '('u 'v) '('p 'q))) 
;; ==> ((10 11 'u 'v) 
;;  (10 11 'p 'q) 
;;  (20 21 'u 'v) 
;;  (20 21 'p 'q)) 
(define mix-rows 
    (lambda (rows1 rows2) 
    (map (lambda (row1) 
      (foldr (lambda (row2) 
        (append row1 row2)) 
        '() 
       rows2)) 
     rows1))) 

最後ラムダはrows1を反復処理する関数マップから与えられたROW1を認識しません何らかの理由:ここ

は、私が書いたものです。

最後のラムダをrows2で繰り返し、各要素をrow1に追加し、すべてのrows2要素を追加した後に、row1はrows1の次の要素に変更されます。

なぜラムダはロー1を認識できませんか?

ありがとうございました。

+0

あなたは 'uvpq'を二重引用するつもりはないでしょう。'(list(quote u)(quote v)) 'のsugaredバージョンである' '(uv)と ''(pq) '(list(quote p)(quote q))' – naomik

答えて

1

まず、cartesian-productの機能があればcartesian-productracket/listから使用できます。

> (cartesian-product 
    (list '(10 11) '(20 21)) 
    (list '('u 'v) '('p 'q))) 
'(((10 11) ('u 'v)) ((10 11) ('p 'q)) ((20 21) ('u 'v)) ((20 21) ('p 'q))) 

テストケースが内部リストをスプライスするため、テストケースがこれとは多少異なります。これはそうではありません。しかし、それが必要ならば簡単に(map append* ...)で修正できます。 append*関数は、1レベル下のリストのリストを平坦化します。

> (define (mix-rows rows1 rows2) 
    (map append* (cartesian-product rows1 rows2))) 
> (mix-rows 
    (list '(10 11) '(20 21)) 
    (list '('u 'v) '('p 'q))) 
'((10 11 'u 'v) (10 11 'p 'q) (20 21 'u 'v) (20 21 'p 'q)) 

あなたが最初からそれを設計したい場合は、あなたの実装に問題がfoldrが機能(X Y -> Y)、2つの引数の機能を期待していることですが、あなたはそれを機能(Row -> Row)、1つの引数関数を与えたが。あなたはそれを修正することができますが、私が見ることのできるところから、実際にはfoldrは必要ありません。おそらくmapも意味していました。

(define mix-rows 
    (lambda (rows1 rows2) 
    (map (lambda (row1) 
      (map (lambda (row2) 
        (append row1 row2)) 
       rows2)) 
     rows1))) 

、これはまだネストされたリストの余分な層を取り除くために

> (mix-rows 
    (list '(10 11) '(20 21)) 
    (list '('u 'v) '('p 'q))) 
'(((10 11 'u 'v) (10 11 'p 'q)) ((20 21 'u 'v) (20 21 'p 'q))) 

を生成、テストケースを失敗していますが、リストの1レベル下のリストを平らにするappend*を使用することができます。

;; Signature: mix-rows(rows1 rows2) 
;; Purpose: returns a list of rows of the cartesian product of both rows 
;; Type: [ List(Row) * List(Row) -> List(Row) ] 
;; Tests: 
;; (mix-rows (list '(10 11) '(20 21)) (list '('u 'v) '('p 'q))) 
;; ==> ((10 11 'u 'v) 
;;  (10 11 'p 'q) 
;;  (20 21 'u 'v) 
;;  (20 21 'p 'q)) 
(define mix-rows 
    (lambda (rows1 rows2) 
    (append* 
    (map (lambda (row1) 
      (map (lambda (row2) 
        (append row1 row2)) 
       rows2)) 
      rows1)))) 

しかし、あなたは本当のデカルト積をしたい場合は、行をスプライシングすることなく、あなたは(list row1 row2)(append row1 row2)を変更することにより、それを修正することができます。

(define mix-rows 
    (lambda (rows1 rows2) 
    (append* 
    (map (lambda (row1) 
      (map (lambda (row2) 
        (list row1 row2)) 
       rows2)) 
      rows1)))) 

次に、cartesian-productと一致します。

関連する問題