Consider the function f : positive -> positive,
f(n) = | 1 | if n=1 |
n/2 | if n is even | |
3n+1 | if n is odd |
; threes : N[>=1] -> N[>=1] (define (threes n) (cond [(= n 1) 1] [else (cond [(even? n) (threes (/ n 2))] [else (threes (+ 1 (* n 3)))])]))Note that it is generative recursive.
An example: if we start with (say) 5, we find that:
To do: Write a program stops? which takes a number n, and returns true if n, f(n), f(f(n)), ... ever reaches the number 1, i.e., if (threes n) stops. (What does your program do if this doesn't happen?) It should not call threes, but it will resemble it. (Hint: Add an accumulator to a copy of threes.)
Q: Why do we choose to stop at f(1)?
Q: Does threes stop for all inputs? (Don't feel bad if you can't answer this. No one else has yet.)
To do: Now, write a function time-til-stop, which instead of returning true, it returns the number of steps until 1 is reached. That is, (time-til-stop 5) = 5. Test your program on some large numbers, say 1001, 2349872349247990, and 2349872349247991.
To do: Recall the equational definition of foldl:
(foldl f base (list x1 x2 ... xN)) = (f xN ... (f x2 (f x1 base))...)Write foldl using structural recursion and an accumulator.
In lab, we will discuss some ideas about what states are for the Missionaries & Cannibals problem. The following are some generalities to consider:
E.g., if we are representing only right triangles, the data might be the lengths of the three sides, but having two side lengths is sufficient. We may want to keep track of only the minimal amount of information (here, two sides' lengths), or all of the data (here, all three sides' lengths). The latter choice makes it easier to get at all of the data, but we may have to worry about having inconsistent data (here, three lengths that don't make a right triangle).
Your M&C program needs to build up a list of moves to the result. That sounds sort of similar to our in-class example that built up a list of cities for a path in a graph.