How to have an increasing variable correctly here? - scheme

(define (teken-n x y n)
(if (not (zero? n))
(begin
(teken-symbolen x y)
(teken-n x y (- n 1)))))
(define (teken-symbolen-combinatie x y n)
(if (not (zero? n))
(begin
(let ((acc 0))
(teken-n x y (+ acc 1))
(newline)
(teken-symbolen-combinatie x y (- n 1))))))
The use of (teken-n x y n) is to print 2 symbols, 'x 'y in the form xyx n times on 1 line without any spaces. It works correctly.
what I'm trying to accomplish with (teken-symbolen-combinatie x y n) would be the output
(teken-symbolen-combinatie '- '* 3)
-*-
-*--*-
-*--*--*-
My code only gives the first symbol combination, in this example -*- 3 times seperated with a newline. Meaning that my first function's last variable doesn't get incremented correctly. I can't figure out why.
EDIT: correction of mistakes within question

The thing that doesn't get incremented is acc. The function + returns a new value, it doesn't change any of its arguments.
The usual way in Scheme would be to have an inner loop that has another variable (which seems to be what your acc is intended for) increase to n. You do not need to have the outer function loop.

This might be what you're looking for (not tested; I don't have your other functions)
(define (teken-symbolen-combinatie x y n)
(define (loop acc)
(if (not (= acc n))
(begin
(teken-n x y (+ acc 1))
(newline)
(loop (+ acc 1)))))
(loop 0))
This uses #Svante's suggestion of creating an inner loop: here it is a recursive function named loop that call itself with an incrementing counter. After its definition, the outer function fires the loop off with an initial value of 0.
This is a pretty common pattern in Scheme: define a function within another that works like a loop by calling itself recursively. If the inner loop is tail-recursive, Scheme will optimize it so it runs fast!

Related

Understanding how a sequence works

I have the following accumulate function:
; accumulate
(define (accumulate op initial sequence)
(if (null? sequence)
initial
(op (car sequence) (accumulate op initial (cdr sequence)))))
I'm trying to write a length function to get the length of a sequence using the accumulate function.
For the function to plug into accumulate, why is it (+ y 1) instead of (+ x 1) ? That's the part I can't figure out:
(define (length sequence)
(accumulate (lambda (x y) (+ x 1)) ; wrong
0
sequence))
(define (length sequence)
(accumulate (lambda (x y) (+ y 1)) ; correct
0
sequence))
Your problem is that x and y doesn't tell you anything what it is. However if you look at accumulate you can see how op is called:
(op (car sequence) ; first argument is the element
(accumulate op initial (cdr sequence))) ; second argument is the accumulated value
While it doesn't really look that way Imagine that the second argument is calling accumulate on the empty sequence. Then you get this:
(op (car sequence)
initial)
So lets make length:
(define (length sequence)
(accumulate (lambda (element initial)
;; initial is often also called acc / accumulator
(+ 1 initial))
0
sequence))
So the answer is that the first argument is the individual element while the second is either the initial value (0) or the previous calculated value which is 0 with as many 1 added as the tail of the sequence had. Thus a number. WHy you don't use the first argument is that you can't really use "a" or whatever the list contains to count elements since you need to just count them not use them as values. If you use the first argument and it happens to be strings what is (+ "a" 0) supposed to help in finding out that the list has length 1?
If you use (lambda (x y) (+ x 1)) as op, then your length (or to be precise, the accumulate) function will not use the result of the recursive calls to the accumulate function. It will essentially only do one computation, (+ x 1) ,where x is (car sequence), the first element of sequence -- and this one computation may or may not even make sense, depending on whether or not x is a number, and even if it did the answer would be wrong.
On the other hand, if op is (lambda (x y) (+ y 1)), then your function will replace
(op (car sequence) (accumulate op initial (cdr sequence)))
with
(+ (accumulate op initial (cdr sequence)) 1)
The recursion bottoms out with the computation (+ 0 1), so you ultimately get the length of the list, when each of the nested recursive calls to accumulate return the length of the sub-lists to their calling functions.

SICP 1.45 - Why are these two higher order functions not equivalent?

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.

How does the named let in the form of a loop work?

