【发布时间】:2020-04-07 22:43:17
【问题描述】:
Peter Norvig 的 PAIP 书籍包含此 code 作为排列问题的解决方案(为简洁起见,删除了某些部分)
(defun permutations (bag)
;; If the input is nil, there is only one permutation:
;; nil itself
(if (null bag)
'(())
;; Otherwise, take an element, e, out of the bag.
;; Generate all permutations of the remaining elements,
;; And add e to the front of each of these.
;; Do this for all possible e to generate all permutations.
(mapcan #'(lambda (e)
(mapcar #'(lambda (p) (cons e p))
(permutations (remove e bag))))
bag)))
涉及 2 个 lambda 的部分确实很棒,但有点难以理解,因为有许多活动部分相互混合。我的问题是:
1- 如何正确解释这 2 个 lambda?欢迎详细解释。
2- Norvig 如何正确推断出第一个 map 函数应该是 mapcan?
可选:他最初是如何想到这样一个简短而有效的解决方案的?
【问题讨论】:
-
我很确定,我无法告诉您 Peter Norvig 的想法 ;-) 但是如果您查看 mapcan 的文档并在代码中将其替换为 @987654326 @你会很清楚地看到差异。此外,如果您
tracepermutations您会看到lambdas 按照评论中的说明工作。 -
感谢您的评论。老实说,
mapcan的文档并没有多大帮助,因为它没有显示它的任何实际用例。trace也没有多大帮助,因为它只显示了permutations的两次调用,一次是输入,一次是最终输出,即它没有显示mapcan和mapcar的各个进程。唯一有用的是将mapcan替换为mapcar,因为它显示了进展,但它再次没有清楚地显示这两个lambdas 如何完美和谐地工作以产生正确的输出,也没有解释何时使用mapcan。 -
你的输入数据是什么?如果您从
(a b)之类的简单测试用例开始,然后增加到(a b c),它应该会在跟踪中显示差异。 -
对于
'(a b)的输入,跟踪输出为:1. Trace: (PERMUTATION '(A B))1. Trace: PERMUTATION ==> ((A B) (B A)),即只有输入和输出重复。 -
它是
clisp,它只为 2 个元素输入'(a b)提供了 2 个跟踪输出,显然它有问题,所以我在sbcl上尝试了 3 个元素输入'(a b c)它提供了 31 行跟踪输出,信息量很大。 Here it is谢谢你的评论,很有帮助。
标签: recursion functional-programming lisp common-lisp permutation