sicp-126
Posted on 2015-02-13 19:50:38 +0900 in SICP
1.21
(define (square x) (* x x))
(define (smallest-divisor n) (find-divisor n 2))
(define (find-divisor n test-divisor)
(cond ((> (square test-divisor) n) n)
((divides? test-divisor n) test-divisor)
(else (find-divisor n (+ test-divisor 1)))))
(define (divides? a b) (= (remainder b a) 0))
199 and 1999 are primes, 19999’s smallest divisor is 7
1.22
(define (square x) (* x x))
(define (smallest-divisor n) (find-divisor n 2))
(define (find-divisor n test-divisor)
(cond ((> (square test-divisor) n) n)
((divides? test-divisor n) test-divisor)
(else (find-divisor n (+ test-divisor 1)))))
(define (divides? a b) (= (remainder b a) 0))
(define (expmod base exp m)
(cond ((= exp 0) 1)
((even? exp)
(remainder
(square (expomod base (/ exp 2) m))
m))
(else
(remainder
(* base (expmod base (- exp 1) m))
m))))
(define (fermat-test n)
(define (try-it a)
(= (expmod a n n) a))
(try-it (+ 1 (random (- n 1)))))
(define (fast-prime? n times)
(cond ((= times 0) true)
((fermat-test n) (fast-prime? n (- times 1)))
(else false)))
(define (timed-prime-test n)
(newline)
(display n)
(start-prime-test n (runtime))
(define (start-prime-test n start-time)
(cond ((prime? n)
(report-prime (- (runtime) start-time)))))
(define (report-prime elapsed-time)
(display " *** ")
(display elapsed-time))
(define (prime? n)
(= n (smallest-divisor n)))
(define (search-for-primes start end)
(if (even? start) (search-for-primes (+ start 1) end)
(cond ((<= start end)
(timed-prime-test start) (search-for-primes (+ start 2) end)))))
The tricky part is how to run evaluate expressions sequencely.
According to cond expressio, the then-body
s are evaluated in order and the results of the last then body
provide the result
for the whole cond
form.
1.26
(define (expmod base exp m)
(cond ((= exp 0) 1)
((even? exp)
(remainder (* (expmod base (/ exp 2) m)
(expmod base (/ exp 2) m))
m))
(else
(remainder (* base (expmod base (- exp 1) m))
m))))
The time complexity of this code is $\sum_{i=0}^{log_n} 2^n = O(n)$
1.27
(define (fixed-fermat-test n a)
(= (expmod a n n) a))
(define (fermat-full n)
(define (iter a)
(cond ((= a 1) #t)
((not (fixed-fermat-test n a)) #f)
(else (iter (- a 1)))))
(iter (- n 1)))
1.28
(define (MR-expmod base exp m)
(cond ((= exp 0) 1)
((even? exp)
(let* ([part (expmod base (/ exp 2) m)]
[ans (remainder (square part) m)])
(if (and (not (or (= part 1) (= part (- m 1))))
(= ans 1))
0
ans)))
(else
(remainder
(* base (expmod base (- exp 1) m))
m))))
(define (MR-test n)
(define (try-it a)
(= (MR-expmod a (- n 1) n) 1))
(try-it (+ 2 (random (- n 2)))))
Used let*
to deal with the local variable.
Hide Comments
comments powered by Disqus