This preview shows pages 1–3. Sign up to view the full content.
This preview has intentionally blurred sections. Sign up to view the full version.
View Full Document
Unformatted text preview: Module 3 Algorithms that remember: accumulative recursion Because its best not to compute the same thing over and over CS 116: Introduction to Computer Science 2 Daniel G. Brown/Troy Vasiga, University of Waterloo 3.1 Purpose of Module 3 Accumulative recursion: the idea behind it Several examples of accumulative recursion Designing and debugging accumulatively recursive code. Readings: HtDP 30, 31 3.2 1 The idea of accumulative recursion Accumulative recursion Accumulative recursion is another kind of recursion that keeps information from one recursive call to the next. Example 1 . The factorial of n , written n !, is the product of all numbers from 1 up to n . We can compute this very easily in Scheme. ;; factorial: nat[>0] nat[>0] ;; compute the product of the numbers from 1 to n ;; Examples: ;; (factorial 3) 6 ;; (factorial 1) 1 ( define ( factorial n ) ( cond [(= n 1) 1] [ else ( * n ( factorial ( sub1 n )))])) 3.3 The reason for accumulative recursion What happens when we compute ( factorial 6) ? ( factorial 6) ( * 6 ( factorial 5)) ( * 6 ( * 5 ( factorial 4))) ( * 6 ( * 5 ( * 4 ( factorial 3)))) ( * 6 ( * 5 ( * 4 ( * 3 ( factorial 2))))) ( * 6 ( * 5 ( * 4 ( * 3 ( * 2 ( factorial 1)))))) ( * 6 ( * 5 ( * 4 ( * 3 ( * 2 1))))) ( * 6 ( * 5 ( * 4 ( * 3 2)))) 1 ... 720 Note: the formula gets more and more complicated. This doesnt matter for us if we think of computing in terms of rewriting formulas. But computers exist as physical devices, and carrying all of these recursive calls takes up memory on the physical device. We might run out of space very quickly. Its also probably not how human beings would do it. 3.4 An alternative approach We could keep the intermediate formulas much smaller, by doing one multiplication in each recursive call, and keeping the product of all the numbers weve seen so far as a function argument. ;; factorial2: nat[>0] nat[>0] ;; (purpose and examples as in factorial) ( define ( factorial2 n ) ;; runningproduct: nat[>0] nat[>0] nat[>0] ;; compute the product n0! * prodsofar ( local [( define ( runningproduct n0 prodsofar ) ( cond [(= n0 1) prodsofar ] [ else ( runningproduct ( sub1 n0 ) ( * prodsofar n0 ))]))] ( runningproduct n 1))) Here, each successive call to runningproduct has two arguments: n0 , the number that counts down to 1 , and prodsofar , the product of all of the numbers from n down to n0 3.5 An example trace of this function Heres what happens when we compute ( factorial2 6) : ( factorial2 6) ( runningproduct 6 1) ( runningproduct 5 ( * 1 6 )) ( runningproduct 5 6) ( runningproduct 4 ( * 6 5)) ( runningproduct 4 30) ( runningproduct 3 ( * 30 4)) ( runningproduct 3 120) ( runningproduct 2 ( * 120 3)) ( runningproduct 2 360) ( runningproduct 1 ( * 360 2)) ( runningproduct 1 720) 720 3.6 Differences between the two implementations...
View
Full
Document
This note was uploaded on 07/26/2011 for the course CS 116 taught by Professor T.vasiga during the Spring '09 term at Waterloo.
 Spring '09
 T.VASIGA
 Algorithms, Recursion

Click to edit the document details