Initial commit

This commit is contained in:
Oliver Payne 2021-05-10 21:57:13 +01:00
commit bdfff4a9a2
21 changed files with 585 additions and 0 deletions

21
1_10.sch Normal file
View File

@ -0,0 +1,21 @@
(define (A x y)
(cond ((= y 0) 0)
((= x 0) (+ 2 y))
((= y 1) 2)
(else (A (- x 1)
(A x (- y 1))))))
; 2+n
(define (f n)
(A 0 n))
; 2*n
(define (g n)
(A 1 n))
; 2^n
(define (h n)
(A 2 n))
(define (k n)
(* 5 n n))

23
1_11.sch Normal file
View File

@ -0,0 +1,23 @@
; f(n) = n, n < 3, f(n) = f(n-1) + 2f(n-2) + 3f(n-3) n >= 3
(define (f1 n)
(if (< n 3)
n
(+ (f1 (- n 1))
(* 2 (f1 (- n 2)))
(* 3 (f1 (- n 3))))))
(define (f2 n)
(if (< n 3)
n
(f-iter 2 1 0 n)))
; a = f(2), b = f(1), c = f(0)
; a <- a + 2b + 3c, b <- a, c <- b
(define (f-iter a b c count)
(if (< count 3)
a
(f-iter (+ a (* 2 b) (* 3 c))
a
b
(- count 1))))

6
1_12.sch Normal file
View File

@ -0,0 +1,6 @@
(define (pascal row col)
(cond
((= col 1) 1)
((or (= col 1) (= col row)) 1)
(else (+ (pascal (- row 1) (- col 1))
(pascal (- row 1) col)))))

11
1_16.sch Normal file
View File

@ -0,0 +1,11 @@
(define (expt1 b n)
(expt-iter b n 1))
(define (expt-iter b n a)
(cond ((= n 0) a)
((odd? n)
(expt-iter b (- n 1) (* a b)))
(else (expt-iter (square b) (/ n 2) a))))
(define (square x) (* x x))

17
1_17.sch Normal file
View File

@ -0,0 +1,17 @@
(define (mult-rec a b)
(cond ((= b 0) 0)
((even? b) (mult-rec (double a) (halve b)))
(else (+ a (mult-rec a (- b 1))))))
(define (mult-iter a b n)
(cond ((= b 0) n)
((even? b) (mult-iter (double a) (halve b) n))
(else (mult-iter a (- b 1) (+ a n)))))
(define (mult a b)
(mult-iter a b 0))
(define (double a) (+ a a))
(define (halve a) (/ a 2))

125
1_21.sch Normal file
View File

