使用(约束)Racket查找列表的深度

时间:2016-02-01 14:10:51

标签: list recursion lisp racket depth

逻辑的另一个问题,任务是找到列表的深度,例如:给定(A B (C D (E)))列表它应该以某种方式指示深度为2(如果包含基本列表则为3) 。我被限制在一组常见的Racket函数中,我将在下面列出。在我所在的地方,我可以遍历列表,但最终会在第一个子列表中停止,即:(A (B (C)) (D (E (F))))仅为2。

以下是可用功能列表:

  • 缺点,汽车,cdr,定义,引用,if,cond,else
  • 算术的基本形式(+, - ,*,/)
  • 非常基本的测试(null?,list?,eq?,数字比较)

到目前为止,这是我的定义,如果有人能让我朝着正确的方向转移,我真的很感激。

(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))

3 个答案:

答案 0 :(得分:2)

这是我在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是原子(不是列表),则不会增加深度,找到列表的其余部分(cdr)的深度。
  • 否则,深度将是car的+1深度(记住,现在是列表)和列表的cdr的深度之间的最大值。注意car而不是cdr的深度增加。

使用的预定义程序:+maxnull?list?carcdrnot

答案 1 :(得分:0)

每个列表都是在car下的当前元素和cdr下的列表的其余部分构建的。

  • 列表的深度与列表其余部分的深度相同,如果这是最深的。

  • 如果这是最深的,那么列表的深度比其car的深度多一个。

所以,

(define (depth lst)
  (define a-depth (+ 1 (depth (car lst))))
  (define d-depth (depth (cdr lst)))
  (if (< ..... ) ..... 
    ; or else
    ...... ))

当然,当列表为空或原子(一对 - 你不能称car或{{1}时,不要忘记处理这种情况使用非配对参数,如果你这样做会导致错误):

  • 空列表的深度为零。

  • 原子的深度为零。

答案 2 :(得分:0)

  

在我的回答中,列表以 0 的深度开始,并且对于每个嵌套级别增加 1 。如果您希望他们以1的深度开头,您可以在(y 0)程序中将(y 1)更改为list-depth

这可以通过简单的折叠实现

(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

如果您不想使用折叠抽象,可以在list-depth内展开折叠

;; 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))]))

两者都会产生相同的输出,但在此实现中,折叠和最大值这两个概念纠结在一起。与第一个相比,看到折叠的内脏使得阅读这个答案要困难得多。

褶皱的内脏使得虫子很容易隐藏在最后一段片段中。我不能建议首先写这种方式,所以我不打算花费精力来修复它。