This is a little tricky to get right. Here are a few suggestions on one way to do it:
As stated, the problem is to walk the list, finding the most deeply nested lists that don't contain any other lists (these are sometimes called "lists of atoms"), and replacing them with something else. It's possible to do this in one recursive function, but I think it's clearer to break it up into parts:
First, we need a predicate (a function that returns a boolean #t
or #f
) to determine whether a list is a list of atoms. (This is sometimes called lat?
). You can write this as a simple recursive function, or you could use the library functions any
and list?
Then we need a function (define (max-lat-depth lst) ...)
to find how deeply nested the most-deeply-nested list of atoms in its argument is. This will be a doubly recursive function -- it needs to check the first
of each list as well as all the elements in the rest
. We can define max-lat-depth
as follows:
a. If the argument is a lat
itself, the maximum depth is zero, so (max-lat-depth '(1 2 3))
== 0
b. If the first element of the argument isn't a list, it can't affect the maximum nesting depth overall. So in this case the max-lat-depth
of the whole argument will be the same as the max-lat-depth
of the rest
(cdr
) of the list: (max-lat-depth '(1 (2 (3 4)))
== (max-lat-depth '((2 (3 4)))
== 2
c. The tricky case: if the first element of the argument is a list (as in ((1 2) (3 4))
), we'll need to recur on both the first
(or car
) and rest
(or cdr
) of lst
, returning the maximum of these values. However, we need to add 1 to one of these two results before taking the maximum. I'll let you figure out which one and why.
Finally, we write a function (define (replace-lats-at-depth depth lst r) ...)
that will take a nesting depth as returned from max-lat-depth
, a list lst
, and a replacement r
. It will return a copy of lst
where all the lists-of-atoms at depth depth
have been replaced by r
. For example:
(replace-lats-at-depth 0 '(1 2 3) '*)
== '*
(replace-lats-at-depth 1 '(1 (2) 3) '*)
== '(1 * 3)
.
Like max-lat-depth
, replace-lats-at-depth
recurs on both the first
and rest
of lst
. It will call cons
on the result of its recursive calls to construct a new tree structure. Also like max-lat-depth
, it has several cases, and it will need to subtract 1 from depth
in one of its recursive calls.
Once you have replace-lats-at-depth
working to replace the nested lists with a constant value r
, it shouldn't be too hard to improve it with a function that produces leaf1
, leaf2
, etc. as in your original example.
I hope that's helpful without saying too much. Let me know if not and I can try to clarify.