Module 4
Algorithms that remember:
accumulative recursion
Because it’s 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
4.1
Purpose of Module 4
•
Accumulative recursion: the idea behind it
•
Several examples of accumulative recursion
•
Designing and debugging accumulatively recursive code.
•
Readings:
HtDP 30, 31
4.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: num
→
num
;; 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
)))]))
4.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
This preview has intentionally blurred sections. Sign up to view the full version.
View Full Document
...
⇒
720
Note: the formula gets more and more complicated.
•
This doesn’t 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.
•
It’s also probably not how human beings would do it.
4.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 we’ve seen so far as a function argument.
;; factorial2: num
→
num
;; (purpose and examples as in factorial)
(
define
(
factorial2 n
)
;; runningproduct: num num
→
num
;; compute the product of 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
4.5
An example trace of this function
Here’s 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
4.6
Differences between the two implementations
There are two big differences:
•
We keep track of the product of the numbers we’ve seen so far in a second parameter,
prodsofar
.
This is the end of the preview.
Sign up
to
access the rest of the document.
 Fall '09
 T.VASIGA
 Computer Science, Algorithms, Recursion, Recurrence relation, Fibonacci number, Golden ratio

Click to edit the document details