sicp-ex-3.4



<< Previous exercise (3.3) | Index | Next exercise (3.5) >>


Igor Saprykin

  
  
  
 (define (make-account balance password) 
   (define (call-the-cops) "Call the cops") 
   (let ((count 0) 
         (limit 7)) 
     (define (withdraw amount) 
       (if (>= balance amount) 
           (begin (set! balance (- balance amount)) 
                  balance) 
           "Not enough money")) 
     (define (deposit amount) 
       (set! balance (+ balance amount)) 
       balance) 
     (define (dispatch pass m) 
       (if (not (eq? pass password)) 
           (lambda (amount) 
             (if (> count limit) 
                 (call-the-cops) 
                 (begin (set! count (+ count 1)) 
                        "Wrong password"))) 
           (begin (set! count 0) 
                  (cond ((eq? m 'withdraw) withdraw) 
                        ((eq? m 'deposit) deposit) 
                        (else (error "Unknown call -- MAKE-ACCOUNT" 
                                     m)))))) 
       dispatch)) 


Daniel-Amariei

  
  
  
 (define (make-accumulator acc) 
   (lambda (x)  
     (set! acc (+ acc x)) 
     acc)) 
  
  
 (define (make-account balance secret-password) 
   (define (call-the-cops) "The cops have been caled!") 
   (define attempts (make-accumulator 0)) 
   (define (attempts-made) (attempts 0)) 
   (define (reset-attempts) (attempts (- (attempts 0)))) 
    
   (define (is-correct-password? password) 
    (cond ((equal? secret-password password) 
           (reset-attempts) true) 
           (else (attempts 1)  
                 false))) 
    
   (define (withdraw amount) 
     (cond ((>= balance amount) 
            (set! balance (- balance amount)) 
            balance) 
           (else  
            "Insufficient funds"))) 
   
    
   (define (deposit amount) 
     (set! balance (+ balance amount)) 
     balance) 
    
   (define (dispatch password m) 
     (cond ((not (is-correct-password? password)) 
            (if (> (attempts-made) 7) 
                (lambda (x) (call-the-cops)) 
                (lambda (x) "Incorrect password"))) 
           ((equal? m 'withdraw) withdraw) 
           ((equal? m 'deposit) deposit) 
           (else (error "Unknown request: MAKE-ACCOUNT" m)))) 
   dispatch) 


eliyak

I put all the password-checking functionality into a separate internal function called correct-password?. Unfortunately my implementation of scheme does not know how to (call-the-cops).

 (define (make-account balance password) 
   (define bad-password-count 0) 
   (define (correct-password? p) 
     (if (eq? p password) 
         (set! bad-password-count 0) 
         (begin 
           (if (= bad-password-count 7) 
               (call-the-cops) 
               (set! bad-password-count (+ bad-password-count 1))) 
           (display "Incorrect password") 
           #f))) 
   (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 (correct-password? p) 
         (cond 
           ((eq? m 'withdraw) withdraw) 
           ((eq? m 'deposit) deposit) 
           (else (error "Unknown request -- MAKE-ACCOUNT" m))) 
         (lambda (x) (display "")))) 
   dispatch) 


 (define (make-account balance password) 
   (let ((bad-passwords 0)) 
     (define (withdraw amount) 
       (if (>= balance amount) 
           (begin (set! balance (- balance amount)) 
                  balance) 
           (print "Insufficient funds"))) 
     (define (deposit amount) 
       (set! balance (+ balance amount)) 
       balance) 
     (define (dispatch p m) 
       (if (good-password? p) 
           (cond ((eq? m 'withdraw) withdraw) 
                 ((eq? m 'deposit) deposit) 
                 (else (error "Unknown request -- MAKE-ACCOUNT" m))) 
           (lambda (x) (print "Incorrect password") (newline)))) 
     (define (good-password? p) 
       (cond ((eq? p password) 
              (set! bad-passwords 0) 
              true) 
             ((< bad-passwords 7) 
              (set! bad-passwords (+ bad-passwords 1)) 
              false) 
             (else 
              (call-the-cops)))) 
     (define (call-the-cops) 
       (print "Cops called!") 
       false) 
     dispatch)) 

Caleb Gossler

I wrapped dispatch in a function that handles the password checking. It keeps dispatch much cleaner.

 (define (make-account password balance) 
   (define (withdraw amount) 
     (if (>= balance amount) 
         (begin (set! balance (- balance amount)) 
                balance) 
         "Insufficient funds")) 
   (define (deposit amount) 
     (set! balance (+ balance amount)) 
     balance) 
   (define (dispatch m) 
     (cond ((eq? m 'withdraw) withdraw) 
           ((eq? m 'deposit) deposit) 
           (else (error "Unknown request -- MAKE-ACCOUNT" 
                        m)))) 
   (password-protect password dispatch)) 
  
 (define (password-protect user-password f) 
   (define invalid-attempts 0) 
   (lambda (password m) 
     (cond [(= invalid-attempts 7) 
            (call-the-cops)] 
           [(eq? password user-password) 
            (set! invalid-attempts 0) 
            (f m)] 
           [else 
            (set! invalid-attempts (+ 1 invalid-attempts)) 
            (error "Incorrect password")]))) 
  
 (define (call-the-cops) 
   (error "The cops have been called!"))