timothy235 icon

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

timothy235 | PRO | 12/19/24 01:15:51 AM UTC (Edited) | 0 ⭐ | 7107 👁️ | Never ⏰ | []
Racket |

6.49 KB

|

None

|

0 👍

/

0 👎

#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

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