Here’s the generalized tally procedure from the reading.
(define deep-tally
(lambda (lst pred?)
(cond
[(null? lst)
0]
[(pred? (car lst))
(+ 1 (deep-tally (cdr lst) pred?))]
[(list? (car lst))
(+ (deep-tally (car lst) pred?) (deep-tally (cdr lst) pred?))]
[else
(deep-tally (cdr lst) pred?)])))
Here’s a more general pattern for deep recursion.
(define DEEP-FUN
(lambda (lst)
(cond
[(BASE-CASE-TEST? lst)
(BASE-CASE-COMPUTATION lst)]
[(list? (car lst))
(COMBINE1 (DEEP-FUN (car lst)) (DEEP-FUN (cdr lst)))]
[else
(COMBINE2 (car lst) (DEEP-FUN (cdr lst)))])))
a. Review the two patterns of deep recursion given above.
b. Go over the self checks from the reading.
Write a procedure, (deep-contains? lst val)
, that takes a nested
list and a value as parameters, and determines whether the value appears
in the list or any of its sublists (or sub-sublists or …).
You should use equal?
to compare values.
> (deep-contains? '(a (b (c) d) ((e))) 'c)
#t
> (deep-contains? '(a (b (c) d) ((e))) 'x)
#f
Write a procedure, (select-strings lst)
, that uses the pattern of deep
recursion to select all of the strings from a nested list and return
them as a list.
> (select-strings '(("this") "is" "a" (((("somewhat")) "nested")) "list"))
'("this" "is" "a" "somewhat" "nested" "list")
> (select-strings '("a" 1 ("and" "a" 2 ("and" "a" 3))))
'("a" "and" "a" "and" "a")
Write a generalized version of select-strings
, (deep-select lst
pred?)
, that selects all the values from a nested list for which
a predicate holds.
Write a procedure, (flatten lst)
, that takes a nested list as a
parameter and returns a “flat” list (one with no sublists) that
contains the same values in the same order.
> (flatten '(1 (2 3 (4 5 (6)) 7) 8 (9 10) 11))
'(1 2 3 4 5 6 7 8 9 10 11)
Write a procedure, (deep-alphabetically-first lst)
, that takes a
nonempety nested list of strings as a parameter and returns the
alphabetically first string in that nested list. You should process
the nested list directly, rather than, say, flattening it first.
> (deep-alphabetically-first '("simple"))
"simple"
> (deep-alphabetically-first '("not" ("quite" ("as") "simple")))
"as"
> (deep-alphabetically-first '(("is" (("this" ("any") ("more" ("complex")))))))
"any"
Note: You will need a somewhat different base case than we’ve used in the prior procedures.
Note: This procedure should accept strings that contain non-letters
and order them using modified ASCII order as determined by string-ci<=?
.
Hint: As in past “best of” procedures, you will find it helpful to write a helper procedure that takes two strings as inputs and returns whichever of the two strings is alphabetically first.
Write a procedure, (deep-reverse val)
, that takes any Scheme value
as a parameter. If the parameter is a list, deep-reverse
should
reverse both that list and any sublists that it may have. If the
parameter is not a list, deep-reverse
should return the value.
> (deep-reverse 1)
1
> (deep-reverse '(1 2 3))
'(3 2 1)
> (deep-reverse '(1 (2 3 (4 5) 6) 7 (8 9) 10))
'(10 (9 8) 7 (6 (5 4) 3 2) 1)
Warning: You may need a very different pattern of recursion than we used in the procedures above.
If you find yourself with extra time, you might try one or more of the following problems.
Rewrite deep-contains?
using and
and or
, rather than cond
or
`if.
You may have noted that using (deep-tally lst pair?)
does not
compute quite the value you would have expected. Write a procedure,
(deep-tally-pairs val)
, that counts all the pairs in a Scheme
value that does not contain any vectors.
> (deep-tally-pairs '(1 2 3))
3
> (deep-tally-pairs '(1 (2 3)))
4
> (deep-tally-pairs '((1) (2) (3)))
6
This lab was newly written for spring 2019. Although some of the problems resemble questions students asked earlier in the semester, those students should not be blamed for the questions on this lab, which were planned.