Racket conditional sum of series by recursion - scheme

I am new to Racket. I need to sum all the natural numbers less than 1000 (or any nth value) and the numbers will be divisible by 3 or 5. I have a code which can do that but using iteration. But I have to do same thing by recursion. The code is as follows:
(define (sum-divisibles limit)
(for/sum ([i (in-range 1 limit)]
#:when (or (divides? i 3)
(divides? i 5)))
i))
(define (divides? m n)
(= 0 (remainder m n)))
I need to do same thing but with recursion but not with loop or iteration.

This is straightforward, as long as you visualize each iteration in the loop as a function call. Think about it: the original for loop goes from 1 up to and including limit-1. That's the same as starting from limit-1, decreasing the limit by 1 at each function call, and stopping when we reach 0.
There are two important things to remember wen writing recursive procedure:
We have to make sure that we stop at some point - this is called the base case; for this example, that happens when we reach 0 (because the original loop includes 1).
We have to combine the partial results that we obtain along when calling the recursion: if the current number happens to be divisible by 3 or 5 then we add it to the rest of the recursive calls, otherwise we ignore it but keep advancing the recursion anyway, until we reach the base case.
This is what I mean:
(define (sum-divisibles limit)
(cond ((= limit 0) 0) ; base case, stop recursion
((or (divides? limit 3) (divides? limit 5)) ; does the condition hold?
(+ limit ; then we add current value
(sum-divisibles (- limit 1)))) ; and advance the recursion
(else ; otherwise skip it
(sum-divisibles (- limit 1))))) ; and advance the recursion
Be careful with the initial limit value, remember that in your original code the limit is not added to the sum (the iteration stops right before reaching it), hence the equivalent way to call the recursive version is this:
(sum-divisibles (- n 1))
For example, to obtain the same value as (sum-divisibles 50) with your code, we have to call it like this in the recursive version:
(sum-divisibles 49)
=> 543
Alternatively you could write a helper procedure that takes care of decreasing the input limit by one before calling the actual recursive procedure, but that's left as an exercise for the reader.

Let have n be some positive number and m is predecessor, m = n - 1.
Now, suppose you know that (sum-divisibles m) equals some value s. How would you do to compute (sum-divisible n)?
Try writing a function which takes a value n and the value s, and computes the sum for n.
(define (recur n s) ...)
Then you will be able to define sum-divisibles in terms of limit and the recursive application of sum-divisibles for limit - 1. You also need to take care of the base case of the recursion, when limit is zero.

One can use 'named let' for recursion:
(define limit 1000)
(let loop ((n 1) ; starting values
(sum 0))
(cond
[(> n limit) sum] ; print out sum if limit reached;
[(or (= 0 (modulo n 3)) ; if n is divisible by 3 or 5
(= 0 (modulo n 5)))
(loop (add1 n) (+ sum n))] ; add this number to sum and loop again with next number
[else ; if not divisible
(loop (add1 n) sum)] ; loop with next number without adding to sum
))

Related

Using a counter within a function Scheme

I want to find a way to use a counter within a function where the counter is also a variable within the recursive function. An example of this is with a program that takes a list and then "sifts" through it until it finds all the numbers within it that are multiples of i:
(define (multiples-of lst) (lambda (i) (if (> i 3))
'()
(multiplefilter (ismultipleof (+ i 1)) (lst)))))
where ismultipleof checks if the car of each list is a multiple of i + 1 (with i starting at 1) and then the multiplefilter is a separate function that scraps any values of the list that are not multiples of i. So that if I put in the list (1 2 3 4 5 6 7 8 9 10 11 12) the output would just be (6 12). The biggest issue is getting said counter to work within the function.
Well, here's a simple function that uses a counter in its execution. range just returns a list of integers from 0 up to (- n 1). It's just as easy to write something that increments a counter.
(define (range n)
(let loop ((acc '())
(list-start (- n 1)))
(if (negative? list-start)
acc
(loop (cons list-start acc) (- list-start 1)))))
This function counts down rather than up because recursion usually builds lists "backwards". Counting down just avoids the need call reverse on the acc when the recursion is finished.
Iteration is usually accomplished with recursion in Scheme instead of for loops as in some languages. In particular, recursion from the tail is something to strive for since it will not "blow the stack".

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.)

Lisp : how to use recursion to defun a function that given a nonnegative integer N, produce the list of all integers from 1 up to and including N?

