Skip to main content

CSC 151 2019S, Class (expt 2 5): Deep recursion

Overview

  • Preliminaries
    • Notes and news
    • Upcoming work
    • Extra credit
    • Questions
  • Quick preview
  • Lab

Preliminaries

News / Etc.

  • Mentor sessions Thursday 7-8 p.m., Thursday 8-9 p.m., Sunday 5-6 p.m.
    • Note change in schedule.
  • Folks should think about taking CSC 161 in the fall. It’s a great class, and you get to work with robots!
  • Sorry that I remain a bit behind on way too much. I’m working on it.

Upcoming work

Extra Credit

I would certainly appreciate suggestions of other extra credit activities (preferably via email).

Extra credit (Academic/Artistic)

  • New: CS Table, Tomorrow, “The Cathedral and the Bazaar”
  • New: “Plan your CS major with WGMC”, tomorrow at 7pm. All genders welcome.
  • Dartanyan Brown discussion, 4pm Wednesday April 24, HSSC S3325
  • Dartanyan Brown concert, 7:30 pm Wednesday April 24, Sebring-Lewis
  • PBK Convo, Thursday, 11am: “Antievolutionism in Historical Perspective”
  • New: McKibben lecture, Thursday, 4:15 p.m., JRC 101

Extra credit (Peer)

  • New: Track and Field at Grand View on Friday.

Extra credit (Wellness)

Extra credit (Wellness, Regular)

  • Today 30 Minutes of Mindfulness at SHACS (SHAW) every Monday 4:15-4:45
  • Any organized exercise. (See previous eboards for a list.)
  • 60 minutes of some solitary self-care activities that are unrelated to academics or work. Your email reflection must explain how the activity contributed to your wellness.
  • 60 minutes of some shared self-care activity with friends. Your email reflection must explain how the activity contributed to your wellness.

Extra credit (Misc)

  • Tonight Public speaking workshop - April 22 at 7pm in HSSC S3325, with Kathy Clemons-Beasley ‘05.

Other good things

Questions

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.

https://www.cs.grinnell.edu/~rebelsky/musings/

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->string with map to extract the contents of each.

We can join them together with apply and string-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)))))

Quick preview

  • When I’m doing something with lists, what if I also want to look at the sublists?
  • E.g., tallying strings.
(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:

  • Nested ifs. Consider using cond.
  • Three calls to (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.

Lab

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.