Finish exercises for chapter 1 section 1 and 2
This commit is contained in:
@@ -18,12 +18,12 @@
|
||||
; (else -1))
|
||||
; (+ a 1)) ->
|
||||
|
||||
(display "ex-1.2 - ")
|
||||
(display "\nex-1.2 - ")
|
||||
(display (/ (+ 5 4 (- 2 (- 3 (+ 6 (/ 4 5)))))
|
||||
(* 3 (- 6 2) (- 2 7))))
|
||||
(newline)
|
||||
|
||||
(display "ex-1.3 - ")
|
||||
(display "\nex-1.3 - ")
|
||||
|
||||
(define (sum-squares a b) (+ (* a a) (* b b)))
|
||||
|
||||
@@ -35,11 +35,11 @@
|
||||
(display (sum-squares-max 2 -6 1))
|
||||
(newline)
|
||||
|
||||
(display "ex-1.4 - Operator becomes + or - depending on the value of b\n")
|
||||
(display "\nex-1.4 - Operator becomes + or - depending on the value of b\n")
|
||||
; (define (a-plus-abs-b a b)
|
||||
; ((if (> b 0) + -) a b))
|
||||
|
||||
(display "ex-1.5 - Only normal-order terminates\n")
|
||||
(display "\nex-1.5 - Only normal-order terminates\n")
|
||||
;(define (p) (p))
|
||||
;(define (test x y)
|
||||
; (if (= x 0) 0 y))
|
||||
@@ -47,7 +47,7 @@
|
||||
; Will not terminate:
|
||||
;(display (test 0 (p)))
|
||||
|
||||
(display "\n; Square roots via Newton's Method") (newline)
|
||||
(display "\nexample - Square roots via Newton's Method") (newline)
|
||||
(define (sqrt-iter guess x)
|
||||
(if (good-enough? guess x)
|
||||
guess
|
||||
@@ -131,3 +131,107 @@
|
||||
|
||||
(display (cbrt 27)) (newline)
|
||||
(display (cbrt 0.001)) (newline)
|
||||
|
||||
|
||||
(newline) (display "ex-1.9 - see comments in code\n")
|
||||
|
||||
;(define (+ a b)
|
||||
; (if (= a 0)
|
||||
; b
|
||||
; (inc (+ (dec a) b))))
|
||||
; + 3 2
|
||||
; (inc (+ 2 2))
|
||||
; (inc (inc (+ 1 2)))
|
||||
; (inc (inc (inc (+ 0 2)))
|
||||
; (inc (inc (inc 2)))
|
||||
; -> recursive process
|
||||
|
||||
;(define (+ a b)
|
||||
; (if (= a 0)
|
||||
; b
|
||||
; (+ (dec a) (inc b))))
|
||||
; (+ 3 2)
|
||||
; (+ 2 3)
|
||||
; (+ 1 4)
|
||||
; (+ 0 5)
|
||||
; 5
|
||||
; -> iterative process
|
||||
|
||||
|
||||
(display "\nex-1.10 - Ackermann") (newline)
|
||||
(define (A x y)
|
||||
(cond ((= y 0) 0)
|
||||
((= x 0) (* 2 y))
|
||||
((= y 1) 2)
|
||||
(else (A (- x 1)
|
||||
(A x (- y 1))))))
|
||||
|
||||
(display (A 1 10)) (newline)
|
||||
; (A 1 10)
|
||||
; (A 0 (A 1 9))
|
||||
; (* 2 (A 1 9))
|
||||
; (* 2 (A 0 (A 1 8))
|
||||
; (* 2 (* 2 (A 1 8))
|
||||
; -> 2^10 = 1024
|
||||
(display (A 2 4)) (newline)
|
||||
; (A 2 4)
|
||||
; (A 1 (A 2 3))
|
||||
; (2 ^ (A 2 3))
|
||||
; (2 ^ (A 1 (A 2 2))
|
||||
; (2 ^ 2 ^ (A 2 2)
|
||||
; -> 2^2^2^2 = 65536
|
||||
(display (A 3 3)) (newline)
|
||||
; (A 3 3)
|
||||
; (A 2 (A 3 2))
|
||||
; (2 ^* (A 3 2))
|
||||
; (2 ^* (A 2 (A 3 1)))
|
||||
; (2 ^* 2 ^* 2)
|
||||
; (2 ^* (2^2))
|
||||
; (2^2^2^2) = 65536
|
||||
|
||||
(define (f n) (A 0 n)) ; f(n)=2*n
|
||||
(display (f 111)) (newline)
|
||||
|
||||
(define (g n) (A 1 n)) ; g(n)=2^n
|
||||
(display (g 12)) (newline)
|
||||
|
||||
(define (h n) (A 2 n)) ; h(n)=2^2^2^... or 2^(h(n-1))
|
||||
(display (h 4)) (newline)
|
||||
|
||||
|
||||
(newline) (display "example - Couting Change") (newline)
|
||||
|
||||
(define (dec x) (- x 1))
|
||||
|
||||
(define (counting-change-iter amount current-coin)
|
||||
(cond ((= amount 0) 1)
|
||||
((= current-coin 0) 0)
|
||||
((< amount 0) 0)
|
||||
(else (+ (counting-change-iter (- amount (list-of-coins current-coin)) current-coin)
|
||||
(counting-change-iter amount (dec current-coin)))
|
||||
)))
|
||||
|
||||
(define (list-of-coins coin-index)
|
||||
(cond ((= coin-index 1) 1)
|
||||
((= coin-index 2) 5)
|
||||
((= coin-index 3) 10)
|
||||
((= coin-index 4) 25)
|
||||
((= coin-index 5) 50)))
|
||||
|
||||
(define (count-change amount) (counting-change-iter amount 5))
|
||||
|
||||
(display "(count-change 100) = ")
|
||||
(display (count-change 100)) (newline)
|
||||
|
||||
; Try to implement a better version. Worked in Python. See Euler.
|
||||
;(define (counting-change-iter amount count-coin current-coin)
|
||||
; (cond ((= current-coin 0) 0)
|
||||
; ((<= amount 0) 0)
|
||||
; (else (+ (counting-change-iter (- amount (list-of-coins current-coin)) (+ count-coin 1) current-coin)
|
||||
; (if (and (= count-coin 0)(= (modulo amount (list-of-coins current-coin)) 0)) 1 0)
|
||||
; (counting-change-iter amount 0 (- current-coin 1))
|
||||
; ))))
|
||||
|
||||
;(display "(count-change 100) = ")
|
||||
;(display (counting-change-iter 100 0 5)) (newline)
|
||||
|
||||
186
ex-1_11-20.scm
Normal file
186
ex-1_11-20.scm
Normal file
@@ -0,0 +1,186 @@
|
||||
(display "ex-1.11\n")
|
||||
|
||||
(define (f_rec n)
|
||||
(cond ((< n 3) n)
|
||||
(else (+ (f_rec (- n 1)) (* 2 (f_rec (- n 2))) (* 3 (f_rec (- n 3)))))))
|
||||
|
||||
(display "(f_rec 10) = ")
|
||||
(display (f_rec 10)) (newline)
|
||||
|
||||
(define (f_iter_step n a b c count)
|
||||
(cond ((= n count) c)
|
||||
(else (f_iter_step n b c (+ (* 3 a) (* 2 b) c) (+ count 1)))))
|
||||
|
||||
(define (f_iter n)
|
||||
(cond ((< n 3) n)
|
||||
(else (f_iter_step n 0 1 2 2))))
|
||||
|
||||
(display "(f_iter 10) = ")
|
||||
(display (f_iter 10)) (newline)
|
||||
|
||||
|
||||
(newline) (display "ex-1.12") (newline)
|
||||
(define (pascal row col)
|
||||
(cond ((= row 1) 1)
|
||||
((= col 1) 1)
|
||||
((= col row) 1)
|
||||
(else (+ (pascal (- row 1) (- col 1)) (pascal (- row 1) col)))))
|
||||
|
||||
(display "(pascal 6 2) = ")
|
||||
(display (pascal 6 3)) (newline)
|
||||
|
||||
|
||||
(newline) (display "ex-1.13") (newline)
|
||||
(display "I was not able to prove this.\n")
|
||||
|
||||
|
||||
(newline) (display "ex-1.14") (newline)
|
||||
(display "I did that on paper. See page 92 Bullet Journal 2018.")
|
||||
(newline)
|
||||
|
||||
(newline) (display "ex-1.15") (newline)
|
||||
|
||||
(define (cube x) (* x x x))
|
||||
(define (p x) (- (* 3 x) (* 4 (cube x))))
|
||||
(define (sine angle)
|
||||
(if (not (> (abs angle) 0.1))
|
||||
angle
|
||||
(p (sine (/ angle 3.0)))))
|
||||
|
||||
; a) (/ 12.5 3) -> 4.16 -> 1.38888 -> 0.462 -> 0.154 -> 0.051 (count = 5)
|
||||
; 12.5 / 3^n < 0.1 <=> 125 < 3^n <=> 4.39 < n
|
||||
(define (count-sine-calls value count)
|
||||
(if (> (abs value) 0.1) (count-sine-calls (/ value 3.0) (+ 1 count)) count))
|
||||
(display "a) Calls for 12.5 = ") (display (count-sine-calls 12.5 0)) (newline)
|
||||
(display (sine (* 3.14 0.5))) (newline)
|
||||
|
||||
; b. What is the order of growth in space and number of steps
|
||||
; (as a function of a) used by the process generated by the sine procedure when (sine a) is evaluated?
|
||||
; O(log_3 a)
|
||||
|
||||
(newline) (display "ex-1.16") (newline)
|
||||
|
||||
(define (expt-rec x n)
|
||||
(cond ((= n 0) 1)
|
||||
(else (* x (expt-rec x (- n 1))))))
|
||||
|
||||
(define (expt-iter b counter product)
|
||||
(cond ((= counter 0) product)
|
||||
(else (expt-iter b (- counter 1) (* product b)))))
|
||||
|
||||
(define (expt b n) (expt-iter b n 1))
|
||||
|
||||
(define (fast-expt b n)
|
||||
(cond ((= n 0) 1)
|
||||
((even? n) (square (fast-expt b (/ n 2))))
|
||||
(else (* b (fast-expt b (- n 1))))))
|
||||
|
||||
(define (even? n)
|
||||
(= (remainder n 2) 0))
|
||||
|
||||
(define (expt-fast b n)
|
||||
(expt-iter-fast b n 1))
|
||||
|
||||
(define (expt-iter-fast b n a)
|
||||
(cond ((= n 1) (* b a))
|
||||
((even? n) (expt-iter-fast (* b b) (/ n 2) a))
|
||||
(else (expt-iter-fast b (- n 1) (* a b)))))
|
||||
|
||||
(display "expt-fast 2 37 = ")
|
||||
(display (expt-fast 2 37))
|
||||
(newline)
|
||||
|
||||
|
||||
(newline) (display "ex-1.17") (newline)
|
||||
(define (mul a b)
|
||||
(if (= b 0)
|
||||
0
|
||||
(+ a (mul a (- b 1)))))
|
||||
|
||||
(define (double x) (+ x x))
|
||||
(define (half x) (/ x 2))
|
||||
|
||||
(define (mul-rec a b)
|
||||
(cond ((= b 0) 0)
|
||||
((even? b) (double (mul-rec a (half b))))
|
||||
(else (+ a (mul-rec a (- b 1))))))
|
||||
|
||||
(display "mul-rec 17 53 = ")
|
||||
(display (mul-rec 17 53)) (newline)
|
||||
|
||||
|
||||
(newline) (display "ex-1.18") (newline)
|
||||
(define (mul-fast-iter b n a)
|
||||
(cond ((= n 0) a)
|
||||
((even? n) (mul-fast-iter (double b) (half n) a))
|
||||
(else (mul-fast-iter b (- n 1) (+ a b)))))
|
||||
|
||||
(define (mul-fast a b) (mul-fast-iter a b 0))
|
||||
|
||||
(display "mul-fast 17 53 = ")
|
||||
(display (mul-fast 17 53))
|
||||
(newline)
|
||||
|
||||
|
||||
(newline) (display "ex-1.19") (newline)
|
||||
(define (fib n)
|
||||
(fib-iter 1 0 0 1 n))
|
||||
(define (fib-iter a b p q count)
|
||||
(cond ((= count 0) b)
|
||||
((even? count)
|
||||
(fib-iter a
|
||||
b
|
||||
(+ (* q q) (* p p)) ; compute p'
|
||||
(+ (* q q) (* 2 p q)) ; compute q'
|
||||
(/ count 2)))
|
||||
(else (fib-iter (+ (* b q) (* a q) (* a p))
|
||||
(+ (* b p) (* a q))
|
||||
p
|
||||
q
|
||||
(- count 1)))))
|
||||
|
||||
(display "fib 19 = ")
|
||||
(display (fib 19))
|
||||
(newline)
|
||||
|
||||
|
||||
(newline) (display "ex-1.20") (newline)
|
||||
(define (gcd-naiv a b)
|
||||
(cond ((= a b) a)
|
||||
((> a b) (gcd-naiv (- a b) b))
|
||||
(else (gcd-naiv a (- b a)))))
|
||||
|
||||
(display "gcd-naiv 60 14 = ")
|
||||
(display (gcd-naiv 60 14))
|
||||
(newline)
|
||||
|
||||
(define (gcd a b)
|
||||
(if (= b 0)
|
||||
a
|
||||
(gcd b (remainder a b))))
|
||||
|
||||
(display "gcd 60 14 = ")
|
||||
(display (gcd 60 14))
|
||||
(newline)
|
||||
; normaler order
|
||||
; gcd 206 40
|
||||
; gcd 40 (r 206 40)
|
||||
; zero? (r 206 40)
|
||||
; zero? 6
|
||||
; gcd (r 206 40) (r 40 (r 206 40))
|
||||
; zero? (r 40 (r 206 40))
|
||||
; gcd (r 40 (r 206 40)) (r (r 206 40) (r 40 (r 206 40))))
|
||||
; etc.
|
||||
|
||||
; applicative order
|
||||
; gcd 206 40
|
||||
; gcd 40 (r 206 40)
|
||||
; gcd 40 6
|
||||
; gcd 6 (r 40 6)
|
||||
; gcd 6 4
|
||||
; gcd 4 (r 6 4)
|
||||
; gcd 4 2
|
||||
; gcd 2 (r 4 2)
|
||||
; gcd 2 0 -> 2
|
||||
|
||||
|
||||
264
ex-1_21-28.scm
Normal file
264
ex-1_21-28.scm
Normal file
@@ -0,0 +1,264 @@
|
||||
(display "ex-1.21") (newline)
|
||||
|
||||
(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 (prime? n) (= n (smallest-divisor n)))
|
||||
|
||||
(display "(smallest-divisor 33) = ")
|
||||
(display (smallest-divisor 33))
|
||||
(newline)
|
||||
(display "(prime? 37) = ")
|
||||
(display (prime? 37))
|
||||
(newline)
|
||||
|
||||
;a^n = a (mod n) ; fermat's theorem
|
||||
(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))))
|
||||
|
||||
(display "(expmod 11 23 3) = ")
|
||||
(display (expmod 11 23 3))
|
||||
(newline)
|
||||
|
||||
(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) #t)
|
||||
((fermat-test n) (fast-prime? n (- times 1)))
|
||||
(else #f)))
|
||||
|
||||
(display "(fast-prime? 11) = ")
|
||||
(display (fast-prime? 11 1))
|
||||
|
||||
(display "\n\nex-1.22\n")
|
||||
(display "(smallest-divisor 199) = ")
|
||||
(display (smallest-divisor 199)) (newline)
|
||||
(display "(smallest-divisor 1999) = ")
|
||||
(display (smallest-divisor 1999)) (newline)
|
||||
(display "(smallest-divisor 19999) = ")
|
||||
(display (smallest-divisor 19999)) (newline)
|
||||
|
||||
(newline) (display "ex-1.23 - more tests in comments")
|
||||
|
||||
(define (timed-prime-test n)
|
||||
(newline)
|
||||
(display n)
|
||||
(start-prime-test n (runtime)))
|
||||
(define (start-prime-test n start-time)
|
||||
(if (prime? n)
|
||||
(report-prime (- (runtime) start-time))))
|
||||
(define (report-prime elapsed-time)
|
||||
(display " *** ")
|
||||
(display elapsed-time)
|
||||
)
|
||||
|
||||
(define (search-for-primes n a)
|
||||
(cond ((= a 3) 0)
|
||||
((prime? n) (timed-prime-test n) (search-for-primes (+ n 1) (+ a 1)))
|
||||
((search-for-primes (+ n 1) a))))
|
||||
|
||||
(newline) (display "search-for-primes 1000")
|
||||
(search-for-primes 1000 0)
|
||||
|
||||
;(newline)(newline) (display "search-for-primes 100000000")
|
||||
;(search-for-primes 100000000 0)
|
||||
;
|
||||
;(newline)(newline) (display "search-for-primes 1000000000")
|
||||
;(search-for-primes 1000000000 0)
|
||||
;
|
||||
;(newline)(newline) (display "search-for-primes 10000000000")
|
||||
;(search-for-primes 10000000000 0)
|
||||
;
|
||||
;(newline)(newline) (display "search-for-primes 100000000000")
|
||||
;(search-for-primes 100000000000 0)
|
||||
|
||||
; It is amazing how exact the time represents the expected increase. If we
|
||||
; increase n by factor 10 the time increase by factor sqrt(10) = 3.3. I knew
|
||||
; this, but it is cool to see it.
|
||||
; search-for-primes 1000000000
|
||||
; 1000000007 *** 4.0000000000000036e-2
|
||||
; 1000000009 *** .04999999999999999
|
||||
; 1000000021 *** 5.0000000000000044e-2
|
||||
;
|
||||
; search-for-primes 10000000000
|
||||
; 10000000019 *** .15000000000000002
|
||||
; 10000000033 *** .1399999999999999
|
||||
; 10000000061 *** .1399999999999999
|
||||
;
|
||||
; search-for-primes 100000000000
|
||||
; 100000000003 *** .4500000000000002
|
||||
; 100000000019 *** .43999999999999995
|
||||
; 100000000057 *** .4299999999999997
|
||||
|
||||
(display "ex-1.23") (newline)
|
||||
|
||||
(define (next n)
|
||||
(if (= n 2) 3 (+ n 2)))
|
||||
|
||||
(define (find-divisor n test-divisor)
|
||||
(cond ((> (square test-divisor) n) n)
|
||||
((divides? test-divisor n) test-divisor)
|
||||
(else (find-divisor n (next test-divisor)))))
|
||||
|
||||
;(timed-prime-test 100000000003)
|
||||
;(timed-prime-test 100000000019)
|
||||
;(timed-prime-test 100000000057)
|
||||
|
||||
; I did not really expect the time to half, but to 2/3. That is because we skip
|
||||
; one number per every three numbers. For example, instead of 3,4,5 we do 3,5
|
||||
; 100000000003 *** .30000000000000004
|
||||
; 100000000019 *** .29
|
||||
; 100000000057 *** .28
|
||||
|
||||
(newline) (display "ex-1.24")
|
||||
|
||||
(define (prime? n) (fast-prime? n 100))
|
||||
|
||||
(define (start-prime-test n start-time)
|
||||
(if (prime? n)
|
||||
(report-prime (- (runtime) start-time))))
|
||||
|
||||
(newline)(newline) (display "search-for-primes 1000000000000")
|
||||
(search-for-primes 1000000000000 0)
|
||||
|
||||
(newline)(newline) (display "search-for-primes 1000000000000000000000")
|
||||
(search-for-primes 1000000000000000000000000 0)
|
||||
|
||||
; This very nicely shows that in order to double the execution time we have to
|
||||
; square the input. For example:
|
||||
|
||||
;search-for-primes 1000000000000
|
||||
; 1.9999999999999962e-2 / 9.999999999999981e-3 = 2
|
||||
|
||||
; I feel like all discrepancies must be explained by the random function. If
|
||||
; the factor is bigger it takes more steps.
|
||||
;1000000000039 *** 9.999999999999981e-3
|
||||
;1000000000061 *** 9.999999999999981e-3
|
||||
;1000000000063 *** 9.999999999999981e-3
|
||||
|
||||
;search-for-primes 1000000000000000000000
|
||||
;1000000000000000000000007 *** 1.9999999999999962e-2
|
||||
;1000000000000000000000049 *** .02999999999999997
|
||||
;1000000000000000000000121 *** 3.0000000000000027e-2
|
||||
|
||||
(newline)(newline) (display "ex-1.25") (newline)
|
||||
|
||||
;(define (square m)
|
||||
; (display "square ")(display m)(newline)
|
||||
; (* m m))
|
||||
|
||||
(define (expmod-naiv base exp m)
|
||||
(remainder (fast-expt base exp) m))
|
||||
|
||||
; Terminates quickly.
|
||||
(display "(expmod 10000000000 1000000 100) ; runs quickly") (newline)
|
||||
(expmod 10000000000 1000000 100)
|
||||
|
||||
; Scheme can handle arbitrary precision arithmetic. However,
|
||||
; when the numbers get really big that takes more time. When
|
||||
; using expmod the number to be squared stays lower than the
|
||||
; prime to be tested.
|
||||
; When we do the naiv approach the numbers become really big
|
||||
; and the same call will not terminate.
|
||||
(display "(expmod-naiv 10000000000 1000000 100) ; doesn't terminate")
|
||||
;(expmod-naiv 10000000000 1000000 100)
|
||||
|
||||
(newline)(newline) (display "ex-1.26 - see comment") (newline)
|
||||
; With that function for every of the log(n) steps the
|
||||
; function is called twice which means the complexity
|
||||
; grows exponantially which gives us log(n)^2 a O(n) process.
|
||||
|
||||
(newline) (display "ex-1.27") (newline)
|
||||
|
||||
; Do fermat tests for all a in [2, p - 1].
|
||||
(define (fermat-test-all n) (fermat-test-all-iter 2 n))
|
||||
|
||||
(define (fermat-test-all-iter x n)
|
||||
(cond ((= x n) #t)
|
||||
((= (expmod x n n) x) (fermat-test-all-iter (+ x 1) n))
|
||||
(else (display x)(newline) #f)))
|
||||
|
||||
|
||||
; 561, 1105, 1729, 2465, 2821, and 6601
|
||||
(display (fermat-test-all 561)) (newline)
|
||||
(display (fermat-test-all 1105)) (newline)
|
||||
(display (fermat-test-all 1729)) (newline)
|
||||
(display (fermat-test-all 2465)) (newline)
|
||||
(display (fermat-test-all 2821)) (newline)
|
||||
(display (fermat-test-all 6601)) (newline)
|
||||
; I am really unhappy with that exercise, because it wouldn't
|
||||
; worked if we used the condition a ** (p - 1) = 1 (mod p) and
|
||||
; I don't know the exact reason for that.
|
||||
|
||||
(newline) (display "ex-1.28") (newline)
|
||||
|
||||
; 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 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.
|
||||
|
||||
(define (is-nontrivial-square n m)
|
||||
(cond ((= n 1) n)
|
||||
((= n (- m 1)) n)
|
||||
((= (remainder (square n) m) 1) 0) ; non-trivial square root
|
||||
(else n)))
|
||||
|
||||
(define (expmod-mr base exp m)
|
||||
(cond ((= exp 0) 1)
|
||||
((even? exp)
|
||||
(remainder (square (is-nontrivial-square (expmod-mr base (/ exp 2) m) m))
|
||||
m))
|
||||
(else
|
||||
(remainder (* base (expmod-mr base (- exp 1) m))
|
||||
m))))
|
||||
|
||||
(define (miller-rabin-test n)
|
||||
(define (try-it a)
|
||||
(= (expmod-mr a (- n 1) n) 1))
|
||||
(try-it (+ 1 (random (- n 1)))))
|
||||
|
||||
(define (fast-prime? n times)
|
||||
(cond ((= times 0) #t)
|
||||
((miller-rabin-test n) (fast-prime? n (- times 1)))
|
||||
(else #f)))
|
||||
|
||||
(display (fast-prime? 17 10)) (newline)
|
||||
(display (fast-prime? 561 10)) (newline)
|
||||
(display (fast-prime? 1105 10)) (newline)
|
||||
(display (fast-prime? 1729 10)) (newline)
|
||||
(display (fast-prime? 231082301002031230 10)) (newline)
|
||||
(display (fast-prime? 1000000000000000000000121 10)) (newline)
|
||||
(display (fast-prime? 2 10)) (newline)
|
||||
(display (fast-prime? 4 10)) (newline)
|
||||
|
||||
8
run
Executable file
8
run
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
for a in "$@"
|
||||
do
|
||||
echo "run: $a"
|
||||
mit-scheme --quiet < $a
|
||||
done
|
||||
|
||||
Reference in New Issue
Block a user