List 使用(受约束的)球拍查找列表的深度
另一个逻辑问题是,任务是找到列表的深度,例如:给定一个List 使用(受约束的)球拍查找列表的深度,list,recursion,lisp,racket,depth,List,Recursion,Lisp,Racket,Depth,另一个逻辑问题是,任务是找到列表的深度,例如:给定一个(ab(cd(E))列表,它应该以某种方式指示深度为2(如果包含基本列表,则为3)。我仅限于一组常见的球拍功能,我将在下面列出这些功能。在我所处的位置,我可以遍历列表,但在第一个子列表处停止,即:(A(B(C))(D(e(F))仅显示为2 以下是可用功能的列表: cons、car、cdr、define、quote、if、cond、else 算术的基本形式(+、-、*、/) 非常基本的测试(空?、列表?、等式?、数字比较) 这是我到目前为止
(ab(cd(E))
列表,它应该以某种方式指示深度为2(如果包含基本列表,则为3)。我仅限于一组常见的球拍功能,我将在下面列出这些功能。在我所处的位置,我可以遍历列表,但在第一个子列表处停止,即:(A(B(C))(D(e(F))
仅显示为2
以下是可用功能的列表:
- cons、car、cdr、define、quote、if、cond、else
- 算术的基本形式(+、-、*、/)
- 非常基本的测试(空?、列表?、等式?、数字比较)
(define (len l) (if (null? l) 0 (+ 1 (len (cdr l)))))
(define A '(A (B) (C (D))))
(define (depth l) (cond
[(null? l) '()]
[(list? (car l)) (cons (car l) (depth (car l)))]
[else (depth (cdr l))]
))
(depth A)
(len (depth A))
每个列表都是由一个当前元素构建的,位于其
car
下,列表的其余部分位于cdr
下
- 如果列表的深度是最深的,那么列表的深度与列表其余部分的深度相同
- 列表的深度比其
汽车的深度大一倍,如果这是最深的
(定义(深度lst)
(定义a深度(+1(深度(车辆lst)))
(定义d深度(深度(cdr lst)))
(如果(<…)。。。。。
;否则
...... ))
当然,不要忘记处理列表为空或原子(不是对-不能使用非对参数调用car
或cdr
,否则会导致错误)的情况:
- 空列表的深度为零
- 原子的深度为零
- 以下是我在Common Lisp中的定义
(defun list-depth (list &optional (depth 0))
(cond ((null list) depth)
((atom (first list)) (list-depth (rest list) depth))
(t (max (list-depth (first list) (1+ depth))
(list-depth (rest list) depth)))))
我没有在这台计算机上安装Racket,因此这里是对Scheme/Racket的未经测试的翻译:
(define (list-depth lst depth)
(cond ((null? lst) depth)
((not (list? (car lst)) (list-depth (cdr list) depth))
(else (max (list-depth (car lst) (+ 1 depth))
(list-depth (cdr lst) depth)))))
逻辑如下:
- 如果列表为空,则返回当前深度
- 如果列表的
是atom(而不是list),则它不会增加深度,请查找列表其余(car
)的深度cdr
- 否则,深度将是
的+1深度(记住,现在是列表)和列表的car
深度之间的最大值。注意cdr
的深度增加,而不是car
的深度增加cdr
+
,max
,null?
,列表?
,汽车
,cdr
,非
在我这里的回答中,列表以0的深度开始,每层嵌套增加1。如果希望它们以深度1开始,可以在列表深度
过程中将(y0)
更改为(y1)
这可以通过简单的折叠实现
(define (list-depth xs (y 0))
(foldl (λ (x z)
(if (list? x)
(max z (list-depth x (+ 1 y)))
(max z y)))
y
xs))
foldl
有一个简单的
(define (foldl f y xs)
(if (null? xs)
y
(foldl f (f (car xs) y) (cdr xs))))
这里有一些输出
(list-depth '()) ; ⇒ 0
(list-depth '(A)) ; ⇒ 0
(list-depth '(A (B))) ; ⇒ 1
(list-depth '(A (B (C)))) ; ⇒ 2
(list-depth '(A (B (C (D (E)))) (B (C)) (B))) ; ⇒ 4
如果不想使用折叠抽象,可以将
列表深度中的折叠扩展到
;; THIS CODE IS BROKEN, DO NOT USE
;; @mobiuseng found bugs
(define (list-depth xs (y 0))
(cond
[(null? xs) y]
[(list? (car xs))
(max y (list-depth (car xs) (+ 1 y)))]
[else
(max y (list-depth (cdr xs) y))]))
两者的结果相同,但在这个实现中,折叠和最大这两个概念纠缠在一起。与第一个答案相比,看到这些问题的本质使得阅读这个答案变得更加困难
在这最后一段代码中,这些折叠的内脏使得bug很容易隐藏起来。首先,我不建议这样写,所以我不打算费心去修复它。最后一段代码:第二个分支不正确:您忽略了cdr
可能包含更深层次的事实。在最后一个分支中,max
是冗余的,因为(列表深度(cdr xs)y)
将返回=y
值。捕捉得好,@mobiuseng,tyvm。最后一段代码过于复杂,使得bug很容易隐藏,这是一个很好的证明!
;; THIS CODE IS BROKEN, DO NOT USE
;; @mobiuseng found bugs
(define (list-depth xs (y 0))
(cond
[(null? xs) y]
[(list? (car xs))
(max y (list-depth (car xs) (+ 1 y)))]
[else
(max y (list-depth (cdr xs) y))]))