问题
I need to find the leaves in a list in Scheme.
For example, if I have (1 (2 3) (4 (5) (7 (8) (10 11 12)))))), my leaves are (8) and (10 11 12). So my function will return (1 (2 3) (4 (5) (7 leaf1 leaf2))))).
Definition: a leaf is an element with the deepest nesting possible.
Examples: In (1 (2 (3))) the element (3) is a leaf.
In ((1 2) (3 4)) the elements (1 2) and (3 4) are leaves.
I tried to use the map function, that will check if the list is composed from lists. If it is - so I call the function again, and if not, I break and change the lists to symbols of leafs. It doesn't work.
I have been stuck on it for 2 days. I am trying to find an idea, not an implementation. Thanks.
回答1:
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
#tor#f) to determine whether a list is a list of atoms. (This is sometimes calledlat?). You can write this as a simple recursive function, or you could use the library functions any andlist?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 thefirstof each list as well as all the elements in therest. We can definemax-lat-depthas follows:a. If the argument is a
latitself, the maximum depth is zero, so(max-lat-depth '(1 2 3))==0b. 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-depthof the whole argument will be the same as themax-lat-depthof therest(cdr) of the list:(max-lat-depth '(1 (2 (3 4)))==(max-lat-depth '((2 (3 4)))== 2c. 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 thefirst(orcar) andrest(orcdr) oflst, 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 frommax-lat-depth, a listlst, and a replacementr. It will return a copy oflstwhere all the lists-of-atoms at depthdepthhave been replaced byr. 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.
来源:https://stackoverflow.com/questions/8355428/scheme-find-most-deeply-nested-lists