Lisp中的超级新手,但至少我尝试如此原谅我,如果方法看起来有些奇怪。
我乐于学习新想法,但我绝对需要学习我的方法有什么问题。
我有一个使用迭代递归方法构建列表的函数。
(defun create-tree-iteratively(sub-list)
(if (equal (length sub-list) 1)
sub-list
(loop for i in sub-list
do(setq subtree (list i))
do(setq sub-sub-list (remove i sub-list))
do(append subtree (create-tree-iteratively sub-sub-list))
)
)
)
我的程序的输入是
'(1 2 3)
预期输出为
'((1 (2 3) (3 2)) (2 (1 3) (3 1)) (3 (1 2) (2 1)))
我的循环(递归)运行文件。我在适当地组合递归的输出时遇到问题。
答案 0 :(得分:4)
通常情况下,最好不要在自己的行上加上右括号
Lisp中的约定是在括号的末尾进行分组,如下所示:
)))
。
由于约束单元只有两个插槽CAR
和CDR
,因此当它们用作列表时,它们不包含
列表的长度。所以唯一的方法
计算长度是要遍历整个单元链,这正是
您的功能已经在做什么。如果您的清单大小为N,则必须
计算长度N次,这会使函数中的步数与N * N成比例。
在一个循环中,一个DO可以跟多个表达式,您不需要 重复DO关键字。另外,在括号前添加空格。
SETQ不应与未绑定变量一起使用,例如subtree
或
sub-sub-list
。首先,您应该在周围let
进行介绍
局部变量(例如,loop
附近),或在您的变量中使用with
子句
环。或者更好的方法是,使用现有的LOOP工具避免进行突变
你自己。
APPEND
的返回值很重要,因为它是
附加参数的结果(保留不变)。但是你在这里
不使用返回值,这会使整个表达式无用。
检查输入是否足够,而不是计算长度
列表为空,包含一个或多个元素(不计)。另外,你可以
使用collect
收集所有树木作为列表。我不确定结果是否
单例输入列表正确,也许应该是(list list)
。
(defun create-tree (list)
(if (null (rest list))
;; covers both empty list and list with a single element
list
;; otherwise, collect a list of trees
(loop
for i in list
;; collect all trees rooted at i, where a tree is a list (r c1 .. cn)
;; with R the root node and C1...CN each child tree. The child trees
;; are build recursively, with i removed from the list of values.
collect (list* i (create-tree (remove i list))))))
答案 1 :(得分:4)
一些初始笔记。
setq
在函数中创建新绑定,而不会通过诸如let
; append
在列表末尾添加新内容,而是创建一个添加了新内容的新列表,并且由于列表是链接列表,而不是列表中的可变长度数组拖动append
所花费的时间与列表的长度成正比。话虽如此,这是我想要的三个版本:第一个实现了我认为是一致算法的东西,第二个实现了我认为你想要的东西,以及最后一个抽象出终止测试,并且可以(或做其他任何事情)。
(defun make-permuted-tree (l)
;; this builds the tree all the way down
(if (null l)
'()
(loop for e in l
collect (cons e (make-permuted-tree (remove e l))))))
(defun make-permuted-tree/strange (l)
;; this stops before the end
(if (null (rest l))
l
(loop for e in l
collect (cons e (make-permuted-tree/strange (remove e l))))))
(defun make-permuted-tree/general (l &key (base-test (lambda (b)
(null b))))
;; this stops where you want it to, which by default is at the end
(labels ((make-permuted-tree (lt)
(if (funcall base-test lt)
lt
(loop for e in lt
collect (cons e (make-permuted-tree (remove e lt)))))))
(make-permuted-tree l)))
例如:
> (make-permuted-tree/strange '(1 2 3))
((1 (2 3) (3 2)) (2 (1 3) (3 1)) (3 (1 2) (2 1)))
> (make-permuted-tree '(1 2 3))
((1 (2 (3)) (3 (2))) (2 (1 (3)) (3 (1))) (3 (1 (2)) (2 (1))))
> (make-permuted-tree/general '(1 2 3))
((1 (2 (3)) (3 (2))) (2 (1 (3)) (3 (1))) (3 (1 (2)) (2 (1))))
> (make-permuted-tree/general '(1 2 3) :base-test (lambda (b)
(null (rest b))))
((1 (2 3) (3 2)) (2 (1 3) (3 1)) (3 (1 2) (2 1)))