SICP exercise 1.17 issue - scheme

I'm doing exercise 1.18 in SICP and I face some trouble. The goal is to make a procedure based on 2 previous exercises. This procedure implements so-called Russian peasant method (or Ancient Egyptian multiplication). I wrote a code, but one procedure just doesn't want to execute. Here's my code:
#lang sicp
(define (double a) (+ a a))
(define (halve a) (/ a 2))
(define (r_m a b)
(iter a b 0))
(define (iter a b n)
(cond ((= b 0) 0)
((even? a) (iter (halve a) (double b) (+ n b)))
(else (iter (halve a) (double b) n))))
So, when I call my procedure (r_m) with such arguments (r_m 13 19) it stops after 1st iteration.
(iter (halve a) (double b) (+ n b) (with arguments 13 and 19) gives this result: iter (13/2) 38 19
After that, program tries to check if 13/2 is odd. But it can't check such number (13/2), because odd? expects an integer, not this undone division.
For some reason, the halve procedure doesn't work when called. I don't really understand why, because other procedures (double and simple + n b) work fine.
Thank you in advance and I hope my grammar doesn't hurt you too much.

There are several things wrong with your program. Apart from anything else, even if halve worked the way you want it to work, how would b become zero? This is not the only problem!
However the particular case of halve happens because you are assuming programming languages to do what they normally do: incorrect arithmetic which is convenient for the machine, rather than correct arithmetic which is convenient for humans. Scheme tries hard to do correct arithmetic. What, mathematically, is 13/2? It's not 6, or 7, or 3, it's 13/2, or 6 + 1/2: it's a rational number, not an integer.
If you want the next integer below 13/2, the way you want to get it is by subtracting 1 before you divide: (halve (- 13 1)) is 6, exactly. So if you change that cond clause to have (halve (- a 1)) your program will be closer to working (but, in fact it will then fail to terminate, so in a sense it will be further from working...).

Related

SICP Exercise 1.16 - Is my solution correct?

Exercise 1.16: Design a procedure that evolves an iterative exponentiation process that uses successive squaring and uses a logarithmic number of steps, as does fast-expt. (Hint: Using the observation that (b(^n/2))^2 = (b(^2))^n/2 , keep, along with the exponent n and the base b, an additional state variable a, and define the state transformation in such a way that the product ab^n is unchanged from state to state. At the beginning of the process a is taken to be 1, and the answer is given by the value of a at the end of the process. In general, the technique of defining an invariant quantity that remains unchanged from state to state is a powerful way to think about the design of iterative algorithms.)
So I've tried really hard and came up with this solution:
(define (exp b n)
(exp-iter b n 1))
(define (square p) (* p p))
(define (even? k)
(= (remainder k 2) 0))
(define (exp-iter b counter product)
(define (smash counter)
(if (even? counter) (square (exp-iter b (/ 2 counter) product)) (* b (exp-iter b (- counter 1) product))))
(if (= counter 0) product (smash counter)))
(exp 4 3) ;test
This runs perfectly but I'm not sure if this is what the author asked me to do. Are there any problems with this? Is my solution really iterative?
Your solution is not iterative. An iterative process is one that doesn't call anything after the recursive call, and that's not the case in these two lines:
(square (exp-iter b (/ 2 counter) product))
(* b (exp-iter b (- counter 1) product))
After invoking exp-iter, in the first line you're passing the result to square, and in the second line you're multiplying the result by b. Compare it with this, a tail recursive solution:
(define (exp-iter b counter product)
(cond ((= counter 0)
product)
((even? counter)
(exp-iter (square b) (/ counter 2) product))
(else
(exp-iter b (- counter 1) (* b product)))))
Notice that after invoking exp-iter there's nothing left to do and the procedure simply returns its value. A smart compiler will detect this, and transform the recursive call into a loop that will use a constant amount of stack memory (instead of increasing with every recursive call.)

Scheme : recursive process much faster than iterative

I am studying SICP and wrote two procedures to compute the sum of 1/n^2, the first generating a recursive process and the second generating an iterative process :
(define (sum-rec a b)
(if (> a b)
0
(exact->inexact (+ (/ 1 (* a a)) (sum-rec (1+ a) b)))))
(define (sum-it a b)
(define (sum_iter a tot)
(if (> a b)
tot
(sum_iter (1+ a) (+ (/ 1 (* a a)) tot))))
(exact->inexact (sum_iter a 0)))
I tested that both procedures give exactly the same results when called with small values of b, and that the result is approaching $pi^2/6$ as b gets larger, as expected.
But surprisingly, calling (sum-rec 1 250000) is almost instantaneous whereas calling (sum-it 1 250000) takes forever.
Is there an explanation for that?
As was mentioned in the comments, sum-it in its present form is adding numbers using exact arithmetic, which is slower than the inexact arithmetic being used in sum-rec. To do an equivalent comparison, this is how you should implement it:
(define (sum-it a b)
(define (sum_iter a tot)
(if (> a b)
tot
(sum_iter (1+ a) (+ (/ 1.0 (* a a)) tot))))
(sum_iter a 0))
Notice that replacing the 1 with a 1.0 forces the interpreter to use inexact arithmetic. Now this will return immediately:
(sum-it 1 250000)
=> 1.6449300668562465
You can reframe both of these versions so that they do exact or inexact arithmetic appropriately, simply by controlling what value they use for zero and relying on the contagion rules. These two are in Racket, which doesn't have 1+ by default but does have a nice syntax for optional arguments with defaults:
(define (sum-rec low high (zero 0.0))
(let recurse ([i low])
(if (> i high)
zero
(+ (/ 1 (* i i)) (recurse (+ i 1))))))
(define (sum-iter low high (zero 0.0))
(let iterate ([i low] [accum zero])
(if (> i high)
accum
(iterate (+ i 1) (+ (/ 1 (* i i)) accum)))))
The advantage of this is you can see the performance difference easily for both versions. The disadvantage is that you'd need a really smart compiler to be able to optimize the numerical operations here (I think, even if it knew low and high were machine integers, it would have to infer that zero is going to be some numerical type and generate copies of the function body for all the possible types).

mutable variables racket for finding range

I am trying to solve this C question to find a function that takes in 2 integer parameters, a and b and produces the range of all the elements between them, I am trying to do this in Racket.
This is what I have got so far, I don't know how to move ahead. Would I need to use mutable variables?
(define (list-range a b)
(local [(define sum a)]
(build-list (+ (- a b) 1)
lambda (x y)
[(<= sum b)(+ sum 1)]
))
Please help me understand and solve this
This builds a list from from inclusive to to exclusive.
The inclusive/exclusive thing is the convention in Racket.
It is simply the most convenient due to the fact that list
indices start from 0.
#lang racket
(define (list-range from to)
(build-list (- to from)
(lambda (i) (+ from i))))
(list-range 5 7)
Output:
'(5 6)

Incrementing an alphabetic string in Scheme

I am trying to programmatically increment a purely alphabetical string in Scheme.
Like this "MA", then "MB" and when it reaches "MZ", it should become "MAA" and so on till "MZZ" and then it should become "MAAA" and so on.The "M" needs to be added as a prefix for the kind of work that I am doing.
I looked at this question: Incrementing alphabets and this is exactly what I want.
However, I have absolutely no idea from where to start. For starters I am not even sure how to handle ASCII in scheme. I am not expecting the whole code, but I would appreciate it if I got a few hints.
Here's my implementation. Note that you need to load SRFI 1, which provides unfold-right:
(define letters "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
(define (number->letters num)
(unfold-right negative?
(lambda (i) (string-ref letters (remainder i 26)))
(lambda (i) (- (quotient i 26) 1))
num))
(define (number->tag num)
(list->string (cons #\M (number->letters num))))
Examples:
> (number->tag 0)
"MA"
> (number->tag 18277)
"MZZZ"
> (number->tag 18278)
"MAAAA"
The OP asked for an explanation of what the code does. So, with the understanding that the OP already understands the algorithm (since they linked to it already), what's basically left is the unfold operation.
Fold and unfold are a bit lengthy to explain and I don't want to derail this post by explaining them, but it's possible to "expand" the unfold into the equivalent loop (using the same variable names as the SRFI 1 reference implementation of unfold-right) to express what's going on:
(define (number->letters num)
(let lp ((seed num) (ans '()))
(if (negative? seed)
ans
(lp (- (quotient seed 26) 1)
(cons (string-ref letters (remainder seed 26)) ans)))))
Basically, it builds a list, from right to left, using (string-ref letters (remainder seed 26)) each iteration (where seed is num in the initial iteration). seed's value is then updated to (- (quotient seed 26) 1) for the next iteration. The list stops when (negative? seed) is true.
You might then ask why one would use an unfold instead of the loop. Basically, in functional programming, when a "concept" can be expressed in higher-level terms (e.g., for-each, map, filter, fold, or unfold), using those terms helps other programmers understand what the code does. It's a bit like "design patterns" (as commonly used in object-oriented programming), within a functional programming context. :-)

Variadic Function in Scheme

I have to define a variadic function in Scheme that takes the following form:
(define (n-loop procedure [a list of pairs (x,y)]) where the list of pairs can be any length.
Each pair specifies a lower and upper bound. That is, the following function call: (n-loop (lambda (x y) (inspect (list x y))) (0 2) (0 3)) produces:
(list x y) is (0 0)
(list x y) is (0 1)
(list x y) is (0 2)
(list x y) is (1 0)
(list x y) is (1 1)
(list x y) is (1 2)
Obviously, car and cdr are going to have to be involved in my solution. But the stipulation that makes this difficult is the following. There are to be no assignment statements or iterative loops (while and for) used at all.
I could handle it using while and for to index through the list of pairs, but it appears I have to use recursion. I don't want any code solutions, unless you feel it is necessary for explanation, but does anyone have a suggestion as to how this might be attacked?
The standard way to do looping in Scheme is to use tail recursion. In fact, let's say you have this loop:
(do ((a 0 b)
(b 1 (+ a b))
(i 0 (+ i 1)))
((>= i 10) a)
(eprintf "(fib ~a) = ~a~%" i a))
This actually get macro-expanded into something like the following:
(let loop ((a 0)
(b 1)
(i 0))
(cond ((>= i 10) a)
(else (eprintf "(fib ~a) = ~a~%" i a)
(loop b (+ a b) (+ i 1)))))
Which, further, gets macro-expanded into this (I won't macro-expand the cond, since that's irrelevant to my point):
(letrec ((loop (lambda (a b i)
(cond ((>= i 10) a)
(else (eprintf "(fib ~a) = ~a~%" i a)
(loop b (+ a b) (+ i 1)))))))
(loop 0 1 0))
You should be seeing the letrec here and thinking, "aha! I see recursion!". Indeed you do (specifically in this case, tail recursion, though letrec can be used for non-tail recursions too).
Any iterative loop in Scheme can be rewritten as that (the named let version is how loops are idiomatically written in Scheme, but if your assignment won't let you use named let, expand one step further and use the letrec). The macro-expansions I've described above are straightforward and mechanical, and you should be able to see how one gets translated to the other.
Since your question asked how about variadic functions, you can write a variadic function this way:
(define (sum x . xs)
(if (null? xs) x
(apply sum (+ x (car xs)) (cdr xs))))
(This is, BTW, a horribly inefficient way to write a sum function; I am just using it to demonstrate how you would send (using apply) and receive (using an improper lambda list) arbitrary numbers of arguments.)
Update
Okay, so here is some general advice: you will need two loops:
an outer loop, that goes through the range levels (that's your variadic stuff)
an inner loop, that loops through the numbers in each range level
In each of these loops, think carefully about:
what the starting condition is
what the ending condition is
what you want to do at each iteration
whether there is any state you need to keep between iterations
In particular, think carefully about the last point, as that is how you will nest your loops, given an arbitrary number of nesting levels. (In my sample solution below, that's what the cur variable is.)
After you have decided on all these things, you can then frame the general structure of your solution. I will post the basic structure of my solution below, but you should have a good think about how you want to go about solving the problem, before you look at my code, because it will give you a good grasp of what differences there are between your solution approach and mine, and it will help you understand my code better.
Also, don't be afraid to write it using an imperative-style loop first (like do), then transforming it to the equivalent named let when it's all working. Just reread the first section to see how to do that transformation.
All that said, here is my solution (with the specifics stripped out):
(define (n-loop proc . ranges)
(let outer ((cur ???)
(ranges ranges))
(cond ((null? ranges) ???)
(else (do ((i (caar ranges) (+ i 1)))
((>= i (cadar ranges)))
(outer ??? ???))))))
Remember, once you get this working, you will still need to transform the do loop into one based on named let. (Or, you may have to go even further and transform both the outer and inner loops into their letrec forms.)

Resources