scheme - 置换方案代码的解释
问题描述
这是一个生成元素列表排列的方案代码:
(define (remove x lst) (cond
((null? lst) '())
((= x (car lst)) (remove x (cdr lst)))
(else (cons (car lst) (remove x (cdr lst))))))
(define (permute lst) (cond
((= (length lst) 1) (list lst))
(else (apply append
(map (lambda (i)
(map (lambda (j) (cons i j))
(permute (remove i lst)))) lst)))))
如果我们将代码分开,我确实理解代码的每一部分,但我无法理解的是这一切如何导致生成排列?
假设我们获取列表‘(a b)
,它是如何生成‘(a b)
的‘(b a)
?
我们首先a
从列表中删除并b
保留,但是您现在必须反对a
的地方写在哪里b
?b
是单个元素,但在我对代码的解释中,b
也将被删除,什么都没有了……</p>
解决方案
(TL;DR: the verbal explanation is at the very end of this answer.)
Let's try following the definitions with let*
-rewrites. The definitions are
(define (remove x lst) (cond
((null? lst) '())
((= x (car lst)) (remove x (cdr lst)))
(else (cons (car lst) (remove x (cdr lst))))))
(define (permute lst) (cond
((= (length lst) 1) (list lst))
(else (apply append
(map (lambda (i)
(map (lambda (j) (cons i j))
(permute (remove i lst)))) lst)))))
We try
(permute '(a b))
≡
(let* ((lst '(a b)))
(apply append
(map (lambda (i)
(map (lambda (j) (cons i j))
(permute (remove i lst))))
lst)))
≡
(let* ((lst '(a b))
(r (map (lambda (i)
(map (lambda (j) (cons i j))
(permute (remove i lst))))
lst)))
(apply append r))
≡
(let* ((lst '(a b))
(i1 'a)
(r1 (map (lambda (j) (cons i1 j))
(permute (remove i1 lst))))
(i2 'b)
(r2 (map (lambda (j) (cons i2 j))
(permute (remove i2 lst))))
(r (list r1 r2)))
(apply append r))
≡
(let* ((lst '(a b))
(i1 'a)
(t1 (permute (remove i1 lst)))
(r1 (map (lambda (j) (cons i1 j)) t1))
(i2 'b)
(t2 (permute (remove i2 lst)))
(r2 (map (lambda (j) (cons i2 j)) t2))
(r (list r1 r2)))
(apply append r))
≡
(let* ((i1 'a)
(t1 (permute '(b)))
(r1 (map (lambda (j) (cons i1 j)) t1))
(i2 'b)
(t2 (permute '(a)))
(r2 (map (lambda (j) (cons i2 j)) t2))
(r (list r1 r2)))
(apply append r))
≡
(let* ((i1 'a)
(t1 '( (b) ))
(r1 (map (lambda (j) (cons i1 j)) t1))
(i2 'b)
(t2 '( (a) ))
(r2 (map (lambda (j) (cons i2 j)) t2))
(r (list r1 r2)))
(apply append r))
and so we get
(let* ((r1 (map (lambda (j) (cons 'a j)) '( (b) )))
(r2 (map (lambda (j) (cons 'b j)) '( (a) )))
(r (list r1 r2)))
(apply append r))
≡
(let* ((r1 (list (cons 'a '(b))))
(r2 (list (cons 'b '(a))))
(r (list r1 r2)))
(apply append r))
≡
(let* ((r1 (list '(a b)))
(r2 (list '(b a)))
(r (list r1 r2)))
(apply append r))
≡
(let* ((r1 '((a b)))
(r2 '((b a)))
(r (list r1 r2)))
(apply append r))
≡
(apply append (list '((a b)) '((b a))))
≡
( append '((a b)) '((b a)) )
≡
'( (a b) (b a) )
Follow the same technique if you need to convince yourself in the validity of the intermediate results.
In hindsight, we could simplify it a bit more aggressively, like
(let* ((lst '(a b))
(i1 'a)
(r1 (map (lambda (j) (cons i1 j))
(permute (remove i1 lst))))
(i2 'b)
(r2 (map (lambda (j) (cons i2 j))
(permute (remove i2 lst))))
(r (list r1 r2)))
(apply append r))
≡
(let* ((lst '(a b))
(i1 'a)
(t1 (permute (remove i1 lst)))
(r1 (map (lambda (j) (cons i1 j)) t1))
(i2 'b)
(t2 (permute (remove i2 lst)))
(r2 (map (lambda (j) (cons i2 j)) t2)))
(apply append (list r1 r2)))
≡
(let* ((t1 (permute '(b)))
(r1 (map (lambda (j) (cons 'a j)) t1))
(t2 (permute '(a)))
(r2 (map (lambda (j) (cons 'b j)) t2)))
(append r1 r2))
≡
(let* ((r1 (map (lambda (j) (cons 'a j)) '( (b) )))
(r2 (map (lambda (j) (cons 'b j)) '( (a) )))
)
(append r1 ; one row for each elt '( a
r2 ; of the input list, b
)) ; spliced in place by append )
etc., in the end revealing the structure of the computation in the more visually apparent manner:
- for each element of the input list,
- find all the permutations of the remainder,
- prepend that element to each of them,
- and join together the results from thus processing each element in the input list, by appending all those results together.
(thus justifying my other, pseudocode-based answer here).
推荐阅读
- java - 如何使用等效线性运算符“=”
- dart - Dart - 如何订购日期时间对象?
- powerbi - 使用 DAX 或查询编辑器替换或替换 - Power BI
- javascript - 使用 axios 发出 xml 请求时浏览器中出现 415(不支持的媒体类型)
- php - 字符串php的深色十六进制颜色
- artificial-intelligence - 我在游戏机里造吃豆人,怎么造幽灵来追吃豆人像AI贪婪
- php - PHP 5.4 自动加载器无法按预期使用命名空间
- node.js - 在 nodejs 中进行验证的 Mongodb 查询
- python - Jupyter Lab 交互式绘图:*:“FloatSlider”和“float”不支持的操作数类型
- python - 使用 Python 库或正则表达式的数字分钟持续时间