I am trying to Define a recursive procedure called (nDivide x y n) with three parameters x, y, and n. It returns the result of x divided by y n times. I have a function that divides
(define (Divide x y)
(/ x y)).
Now I am trying to use the Divide functions in to nDivide and I cant get it to work
There are basically two ways to do something n times:
Do it once, then do it n - 1 times;
Do it n - 1 times, then do it once.
You get different procedures depending on which path you choose:
; divide, then recurse
(define (nDivide x y n)
(if (zero? n)
x
(nDivide (Divide x y) y (- n 1))))
; recurse, then divide
(define (nDivide x y n)
(if (zero? n)
x
(Divide (nDivide x y (- n 1)) y)))
Recursive implementation (though why would anyone do this):
(define (nDivide x y n)
(if (= n 0)
x
(Divide (nDivide x y (- n 1)) y)))
Here is an iterative implementation of nDivide, which is more straightforward:
(define (nDivide x y n)
(if (= n 0)
x
(nDivide (Divide x y) y (- n 1))))
(define (Divide x y) (/ x y))
Example:
(nDivide 10000 3 4)
;Value: 10000/81
Related
I'm having trouble figuring out how to sort out the 2 biggest numbers and return them into the sum of squares procedure. I am struggling to write the code out in Scheme's syntax. I'm trying to write it as cleanly as possible, and I keep running circles in my head and on paper trying to do so. the book describes thinking "procedurally" and I think I'm having trouble with that aspect.
The book provides code for the sum-of-squares and square procedures. I would include my pseudo code but I'm severely lost. Here is the code the book provides:
(define (square x) (* x x))
(define (sum-of-squares x y)
(+ (square x) (square y)))
How to define a procedure that takes three numbers as arguments and returns the sum of the squares of the two larger numbers?
How to define a procedure that takes three numbers as arguments and returns the sum of the squares of the two larger numbers?
First you need a name for the procedure. Let's called it sum-of-squares-two-largest.
(define (sum-of-squares-two-largest x y z)
...)
It can make use of the sum-of-squares function, but it needs to find the two largest numbers out of x,y,z first.
One way to do this would be to get rid of the smallest number. You could define a helper procedure smallest? a b c that checks that a is the smallest of the 3 numbers by doing (and (<= a b) (<= a c)).
(define (sum-of-squares-two-largest x y z)
(if (smallest? x y z)
(sum-of-squares y z)
(if (smallest? y x z)
...]
Write the code for min-of-three. Its negative (as in photography) is what you need:
(define (negative-min-of-three a b c)
(if (<= a b)
(if (<= a c)
(..... b ... c .....)
(..... a ... b .....))
(if (<=
..........
You can complete the code, and rename it. The clock is ticking!
I created two methods to get the largest and the one in the middle for the time being.
(define (largest x y z)
(cond ((and (> x y) (> x z)) x)
((and (> y x) (> y z)) y)
(else z))
)
(define (mid x y z)
(cond ((and (> x y) (< x z)) x)
((and (> y x) (< y z)) y)
(else z))
)
(define (square a)
(* a a)
)
(define (sum-of-two-largest x y z)
(+ (square (largest x y z)) (square (mid x y z)))
)
(sum-of-two-largest -12 -4 1)
The hard part of this is, if you're reading SICP book, finding the 2nd largest number of the three. You can observe, if we let c < b < a, that:
a = max(a, b) gives the largest of the two numbers
b = max(c, b) gives the largest of the two smaller numbers
But how do we get the variable b on the second line. It can so happen that a is the smaller of the two? We can observe that:
b = min(a, b)
If we substitute min(a, b) for b in the max function on the third line, we get:
b = max(c, min(a, b))
This strategy is implemented in the following code, using only the constructs introduced in the book so far:
(define (square x) (* x x))
(define (max a b) (if (> a b) a b))
(define (min a b) (if (< a b) a b))
(define (sum-of-squares-two-largest a b c)
(+ (square (max a b)) (square (max c (min a b)))))
(sum-of-squares-two-largest 1 2 3)
(sum-of-squares-two-largest 1 2 1)
I'm going through the exercises in [SICP][1] and am wondering if someone can explain the difference between these two seemingly equivalent functions that are giving different results! Is this because of rounding?? I'm thinking the order of functions shouldn't matter here but somehow it does? Can someone explain what's going on here and why it's different?
Details:
Exercise 1.45: ..saw that finding a fixed point of y => x/y does not
converge, and that this can be fixed by average damping. The same
method works for finding cube roots as fixed points of the
average-damped y => x/y^2. Unfortunately, the process does not work
for fourth roots—a single average damp is not enough to make a
fixed-point search for y => x/y^3 converge.
On the other hand, if we
average damp twice (i.e., use the average damp of the average damp of
y => x/y^3) the fixed-point search does converge. Do some experiments
to determine how many average damps are required to compute nth roots
as a fixed-point search based upon repeated average damping of y => x/y^(n-1).
Use this to implement a simple procedure for computing the roots
using fixed-point, average-damp, and the repeated procedure
of Exercise 1.43. Assume that any arithmetic operations you need are
available as primitives.
My answer (note order of repeat and average-damping):
(define (nth-root-me x n num-repetitions)
(fixed-point (repeat (average-damping (lambda (y)
(/ x (expt y (- n 1)))))
num-repetitions)
1.0))
I see an alternate web solution where repeat is called directly on average damp and then that function is called with the argument
(define (nth-root-web-solution x n num-repetitions)
(fixed-point
((repeat average-damping num-repetition)
(lambda (y) (/ x (expt y (- n 1)))))
1.0))
Now calling both of these, there seems to be a difference in the answers and I can't understand why! My understanding is the order of the functions shouldn't affect the output (they're associative right?), but clearly it is!
> (nth-root-me 10000 4 2)
>
> 10.050110705350287
>
> (nth-root-web-solution 10000 4 2)
>
> 10.0
I did more tests and it's always like this, my answer is close, but the other answer is almost always closer! Can someone explain what's going on? Why aren't these equivalent? My guess is the order of calling these functions is messing with it but they seem associative to me.
For example:
(repeat (average-damping (lambda (y) (/ x (expt y (- n 1)))))
num-repetitions)
vs
((repeat average-damping num-repetition)
(lambda (y) (/ x (expt y (- n 1)))))
Other Helper functions:
(define (fixed-point f first-guess)
(define (close-enough? v1 v2)
(< (abs (- v1 v2))
tolerance))
(let ((next-guess (f first-guess)))
(if (close-enough? next-guess first-guess)
next-guess
(fixed-point f next-guess))))
(define (average-damping f)
(lambda (x) (average x (f x))))
(define (repeat f k)
(define (repeat-helper f k acc)
(if (<= k 1)
acc
;; compose the original function with the modified one
(repeat-helper f (- k 1) (compose f acc))))
(repeat-helper f k f))
(define (compose f g)
(lambda (x)
(f (g x))))
You are asking why “two seemingly equivalent functions” produce a different result, but the two functions are in effect very different.
Let’s try to simplify the problem to see why they are different. The only difference between the two functions are the two expressions:
(repeat (average-damping (lambda (y) (/ x (expt y (- n 1)))))
num-repetitions)
((repeat average-damping num-repetition)
(lambda (y) (/ x (expt y (- n 1)))))
In order to simplify our discussion, we assume num-repetition equal to 2, and a simpler function then that lambda, for instance the following function:
(define (succ x) (+ x 1))
So the two different parts are now:
(repeat (average-damping succ) 2)
and
((repeat average-damping 2) succ)
Now, for the first expression, (average-damping succ) returns a numeric function that calculates the average between a parameter and its successor:
(define h (average-damping succ))
(h 3) ; => (3 + succ(3))/2 = (3 + 4)/2 = 3.5
So, the expression (repeat (average-damping succ) 2) is equivalent to:
(lambda (x) ((compose h h) x)
which is equivalent to:
(lambda (x) (h (h x))
Again, this is a numeric function and if we apply this function to 3, we have:
((lambda (x) (h (h x)) 3) ; => (h 3.5) => (3.5 + 4.5)/2 = 4
In the second case, instead, we have (repeat average-damping 2) that produces a completely different function:
(lambda (x) ((compose average-damping average-damping) x)
which is equivalent to:
(lambda (x) (average-damping (average-damping x)))
You can see that the result this time is a high-level function, not an integer one, that takes a function x and applies two times the average-damping function to it. Let’s verify this by applying this function to succ and then applying the result to the number 3:
(define g ((lambda (x) (average-damping (average-damping x))) succ))
(g 3) ; => 3.25
The difference in the result is not due to numeric approximation, but to a different computation: first (average-damping succ) returns the function h, which computes the average between the parameter and its successor; then (average-damping h) returns a new function that computes the average between the parameter and the result of the function h. Such a function, if passed a number like 3, first calculates the average between 3 and 4, which is 3.5, then calculates the average between 3 (again the parameter), and 3.5 (the previous result), producing 3.25.
The definition of repeat entails
((repeat f k) x) = (f (f (f (... (f x) ...))))
; 1 2 3 k
with k nested calls to f in total. Let's write this as
= ((f^k) x)
and also define
(define (foo n) (lambda (y) (/ x (expt y (- n 1)))))
; ((foo n) y) = (/ x (expt y (- n 1)))
Then we have
(nth-root-you x n k) = (fixed-point ((average-damping (foo n))^k) 1.0)
(nth-root-web x n k) = (fixed-point ((average-damping^k) (foo n)) 1.0)
So your version makes k steps with the once-average-damped (foo n) function on each iteration step performed by fixed-point; the web's uses the k-times-average-damped (foo n) as its iteration step. Notice that no matter how many times it is used, a once-average-damped function is still average-damped only once, and using it several times is probably only going to exacerbate a problem, not solve it.
For k == 1 the two resulting iteration step functions are of course equivalent.
In your case k == 2, and so
(your-step y) = ((average-damping (foo n))
((average-damping (foo n)) y)) ; and,
(web-step y) = ((average-damping (average-damping (foo n))) y)
Since
((average-damping f) y) = (average y (f y))
we have
(your-step y) = ((average-damping (foo n))
(average y ((foo n) y)))
= (let ((z (average y ((foo n) y))))
(average z ((foo n) z)))
(web-step y) = (average y ((average-damping (foo n)) y))
= (average y (average y ((foo n) y)))
= (+ (* 0.5 y) (* 0.5 (average y ((foo n) y))))
= (+ (* 0.75 y) (* 0.25 ((foo n) y)))
;; and in general:
;; = (2^k-1)/2^k * y + 1/2^k * ((foo n) y)
The difference is clear. Average damping is used to dampen the possibly erratic jumps of (foo n) at certain ys, and the higher the k the stronger the damping effect, as is clearly seen from the last formula.
I have asked an earlier question regarding how to set-up my function based on the requirements in the problem, and using already the code I had written, the problem now is that, no matter what, the output stays the same, no matter how much I change the value of the parameter k in first-value-k-or-higher x tol 1.
Here is my code based on the feedback in my other question:
(define (square x)
(* x x))
(define (first-value-k-or-higher x tol k)
(if (<= (abs(- x
(square (babylonian x k))))
tol)
k
(first-value-k-or-higher x tol (+ k 1))))
(define (terms-needed x tol)
(first-value-k-or-higher x tol 1))
Here is a couple example outputs if the function looks like the one I have above:
> (terms-needed 15 .001)
1
> (terms-needed 234 3)
1
> (terms-needed 23421 453)
1
>
If I change the function terms-needed x tol to something like this:
(define (square x)
(* x x))
(define (first-value-k-or-higher x tol k)
(if (<= (abs(- x
(square (babylonian x k))))
tol)
k
(first-value-k-or-higher x tol (+ k 1))))
(define (terms-needed x tol)
(first-value-k-or-higher x tol 100))
The new function will output:
> (terms-needed 15 .0001)
100
> (terms-needed 243 3)
100
>
Terms-needed is supposed to evaluate to the number of terms in the infinite sum needed to be within tol, that is, the smallest k such that the difference between x and (square (babylonian x k)) is less than tol. As I have mentioned the problem is I keep getting the same output of "1" no matter what I put down for the values of the parameters of terms-needed x tol. I also believe that is where the problem is coming from, because if I change (first-value-k-or-higher x tol 1)) to something like (first-value-k-or-higher x tol 2)) or any other value (first-value-k-or-higher x tol 2)) will output that value, for example with (first-value-k-or-higher x tol 2)) will output 2.
Here is the function babylonian x k that is needed to run the program first-value-k-or-higher x tol k which is needed to run terms-needed x tol:
(define (babylonian x k)
(if (>= x 1)
(if (= k 0)
(/ x 2)
(* (/ 1 2) (+ (expt x (/ 1 2)) (/ x (expt x (/ 1 2))))))
1)
)
The babylonian function is supposed to compute roots using the babylonian method and evaluates to the k^th approximation (Sk). The babylonian function passes all the tests as well.
Here is my earlier problem for more background information
No,
(define (babylonian x k)
(if (>= x 1)
(if (= k 0)
(/ x 2)
(* (/ 1 2) (+ (expt x (/ 1 2)) (/ x (expt x (/ 1 2))))))
1)
)
could not possibly be computing "the k^th approximation" of x, because there's no k in the alternative of the inner if expression.
I am having trouble where my code feels incomplete and plain wrong. For my function (terms-needed x tol) I am supposed to find the smallest k such that the difference between x and (square (babylonian x k)) is less than tol (tolerance). In other words we are supposed to measure how large k needs to be in the function (babylonian x k) to provide a good approximation of the square root.
As of right now I am getting an error of "application: not a procedure;" with my code
(define (square x)
(* x x))
(define (first-value-k-or-higher x tol k)
(if (<= (x)
(square (babylonian x k)) tol)
k)
(first-value-k-or-higher x tol (+ k 1))
)
(define (terms-needed x tol)
(first-value-k-or-higher x tol 1))
We are supposed to use a helper-function (first-value-k-or-higher x tol k) that evaluates to k if (square (bablyonian x k)) is within tol of the argument x, otherwise calls itself recursively
with larger k.
This is the function that is needed to make (terms-needed x tol) work:
(define (babylonian x k)
(if (>= x 1)
(if (= k 0)
(/ x 2)
(* (/ 1 2) (+ (expt x (/ 1 2)) (/ x (expt x (/ 1 2))))))
1)
)
Here is the full text, providing the full context on what the problem is supposed to be.
We will now measure how large k needs to be in the above function to provide a good approximation
of the square root. You will write a SCHEME function (terms-needed x tol) that will
evaluate to the number of terms in the infinite sum needed to be within tol, that is, the smallest
k such that the difference between x and (square (babylonian x k)) is less than tol.
Remark 2. At first glance, the problem of defining (terms-needed x tol) appears a little challenging,
because it’s not at all obvious how to express it in terms of a smaller problem. But you might
consider writing a helper function (first-value-k-or-higher x tol k) that evaluates to k if
(square (bablyonian x k)) is within tol of the argument x, otherwise calls itself recursively
with larger k.
You have several problems.
First, you have parentheses around x in
(if (<= (x)
That's causing the error you're seeing, because it's trying to call the function named x, but x names a number, not a function.
Second, you're not calculating the difference between x and (square (babylonian x k)). Instead, you gave 3 arguments to <=.
Third, you're not making the recursive call when the comparison fails. It's outside the if, so it's being done all the time (if you make use of an editor's automatic indentation feature, you might have noticed this problem yourself).
Fourth, you need to get the absolute value of the difference, not just the difference itself. Otherwise, if the difference is a large negative number, you'll consider it within the tolerance, which it shouldn't be.
(define (first-value-k-or-higher x tol k)
(if (<= (abs (- x (square (babylonian x k))))
tol)
k
(first-value-k-or-higher x tol (+ k 1))))
I'm reading SICP and doing exercise 2.5:
Exercise 2.5. Show that we can represent pairs of nonnegative
integers using only numbers and arithmetic operations if we represent
the pair a and b as the integer that is the product 2^a*3^b.
Give the corresponding definitions of the procedures cons, car,
and cdr.
Here is my solution:
;;; Exercise 2.5
;;; ============
(define (cons x y)
(* (expt 2 x)
(expt 3 y)))
(define (car z)
; n is a power of 2, which is greater than z
(let ((n (expt 2 (ceiling (/ (log z) (log 2))))))
(/ (log (gcd z n)) (log 2))))
(define (cdr z)
; n is a power of 3, which is greater than z
(let ((n (expt 3 (ceiling (/ (log z) (log 2))))))
(/ (log (gcd z n)) (log 3))))
My code works well with relatively small test cases:
(define x 12)
(define y 13)
(define z (cons x y))
(car z)
;Value: 12.
(cdr z)
;Value: 12.999999999999998
However, it produces incorrect results when the number grows bigger:
(define x 12)
(define y 14)
(define z (cons x y))
(car z)
;Value: 12.
(cdr z)
;Value: 2.8927892607143724 <-- Expected 14
I want to know what's wrong with my implementation. Is there anything wrong with the algorithm? The idea is that the greatest common devisor of z = 2 ^ x * 3 ^ y and n (a power of 2 which is greater than z) is exactly 2 ^ x.
If my algorithm is correct, is this inconsistency caused by a rounding error and/or an overflow?
One solution is to avoid floating point numbers.
Consider max-power-dividing which finds the maximal exponent k such that p^k divides n:
(define (max-power-dividing p n)
(if (zero? (remainder n p))
(+ 1 (max-power-dividing p (/ n p)))
0))
Then we can write:
(define (car z) (max-power-dividing 2 z))
(define (cdr z) (max-power-dividing 3 z))
As far as I can tell, your solution uses the right idea, but the floating point computation breaks for large numbers.