Overview
I would certainly appreciate suggestions of other extra credit activities (preferably via email).
Someone posted Sam’s dining hall price rant. What’s that about?
I used to write an essay (‘blog post) every day.
I’m a Grinnell parent and a curmudgeon.
I did the math. Dining plans were more expensive than buying individual meals.
But it appears they were discussing a different rant, one about the “cash value” of a dining hall meal. There are too many for me too keep track of.
How do I extract text from a directory?
The files have a pattern. Sam can also work on writing some helper code.
The
(directory-list dir)procedure produces a list of “paths”. (Something like filenames, but not as strings.)
The
(path->string path)procedure converts a path to a string.
We can filter out the ones of interest.
We can use
file->stringwithmapto extract the contents of each.
We can join them together with
applyandstring-append.
;;; Procedure:
;;; sandb-files
;;; Parameters:
;;; pattern, a regular expression
;;; Purpose:
;;; Make a list of all the SandB files that match the particular expression.
;;; Produces:
;;; fnames, a list of strings.
(define sandb-files
(lambda (pattern)
(map (section string-append sandb <>)
(filter (section regexp-match? pattern <>)
(map path->string
(directory-list sandb))))))
;;; Procedure:
;;; sandb-text
;;; Parameters:
;;; pattern, a regular expression
;;; Purpose:
;;; Extract the text from all of the files that match the pattern.
;;; Produces:
;;; text, a string
(define sandb-text
(lambda (pattern)
(apply string-append (map file->string (sandb-files pattern)))))
(define tally-strings
(lambda (lst)
(if (null? lst)
0
(if (string? (car lst))
(+ 1 (tally-strings (cdr lst)))
(tally-strings (cdr lst))))))
> (tally-strings '("a" 2 3 "b" ("d" "e")))
2
Question: Can we make it count the “d” and the “e”?
(define deep-tally-strings
(lambda (lst)
(if (null? lst)
0
(if (string? (car lst))
(+ 1 (deep-tally-strings (cdr lst)))
(if (list? (car lst))
(+ (deep-tally-strings (car lst))
(deep-tally-strings (cdr lst)))
(deep-tally-strings (cdr lst)))))))
Key idea: If the first element of the list is also a list, recurse on both the car and the cdr.
Problems with code above:
(deep-tally-strings (cdr lst)). Makes code harder
to read. (Fortunately, only one will be executed.)(define deep-tally-strings
(lambda (lst)
(if (null? lst)
0
(let ([tally-of-rest (deep-tally-strings (cdr lst))])
(cond
[(string? (car lst))
(+ 1 tally-of-rest)]
[(list? (car lst))
(+ (deep-tally-strings (car lst)) tally-of-rest)]
[else
tally-of-rest])))))
(define deep-tally-strings
(lambda (lst)
(if (null? lst)
0
(+ (cond
[(string? (car lst))
1]
[(list? (car lst))
(deep-tally-strings (car lst))]
[else
0])
(deep-tally-strings (cdr lst))))))
Note: Deep recursion does not generally work well with tail recursion (so-far and remaining). Use direct recursion.
For deep-contains?, assume that the value is not a list or pair.
For deep recursion, don’t use a helper with so-far and remaining. (It makes things harder.)
For deep-alphabetically-first, you can assume that none of the lists
are empty.
For exercise 6, you may find it easier to allow deep-reverse to act on non-lists.
Writeup exercise 5.