我一直在尝试编写一个函数,该函数返回n个集合的笛卡尔积。在Dr Scheme中,这些集合以列表的形式给出,我已经陷入困境了一整天,希望能得到一些指导。
----稍后编辑-----
这是我想出的解决方案,我相信它远非最有效或最整洁,但我只学了3周的Scheme,所以请对我宽容点。
我一直在尝试编写一个函数,该函数返回n个集合的笛卡尔积。在Dr Scheme中,这些集合以列表的形式给出,我已经陷入困境了一整天,希望能得到一些指导。
----稍后编辑-----
这是我想出的解决方案,我相信它远非最有效或最整洁,但我只学了3周的Scheme,所以请对我宽容点。
(define (cartesian-product . lists)
(fold-right (lambda (xs ys)
(append-map (lambda (x)
(map (lambda (y)
(cons x y))
ys))
xs))
'(())
lists))
;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))
;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))))
这是我的第一个解决方案(不够优化):
#lang scheme
(define (cartesian-product . lofl)
(define (cartOf2 l1 l2)
(foldl
(lambda (x res)
(append
(foldl
(lambda (y acc) (cons (cons x y) acc))
'() l2) res))
'() l1))
(foldl cartOf2 (first lofl) (rest lofl)))
(cartesian-product '(1 2) '(3 4) '(5 6))
我尝试着让 Mark H Weaver 的优雅解决方案(https://dev59.com/MkzSa4cB1Zd3GeqPorL0#20591545)更易于理解。
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
(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上使用Guile。
(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))