Search code examples
listschemenestedracketdepth

Return all elements on nesting depth n of a nested list


I'm really puzzled on how to do this... I can't even figure out how to start, I know how to do it for a binary tree but I want to be able to do it with any form of nested list, can anyone help me out please?


Solution

  • For this one, you need to use the template for traversing an arbitrarily nested list of elements. For example, study this procedure that copies an arbitrarily nested list:

    (define (copy lst)
      (cond ((null? lst)                ; if list is empty
             '())                       ; return the empty list
            ((not (list? (car lst)))    ; if current element is not a list
             (cons (car lst)            ; cons current element
                   (copy (cdr lst))))   ; with the rest of the list
            (else                       ; if current element is a list
             (cons (copy (car lst))     ; cons recursive call over current element
                   (copy (cdr lst)))))) ; with recursive call over rest of the list
    

    A little convention first. Let's say that 1 is the base level, and that all the elements returned will be in a flat output list (without preserving the original structure of the input list). For example:

    (elements-level '(1 2 3) 1)
    ; => '(1 2 3)
    
    (elements-level '(1 (2) 3) 2)
    ; => '(2)
    

    With the above template in mind, let's see how we can modify it for solving the problem at hand. I'll let you fill-in the blanks, because the question looks like homework:

    (define (elements-level lst lvl)
      (cond ((or (null? lst) (< lvl 1))        ; if list is empty or below level
             '())                              ; return the empty list
            ((not (list? (car lst)))           ; if current element is not a list
             (if (= lvl <???>)                 ; if `lvl` is the base level
                 (cons <???>                   ; cons current element in list
                   (elements-level <???> lvl)) ; and advance recursion over cdr part
                 (elements-level <???> lvl)))  ; else advance recursion over cdr part
            (else                              ; if current element is a list
             (append                           ; use `append` for flattening the list
              (elements-level <???> <???>)     ; recur over car, decrease one level
              (elements-level <???> <???>))))) ; recur over cdr, keep the same level
    

    Test the procedure with this list, it must return '(1) for level 1, '(2) for level 2, and so on:

    (elements-level '(1 (2 (3 (4 (5))))) 1)
    ; => '(1)