List 在方案中生成2个列表的列表
调用List 在方案中生成2个列表的列表,list,scheme,cartesian-product,List,Scheme,Cartesian Product,调用(购物车产品(qw)-(xy))生成((qx)(qy))((wx)(wy)) 如何生成((qx)(qy)(wx)(wy))?未经测试。注意,我定义的append list过程实际上返回一个以sos2结尾的列表。这在这里是合适的(也是正确的做法),但不是一般的 (define cart-product (lambda (sos1 sos2) (if (null? sos1) '() (cons (cart-prod-sexpr (car sos1) sos
(购物车产品(qw)-(xy))
生成((qx)(qy))((wx)(wy))
如何生成
((qx)(qy)(wx)(wy))
?未经测试。注意,我定义的append list
过程实际上返回一个以sos2
结尾的列表。这在这里是合适的(也是正确的做法),但不是一般的
(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))))))
请注意,如果列表的大小为n,则需要时间O(n3)来生成大小为O(n2)的列表。使用常规的append
将需要O(n4)。我只是实现了常规的append
,但没有意识到这一点。如果你想取O(n2),你必须更聪明。在这个未经测试的代码中
(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)))))
如果我有一个bug,我们的想法是递归地循环第一个和第二个元素的所有组合,每一个都用另一个组合替换
cons
,然后是我们已经找到的所有其他组合。由于尾部调用优化,这应该是有效的。未经测试。注意,我定义的append list
过程实际上返回一个以sos2
结尾的列表。这在这里是合适的(也是正确的做法),但不是一般的
(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))))))
请注意,如果列表的大小为n,则需要时间O(n3)来生成大小为O(n2)的列表。使用常规的append
将需要O(n4)。我只是实现了常规的append
,但没有意识到这一点。如果你想取O(n2),你必须更聪明。在这个未经测试的代码中
(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)))))
如果我有一个bug,我们的想法是递归地循环第一个和第二个元素的所有组合,每一个都用另一个组合替换
cons
,然后是我们已经找到的所有其他组合。多亏了尾部呼叫优化,这应该是高效的。我的脑海中浮现出:
(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 '() '())))
不经意间:
(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 '() '())))
高阶函数用于win。Haskell的列表压缩转换为Scheme以获得更好的解决方案:
(define cart-product
(lambda (sos1 sos2)
(if (null? sos1)
'()
(append
(cart-prod-sexpr (car sos1) sos2)
(cart-product (cdr sos1) sos2)))))
;cart xs ys=[[x,y]|xwin的高阶函数。Haskell的列表压缩转换为Scheme以获得更好的解决方案:
(define cart-product
(lambda (sos1 sos2)
(if (null? sos1)
'()
(append
(cart-prod-sexpr (car sos1) sos2)
(cart-product (cdr sos1) sos2)))))
;购物车xs ys=[[x,y]|x
=>((1A)(1B)(1C)(2A)(2B)(2C)(3A)(3B)(3C))
[注意:解决方案适用于Common Lisp(CLisp),而不是Scheme,但我认为它在Scheme中应该非常相似]
外部(reduce#'append)用于替换(concatenate(map)),如knivil在解决方案中给出的那样
然而,我不确定我的解决方案与其他解决方案相比在性能参数方面的表现如何。有人能对此发表评论吗
=>((1A)(1B)(1C)(2A)(2B)(2C)(3A)(3B)(3C))
[注意:解决方案适用于Common Lisp(CLisp),而不是Scheme,但我认为它在Scheme中应该非常相似]
外部(reduce#'append)用于替换(concatenate(map)),如knivil在解决方案中给出的那样
但是,与其他解决方案相比,我不确定我的解决方案在性能参数方面的表现如何。有人能对此发表评论吗?这里是针对同一问题的不同解决方案。我认为这很容易理解,可能会对某些人有所帮助
(reduce #'append
(mapcar #'(lambda(x)
(mapcar #'(lambda(y)
(list x y))
'(a b c)))
'(1 2 3)))
对于同一个问题,这里有不同的解决方案。我认为这很容易理解,可能会对某些人有所帮助
(reduce #'append
(mapcar #'(lambda(x)
(mapcar #'(lambda(y)
(list x y))
'(a b c)))
'(1 2 3)))
很抱歉,您的解决方案解决了这个问题,但它非常复杂。在其他语言中,您使用了两个嵌套循环。在Scheme中,有一个名为let的解决方案。@knivil:有没有一个更简单的解决方案也同样有效?(我将稍微简化这个解决方案,但我看不出它可以在不牺牲效率的情况下进一步简化。)很抱歉,您的解决方案解决了这个问题,但它非常复杂。在其他语言中,您使用了两个嵌套循环。在Scheme中,有一个名为let的解决方案。@knivil:有没有一个更简单的解决方案也同样有效?(我将稍微简化这个解决方案,但我看不出它可以在不牺牲效率的情况下进一步简化。)这不应该在mnn中运行吗?您生成长度为n的m个列表,然后concatenate必须遍历每个列表以找到下一个列表的开头。对于紧凑的代码仍然是+1。这是一个极好的解决方案。尽管我花了一个多小时才弄清楚机制。解决方案首先定义了名为let binding f的元素,它接受x和ge的每个元素生成2个列表的列表。(映射f xs)对xs的每个元素执行f以生成Listof(Listof(2个列表))。此列表被展平为Listof(2个列表)通过调用concatenate函数。我希望我的理解是正确的。这不应该在mnn中运行吗?您生成长度为n的m个列表,然后concatenate必须遍历每个列表,以找到下一个列表的开头。对于紧凑的代码,仍然是+1。非常好的解决方案。尽管我花了一个多小时才弄清楚机制。解决方案first定义了命名的let绑定f,它接受x的每个元素并生成一个2列表的列表。(map f xs)为x的每个元素执行f以生成一个Listof(Listof(2列表))。通过调用concatenate函数,这个列表被展平为Listof(2列表)。我希望我的理解是正确的。