1
(define cart-product
  (lambda (sos1 sos2)
    (if (null? sos1) '()
      (cons
       (cart-prod-sexpr (car sos1) sos2)
       (cart-product (cdr sos1) sos2)))))

(define cart-prod-sexpr
  (lambda (s sos)
    (if (null? sos) '()
        (cons
         (list s (car sos))
         (cart-prod-sexpr s (cdr sos))))))

调用(cart-product '(q w) '(x y))产生(((q x) (q y)) ((w x) (w y))).

我怎样才能生产((q x) (q y) (w x) (w y))呢?

4

5 回答 5

4

获胜的高阶函数。Haskell 的列表理解转换为 Scheme 以获得更好的解决方案:

; cart xs ys = [ [x,y] | x <- xs, y <- ys ]
(define (cart xs ys)
  (let ((f (lambda (x) (map (lambda (y) (list x y)) ys))))
    (concatenate (map f xs))))

(cart '(a b c) '(x y)) => ((a x) (a y) (b x) (b y) (c x) (c y))

它以 m*n (m = |xs|, n = |ys|) 运行。连接来自 SRFI-1。

于 2011-02-20T21:17:55.967 回答
2

未经测试。请注意,append-list我定义的过程实际上返回一个以sos2. 这在这里是合适的(也是正确的做法),但不是一般的。

(define cart-product
  (lambda (sos1 sos2)
    (if (null? sos1) '()
      (append-list
       (cart-prod-sexpr (car sos1) sos2)
       (cart-product (cdr sos1) sos2)))))

(define cart-prod-sexpr
  (lambda (s sos)
    (if (null? sos) '()
        (cons
         (list s (car sos))
         (cart-prod-sexpr s (cdr sos))))))

(define append-list
  (lambda (sos1 sos2)
    (if (null? sos1) sos2
      (cons
        (car sos1)
        (append-list (cdr sos1) sos2)))))

请注意,如果列表大小为 n,则生成大小为 O(n 2 ) 的列表将花费时间 O(n 3 )。 使用常规将采用 O(n 4 ) 代替。我只是在没有意识到的情况下实施了常规。 如果你想取 O(n 2 ) 你必须更聪明。就像在这个未经测试的代码中一样。append append

(define cart-product
  (lambda (sos1 sos2)
    (let cart-product-finish
      (lambda (list1-current list2-current answer-current)
        (if (null? list2-current)
          (if (null? list1-current)
             answer-current
             (cart-product-finish (car list1-current) sos2 answer-current))
          (cart-product-finish list1-current (car sos2)
            (cons (cons (cdr list1-current) (cdr list2-current)) answer-current))))
    (cart-product-finish list1 '() '())))

万一我有一个错误,想法是递归循环第一个和第二个元素的所有组合,每个组合都用一个替换answer-currentcons然后是我们已经找到的所有其他组合。由于尾部调用优化,这应该是有效的。

于 2011-02-20T16:20:56.543 回答
2

在我的头顶上:

(define cart-product
  (lambda (sos1 sos2)
    (if (null? sos1) 
        '()
        (append
         (cart-prod-sexpr (car sos1) sos2)
         (cart-product (cdr sos1) sos2)))))
于 2011-02-20T16:29:55.690 回答
1
(reduce #'append 
           (mapcar #'(lambda(x)
                         (mapcar #'(lambda(y) 
                                       (list x y))
                          '(a b c))) 
           '(1 2 3)))

=>((1 A) (1 B) (1 C) (2 A) (2 B) (2 C) (3 A) (3 B) (3 C))

[注意:解决方案是针对 Common Lisp (CLisp) 而不是 Scheme,但我想它应该在 Scheme 中非常相似]

外部 (reduce #'append ) 用于替换 knivil 在解决方案中给出的 (concatenate (map )

但是,与其他解决方案相比,我不确定我的解决方案在性能参数上的表现如何。有人可以对此发表评论吗?

于 2011-09-23T18:24:49.113 回答
1

这里只是针对同一问题的不同解决方案。我认为这很容易理解,也许会对某人有所帮助。

(define (cart-product l1 l2)
  (define (cart-product-helper l1 l2 org_l2)
    (cond
      ((and (null? l1)) `())
      ((null? l2) (cart-product-helper (cdr l1) org_l2 org_l2))
      (else (cons (cons (car l1) (car l2)) (cart-product-helper l1 (cdr l2) org_l2)))
    )
  )
  (cart-product-helper l1 l2 l2)
)
于 2014-08-21T20:59:45.443 回答