List 如何用lisp编写递归?
我需要你的大力帮助。 我想在Lisp中编写一个名为rec的函数,该函数将收到如下列表: 记录'101252921443115 我的代码应该检查内部列表的和是否等于外部列表的数字5+2+2=9等于9,然后我进一步检查9+9+12=30,3+3+1=5等于5,然后5+5+4=14等于14,14+14+2=30,30等于30,至少我把10加到30+30,整个列表的和是70。如果我的和等于这些数字,我将返回整个列表的和,否则我将返回Nil。我希望你明白我的意思…现在我想用递归来解决它,我尝试了一些方法,但我不能解决它,我希望有人能进一步帮助我List 如何用lisp编写递归?,list,recursion,lisp,List,Recursion,Lisp,我需要你的大力帮助。 我想在Lisp中编写一个名为rec的函数,该函数将收到如下列表: 记录'101252921443115 我的代码应该检查内部列表的和是否等于外部列表的数字5+2+2=9等于9,然后我进一步检查9+9+12=30,3+3+1=5等于5,然后5+5+4=14等于14,14+14+2=30,30等于30,至少我把10加到30+30,整个列表的和是70。如果我的和等于这些数字,我将返回整个列表的和,否则我将返回Nil。我希望你明白我的意思…现在我想用递归来解决它,我尝试了一些方法,
(defun rec(list)
)
(rec '(10 (12 (5 2 2) 9) (2 14 (4 (3 1 1) 5))))
一旦您明确了需要做什么,如何实现该功能将更容易
输入
您的输入是一个列表,但不是任何类型的列表。
让我们将这种特定的列表命名为节点
节点为空列表或3个元素的列表v n1 n2,其中:
v是一个数字,
n1分别为。n2是节点或数字。
输出
在节点上调用rec时,它应该输出一个数字或nil
概述
让我们定义一个辅助num函数,该函数通过调用rec获取一个数字或一个节点并返回一个数字或nil:
数字n的num n应返回n
节点n的num n应返回rec n
然后,rec可定义如下:
rec nil应该是nil
当num n1和num n2是相等的数字时,rec v n1 n2应该返回+v num n1 num n2。在任何其他情况下,rec应返回nil。
实例
下面是一种可能的实现方法,它依赖于诸如本地函数定义之类的运算符,基于值的类型和早期返回技术进行切换。另见。使用逻辑运算符和/或有助于组合可能的NIL中间结果:
(defun rec (node)
(flet ((num-or-fail (n)
(or (typecase n
(number n)
(cons (rec n)))
(return-from rec))))
(and node
(destructuring-bind (v n1 n2) node
(let ((v1 (num-or-fail n1))
(v2 (num-or-fail n2)))
(and (= v1 v2)
(+ v v1 v2)))))))
在REPL命令行中,可以为rec激活跟踪:
然后您可以测试:
CL-USER> (rec '(10 (12 (5 2 2) 9) (2 14 (4 (3 1 1) 5))))
上面返回70并在SBCL中打印以下跟踪:
0: (REC (10 (12 (5 2 2) 9) (2 14 (4 (3 1 1) 5))))
1: (REC (12 (5 2 2) 9))
2: (REC (5 2 2))
2: REC returned 9
1: REC returned 30
1: (REC (2 14 (4 (3 1 1) 5)))
2: (REC (4 (3 1 1) 5))
3: (REC (3 1 1))
3: REC returned 5
2: REC returned 14
1: REC returned 30
0: REC returned 70
提前返回甚至可以从最外层的调用中转义,因为它意味着整个结果是NIL,有点像异常。您也可以将rec设置为本地函数,与num或fail相互递归,并以不同的方式命名主函数:
(defun sumtree (node)
(labels ((num-or-fail (n)
(or (typecase n
(number n)
(cons (rec n)))
(return-from sumtree)))
(rec (node)
(and node
(destructuring-bind (v n1 n2) node
(let ((v1 (num-or-fail n1))
(v2 (num-or-fail n2)))
(and (= v1 v2)
(+ v v1 v2)))))))
(rec node)))
在上面的这里,当中间结果之一为nil时,从的返回将展开整个递归调用堆栈并直接返回nil。一旦您明确了需要做什么,如何实现该函数将变得更容易
输入
您的输入是一个列表,但不是任何类型的列表。
让我们将这种特定的列表命名为节点
节点为空列表或3个元素的列表v n1 n2,其中:
v是一个数字,
n1分别为。n2是节点或数字。
输出
在节点上调用rec时,它应该输出一个数字或nil
概述
让我们定义一个辅助num函数,该函数通过调用rec获取一个数字或一个节点并返回一个数字或nil:
数字n的num n应返回n
节点n的num n应返回rec n
然后,rec可定义如下:
rec nil应该是nil
当num n1和num n2是相等的数字时,rec v n1 n2应该返回+v num n1 num n2。在任何其他情况下,rec应返回nil。
实例
下面是一种可能的实现方法,它依赖于诸如本地函数定义之类的运算符,基于值的类型和早期返回技术进行切换。另见。使用逻辑运算符和/或有助于组合可能的NIL中间结果:
(defun rec (node)
(flet ((num-or-fail (n)
(or (typecase n
(number n)
(cons (rec n)))
(return-from rec))))
(and node
(destructuring-bind (v n1 n2) node
(let ((v1 (num-or-fail n1))
(v2 (num-or-fail n2)))
(and (= v1 v2)
(+ v v1 v2)))))))
在REPL命令行中,可以为rec激活跟踪:
然后您可以测试:
CL-USER> (rec '(10 (12 (5 2 2) 9) (2 14 (4 (3 1 1) 5))))
上面返回70并在SBCL中打印以下跟踪:
0: (REC (10 (12 (5 2 2) 9) (2 14 (4 (3 1 1) 5))))
1: (REC (12 (5 2 2) 9))
2: (REC (5 2 2))
2: REC returned 9
1: REC returned 30
1: (REC (2 14 (4 (3 1 1) 5)))
2: (REC (4 (3 1 1) 5))
3: (REC (3 1 1))
3: REC returned 5
2: REC returned 14
1: REC returned 30
0: REC returned 70
提前返回甚至可以从最外层的调用中转义,因为它意味着整个结果是NIL,有点像异常。您也可以将rec设置为本地函数,与num或fail相互递归,并以不同的方式命名主函数:
(defun sumtree (node)
(labels ((num-or-fail (n)
(or (typecase n
(number n)
(cons (rec n)))
(return-from sumtree)))
(rec (node)
(and node
(destructuring-bind (v n1 n2) node
(let ((v1 (num-or-fail n1))
(v2 (num-or-fail n2)))
(and (= v1 v2)
(+ v v1 v2)))))))
(rec node)))
在上面的这里,当中间结果之一为nil时,从的返回将展开整个递归调用堆栈并直接返回nil。对于我来说,似乎唯一可行的方法是如果所有列表都有3个元素。我们称之为三倍 德芬三联肽e 和Listpe =3长度e ;; 测验 三步5;==>无 三步'3 4 5;==>T 我不喜欢rec这个名字,所以我叫它sum triple。我猜: 三重和5;==>5. 和三元组'3 1;==> 让x2和三重1 x3和三1 如果=x2 x3 +三重和3 x2 x3 0 现在要让它返回“你需要包装它”。第一个调用需要与所有其他调用不同,以便您可以跳出帮助程序,在需要时执行完全不同的操作: 解除我的乐趣 标签辅助器x acc;acc在这里只是为了表明你可以保持状态 ;; 调用自身的实际实现 ;; 如果它发现一个坏值,它可以用 从我的乐趣中归来 助手x' 为了 在我看来,如果所有列表都有3个元素,这似乎是唯一可行的方法。我们称之为三倍 德芬三联肽e 和Listpe =3长度e ;; 测验 三步5;==>无 三步'3 4 5;==>T 我不喜欢rec这个名字,所以我叫它sum triple。我猜: 三重和5;==>5. 和三元组'3 1;==> 让x2和三重1 x3和三1 如果=x2 x3 +三重和3 x2 x3 0 现在要让它返回“你需要包装它”。第一个调用需要与所有其他调用不同,以便您可以跳出帮助程序,在需要时执行完全不同的操作: 解除我的乐趣 标签辅助器x acc;acc在这里只是为了表明你可以保持状态 ;; 调用自身的实际实现 ;; 如果它发现一个坏值,它可以用 从我的乐趣中归来 助手x'
请注意,该示例故意使用了学生不应该知道的功能,而不仅仅是复制。请注意,该示例故意使用了学生不应该知道的功能,而不仅仅是复制。