In an answer which explains how to convert a number to a list the number->list procedure is defined as follows:
(define (number->list n)
(let loop ((n n)
(acc '()))
(if (< n 10)
(cons n acc)
(loop (quotient n 10)
(cons (remainder n 10) acc)))))
Here a "named let" is used. I don't understand how this named let works.
I see that a loop is defined where the variable n is equal to n, and the variable acc equal to the empty list. Then if n is smaller than 10 the n is consed to the acc. Otherwise, "the loop" is applied with n equal to n/10 and acc equal to the cons of the remainder of n/10 and the previous accumulated stuff, and then calls itself.
I don't understand why loop is called loop (what is looping?), how it can automatically execute and call itself, and how it will actually add each number multiplied by its appropriate multiplier to form a number in base 10.
I hope someone can shine his or her light on the procedure and the above questions so I can better understand it. Thanks.
The basic idea behind a named let is that it allows you to create an internal function, that can call itself, and invoke it automatically. So your code is equivalent to:
(define (number->list n)
(define (loop n acc)
(if (< n 10)
(cons n acc)
(loop (quotient n 10)
(cons (remainder n 10) acc))))
(loop n '()))
Hopefully, that is easier for you to read and understand.
You might, then, ask why people tend to use a named let rather than defining an internal function and invoking it. It's the same rationale people have for using (unnamed) let: it turns a two-step process (define a function and invoke it) into one single, convenient form.
It's called a loop because the function calls itself in tail position. This is known as tail recursion. With tail recursion, the recursive call returns directly to your caller, so there's no need to keep the current call frame around. You can do tail recursion as many times as you like without causing a stack overflow. In that way, it works exactly like a loop.
If you'd like more information about named let and how it works, I wrote a blog post about it. (You don't need to read it to understand this answer, though. It's just there if you're curious.)
A normal let usage can be considered an anonymous procedure call:
(let ((a 10) (b 20))
(+ a b))
;; is the same as
((lambda (a b)
(+ a b))
10
20)
A named let just binds that procedure to a name in the scope of the procedure so that it is equal to a single procedure letrec:
(let my-chosen-name ((n 10) (acc '()))
(if (zero? n)
acc
(my-chosen-name (- n 1) (cons n acc)))) ; ==> (1 2 3 4 5 6 7 8 9 10)
;; Is the same as:
((letrec ((my-chosen-name
(lambda (n acc)
(if (zero? n)
acc
(my-chosen-name (- n 1) (cons n acc))))))
my-chosen-name)
10
'()) ; ==> (1 2 3 4 5 6 7 8 9 10)
Notice that the body of the letrec just evaluates to the named procedure so that the name isn't in the environment of the first call. Thus you could do this:
(let ((loop 10))
(let loop ((n loop))
(if (zero? n)
'()
(cons n (loop (- n 1))))) ; ==> (10 9 8 7 6 5 4 3 2 1)
the procedure loop is only in the environment of the body of the inner let and does not shadow the variable loop of the outer let.
In your example, the name loop is just a name. In Scheme every loop is ultimately done with recursion, but usually the name is used when it's tail recursion and thus an iterative process.

Computing a list containing the numbers from x to y

How can I create a method which takes two numbers and prepare a list from first number to second number. The first number is always positive and less than second number? I tried the following but the I am not sure how to have a global variable in Scheme to hold previous values.
(define preplist
(let ((temp '()))
(lambda (x y)
(cond ((= x y) (append temp (list x)))
(else (append temp (list x))
(display x)
(preplist (+ x 1) y))))))
Expected result is: (preplist 3 7) => (3 4 5 6 7)
Can some one please help to resolve this problem?
The solution for (x, y) can be computed as: put x on the front of (x+1, y). It is thus clearly recursive. Like this:
(define (preplist x y)
(if (= x y)
(list y)
(cons x (preplist (+ x 1) y))))
See, it works:
> (preplist 1 4)
(1 2 3 4)
> (preplist 5 7)
(5 6 7)
There are several mistakes in your code, for starters you don't need a global variable defined in a let for storing the result, it's enough to build the answer as you advance in the recursion. And don't use append in this case, if the solution template is followed closely, a cons will suffice for building the output list.
You should stick to the recipe for building a new list recursively; this is how the problem should be solved using that recipe, it's perhaps a bit more idiomatic like this:
(define preplist
(lambda (x y)
(cond ((> x y) ; if the exit condition is met
empty) ; then return the empty list
(else ; otherwise
(cons x ; cons the current element
(preplist (add1 x) y)))))) ; and advance the recursion
An altogether different approach would be to write a tail-recursive solution. This is more efficient because a constant amount of stack is used. It doesn't follow the design recipe as outlined above, but is somewhat more similar to the solution you had in mind - but bear in mind that this doesn't use global variables (only a named let for the iteration) and the solution is accumulated and passed around as a parameter:
(define (preplist x y)
(let loop ((i y) ; named let for iteration
(acc empty)) ; define and initialize parameters
(if (> x i) ; if exit condition is met
acc ; return accumulated value
(loop (sub1 i) ; otherwise advance recursion
(cons i acc))))) ; and add to the accumulator
Of course, as pointed by #dyoo in the comments, in a practical setting you'd use the built-in range procedure which does basically the same as the preplist procedure.

How to create a function that multiplies all numbers between 1 and "x" with dotimes?

I'm making a function that multiplies all numbers between an 1 input and a "x" input with dotimes loop. If you please, check my function and say what's wrong since I don't know loops very well in Scheme.
(define (product x)
(let ((result 1))
(dotimes (temp x)
(set! result (* temp (+ result 1))))
result))
Use recursion. It is the way to do things in Scheme/Racket. And try to never use set! and other functions that change variables unless there really is no other choice.
Here's a textbook example of recursion in Scheme:
(define factorial
(lambda (x)
(if (<= x 1)
1
(* x (factorial (- x 1))))))

Resources