How to decrement a value in Scheme? - scheme

I have a procedure that can find the n smallest primes larger than from
(define (primes_range from to n)
(for ([i (in-range from to)])
(if (> n 0)
(cond ((prime? i) (display i)
(- n 1)))
false)))
I add a parameter n to the procedure primes_range and decrement it during the execution only if a prime was found.
But n not changed. How to fix that?

The idiomatic Scheme way to write this function is to use recursion:
(define (primes-range from to n)
(cond ((>= from to) '())
((<= n 0) '())
((prime? from) (cons from (primes-range (+ from 1) to (- n 1))))
(else (primes-range (+ from 1) to n))))
You can easily spell this out in English:
Base cases:
A prime range where the from is equal or greater to to is empty.
A prime range where n is 0 or less is empty.
Recursive cases:
If from is a prime, then the prime range is from, prepended to the result of calling primes-range starting from (+ from 1) and with (- n 1) elements.
Otherwise, the result is calling primes-range starting from (+ from 1) (still with n elements).

Related

Write a function find-abundant that takes a positive number and produces a list of all abundant numbers no greater than the given one

i would like to to that thing but i don't know how to do that
Write a function find-abundant that takes as parameters a positive number and
produces a list of all abundant numbers no greater than the given one, in order from
the largest to the smallest.
(find-abundant 25)
(define (find-abundant n)
(define (check-abundant n)
(define (sum-of-proper-divisors n)
(let loop ((i (sub1 n)))
(cond
[(= i 1) 1]
[(= (remainder n i) 0)
(+ i (loop (sub1 i)))]
[else (loop (sub1 i))])))
(cond
((> (sum-of-proper-divisors n) n) 1)
(else 0)))
(define (enumerate-interval high low)
(if (> low high)
null
(cons high (enumerate-interval (- high 1) low))))
(filter (lambda (n)
(= (check-abundant n) 1))
(enumerate-interval (- n 1) 12)))
It may look complicated at first glance but there are two nested procedure inside find-abundant also check-abundant has a nested procedure which is sum-of-proper-divisors. You can seperate all procedures too.

Miller-Rabin test (SICP 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 less than 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 an-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.
This is what I have so far.
(define (square x) (* x x))
(define (even? n) (= (remainder n 2)))
(define (expmod-signal b n m)
(define (check a)
(and (not (= a 1))
(not (= a (- n 1)))
(= (square a) (remainder 1 n))))
(cond ((= n 0) 1)
((check b) 0)
((even? n) (remainder (square (expmod-signal b (/ n 2) m)) m))
(else (remainder (* b (expmod-signal b (- n 1) m)) m))))
(define (miller-rabin n)
(define (fail? n a)
(or (= n 0) (not (= n a))))
(define (try a)
(cond ((= a 1) #t)
((fail? (expmod-signal a (- n 1) n) a) #f)
(else (try (- a 1)))))
(try (- n 1)))
I think I implemented miller-rabin correctly but I don't understand how the modified expmod is supposed to work. Do you check the number before the square or after the square? I don't know from reading the question.
I solved this by using the original definition of expmod inside of expmod-signal. Somewhere in my tests, expmod-signal was naturally returning zero and messing with the tests. I misunderstood the check function, "whose square is equal to 1 modulo n" means check if a^2 % m = 1. The way this check function works is to return 0 if the argument is a non-trivial square root of 1 mod n, and return the argument otherwise. If it returns zero, the zero propagates through the remainder of expmod-signal and is returned.
(define (square x) (* x x))
(define (even? n) (= (remainder n 2)))
(define (expmod base exp m)
(cond ((= exp 0) 1)
((even? exp) (remainder (square (expmod base (/ exp 2) m)) m))
(else (remainder (* base (expmod base (- exp 1) m)) m))))
(define (expmod-signal b n m)
(define (check a)
(if (and (not (= a 1))
(not (= a (- n 1)))
(= (remainder (square a) n) 1))
0
a))
(cond ((= n 0) 1)
((even? n) (remainder (square (check (expmod b (/ n 2) m))) m))
(else (remainder (* b (expmod b (- n 1) m)) m))))
(define (miller-rabin n)
(define (fail? a)
(or (= a 0) (not (= a 1))))
(define (try a)
(cond ((= a 1) #t)
((fail? (expmod-signal a (- n 1) n)) #f)
(else (try (- a 1)))))
(try (- n 1)))

Different ways to calculate number

I need to write a function that will return the number of ways in which can be n (n is a natural number) written as the sum of natural numbers.
For example: 4 can be written as 1+1+1+1, 1+1+2, 2+2, 3+1 and 4.
I have written a function that returns the number of all the options, but does not take into account that the possibilities 1 + 1 + 2 and 2 + 1 + 1 (and all similar cases) are equal. So for n=4 it returns 8 instead of 5.
Here is my function:
(define (possibilities n)
(define (loop i)
(cond [(= i n) 1]
[(> i n) 0]
[(+ (possibilities (- n i)) (loop (+ i 1)))]))
(cond [(< n 1) 0]
[#t (loop 1)]))
Could you please help me with fixing my function, so it will work the way it should be. Thank you.
This is a well-known function, it's called the partition function P, its possible values are referenced as A000041 in the on-line encyclopedia of integer sequences.
One simple solution (not the fastest!) would be to use this helper function, which denotes the number of ways of writing n as a sum of exactly k terms:
(define (p n k)
(cond ((> k n) 0)
((= k 0) 0)
((= k n) 1)
(else
(+ (p (sub1 n) (sub1 k))
(p (- n k) k)))))
Then we just have to add the possible results, being careful with the edge cases:
(define (possibilities n)
(cond ((negative? n) 0)
((zero? n) 1)
(else
(for/sum ([i (in-range (add1 n))])
(p n i)))))
For example:
(map possibilities (range 11))
=> '(1 1 2 3 5 7 11 15 22 30 42)

Why does this Miller-Rabin Procedure in Scheme works when the code seems to be wrong?

I am working through SICP. In exercise 1.28 about the Miller-Rabin test. I had this code, that I know is wrong because it does not follow the instrcuccions of the exercise.
(define (fast-prime? n times)
(define (even? x)
(= (remainder x 2) 0))
(define (miller-rabin-test n)
(try-it (+ 1 (random (- n 1)))))
(define (try-it a)
(= (expmod a (- n 1) n) 1))
(define (expmod base exp m)
(cond ((= exp 0) 1)
((even? exp)
(if (and (not (= exp (- m 1))) (= (remainder (square exp) m) 1))
0
(remainder (square (expmod base (/ exp 2) m)) m)))
(else
(remainder (* base (expmod base (- exp 1) m)) m))))
(cond ((= times 0) true)
((miller-rabin-test n) (fast-prime? n (- times 1)))
(else false)))
In it I test if the square of the exponent is congruent to 1 mod n. Which according
to what I have read, and other correct implementations I have seen is wrong. I should test
the entire number as in:
...
(square
(trivial-test (expmod base (/ exp 2) m) m))
...
The thing is that I have tested this, with many prime numbers and large Carmicheal numbers,
and it seems to give the correct answer, though a bit slower. I don't understand why this
seems to work.
Your version of the function "works" only because you are lucky. Try this experiment: evaluate (fast-prime? 561 3) a hundred times. Depending on the random witnesses that your function chooses, sometimes it will return true and sometimes it will return false. When I did that I got 12 true and 88 false, but you may get different results, depending on your random number generator.
> (let loop ((k 0) (t 0) (f 0))
(if (= k 100) (values t f)
(if (fast-prime? 561 3)
(loop (+ k 1) (+ t 1) f)
(loop (+ k 1) t (+ f 1)))))
12
88
I don't have SICP in front of me -- my copy is at home -- but I can tell you the right way to perform a Miller-Rabin primality test.
Your expmod function is incorrect; there is no reason to square the exponent. Here is a proper function to perform modular exponentiation:
(define (expm b e m) ; modular exponentiation
(let loop ((b b) (e e) (x 1))
(if (zero? e) x
(loop (modulo (* b b) m) (quotient e 2)
(if (odd? e) (modulo (* b x) m) x)))))
Then Gary Miller's strong pseudoprime test, which is a strong version of your try-it test for which there is a witness a that proves the compositeness of every composite n, looks like this:
(define (strong-pseudoprime? n a) ; strong pseudoprime base a
(let loop ((r 0) (s (- n 1)))
(if (even? s) (loop (+ r 1) (/ s 2))
(if (= (expm a s n) 1) #t
(let loop ((r r) (s s))
(cond ((zero? r) #f)
((= (expm a s n) (- n 1)) #t)
(else (loop (- r 1) (* s 2)))))))))
Assuming the Extended Riemann Hypothesis, testing every a from 2 to n-1 will prove (an actual, deterministic proof, not just a probabilistic estimate of primality) the primality of a prime n, or identify at least one a that is a witness to the compositeness of a composite n. Michael Rabin proved that if n is composite, at least three-quarters of the a from 2 to n-1 are witnesses to that compositeness, so testing k random bases demonstrates, but does not prove, the primality of a prime n to a probability of 4−k. Thus, this implementation of the Miller-Rabin primality test:
(define (prime? n k)
(let loop ((k k))
(cond ((zero? k) #t)
((not (strong-pseudoprime? n (random (+ 2 (- n 3))))) #f)
(else (loop (- k 1))))))
That always works properly:
> (let loop ((k 0) (t 0) (f 0))
(if (= k 100) (values t f)
(if (prime? 561 3)
(loop (+ k 1) (+ t 1) f)
(loop (+ k 1) t (+ f 1)))))
0
100
I know your purpose is to study SICP rather than to program primality tests, but if you're interested in programming with prime numbers, I modestly recommend this essay at my blog, which discusses the Miller-Rabin test, among other topics. You should also know there are better (faster, less likely to report erroneous result) primality tests available than randomized Miller-Rabin.
It seems to me, you still got correct answer, because in each iteration of expmod you check conditions for previous iteration. You could try to debug exp value using display function inside expmod. Really, your code is not very different from this one.

Language Scheme: find the sum of proper divisors

I am wondering how to write a function calculating the sum of proper divisors of a integer greater than 1.
(define (sum-of-proper-divisors n)
(cond
[(= n 1) 1]
[(= 0 (remainder n (sub1 n)))
(+ (remainder n (sub1 n)) (sum-of-proper-divisors (sub1 (sub1 n))))]
[else (sum-of-proper-divisors (sub1 n))]))
This is the code that I wrote, however, it does not work. It will never stop evaluating because it will always do n-1. And I don't know how to fix this. Also, there might be other problems. How to put the restriction that makes the function stop evaluating when the divisor becomes 1?
You're confusing the number n whose divisors you want to find, with said divisors. Notice that n never changes, what must be modified at each step is the current integer being tested (a possible divisor). For that you'll need to pass around two parameters:
(define (sum-of-proper-divisors n i)
(cond
[(= i 1) 1]
[(= (remainder n i) 0)
(+ i (sum-of-proper-divisors n (sub1 i)))]
[else (sum-of-proper-divisors n (sub1 i))]))
Call it like this, at the beginning i must be one unit less than n:
(sum-of-proper-divisors 10 9)
=> 8
If having two parameters bothers you there are several ways to pass a single parameter, for instance using a named let:
(define (sum-of-proper-divisors n)
(let loop ((i (sub1 n)))
(cond
[(= i 1) 1]
[(= (remainder n i) 0)
(+ i (loop (sub1 i)))]
[else (loop (sub1 i))])))

Resources