write a function in lisp called number(N) that you have to use a nonnegative integer N, and produce the list of all integers from 1 up to and including N.
(defun numbers (N)
(if (<= N 0)
nil
(cons N nil)
(numbers (- N 1)))
I checked some questions, but most of them use loop and range, but this question doesn't allowed me to do this, so I have to use recursion instead:
here is my code, but this code keeps giving me warning:
; caught STYLE-WARNING:
; The variable N is defined but never used.
;
; compilation unit finished
; caught 1 ERROR condition
; caught 1 STYLE-WARNING condition
I think my algorithm is correct ,but because I am new to lisp, I still don't know how to write the function properly. It is grateful if anyone could gave me any help.
IF has generally a common syntax, but there are exceptions
Generally in Lisps like Common Lisp the if operator allows the following syntax:
IF test-form then-form [else-form]
This means that in Lisp usually zero or one else-form are allowed. An example is if in Common Lisp.
In Emacs Lisp multiple else-forms are allowed. Emacs Lisp has the following syntax:
IF test-form then-form else-form*
This means that in Emacs Lisp zero or more else-forms are allowed.
Thus: it's important to mention which language&dialect you are actually using.
Your code
a) Let's assume that you use Common Lisp with its IF syntax.
Your code:
(defun numbers (N)
(if (<= N 0)
nil
(cons N nil)
(numbers (- N 1)))
Your code has the problem, that there are more than one else clauses. You need to write a version which has a single else clause.
b) Let's assume that you use Emacs Lisp with its IF syntax with multiple else forms.
Your code:
(defun numbers (N)
(if (<= N 0)
nil
(cons N nil)
(numbers (- N 1)))
Here the (cons N nil) form is allowed, but has no effect. Its return value is not used and it has no side effect. You could delete it and it would make no difference. Again: you would need how to combine its effect with the form (numbers (- N 1)).
Syntax error: missing closing parenthesis
There is another problem in your code. The s-expressions are not complete -> a closing parenthesis is missing:
(defun numbers (N)
(if (<= N 0)
nil
(cons N nil)
(numbers (- N 1)))
As you can see a closing parenthesis is missing at the end.
Thus your code can not be read by Lisp.
There are two ways one generally can avoid this problem:
count the parentheses and set them accordingly
use the editor to count the parentheses
Most people prefer the latter.
The way to think about this is to think about what the algorithm should be:
To compute the numbers from 1 to n:
if n is less than 1 then there are no numbers, so this is the empty list;
otherwise we want a list which looks like (... n), where ... is all the numbers from 1 to n-1.
Note that we want the numbers in forward order: this is going to be critical.
Doing this is slightly difficult in Lisp because we want the number to be at the end of the list, and access to the ends of lists is hard.
Here is the start of a version which builds the list backwards (so this is not the right answer).
(defun numbers (n)
(if (< n 1)
'() ;the empty list
;; n 1 or more, so build a list which is (n . ...)
(cons n <some function involving n>)))
Well, OK, what function should we call recursively? Do we have a function which returns the list we want? Well, yes: it's numbers, with an argument which is one less than n!
(defun numbers (n)
(if (< n 1)
'()
(cons n (numbers (- n 1)))))
And this function works. But it gets the wrong answer: the list is backwards:
> (numbers 10)
(10 9 8 7 6 5 4 3 2 1)
There are two fixes to this problem: the first is to build the list forwards, using append. This version looks like this (remember append wants to append two lists: it doesn't append an element to the end of a list):
(defun numbers (n)
(if (< n 1)
'()
(append (numbers (- n 1)) (list n))))
This gets the right answer:
> (numbers 10)
(1 2 3 4 5 6 7 8 9 10)
but it's a terrible answer: append has to walk all the way down the list (lists in Lisp are chains of conses: there is no fast access to the end of a list), copying it as it goes, to append the new element. So this has absolutely terrible space & time complexity. Programs written like this are why 'Lisp is slow'.
A better approach is to build the list backwards and then reverse it.
(defun numbers (n)
(reverse (numbers-backwards n)))
(defun numbers-backwards (n)
(if (< n 1)
'()
(cons n (numbers-backwards (- n 1)))))
The problem with this, from the homework perspective, might be that using reverse is not allowed. That's OK, we can write it, recursively. The implementation is slightly fiddly, but this is going to help us below.
(defun reverse-list (l)
;; in real life reverse-list-accumulator would be a local function
(reverse-list-accumulator l '()))
(defun reverse-list-accumulator (l accum)
(if (null l)
accum
(reverse-list-accumulator (rest l) (cons (first l) accum))))
The way this works is that reverse-list calls this auxiliary function with an extra argument. The auxiliary function then checks the list, and if it's not empty it calls itself with the tail of the list and the head of the list consed onto the auxiliary argument. If it is empty, it returns the auxiliary argument. It's a little subtle but you can see that this in fact reverses the list.
So now we can write our function using only recursive functions we wrote:
(defun numbers (n)
(reverse-list (numbers-backwards n)))
But now there should be a moment of inspiration: why are we doing this whole
build-it-backwards-and-reverse-it thing? Why don't we just make numbers do the accumulator trick itself! Well, we can do that:
(defun numbers (n)
(numbers-accumulator n '()))
(defun numbers-accumulator (n accum)
(if (< n 1)
accum
(numbers-accumulator (- n 1) (cons n accum))))
And now we don't need to reverse the list, and for added value our
function is 'tail recursive' and will generally be compiled much more
efficiently.
A real-life version of numbers might look more like this, using a local function:
(defun numbers (n)
(labels ((numbers-accumulator (m accum)
(if (< m 1)
accum
(numbers-accumulator (- m 1) (cons m accum)))))
(numbers-accumulator n '())))
Here is a comparison between the version of numbers using append and the above function, on an argument small enough that the append version does not overflow the stack.
> (time (progn (numbers/append 2000) (values)))
Timing the evaluation of (progn (numbers/append 2000) (values))
User time = 0.024
System time = 0.001
Elapsed time = 0.017
Allocation = 32176304 bytes
97 Page faults
> (time (progn (numbers 2000) (values)))
Timing the evaluation of (progn (numbers 2000) (values))
User time = 0.000
System time = 0.000
Elapsed time = 0.001
Allocation = 32000 bytes
0 Page faults
You can see how terrible the append version is, and how good the other one is: this is a 64-bit Lisp, and conses are two words or 16 bytes: it has allocated precisely 2000 cons cells which is the minimum it could do.

SICP exercise 1.28: false negatives in the Miller-Rabin test

Exercise 1.28. One variant of the Fermat test that cannot be fooled is called the Miller-Rabin test (Miller 1976; Rabin 1980). This
starts from an alternate form of Fermat's Little Theorem, which states
that if n is a prime number and a is any positive integer less than n,
then a raised to the (n - 1)st power is congruent to 1 modulo n. To
test the primality of a number n by the Miller-Rabin test, we pick a
random number a < n and raise a to the (n - 1)st power modulo n using
the expmod procedure. However, whenever we perform the squaring step
in expmod, we check to see if we have discovered a ''nontrivial square
root of 1 modulo n,'' that is, a number not equal to 1 or n - 1 whose
square is equal to 1 modulo n. It is possible to prove that if such a
nontrivial square root of 1 exists, then n is not prime. It is also
possible to prove that if n is an odd number that is not prime, then,
for at least half the numbers a < n, computing a^(n-1) in this way will
reveal a nontrivial square root of 1 modulo n. (This is why the
Miller-Rabin test cannot be fooled.) Modify the expmod procedure to
signal if it discovers a nontrivial square root of 1, and use this to
implement the Miller-Rabin test with a procedure analogous to
fermat-test. Check your procedure by testing various known primes and
non-primes. Hint: One convenient way to make expmod signal is to have
it return 0.
(define (fast-prime? n)
(define (fast-prime-iter n counter)
(cond ((= counter 1) #t) ; There is no need to check 1
((miller-rabin-test n counter)
(fast-prime-iter n (- counter 1)))
(else
(newline)
(display counter)
#f)))
(fast-prime-iter n (- n 2)))
(define (miller-rabin-test n a)
(define (expmod base exp m)
(cond ((= exp 0) 1)
((even? exp)
(nontrivial-square-root?
(remainder (square (expmod base (/ exp 2) m))
m)))
(else
(remainder (* base (expmod base (- exp 1) m))
m))))
(= (expmod a (- n 1) n) 1))
(define (nontrivial-square-root? val)
(if (= val 1)
0
val))
My idea is to filter out those so-called "nontrivial square roots of 1 modulo n" with the procedure nontrivial-square-root?. A 0 is returned if (remainder (square (expmod base (/ exp 2) m)) m) is 1, in which case the square of (expmod base (/ exp 2) m) must be equal to 1 modulo n (this is because m always equals n), making it a nontrivial square root.
While nontrivial-square-root? does filter out carmichael numbers such as 561, 1105, 1729, 2465, 2821 and 6601, prime numbers such as 7 and 13 are also reported to be composite.
What causes these false negatives?
The important part of the quote marked with bold text:
However, whenever we perform the squaring step in expmod, we check to see if we have discovered a ''nontrivial square root of 1 modulo n,'' that is, a number not equal to 1 or n - 1 whose square is equal to 1 modulo n
So before you square and take the remainder you have to check that the argument is not 1 or n - 1. This occurs, e.g., if you call (miller-rabin-test 5 3). Working the recursion out you notice that there is a call (nontrivial-square-root? (remainder (square 4) 5)) which evaluates to (nontrivial-square-root? 1). However, 5 can still be prime because 4 is 5 - 1.
So in the squaring part you can, e.g., call a following function:
(define (sqrmod-with-check val n)
(let ((sqrmod (remainder (square val) n)))
(cond ((or (= val (- n 1)) (= val 1)) sqrmod)
((= sqrmod 1) 0)
(else sqrmod))))
where the arguments are the expmod call and m. This does the square and remainder for you except in the case we have found a nontrivial square root of 1 modulo n, when it returns 0. I divided it to three conditions, instead of two, just because of readability.

Find the Hardy–Ramanujan number using R5RS scheme. Please suggest improvements in idiom and calculations.

I remember once going to see
[Srinivasa Ramanujan] when he was ill
at Putney. I had ridden in taxi cab
number 1729 and remarked that the
number seemed to me rather a dull one,
and that I hoped it was not an
unfavorable omen. "No," he replied,
"it is a very interesting number; it
is the smallest number expressible as
the sum of two cubes in two different
ways." [G. H. Hardy as told in "1729
(number)"]
In "Math Wrath" Joseph Tartakovsky says about this feat, "So what?
Give me two minutes and my calculator watch, and I'll do the same
without exerting any little gray cells." I don't know how
Mr. Tartakovsky would accomplish that proof on a calculator watch, but
the following is my scheme function that enumerates numbers starting
at 1 and stops when it finds a number that is expressable in two
seperate ways by summing the cubes of two positive numbers. And it
indeeds returns 1729.
There are two areas where I would appreciate suggestions for
improvement. One area is, being new to scheme, style and idiom. The other area is around the calculations. Sisc
does not return exact numbers for roots, even when they could be. For
example (expt 27 1/3) yields 2.9999999999999996. But I do get exact
retults when cubing an exact number, (expt 3 3) yields 27. My
solution was to get the exact floor of a cube root and then test
against the cube of the floor and the cube of the floor plus one,
counting as a match if either match. This solution seems messy and hard to reason about. Is there a more straightforward way?
; Find the Hardy-Ramanujan number, which is the smallest positive
; integer that is the sum of the cubes of two positivie integers in
; two seperate ways.
(define (hardy-ramanujan-number)
(let ((how-many-sum-of-2-positive-cubes
; while i^3 + 1 < n/1
; tmp := exact_floor(cube-root(n - i^3))
; if n = i^3 + tmp^3 or n = i^3 + (tmp + 1) ^3 then count := count + 1
; return count
(lambda (n)
(let ((cube (lambda (n) (expt n 3)))
(cube-root (lambda (n) (inexact->exact (expt n 1/3)))))
(let iter ((i 1) (count 0))
(if (> (+ (expt i 3) 1) (/ n 2))
count
(let* ((cube-i (cube i))
(tmp (floor (cube-root (- n cube-i)))))
(iter (+ i 1)
(+ count
(if (or (= n (+ cube-i (cube tmp)))
(= n (+ cube-i (cube (+ tmp 1)))))
1
0))))))))))
(let iter ((n 1))
(if (= (how-many-sum-of-2-positive-cubes n) 2)
n
(iter (+ 1 n))))))
Your code looks mostly fine, I see a few very minor things to comment on:
There's no need to define cube and cube-root at the innermost scope,
Using define for internal functions makes it look a little clearer,
This is related to the second part of your question: you're using inexact->exact on a floating point number which can lead to large rationals (in the sense that you allocate a pair of two big integers) -- it would be better to avoid this,
Doing that still doesn't solve the extra test that you do -- but that's only because you're not certain if you have the right number of if you missed by 1. Given that it should be close to an integer, you can just use round and then do one check, saving you one test.
Fixing the above, and doing it in one function that returns the number when it's found, and using some more "obvious" identifier names, I get this:
(define (hardy-ramanujan-number n)
(define (cube n) (expt n 3))
(define (cube-root n) (inexact->exact (round (expt n 1/3))))
(let iter ([i 1] [count 0])
(if (> (+ (cube i) 1) (/ n 2))
(hardy-ramanujan-number (+ n 1))
(let* ([i^3 (cube i)]
[j^3 (cube (cube-root (- n i^3)))]
[count (if (= n (+ i^3 j^3)) (+ count 1) count)])
(if (= count 2) n (iter (+ i 1) count))))))
I'm running this on Racket, and it looks like it's about 10 times faster (50ms vs 5ms).
Different Schemes behave differently when it comes to exact exponentiation: some return an exact result when possible, some an inexact result in all cases. You can look at ExactExpt, one of my set of implementation contrasts pages, to see which Schemes do what.

Resources