#| -- ACCUMULATORS are orthogonal to structural design or generative recursion design. -- Why/when use it? The function somehow doesn't have enough information for the recursive cases to do its job well or efficiently: reverse, route? Symptom 1: you need to re-process the result for structural recursions Symptom 2: your function can't find the solution even though there is one Symptom 3: you want to process things in a different order than the natural one -- Design needs a change to the structural/generative template: Question 1: what information do you need to keep track of? Add a parameter and its contract Question 2: what's the "starting information"? Remember it. Question 3: when your function recurs it "drops" information. How do you add it (accumulate it) to the existing accumulator parameter? ... (selector main-argument) ... accumulator ... cons, +, ... etc. Question 4: how do you use the accumulated information in the function? New base case? Result of base case? The answer to this question may give you a hint for Questions 2/3. DONE: when wrapped up in local and initialized with Starting Information |# (define-struct node (toll left right)) ;; A BT is one of: ;; - 'leaf ;; - (make-node Number BT BT) ;; min-toll : BT -> Number ;; computer the minimum toll you must pay to get from the root of bt ;; to any leaf ;; Version 0 (structural recursion): #;(define (min-toll bt) (cond [(symbol? bt) 0] [(node? bt) (+ (node-toll bt) (min (min-toll (node-left bt)) (min-toll (node-right bt))))])) ;; Version 1 acc: (define (min-toll bt0) (local (;; BT Number -> Number ;; acc represents the toll paid so far along current path ;; (i.e., toll so far from root of bt0 to root of bt) (define (min-toll-acc bt acc) (cond [(symbol? bt) acc] [(node? bt) (min (min-toll-acc (node-left bt) (+ acc (node-toll bt))) (min-toll-acc (node-right bt) (+ acc (node-toll bt))))]))) (min-toll-acc bt0 0))) (define t1 (make-node 4 'leaf 'leaf)) (define t2 (make-node 9 'leaf t1)) (define t3 (make-node 9 t1 t1)) (define t4 (make-node 3 t3 t2)) (check-expect (min-toll 'leaf) 0) (check-expect (min-toll t1) 4) (check-expect (min-toll t2) 9) (check-expect (min-toll t3) 13) (check-expect (min-toll t4) 12) ;; sum-toll : BT -> Number ;; sum the tolls in the given bt ;; Version 0 (structural recursion): #;(define (sum-toll bt) (cond [(symbol? bt) 0] [(node? bt) (+ (node-toll bt) (sum-toll (node-left bt)) (sum-toll (node-right bt)))])) ;; Version 1 acc: #;(define (sum-toll bt0) (local (;; BT Number -> Number ;; acc represents the sum of the tolls encountered in the right ;; trees of the path from bt0 to bt (define (sum-toll-acc bt acc) (cond [(symbol? bt) acc] [(node? bt) (sum-toll-acc (node-left bt) (sum-toll-acc (node-right bt) (+ (node-toll bt) acc)))]))) (sum-toll-acc bt0 0))) ;; Version 2 acc (with todo list): (define (sum-toll bt0) (local (;; BT [Listof BT] -> Number ;; todo represents the list of BTs encountered but not processed (define (sum-toll-acc bt todo) (cond [(symbol? bt) (cond [(empty? todo) 0] [else (sum-toll-acc (first todo) (rest todo))])] [(node? bt) (+ (node-toll bt) (sum-toll-acc (node-left bt) (cons (node-right bt) todo)))]))) (sum-toll-acc bt0 empty))) (check-expect (sum-toll 'leaf) 0) (check-expect (sum-toll t1) 4) (check-expect (sum-toll t2) 13) (check-expect (sum-toll t3) 17) (check-expect (sum-toll t4) 33)