(sicp35)m3.1 ~ m3.5
やる気がでないので、3章を先に始める。
;;m3.1 (use srfi-1) (define (make-accumulator sum) (lambda (n) (set! sum (+ sum n)) sum)) (define A (make-accumulator 5)) ;;適用する回数によって値が変わる。 (map (lambda (x) (A 10)) (iota 10)) ;; gosh> (15 25 35 45 55 65 75 85 95 105) ;;m3.2 (define (make-monitored f) (let ((n 0)) (lambda (mf) (if (eq? 'how-many-calls? mf) n (begin (set! n (+ n 1)) (f mf)))))) (define s (make-monitored sqrt)) (for-each (lambda (x) (s 100)) (iota 10)) (s 'how-many-calls?) ;; gosh> 10 ;;m3.3 (define (make-account balance pass) (define (withdraw amount) (if (>= balance amount) (begin (set! balance (- balance amount)) balance) "Insufficient funds")) (define (deposit amount) (set! balance (+ balance amount)) balance) (define (dispatch p m) (if (eq? p pass) (cond ((eq? m 'withdraw) withdraw) ((eq? m 'deposit) deposit) (else (error "Unknown request -- MAKE-ACOUNT" m))) (lambda (x) "Incorrect pasword!"))) dispatch) (define acc (make-account 100 'secret-password)) ((acc 'some 'deposite) 50) ;;gosh> "Incorrect pasword!" ((acc 'secret-password 'deposit) 50) ;;gosh> 150 ;;m3.4 (define (make-account balance pass) (let ((c 7)) (define (withdraw amount) (if (>= balance amount) (begin (set! balance (- balance amount)) balance) "Insufficient funds")) (define (deposit amount) (set! balance (+ balance amount)) balance) (define (call-the-cops x) "call-the-cops") (define (dispatch p m) (if (eq? p pass) (begin (set! c 7) (cond ((eq? m 'withdraw) withdraw) ((eq? m 'deposit) deposit) (else (error "Unknown request -- MAKE-ACOUNT" m)))) (begin (if (= c 0) call-the-cops (begin (set! c (- c 1)) (lambda (x) "Incorrect pasword!")))))) dispatch)) (define acc (make-account 100 'pass)) ((acc 'pass 'deposit) 19) (define (f a pass word) (map (lambda (x) ((a pass word) 10)) (iota 10))) (f acc 'pass 'deposit ) ;; gosh> (110 120 130 140 150 160 170 180 190 200) (f acc 'wrong 'deposit) ;; gosh> (#0="Incorrect pasword!" #0# #0# #0# #0# #0# #0# #1="call-the-cops" #1# #1#) ;; #0#は Incorrect password! とメモリを共有している部分の表示。 (define rand ;; (let ((x random-init)) ;; (lambda () ;; (set! x (random-update x)) ;; x))) (lambda () (sys-random))) (define (estimate-pi trials) (sqrt (/ 6 (monte-carlo trials cesaro-test)))) (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)) ;;(monte-carlo 10 (lambda () #t)) ;;m3.5 ;;random-in-range が使えない。 ;;てきとーに代用品をつくろう。 ;; (define (f n) ;; (let ((lst (map (lambda (x) (sys-random)) (iota n)))) ;; (apply max lst))) ;; (use srfi-1) ;; (apply max (map (lambda (x) (f 100000)) (iota 10))) (define (random-in-range low high) (let ((range (- high low)) (max 2147480021)) ;;sys-randomを何回かやった内の最大値 (+ low (* range (/ (sys-random) max))))) ;; (map (lambda (x) (random-in-range 1.0 1.5)) (iota 20)) (define (estimate-integral p x1 x2 y1 y2 times) (define area (* (- x1 x2) (- y1 y2))) (define (iter c n) (if (= n 0) (* area (/ c times)) (let ((x (random-in-range x2 x1)) (y (random-in-range y2 y1))) (cond ((p x y) (iter (+ c 1) (- n 1))) (else (iter c (- n 1))))))) (iter 0 times)) ;;あー、 monte-carlo を使った方がいいかも。忘れてた。 (define (estimate-integral p x1 x2 y1 y2 n) (define (experiment) (let ((x (random-in-range x2 x1)) (y (random-in-range y2 y1))) (p x y))) (let ((area (* (- x1 x2) (- y1 y2)))) (* area (monte-carlo n experiment)))) (define (square x) (* x x)) (define (m3-5 coord r n) ;;coord = (x . y) (let* ((x (car coord)) (y (cdr coord)) (min-x (- x r)) (max-x (+ x r)) (min-y (- y r)) (max-y (+ y r))) ;; (print "x(min . max) " min-x " .. " max-x) ;; (print "y(min . max) " min-y " .. " max-y) (estimate-integral (lambda (u v) (> r (sqrt (+ (square (- u x)) (square (- v y)))))) max-x min-x max-y min-y n))) (map (lambda (x) (m3-5 (cons 0 0) 1.0 10000)) (iota 5)) ;; gosh> (3.1688 3.1296 3.1468 3.146 3.18)