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)))))
      
      逻辑如下:

      • 如果列表为空,则返回当前深度
      • 如果列表的
        car
        是atom(而不是list),则它不会增加深度,请查找列表其余(
        cdr
        )的深度
      • 否则,深度将是
        car
        的+1深度(记住,现在是列表)和列表的
        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))]))