#lang racket
;;;;;;;;;
;; 3.1 ;;
;;;;;;;;;
(define (make-accumulator total)
(lambda (amount)
(set! total (+ total amount))
total))
;; tests
(define A (make-accumulator 5))
(A 10)
;; 15
(A 10)
;; 25
;;;;;;;;;
;; 3.2 ;;
;;;;;;;;;
(define (make-monitored f)
(define num-calls 0)
(lambda (input)
(cond [(equal? input 'how-many-calls?) num-calls]
[(equal? input 'reset-num-calls) (set! num-calls 0)]
[else (set! num-calls (add1 num-calls))
(f input)])))
;; tests
(define s (make-monitored sqrt))
(s 100)
;; 10
(s 81)
;; 9
(s 64)
;; 8
(s 'how-many-calls?)
;; 3
(s 'reset-num-calls)
(s 'how-many-calls?)
;; 0
;;;;;;;;;
;; 3.3 ;;
;;;;;;;;;
(define (display-error message)
(lambda (amount) message))
(define (make-account balance password)
(define (withdraw amount)
(cond [(>= balance amount)
(set! balance (- balance amount))
balance]
[else "Insufficient funds"]))
(define (deposit amount)
(set! balance (+ balance amount))
balance)
(define (dispatch pw m)
(if (eq? pw password)
(cond [(eq? m 'withdraw) withdraw]
[(eq? m 'deposit) deposit]
[else (display-error "Unknown request -- MAKE-ACCOUNT")])
(display-error "Incorrect password")))
dispatch)
;; tests
(define acc (make-account 100 'abc))
((acc 'abc 'deposit) 100)
;; 200
((acc 'abc 'withdraw) 50)
;; 150
((acc 'abc 'withdraw) 200)
;; "Insufficient funds"
((acc 'xyz 'withdraw) 1000000)
;; "Incorrect password"
((acc 'abc 'invest) 1000)
;; "Unknown request -- MAKE-ACCOUNT"
((acc 'abc 'deposit) 25)
;; 175
;;;;;;;;;
;; 3.4 ;;
;;;;;;;;;
(define (make-secure-account balance password)
(define number-wrong-guesses 0)
(define (call-the-cops)
(display-error "The police have been called"))
(define (withdraw amount)
(cond [(>= balance amount)
(set! balance (- balance amount))
balance]
[else "Insufficient funds"]))
(define (deposit amount)
(set! balance (+ balance amount))
balance)
(define (dispatch pw m)
(cond [(eq? pw password)
(set! number-wrong-guesses 0)
(cond [(eq? m 'withdraw) withdraw]
[(eq? m 'deposit) deposit]
[else (display-error "Unknown request -- MAKE-ACCOUNT")])]
[(< number-wrong-guesses 7)
(set! number-wrong-guesses (add1 number-wrong-guesses))
(display-error "Incorrect password")]
[else (call-the-cops)]))
dispatch)
;; tests
(define new-acc (make-secure-account 100 'abc))
((new-acc 'abc 'deposit) 50)
;; 150
((new-acc 'xyz1 'withdraw) 1000000)
;; "Incorrect password"
((new-acc 'xyz2 'withdraw) 1000000)
;; "Incorrect password"
((new-acc 'xyz3 'withdraw) 1000000)
;; "Incorrect password"
((new-acc 'xyz4 'withdraw) 1000000)
;; "Incorrect password"
((new-acc 'xyz5 'withdraw) 1000000)
;; "Incorrect password"
((new-acc 'xyz6 'withdraw) 1000000)
;; "Incorrect password"
((new-acc 'xyz7 'withdraw) 1000000)
;; "Incorrect password"
((new-acc 'xyz8 'withdraw) 1000000)
;; "The police have been called"
;;;;;;;;;
;; 3.5 ;;
;;;;;;;;;
(define (inexact-random low high)
; Return a random inexact real in the interval (low, high).
(+ low (* (random) (- high low))))
(define (monte-carlo trials experiment)
(define (iter trials-remaining trials-passed)
;; (printf "~a ~a ~n" trials-remaining trials-passed)
(cond [(zero? trials-remaining)
(exact->inexact (/ trials-passed trials))]
[else
(define hit (experiment))
(if hit
(iter (sub1 trials-remaining) (add1 trials-passed))
(iter (sub1 trials-remaining) trials-passed))]))
(iter trials 0))
(define (estimate-integral predicate x1 x2 y1 y2 num-trials)
(define total-area (* (- x2 x1) (- y2 y1)))
(define (integral-experiment)
(define x (inexact-random x1 x2))
(define y (inexact-random y1 y2))
(predicate x y))
(* (monte-carlo num-trials integral-experiment)
total-area))
(define (estimate-pi num-trials)
(define (in-unit-circle? x y)
(< (+ (sqr x) (sqr y)) 1))
(estimate-integral in-unit-circle? -1 1 -1 1 num-trials))
;; tests
(estimate-pi 10)
;; 3.6
(estimate-pi 100)
;; 3.2
(estimate-pi 1000)
;; 3.176
(estimate-pi 10000)
;; 3.1492
(estimate-pi 100000)
;; 3.14252
(estimate-pi 1000000)
;; 3.14344
;;;;;;;;;
;; 3.6 ;;
;;;;;;;;;
;; We'll use our own very simple prng: x[n+1] = 23 * x[n] + 11 mod 493.
(define (make-resettable-prng seed)
(define (rand-update x) (remainder (+ (* 23 x) 11) 493))
(define x seed)
(lambda (m)
(cond [(eq? m 'generate)
(set! x (rand-update x))
x]
[(eq? m 'reset)
(set! x seed)
"Reset."]
[else "Unknown request -- RAND"])))
(define new-prng (make-resettable-prng 10))
;; tests
(new-prng 'generate)
;; 241
(new-prng 'generate)
;; 131
(new-prng 'generate)
;; 66
(new-prng 'reset)
;; "Reset."
(new-prng 'generate)
;; 241
(new-prng 'generate)
;; 131
(new-prng 'generate)
;; 66
;;;;;;;;;
;; 3.7 ;;
;;;;;;;;;
(define (make-joint account password new-password)
(if (number? ((account password 'deposit) 0)) ; deposit 0 to check original pw
(lambda (pass m)
(if (eq? pass new-password)
(account password m)
(display-error "Incorrect password")))
"Password does not match -- MAKE-JOINT"))
(define paul-acc (make-account 100 'abc))
((paul-acc 'abc 'deposit) 100)
;; 200
(define mary-acc (make-joint paul-acc 'abc 'def))
((mary-acc 'def 'withdraw) 75)
;; 125
((mary-acc 'def 'deposit) 50)
;; 175
((mary-acc 'xyz 'withdraw) 1000000)
;; "Incorrect password"
(make-joint mary-acc 'xyz 'def)
;; "Password does not match -- MAKE-JOINT"
;;;;;;;;;
;; 3.8 ;;
;;;;;;;;;
(define (make-weird-function)
(define state 0)
(lambda (n)
(cond
[(and (even? state) (even? n)) (set! state (add1 state)) -1]
[(and (odd? state) (odd? n)) (set! state (add1 state)) 1]
[(and (even? state) (odd? n)) (set! state (add1 state)) 1]
[(and (odd? state) (even? n)) (set! state (add1 state)) 0])))
;; test
(define f (make-weird-function))
(f 0)
;; -1
(f 1)
;; 1
;; So evaluating (+ (f 0) (f 1)) left to right would produce (+ -1 1) or zero.
(define g (make-weird-function))
(g 1)
;; 1
(g 0)
;; 0
;; So evaluating (+ (g 0) (g 1)) right to left would produce (+ 1 0) or one.
Comments
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