(define-struct dir (name num-files subs))
;; Dir is (make-dir String Natural ListOfDir)
;; interp. a Directory on a computer, with the name of the directory
;; the number of files contained in the directory
;; a list of sub-directories found in the directory
;; ListofDir is one of:
;; - empty
;; - (cons Dir ListOfDir)
;; interp. a list of directories
(define SELFIES (make-dir "Selfies" 853 empty))
(define FIRSTYEAR (make-dir "First Year" 14 empty))
(define HACKATHON (make-dir "Hackathons" 9 empty))
(define UBC (make-dir "UBC" 14 (list FIRSTYEAR HACKATHON)))
(define PROBLEMSETS (make-dir "Problem Sets" 10 empty))
(define PRACTICE (make-dir "Practice Exams" 3 (list (make-dir "MT1" 6 empty)
(make-dir "MT2" 22 empty))))
(define HOMEWORK (make-dir "Homework" 56 (list
(make-dir "Everything else" 4 empty)
(make-dir "CPSC110" 123 (list PROBLEMSETS
PRACTICE)))))
(define DOCUMENTS (make-dir "Documents" 156 (list HOMEWORK
(make-dir "Job" 13 empty))))
(define PICTURES (make-dir "Pictures" 260 (list
(make-dir "Holidays" 28 empty)
UBC
SELFIES)))
(define STUFF (make-dir "My Stuff" 399 (list DOCUMENTS PICTURES)))
#;
(define (fn-for-dir d0)
(local [(define (fn-for-dir d)
(... (dir-name d)
(dir-num-files d)
(fn-for-lod (dir-subs d))))
(define (fn-for-lod lod)
(cond [(empty? lod) (...)]
[else
(... (fn-for-dir (first lod))
(fn-for-lod (rest lod)))]))]
(fn-for-dir d0)))
;Part A
;;=================accumulator with mr + tail==============================
;Design a function consumes a Dir and produces a sum of
;the number of files in that directory combined with the number
;of files in its sub-directories (and their sub-dirs, etc).
;Your solution MUST be tail recursive.
Solution:
;; WebPage -> Natural
;; produce the total number of views for a webpage and its sub-pages
(check-expect (total-files SELFIES) 853)
(check-expect (total-files UBC) (+ 14 14 9))
(check-expect (total-files STUFF) 1970)
;(define (total-files d0) 0) ;stub
;<template as encapsulated function from types with rsf and worklist accumulators>
(define (total-files d0)
(local [;; rsf is Natural: total files seen so far
;; todo is (listof Dir): the dirs that still need to be visited
(define (fn-for-dir d todo rsf)
(fn-for-lod (append (dir-subs d) todo) (+ (dir-num-files d) rsf)))
(define (fn-for-lod todo rsf)
(cond [(empty? todo) rsf]
[else
(fn-for-dir (first todo) (rest todo) rsf)]))]
(fn-for-dir d0 empty 0)))
;PartB
;;=================accumulator with mr + none tail==============================
;Design a function that consumes a Dir and produces a list of the names
;of sub-directories that have more files than their parent directory.
;Note: the directory named "Documents" is considered the parent of the
;directory named "Homework" because the Homework directory is found within
;the Document directory's list of sub-dirs.
;If a directory does not have a parent directory - such as "My Stuff" - or
;the parent is unknown, you may assume the parent contains 0 files.
;NOTE: Your solution does NOT have to be tail-recursive.
;;Solution
;; Dir -> (listof String)
;; produce the names of directories that contain more files than their parent directory
(check-expect (full-dirs UBC) (list "UBC"))
(check-expect (full-dirs PICTURES) (list "Pictures" "Selfies"))
(check-expect (full-dirs PRACTICE) (list "Practice Exams" "MT1" "MT2"))
(check-expect (full-dirs STUFF) (list "My Stuff" "CPSC110" "MT1" "MT2" "Selfies"))
;(define (full-dirs d) empty) ;stub
;<template as encapsulated function from types using cp accumulator>
#;
(define (full-dirs d0)
(local [;; parent-files is Natural: number of files in current dir's parent
(define (fn-for-dir d parent-files)
(if (> (dir-num-files d) parent-files)
(cons (dir-name d) (fn-for-lod (dir-subs d) (dir-num-files d)))
(fn-for-lod (dir-subs d) (dir-num-files d))))
(define (fn-for-lod lod parent-files)
(cond [(empty? lod) empty]
[else
(append (fn-for-dir (first lod) parent-files)
(fn-for-lod (rest lod) parent-files))]))]
(fn-for-dir d0 0)))
;PartC Bonus
;;=================none tail -> tail use tandem worklist==============================
;(Try a tail-recursive solution as an extra challenge if you'd like, but
;you will need to use a tandem worklist accumulator)
(define (full-dirs d0)
(local [;; todo is (listof Dir): todo
;; lopfs is (listof Natural): number of files in current dir's parent
;; rsf is (listof String): resull so far
(define (fn-for-dir d parent-files todo lopfs rsf)
(if (> (dir-num-files d) parent-files)
(fn-for-lod (append (dir-subs d) todo)
(append (map (lambda (cur) (dir-num-files d)) (dir-subs d)) lopfs)
(cons (dir-name d) rsf))
(fn-for-lod (append (dir-subs d) todo)
(append (map (lambda (cur) (dir-num-files d)) (dir-subs d)) lopfs)
rsf)))
(define (fn-for-lod todo lopfs rsf)
(cond [(empty? todo) (reverse rsf)]
[else
(fn-for-dir (first todo)
(first lopfs)
(rest todo)
(rest lopfs)
rsf)]))]
(fn-for-dir d0 0 empty empty empty)))