@ -0,0 +1,125 @@
(import chicken.time) ; for current-milliseconds
(import chicken.random) ; for pseudo-random-integer
(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)))
(define (square x) (* x x))
(define (timed-prime-test n)
;(newline)
;(display n)
(start-prime-test n (current-milliseconds)))
(define (start-prime-test n start-time)
(if (prime? n)
(report-prime n (- (current-milliseconds) start-time))))
(define (report-prime n elapsed-time)
(display n)
(display " *** ")
(display elapsed-time)
(newline))
(define (search-for-primes min max)
(if (<= min max)
(cond ((odd? min) (timed-prime-test min)
(search-for-primes (+ min 2) max))
(else (search-for-primes (+ min 1) max)))))
; (search-for-primes 100000 100100): First 3 take 1 ms each
; (search-for-primes 1000000 1000100): First 3 take 4, 3, 5 ms each
; (search-for-primes 10000000 10000200): First 3 take 14, 12, 13 ms each
; (sqrt 10) is 3.1622, so time increase is around sqrt(n), as expected.
(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)))))
; Now (search-for-primes 10000000 10000200): takes 7, 7, 10 ms each. So approximately
; half for the first two but a bit more for the third. This will be quicker, if the
; procedure has to search through lots of candidate divisors. Each call to next is
; more expensive that adding 1, which may account for the difference.
; Increase the size of the integers (to reduce noisy measurements):
; (search-for-primes 10000000000 10000000200)
; This takes ~141ms for the +1 case and ~87ms for the next case: A speedup of around
; 1.6. This must be accounted for by the extra comparison.
; 1.24
(define (fermat-test n)
(define (try-it a)
(= (expmod a n n) a))
(try-it (+ 1 (pseudo-random-integer (- n 1)))))
(define (expmod base exp m)
(cond ((= exp 0) 1)
((even? exp)
(remainder (square (expmod base (/ exp 2) m))
m))
(else
(remainder (* (expmod base (- exp 1) m) base)
m))))
(define (fast-prime? n times)
(cond ((= times 0) #t)
((fermat-test n) (fast-prime? n (- times 1)))
(else #f)))
(define (prime? n)
(fast-prime? n 10))
; Now prime test as above takes 2-3 ms for the first three answers
; (search-for-primes (square 10000000000) (+ 500 (square 10000000000)))
; This should be about double, given the the algorithm is logarithmic in time.
; We get 6, 8, 8 ms (more like 3 times as long). Maybe this is from the higher
; overhead of the random number generator? Or more likely, because we are running
; the Fermat test 10 times.
; 1.25: The answer should be the same if we take remainders after exponentiating,
; but exponentiating first keeps the numbers smaller, thus enabling testing of
; larger primes with less memory.
; 1.26: Writing out the multiplication instead of using square means that the
; argument is computed twice (once for each argument to * rather than once for
; square. So we are no longer halving the number of steps needed. Hence, this is
; no longer a log n algorithm.
; 1.27
; Test if a^n is congruent to a mod n for all a<n
(define (fermat n)
(define (fermat-rec a n)
(if (= a 1)
#t
(and (= (expmod a n n) a)
(fermat-rec (- a 1) n))))
(fermat-rec (- n 1) n))

14
1_25.sch Normal file
View File

@ -0,0 +1,14 @@
(define (expmod base exp m)
(remainder (fast-expt base exp) m))
(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))
; This appears to be equivalent to calculating the exponent modulo m with the
; exception that for large numbers, fast-expt will get very large before
; calculating the modulus, so it is probably not suitable for a fast prime tester.

44
1_28.sch Normal file
View File

@ -0,0 +1,44 @@
(import chicken.random) ; for pseudo-random-integer
(define (square x) (* x x))
(define (non-trivial-root? x n)
(and (not (= x (- n 1)))
(not (= x 1))
(= (remainder (square x) n) 1)))
(define (expmod base exp m)
(cond ((= exp 0) 1)
((even? exp)
(let ((test (expmod base (/ exp 2) m)))
(if (non-trivial-root? test m)
0 ; Signal non-trivial root
(remainder (square test)
m))))
(else
(remainder (* (expmod base (- exp 1) m) base)
m))))
(define (miller-rabin-test n count)
(let* ((a (+ 1 (pseudo-random-integer (- n 1))))
(result (expmod a (- n 1) n)))
; (display a)
; (newline)
(cond ((= count 0)
; (display "Count 0")
; (newline)
#t) ; Exhausted our attempts. Assumed prime
((= result 0)
; (display "Non-trivial root")
; (newline)
#f) ; Non-trivial root: not prime
((> result 1)
; (display "MR test failed: ")
; (display result)
; (newline)
#f) ; a^(n-1) not congruent 1 (n): not prime
(else (miller-rabin-test n (- count 1))))))
(define (prime? n)
(miller-rabin-test n 25))

17
1_29.sch Normal file
View File

@ -0,0 +1,17 @@
(define (cube x) (* x x x))
(define (simpson-iter f a b n k)
(let* ((h (/ (- b a) n))
(y (f (+ a (* k h))))
(coeff
(cond ((= k 0) 1)
((= k n) 1)
((odd? k) 4)
((even? k) 2))))
(+ (* (/ h 3) (* coeff y))
(if (= k n)
0
(simpson-iter f a b n (+ k 1))))))
(define (simpson-int f a b n)
(simpson-iter f a b n 0))

13
1_30.sch Normal file
View File

@ -0,0 +1,13 @@
(define (sum-iter term a next b)
(define (iter a result)
(if (> a b)
result
(iter (next a) (+ result (term a)))))
(iter a 0))
(define (pi-sum a b)
(define (pi-term x)
(/ 1.0 (* x (+ x 2))))
(define (pi-next x)
(+ x 4))
(sum-iter pi-term a pi-next b))

33
1_31.sch Normal file
View File

@ -0,0 +1,33 @@
(define (square x) (* x x))
(define (product-rec term a next b)
(if (> a b)
1
(* (term a)
(product term (next a) next b))))
(define (product-iter term a next b)
(define (iter a result)
(if (> a b)
result
(iter (next a) (* result (term a)))))
(iter a 1))
(define product product-iter)
;(define product product-rec)
(define (fact n)
(product
(lambda (x) x)
1
(lambda (x) (+ x 1))
n))
; Approximation to pi/4
(define (pi-prod n)
(product
(lambda (a) (/ (* a (+ a 2)) (square (+ a 1))))
2
(lambda (a) (+ a 2))
n))

41
1_32.sch Normal file
View File

@ -0,0 +1,41 @@
(define (accumulate-rec combiner null-value term a next b)
(if (> a b)
null-value
(combiner (term a)
(accumulate combiner null-value term (next a) next b))))
(define (accumulate-iter combiner null-value term a next b)
(define (iter a result)
(if (> a b)
result
(iter (next a) (combiner result (term a)))))
(iter a null-value))
;(define accumulate accumulate-rec)
(define accumulate accumulate-iter)
(define (product term a next b)
(accumulate
(lambda (x y) (* x y))
1
term
a
next
b))
(define (sum term a next b)
(accumulate
(lambda (x y) (+ x y))
0
term
a
next
b))
(define (fact n)
(product
(lambda (x) x)
1
(lambda (x) (+ x 1))
n))

38
1_33.sch Normal file
View File

@ -0,0 +1,38 @@
(load "1_28.sch") ; for prime?
(define (filtered-accumulate combiner null-value pred term a next b)
(if (> a b)
null-value
(combiner
(if (pred a) (term a) null-value)
(filtered-accumulate combiner null-value pred term (next a) next b))))
(define (square x) (* x x))
(define (gcd a b)
(if (= b 0)
a
(gcd b (remainder a b))))
(define (rel-prime a b)
(= (gcd a b) 1))
(define (sum-squares-primes a b)
(filtered-accumulate
(lambda (x y) (+ x y))
0
prime?
square
a
(lambda (x) (+ 1 x))
b))
(define (prod-rel-prime n)
(filtered-accumulate
(lambda (x y) (* x y))
1
(lambda (x) (rel-prime x n))
(lambda (x) x)
1
(lambda (x) (+ 1 x))
n))

15
1_35.sch Normal file
View File

@ -0,0 +1,15 @@
(define tolerance 0.00001)
(define (fixed-point f first-guess)
(define (close-enough? v1 v2)
(< (abs (- v1 v2)) tolerance))
(define (try guess)
(let ((next (f guess)))
(if (close-enough? guess next)
next
(try next))))
(try first-guess))
(define (f x)
(+ 1 (/ 1 x)))

23
1_36.sch Normal file
View File

@ -0,0 +1,23 @@
(define tolerance 0.00001)
(define (fixed-point f first-guess)
(define (close-enough? v1 v2)
(< (abs (- v1 v2)) tolerance))
(define (try guess)
(let ((next (f guess)))
(display next)
(newline)
(if (close-enough? guess next)
next
(try next))))
(try first-guess))
(define (f x)
(/ (log 1000) (log x)))
(define (average x y)
(/ (+ x y) 2))
; Using average damping, converges about 4 times quicker
(define (f2 x)
(average x (f x)))

21
1_37.sch Normal file
View File

@ -0,0 +1,21 @@
(define (cont-frac-rec n d k)
(define (rec i)
(if (= i k)
(/ (n i) (d i))
(/ (n i)
(+ (d i) (rec (+ i 1))))))
(rec 1))
(define (cont-frac-iter n d k)
(define (iter i res)
(if (= i 0)
res
(iter (- i 1)
(/ (n i) (+ res (d i))))))
(iter k 0))
(define phi (/ (+ 1 (sqrt 5)) 2))
; 10 iterations needed to approximate phi using
; (lambda (i) 1.0) for n and d.

11
1_38.sch Normal file
View File

@ -0,0 +1,11 @@
(load "1_37.sch") ; for cont-frac-rec and cont-frac-iter
(define (n i) 1.0)
(define (d i)
(if (= (remainder i 3) 2)
(* (+ (quotient i 3) 1) 2)
1))
(define e
(+ 2 (cont-frac-rec n d 20)))

10
1_39.sch Normal file
View File

@ -0,0 +1,10 @@
(load "1_37.sch") ; for cont-fram-rec
(define (d i) (+ (* (- i 1) 2) 1))
(define (tan-cf x)
(define (n i)
(if (= i 1)
(* 1.0 x)
(* -1.0 (* x x))))
(cont-frac-rec n d 50))

0
1_40.sch Normal file
View File

16
1_8.sch Normal file
View File

@ -0,0 +1,16 @@
(define (cbrt x)
(cbrt-iter 1.0 x))
(define (cbrt-iter guess x)
(if (good-enough? guess x)
guess
(cbrt-iter (improve guess x) x)))
(define (improve guess x)
(/
(+ (/ x (* guess guess)) (* 2 guess))
3))
(define (good-enough? guess x)
(< (abs (- (* guess guess guess) x)) 0.001))

86
notes.txt Normal file
View File

@ -0,0 +1,86 @@
1.9:
(define (+ a b)
(if (= a 0) b (inc (+ (dec a) b))))
(+ 4 5)
(if (= 4 0) 4 (inc (+ (dec 4) 5)))
(inc (+ 3 5))
(inc (inc (+ 2 5)))
(inc (inc (inc (+ 1 5))))
(inc (inc (inc (inc (+ 0 5)))))
(inc (inc (inc (inc 5))))
(inc (inc (inc 6)))
(inc (inc 7))
(inc 8)
9
Recursive
(define (+ a b)
(if (= a 0) b (+ (dec a) (inc b))))
(+ 4 5)
(+ 3 6)
(+ 2 7)
(+ 1 8)
(+ 0 9)
9
Iterative
1.10:
(define (A x y)
(cond ((= y 0) 0)
((= x 0) (+ 2 y))
((= y 1) 2)
(else (A (- x 1)
(A x (- y 1))))))
(A 1 10)
(A 0 (A 1 9))
(A 0 (A 0 (A 1 8)))
(A 0 (A 0 (A 0 (A 1 7))))
(A 0 (A 0 (A 0 (A 0 (A 1 6)))))
(A 0 (A 0 (A 0 (A 0 (A 0 (A 1 5))))))
(A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 4)))))))
(A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 3)))))))))
(A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 2))))))))))
(A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 1)))))))))))
(A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 2))))))))))
(A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 4))))))))))
(A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 6)))))))))
(A 0 (A 0 (A 0 (A 0 (A 0 (A 0 8)))))))
(A 0 (A 0 (A 0 (A 0 (A 0 10))))))
(A 0 (A 0 (A 0 (A 0 12)))))
(A 0 (A 0 (A 0 14))))
(A 0 (A 0 16)))
(A 0 18)
22
(A 2 4) = 16
(A 3 3) = 16
1.34
(define (f g) (g 2))
(f f) gives error Error: call of non-procedure: 2. This is because it is expecting the
second argument to be a procedure (implicitly from the fact that it applies it to 2).
1.35
Golden ratio: phi = (1 + sqrt(5))/2
Let x' be a fixed point of x |-> 1 + 1/x. Then
x' = 1 + 1/x' = (x' + 1)/x'
x'^2 = x' + 1
x'^2 - x' - 1 = 0
Solutions: (1 +- sqrt(1 + 4)) / 2. So phi is one of the fixed points.