Implement 3.5 and 3.6

main
Felix Martin 2020-12-13 12:26:22 -05:00
parent 5c39a8d48f
commit 5d589e3923
4 changed files with 161 additions and 82 deletions

151
ex-3_01-08.scm Normal file
View File

@ -0,0 +1,151 @@
(load "util.scm")
(display "\nex-3.1 - accumulator\n")
(define (make-accumulator value)
(define (accumulate new-value)
(set! value (+ value new-value))
value)
accumulate)
(define A (make-accumulator 5))
(assert (A 10) 15)
(assert (A 10) 25)
(display "\nex-3.2 - monitored calls\n")
(define (make-monitored proc)
(define count 0)
(define (dispatch m)
(cond ((eq? m 'how-many-calls?) count)
((eq? m 'reset-count) (set! count 0) count)
(else (set! count (inc count))
(proc m))))
dispatch)
(define s (make-monitored sqrt))
(assert (s 100) 10)
(assert (s 9) 3)
(assert (s 'how-many-calls?) 2)
(s 'reset-count)
(assert (s 'how-many-calls?) 0)
(display "\nex-3.3 - account with password\n")
(define (make-account balance password)
(define invalid-pw-attempts 0)
(define (withdraw amount)
(if (>= balance amount)
(begin (set! balance (- balance amount))
balance)
"Insufficient funds"))
(define (deposit amount)
(set! balance (+ balance amount))
balance)
(define (incorrect-password value)
"Incorrect password")
(define (call-the-cops value)
"Call the cops!")
(define (dispatch pw m)
(if (eq? pw password)
(begin
(set! invalid-pw-attempts 0)
(cond
((eq? m 'withdraw) withdraw)
((eq? m 'deposit) deposit)
(else (error "Unknown request -- MAKE-ACCOUNT" m))))
(cond
((= invalid-pw-attempts 3) call-the-cops)
(else
(set! invalid-pw-attempts (inc invalid-pw-attempts))
incorrect-password))))
dispatch)
(define acc (make-account 100 'secret-password))
(assert ((acc 'secret-password 'withdraw) 40) 60)
(assert ((acc 'some-other-password 'deposit) 50) "Incorrect password")
(display "\nex-3.4 - call the cops\n")
((acc 'some-other-password 'deposit) 50)
(assert ((acc 'secret-password 'deposit) 50) 110)
((acc 'some-other-password 'deposit) 50)
((acc 'some-other-password 'deposit) 50)
((acc 'some-other-password 'deposit) 50)
(assert ((acc 'some-other-password 'deposit) 50) "Call the cops!")
(display "\nex-3.5 - pi via integral\n")
(define (rand) (random 65536))
(define (estimate-pi trials)
(sqrt (/ 6 (monte-carlo trials cesaro-test))))
(define (cesaro-test)
(= (gcd (rand) (rand)) 1))
(define (monte-carlo trials experiment)
(define (iter trials-remaining trials-passed)
(cond ((= trials-remaining 0)
(/ trials-passed trials))
((experiment)
(iter (- trials-remaining 1) (+ trials-passed 1)))
(else
(iter (- trials-remaining 1) trials-passed))))
(iter trials 0))
(display (estimate-pi 1000)) (newline)
(define (estimate-integral P x1 x2 y1 y2 trials)
(define (area-test)
(P (random-in-range x1 (inc x2))
(random-in-range y1 (inc y2))))
(let ((area-rectangle (* (abs (- x2 x1)) (abs (- y2 y1)))))
(* area-rectangle (monte-carlo trials area-test))))
(define (p x y) (<= (+ (square (- x 50)) (square (- y 50)))
(square 50)))
; I had to use a bigger circle because random-in-range returns integers. If the
; circle is too small the random coordinates lying within and without of the
; circle are skewed.
(let ((area-circle (estimate-integral p 0 100 0 100 1000))
(radius-circle 50.))
(let ((pi (/ area-circle (square radius-circle))))
(assert (< pi 3.4) #t)
(assert (> pi 3.0) #t)))
(display "\nex-3.6 - rand\n")
(define (make-rand)
(define x 0)
(define a 1664525)
(define c 1013904223)
(define m (expt 2 32))
(define (reset new-x)
(set! x new-x))
(define (generate)
(set! x (modulo (+ (* a x) c) m))
x)
(define (dispatch command)
(cond
((eq? command 'reset) reset)
((eq? command 'generate) (generate))
(else (error "Unknown request -- RAND" m))))
dispatch)
(define rand (make-rand))
(let ((r3 (rand 'generate))
(r2 (rand 'generate))
(r1 (rand 'generate)))
((rand 'reset) 0)
(assert r1 (rand 'generate))
(assert r2 (rand 'generate))
(assert r3 (rand 'generate)))
(display "\nex-3.7\n")
(display "\nex-3.8\n")

View File

@ -1,82 +0,0 @@
(load "util.scm")
(display "\nex-3.1\n")
(define (make-accumulator value)
(define (accumulate new-value)
(set! value (+ value new-value))
value)
accumulate)
(define A (make-accumulator 5))
(assert (A 10) 15)
(assert (A 10) 25)
(display "\nex-3.2\n")
(define (make-monitored proc)
(define count 0)
(define (dispatch m)
(cond ((eq? m 'how-many-calls?) count)
((eq? m 'reset-count) (set! count 0) count)
(else (set! count (inc count))
(proc m))))
dispatch)
(define s (make-monitored sqrt))
(assert (s 100) 10)
(assert (s 9) 3)
(assert (s 'how-many-calls?) 2)
(s 'reset-count)
(assert (s 'how-many-calls?) 0)
(display "\nex-3.3\n")
(define (make-account balance password)
(define invalid-pw-attempts 0)
(define (withdraw amount)
(if (>= balance amount)
(begin (set! balance (- balance amount))
balance)
"Insufficient funds"))
(define (deposit amount)
(set! balance (+ balance amount))
balance)
(define (incorrect-password value)
"Incorrect password")
(define (call-the-cops value)
"Call the cops!")
(define (dispatch pw m)
(if (eq? pw password)
(begin
(set! invalid-pw-attempts 0)
(cond
((eq? m 'withdraw) withdraw)
((eq? m 'deposit) deposit)
(else (error "Unknown request -- MAKE-ACCOUNT" m))))
(cond
((= invalid-pw-attempts 3) call-the-cops)
(else
(set! invalid-pw-attempts (inc invalid-pw-attempts))
incorrect-password))))
dispatch)
(define acc (make-account 100 'secret-password))
(assert ((acc 'secret-password 'withdraw) 40) 60)
(assert ((acc 'some-other-password 'deposit) 50) "Incorrect password")
(display "\nex-3.4\n")
((acc 'some-other-password 'deposit) 50)
(assert ((acc 'secret-password 'deposit) 50) 110)
((acc 'some-other-password 'deposit) 50)
((acc 'some-other-password 'deposit) 50)
((acc 'some-other-password 'deposit) 50)
(assert ((acc 'some-other-password 'deposit) 50) "Call the cops!")
(display "\nex-3.5\n")

4
ex-3_09-xx.scm Normal file
View File

@ -0,0 +1,4 @@
(load "util.scm")
(display "\nex-3.9\n")

View File

@ -53,3 +53,9 @@
(op (car sequence)
(fold-right op initial (cdr sequence)))))
; From exercise 3.5
(define (random-in-range low high)
(let ((range (- high low)))
(+ low (random range))))
'util-loaded