Scheme 方案中的笛卡尔乘积

Scheme 方案中的笛卡尔乘积,scheme,racket,cartesian-product,Scheme,Racket,Cartesian Product,我一直在尝试做一个函数,返回n个集合的笛卡尔积,在Dr方案中,集合是作为列表列表给出的,我整天都在做这个,我想知道一些从哪里开始的指南 ----后期编辑----- 这是我提出的解决方案,我相信它不是目前为止最有效或最简洁的,但我只研究了3周的计划,所以对我来说很轻松 ;compute the list of the (x,y) for y in l (define (pairs x l) (define (aux accu x l) (if (null? l) acc

我一直在尝试做一个函数,返回n个集合的笛卡尔积,在Dr方案中,集合是作为列表列表给出的,我整天都在做这个,我想知道一些从哪里开始的指南

----后期编辑-----

这是我提出的解决方案,我相信它不是目前为止最有效或最简洁的,但我只研究了3周的计划,所以对我来说很轻松

;compute the list of the (x,y) for y in l
(define (pairs x l)
  (define (aux accu x l)
    (if (null? l)
        accu
        (let ((y (car l))
              (tail (cdr l)))
          (aux (cons (cons x y) accu) x tail))))
  (aux '() x l))

(define (cartesian-product l m)   
  (define (aux accu l)
    (if (null? l) 
        accu
        (let ((x (car l)) 
              (tail (cdr l)))
          (aux (append (pairs x m) accu) tail))))
  (aux '() l))
来源:

这是我的第一个解决方案(次优):


基本上,您希望生成列表的乘积。

这里有一个简明的实现,它还设计用于通过共享组件列表的尾部来最小化内存中生成的结构的大小。它使用SRFI-1

  ;returs a list wich looks like ((nr l[0]) (nr l[1])......)
  (define cart-1(λ(l nr)
      (if (null? l) 
             l 
             (append (list (list nr (car l))) (cart-1 (cdr l) nr)))))

;Cartesian product for 2 lists
(define cart-2(λ(l1 l2)
                (if(null? l2) 
             '() 
             (append (cart-1 l1 (car l2)) (cart-2 l1 (cdr l2))))))

 ;flattens a list containg sublists
(define flatten
(λ(from)
 (cond [(null? from) from]
      [(list? (car from)) (append (flatten (car from)) (flatten (cdr from)))]
      [else (cons (car from) (flatten (cdr from)))])}) 

;applys flatten to every element of l
(define flat
(λ(l)
(if(null? l)
l
(cons (flatten (car l)) (flat (cdr l))))))

;computes Cartesian product for a list of lists by applying cart-2
(define cart
(lambda (liste aux)
 (if (null? liste)
  aux
  (cart (cdr liste) (cart-2 (car liste) aux)))))


(define (cart-n l) (flat (cart (cdr l ) (car l))))
(define (cartesian-product . lists)
  (fold-right (lambda (xs ys)
                (append-map (lambda (x)
                              (map (lambda (y)
                                     (cons x y))
                                   ys))
                            xs))
              '(())
              lists))

我试图让Mark H Weaver()的优雅解决方案更容易理解

import : srfi srfi-1
define : cartesian-product . lists
    define : product-of-two xs ys
         define : cons-on-each-ys x
            map : lambda (y) (cons x y)
                . ys
         append-map cons-on-each-ys
                  . xs
    fold-right product-of-two '(()) lists
这仍然是相同的逻辑,但命名操作

以上内容见又名SRFI-119。等效平面方案为:

(import (srfi srfi-1))
(define (cartesian-product . lists)
    (define (product-of-two xs ys)
         (define (cons-on-each-ys x)
            (map (lambda (y) (cons x y))
                ys))
         (append-map cons-on-each-ys
                  xs))
    (fold-right product-of-two '(()) lists))

这是我的答案,我正在做一些家庭作业。在Emacs上使用诡计

(define product                                                               
  (lambda (los1 los2)                                                         
    (if (or (null? los1) (null? los2))                                        
        '()                                                                   
        (cons (list (car los1) (car los2))                                    
              (append (product (list (car los1)) (cdr los2))                  
                    (product (cdr los1)  los2))))                             
                                                                              
        )                                                                     
    )                                                                         
                                                                              
(product '(a b c ) '(x y)) 

;; Result:
=> ((a x) (a y) (b x) (b y) (c x) (c y))  



相似:是的,这是家庭作业的一部分,我不一定需要代码,我想要一些指南。这应该有帮助吗?这是两个集合的笛卡尔积,我的问题是n个集合,我知道如何计算两个集合的值,我不知道如何将2个集合的值与fold结合,得到一个n个集合的值。一般来说,对于关联运算,您可以根据带fold的2参数版本定义n参数版本。此外,如果您查看Yuval发布的问题,Paul Hollingsworth发布了一个有良好文档记录的版本,尽管在plt方案中不起作用。关于密码的解决方案,您能做些什么来撤销列表列表?我认为您的意思是,您不希望结果是一个不正确列表(或嵌套对)的列表,而是希望列表的列表。如果是这样,实现这一点的最简单/最简单/最糟糕的方法是将(cons x y)更改为(cons x(If(list?y)y(list y)))。我不喜欢这个。但这不是我的家庭作业……;)
(define product                                                               
  (lambda (los1 los2)                                                         
    (if (or (null? los1) (null? los2))                                        
        '()                                                                   
        (cons (list (car los1) (car los2))                                    
              (append (product (list (car los1)) (cdr los2))                  
                    (product (cdr los1)  los2))))                             
                                                                              
        )                                                                     
    )                                                                         
                                                                              
(product '(a b c ) '(x y)) 

;; Result:
=> ((a x) (a y) (b x) (b y) (c x) (c y))