Advertisement
timothy235

sicp-3-1-assignment-and-local-state

Feb 23rd, 2017
205
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Racket 6.49 KB | None | 0 0
  1. #lang racket
  2.  
  3. ;;;;;;;;;
  4. ;; 3.1 ;;
  5. ;;;;;;;;;
  6.  
  7. (define (make-accumulator total)
  8.   (lambda (amount)
  9.     (set! total (+ total amount))
  10.     total))
  11.  
  12. ;; tests
  13.  
  14. (define A (make-accumulator 5))
  15. (A 10)
  16. ;; 15
  17. (A 10)
  18. ;; 25
  19.  
  20. ;;;;;;;;;
  21. ;; 3.2 ;;
  22. ;;;;;;;;;
  23.  
  24. (define (make-monitored f)
  25.   (define num-calls 0)
  26.   (lambda (input)
  27.     (cond [(equal? input 'how-many-calls?) num-calls]
  28.           [(equal? input 'reset-num-calls) (set! num-calls 0)]
  29.           [else (set! num-calls (add1 num-calls))
  30.                 (f input)])))
  31.  
  32. ;; tests
  33.  
  34. (define s (make-monitored sqrt))
  35. (s 100)
  36. ;; 10
  37. (s 81)
  38. ;; 9
  39. (s 64)
  40. ;; 8
  41. (s 'how-many-calls?)
  42. ;; 3
  43. (s 'reset-num-calls)
  44. (s 'how-many-calls?)
  45. ;; 0
  46.  
  47. ;;;;;;;;;
  48. ;; 3.3 ;;
  49. ;;;;;;;;;
  50.  
  51. (define (display-error message)
  52.   (lambda (amount) message))
  53.  
  54. (define (make-account balance password)
  55.   (define (withdraw amount)
  56.     (cond [(>= balance amount)
  57.            (set! balance (- balance amount))
  58.            balance]
  59.           [else "Insufficient funds"]))
  60.   (define (deposit amount)
  61.     (set! balance (+ balance amount))
  62.     balance)
  63.   (define (dispatch pw m)
  64.     (if (eq? pw password)
  65.       (cond [(eq? m 'withdraw) withdraw]
  66.             [(eq? m 'deposit) deposit]
  67.             [else (display-error "Unknown request -- MAKE-ACCOUNT")])
  68.       (display-error "Incorrect password")))
  69.   dispatch)
  70.  
  71. ;; tests
  72.  
  73. (define acc (make-account 100 'abc))
  74. ((acc 'abc 'deposit) 100)
  75. ;; 200
  76. ((acc 'abc 'withdraw) 50)
  77. ;; 150
  78. ((acc 'abc 'withdraw) 200)
  79. ;; "Insufficient funds"
  80. ((acc 'xyz 'withdraw) 1000000)
  81. ;; "Incorrect password"
  82. ((acc 'abc 'invest) 1000)
  83. ;; "Unknown request -- MAKE-ACCOUNT"
  84. ((acc 'abc 'deposit) 25)
  85. ;; 175
  86.  
  87. ;;;;;;;;;
  88. ;; 3.4 ;;
  89. ;;;;;;;;;
  90.  
  91. (define (make-secure-account balance password)
  92.   (define number-wrong-guesses 0)
  93.   (define (call-the-cops)
  94.     (display-error "The police have been called"))
  95.   (define (withdraw amount)
  96.     (cond [(>= balance amount)
  97.            (set! balance (- balance amount))
  98.            balance]
  99.           [else "Insufficient funds"]))
  100.   (define (deposit amount)
  101.     (set! balance (+ balance amount))
  102.     balance)
  103.   (define (dispatch pw m)
  104.     (cond [(eq? pw password)
  105.            (set! number-wrong-guesses 0)
  106.            (cond [(eq? m 'withdraw) withdraw]
  107.                  [(eq? m 'deposit) deposit]
  108.                  [else (display-error "Unknown request -- MAKE-ACCOUNT")])]
  109.           [(< number-wrong-guesses 7)
  110.            (set! number-wrong-guesses (add1 number-wrong-guesses))
  111.            (display-error "Incorrect password")]
  112.           [else (call-the-cops)]))
  113.   dispatch)
  114.  
  115. ;; tests
  116.  
  117. (define new-acc (make-secure-account 100 'abc))
  118. ((new-acc 'abc 'deposit) 50)
  119. ;; 150
  120. ((new-acc 'xyz1 'withdraw) 1000000)
  121. ;; "Incorrect password"
  122. ((new-acc 'xyz2 'withdraw) 1000000)
  123. ;; "Incorrect password"
  124. ((new-acc 'xyz3 'withdraw) 1000000)
  125. ;; "Incorrect password"
  126. ((new-acc 'xyz4 'withdraw) 1000000)
  127. ;; "Incorrect password"
  128. ((new-acc 'xyz5 'withdraw) 1000000)
  129. ;; "Incorrect password"
  130. ((new-acc 'xyz6 'withdraw) 1000000)
  131. ;; "Incorrect password"
  132. ((new-acc 'xyz7 'withdraw) 1000000)
  133. ;; "Incorrect password"
  134. ((new-acc 'xyz8 'withdraw) 1000000)
  135. ;; "The police have been called"
  136.  
  137. ;;;;;;;;;
  138. ;; 3.5 ;;
  139. ;;;;;;;;;
  140.  
  141. (define (inexact-random low high)
  142.   ; Return a random inexact real in the interval (low, high).
  143.   (+ low (* (random) (- high low))))
  144.  
  145. (define (monte-carlo trials experiment)
  146.   (define (iter trials-remaining trials-passed)
  147.     ;; (printf "~a ~a ~n" trials-remaining trials-passed)
  148.     (cond [(zero? trials-remaining)
  149.            (exact->inexact (/ trials-passed trials))]
  150.           [else
  151.             (define hit (experiment))
  152.             (if hit
  153.               (iter (sub1 trials-remaining) (add1 trials-passed))
  154.               (iter (sub1 trials-remaining) trials-passed))]))
  155.   (iter trials 0))
  156.  
  157. (define (estimate-integral predicate x1 x2 y1 y2 num-trials)
  158.   (define total-area (* (- x2 x1) (- y2 y1)))
  159.   (define (integral-experiment)
  160.     (define x (inexact-random x1 x2))
  161.     (define y (inexact-random y1 y2))
  162.     (predicate x y))
  163.   (* (monte-carlo num-trials integral-experiment)
  164.      total-area))
  165.  
  166. (define (estimate-pi num-trials)
  167.   (define (in-unit-circle? x y)
  168.     (< (+ (sqr x) (sqr y)) 1))
  169.   (estimate-integral in-unit-circle? -1 1 -1 1 num-trials))
  170.  
  171. ;; tests
  172.  
  173. (estimate-pi 10)
  174. ;; 3.6
  175. (estimate-pi 100)
  176. ;; 3.2
  177. (estimate-pi 1000)
  178. ;; 3.176
  179. (estimate-pi 10000)
  180. ;; 3.1492
  181. (estimate-pi 100000)
  182. ;; 3.14252
  183. (estimate-pi 1000000)
  184. ;; 3.14344
  185.  
  186. ;;;;;;;;;
  187. ;; 3.6 ;;
  188. ;;;;;;;;;
  189.  
  190. ;; We'll use our own very simple prng: x[n+1] = 23 * x[n] + 11 mod 493.
  191.  
  192. (define (make-resettable-prng seed)
  193.   (define (rand-update x) (remainder (+ (* 23 x) 11) 493))
  194.   (define x seed)
  195.   (lambda (m)
  196.     (cond [(eq? m 'generate)
  197.            (set! x (rand-update x))
  198.            x]
  199.           [(eq? m 'reset)
  200.            (set! x seed)
  201.            "Reset."]
  202.           [else "Unknown request -- RAND"])))
  203.  
  204. (define new-prng (make-resettable-prng 10))
  205.  
  206. ;; tests
  207.  
  208. (new-prng 'generate)
  209. ;; 241
  210. (new-prng 'generate)
  211. ;; 131
  212. (new-prng 'generate)
  213. ;; 66
  214. (new-prng 'reset)
  215. ;; "Reset."
  216. (new-prng 'generate)
  217. ;; 241
  218. (new-prng 'generate)
  219. ;; 131
  220. (new-prng 'generate)
  221. ;; 66
  222.  
  223. ;;;;;;;;;
  224. ;; 3.7 ;;
  225. ;;;;;;;;;
  226.  
  227. (define (make-joint account password new-password)
  228.   (if (number? ((account password 'deposit) 0)) ; deposit 0 to check original pw
  229.     (lambda (pass m)
  230.       (if (eq? pass new-password)
  231.         (account password m)
  232.         (display-error "Incorrect password")))
  233.     "Password does not match -- MAKE-JOINT"))
  234.  
  235. (define paul-acc (make-account 100 'abc))
  236. ((paul-acc 'abc 'deposit) 100)
  237. ;; 200
  238. (define mary-acc (make-joint paul-acc 'abc 'def))
  239. ((mary-acc 'def 'withdraw) 75)
  240. ;; 125
  241. ((mary-acc 'def 'deposit) 50)
  242. ;; 175
  243. ((mary-acc 'xyz 'withdraw) 1000000)
  244. ;; "Incorrect password"
  245. (make-joint mary-acc 'xyz 'def)
  246. ;; "Password does not match -- MAKE-JOINT"
  247.  
  248. ;;;;;;;;;
  249. ;; 3.8 ;;
  250. ;;;;;;;;;
  251.  
  252. (define (make-weird-function)
  253.   (define state 0)
  254.   (lambda (n)
  255.     (cond
  256.       [(and (even? state) (even? n)) (set! state (add1 state)) -1]
  257.       [(and (odd? state) (odd? n)) (set! state (add1 state)) 1]
  258.       [(and (even? state) (odd? n)) (set! state (add1 state)) 1]
  259.       [(and (odd? state) (even? n)) (set! state (add1 state)) 0])))
  260.  
  261. ;; test
  262.  
  263. (define f (make-weird-function))
  264. (f 0)
  265. ;; -1
  266. (f 1)
  267. ;; 1
  268. ;; So evaluating (+ (f 0) (f 1)) left to right would produce (+ -1 1) or zero.
  269.  
  270. (define g (make-weird-function))
  271. (g 1)
  272. ;; 1
  273. (g 0)
  274. ;; 0
  275. ;; So evaluating (+ (g 0) (g 1)) right to left would produce (+ 1 0) or one.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement