figured it out . What I wrote on this to figure things out is pasted below
Let’s start with (fi 3)
(the “i” standing for iterative).
For (fi n)
where n
= 3:
(fi (- n 1))
= (fi 2)
= 2
(fi (- n 2))
= (fi 1)
= 1
(fi (- n 3))
= (fi 0)
= 0
To figure out (fi 3)
, we want sum up (fi 2)
(or 2), 2 multiplied by (fi 1)
(or 2), and 3 times (fi 0)
(or 0). We get a total of 4 from doing this.
Suppose we want to figure out (fi 4)
. To figure out (fi 4)
, we’ll need the values of (fi 3)
, (fi 2)
, and (fi 1)
. When n = 3 for (fi n)
, those values are:
for (fi 3)
, the sum of (fi 2)
, 2 times (fi 1)
, and 3 times (fi 0)
. This is 4.
for (fi 2)
, the value of (fi (- n 1)
, which is 2.
for (fi 1)
, the value of (fi (- n 2)
, which is 1.
So within (fi 3)
, we can generate all the values we need for calculating (fi 4)
.
We could think of there being three key values. For a given n, there is the value of fi
one step back (fi (- n 1)
, and the value of fi
two step backs, and the value of fi
three steps back ((fi (- n 2)
).
We might call these 1ago, 2ago, and 3ago.
For (fi 3)
, these values are 2, 1, 0.
For (fi 4)
, these values are 4, 2, 1.
For (fi 5)
, these values are 11, 4, 2.
For (fi 6)
, these values are 25, 11, 4.
For (fi 7)
, these values are 50, 25, 11.
Notice that a new value is generated using the existing values in the first slot (for 1ago), and then that value recurs as we increase n by 1, first as 2ago, then as 3ago.
In order to have an iterative procedure that can solve Exercise 1.11 for arbitrary values, we will want to do a recursive call to that iterative procedure with appropriate transformations of these values.
So, suppose we start at a calculation of (fi 3)
as our initial starting place with initial values of 2, 1, 0 for 1ago, 2ago, 3ago. How will we transform these values into a suitable form for calculating (fi 4)
?
As our new 1ago argument, we’ll want to provide (+ 1ago (* 2 2ago)(3 3ago))
. This is 4.
As our new 2ago argument, we’ll want to provide our current 1ago argument, which is (fi 2)
or 2.
As our new 3ago argument, we’ll want to provide our current 2ago argument, which is (fi 1)
or 1.
With these values provided, our procedure will be able to calculate (fi 4)
by engaging in the appropriate transformations of them per the rule specified in the exercise.
I went awry partially cuz I was doing unnecessary operations because I hadn’t thought in sufficient detail about which operations were necessary. He’s some mistaken code that that I wrote:
;bad wrong code; not the answer!
(define (fi n)
(if (< n 3) n
(fi-helper 2 1 0 3 n)))
(define (fi-helper 1ago 2ago 3ago current max)
(if (= current max)
(+ 1ago (* 2 2ago) (* 3 3ago))
(fi-helper
(+ 1ago 2ago 3ago) ;WRONG!
(* 2 1ago) ;WRONG!
(* 3 2ago) ;WRONG!
(+ current 1)
max)))
Multiple problems here.
One is that, for some reason, I’m doing a different operation on the numbers in my recursive call to fi-helper
(specifically, (+ 1ago 2ago 3ago)
) than I do as the consequent for the if
(specifically, (+ 1ago (* 2 2ago) (* 3 3ago))
. It was only after going through and writing all the stuff above that I realized clearly that these should be the same operation, and specifically that they should be (+ 1ago (* 2 2ago) (* 3 3ago))
.
The second issue is that I am unnecessarily multiplying the 1ago and 2ago values by 2 and 3, respectively, in providing them as arguments for my recursive call. Going through the above analysis helped me realize that these values should be left untouched.
Below is a fixed and functioning fi
program. Note that I also keep track of which n value we’re currently calculating (using current) and the final n we need to reach (with max).
(define (fi n)
(if (< n 3) n
(fi-helper 2 1 0 3 n)))
(define (fi-helper 1ago 2ago 3ago current max)
(if (= current max)
(+ 1ago (* 2 2ago) (* 3 3ago))
(fi-helper
(+ 1ago (* 2 2ago) (* 3 3ago))
1ago
2ago
(+ current 1)
max)))
EDIT: trying to write things out really explicitly and precisely was helpful. i was mixing up what I was supposed to do when and was getting myself confused.
Mindmap helped too but sometimes I just really need to write 500-1k words and see if stuff clicks after doing that.