Skip to content

Commit 45be6f7

Browse files
committed
Add exercise3-1 to 3-4.
1 parent 0952998 commit 45be6f7

File tree

5 files changed

+168
-0
lines changed

5 files changed

+168
-0
lines changed

README.org

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,13 @@
2121
#+begin_src shell
2222
raco pkg install --auto --batch # 类似 JavaScript 的 npm install
2323
#+end_src
24+
* 运行
25+
运行所有的习题
26+
#+begin_src shell
27+
raco test -t .
28+
#+end_src
29+
30+
运行指定的习题:
31+
#+begin_src shell
32+
raco test chapter1/exercise1-10.scm
33+
#+end_src

chapter3/exercise3-1.rkt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#lang racket
2+
(define (make-accumulator total)
3+
(lambda (next)
4+
(begin (set! total (+ total next))
5+
total)))
6+
7+
(module+ test
8+
(require rackunit)
9+
(require rackunit/text-ui)
10+
11+
(define acc (make-accumulator 5))
12+
(define module-test
13+
(test-suite
14+
"Tests for make-accumulator"
15+
(check-equal? (acc 5) 10)
16+
(check-equal? (acc 10) 20)
17+
(check-equal? (acc -30) -10)
18+
))
19+
20+
(run-tests module-test))

chapter3/exercise3-2.rkt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#lang racket
2+
3+
(define (make-monitored func)
4+
(let ((count 0))
5+
(lambda (input)
6+
(cond ((eq? input 'how-many-calls?) count)
7+
((eq? input 'reset-count) (set! count 0) 'reset)
8+
(else
9+
(set! count (+ count 1))
10+
(func input))))))
11+
12+
(module+ test
13+
(require rackunit)
14+
(require rackunit/text-ui)
15+
16+
(define s (make-monitored sqrt))
17+
(define module-test
18+
(test-suite
19+
"Tests for make-monitored"
20+
(check-equal? (s 100) 10)
21+
(check-equal? (s 100) 10)
22+
(check-equal? (s 'how-many-calls?) 2)
23+
(s 'reset-count)
24+
(check-equal? (s 'how-many-calls?) 0)
25+
))
26+
27+
(run-tests module-test))

chapter3/exercise3-3.rkt

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#lang racket
2+
(define (make-account balance password)
3+
(define (withdraw amount)
4+
(if (>= balance amount)
5+
(begin (set! balance (- balance amount))
6+
balance)
7+
"Insufficient funds"))
8+
9+
(define (deposit amount)
10+
(set! balance (+ balance amount))
11+
balance)
12+
13+
(define (dispatch pwd m)
14+
(if (eq? pwd password)
15+
(cond ((eq? m 'withdraw) withdraw)
16+
((eq? m 'deposit) deposit)
17+
(else (error "Unknown request --MAKE_ACCOUNT" m)))
18+
(error "Incorrect password")
19+
))
20+
dispatch)
21+
22+
(module+ test
23+
(require rackunit)
24+
(require rackunit/text-ui)
25+
(define acc (make-account 100 'secret-password))
26+
27+
(define module-test
28+
(test-suite
29+
"Tests for make-account with password"
30+
(check-equal? ((acc 'secret-password 'withdraw) 40) 60)
31+
(check-equal? ((acc 'secret-password 'withdraw) 40) 20)
32+
;; Test that an exception is thrown with the correct message
33+
(check-exn exn:fail? (lambda () ((acc 'invalid-password 'deposit) 40)))
34+
(check-exn (regexp "Incorrect password") (lambda () ((acc 'invalid-password 'deposit) 40)))
35+
))
36+
37+
(run-tests module-test))

chapter3/exercise3-4.rkt

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#lang racket
2+
(define (make-account balance password)
3+
(let ((failed-count 0))
4+
(define (withdraw amount)
5+
(if (>= balance amount)
6+
(begin (set! balance (- balance amount))
7+
balance)
8+
"Insufficient funds"))
9+
10+
(define (deposit amount)
11+
(set! balance (+ balance amount))
12+
balance)
13+
14+
(define (call-the-cops)
15+
(error "Calling 911"))
16+
17+
(define (dispatch pwd m)
18+
(if (eq? pwd password)
19+
;; reset the failed count once the password is correct
20+
(begin (set! failed-count 0)
21+
(cond ((eq? m 'withdraw) withdraw)
22+
((eq? m 'deposit) deposit)
23+
(else (error "Unknown request --MAKE_ACCOUNT" m))))
24+
(begin (set! failed-count (+ failed-count 1))
25+
(if (> failed-count 7)
26+
(call-the-cops)
27+
(error "Incorrect password")))
28+
))
29+
dispatch))
30+
31+
(module+ test
32+
(require rackunit)
33+
(require rackunit/text-ui)
34+
(define acc (make-account 100 'secret-password))
35+
(define acc2 (make-account 100 'secret-password))
36+
(define acc3 (make-account 100 'secret-password))
37+
38+
(define module-test
39+
(test-suite
40+
"Tests for make-account with password and limited attempt"
41+
(check-equal? ((acc 'secret-password 'withdraw) 40) 60)
42+
(check-equal? ((acc 'secret-password 'withdraw) 40) 20)
43+
;; Test that an exception is thrown with the correct message
44+
(check-exn exn:fail? (lambda () ((acc 'invalid-password 'deposit) 40)))
45+
(check-exn (regexp "Incorrect password") (lambda () ((acc 'invalid-password 'deposit) 40)))
46+
47+
"Tests for make-account, 7 consecutive attmepts failed, call cops eventually"
48+
(check-exn (regexp "Incorrect password") (lambda () ((acc2 'invalid-password 'deposit) 40)))
49+
(check-exn (regexp "Incorrect password") (lambda () ((acc2 'invalid-password 'deposit) 40)))
50+
(check-exn (regexp "Incorrect password") (lambda () ((acc2 'invalid-password 'deposit) 40)))
51+
(check-exn (regexp "Incorrect password") (lambda () ((acc2 'invalid-password 'deposit) 40)))
52+
(check-exn (regexp "Incorrect password") (lambda () ((acc2 'invalid-password 'deposit) 40)))
53+
(check-exn (regexp "Incorrect password") (lambda () ((acc2 'invalid-password 'deposit) 40)))
54+
(check-exn (regexp "Incorrect password") (lambda () ((acc2 'invalid-password 'deposit) 40)))
55+
(check-exn (regexp "Calling 911") (lambda () ((acc2 'invalid-password 'deposit) 40)))
56+
57+
"Tests for make-account, 1 attempt succeeded, but subsequence attempt failed, call cops eventually"
58+
(check-exn (regexp "Incorrect password") (lambda () ((acc3 'invalid-password 'deposit) 40)))
59+
(check-exn (regexp "Incorrect password") (lambda () ((acc3 'invalid-password 'deposit) 40)))
60+
;; successful attempt reset the failed count
61+
(check-equal? ((acc3 'secret-password 'withdraw) 40) 60)
62+
(check-exn (regexp "Incorrect password") (lambda () ((acc3 'invalid-password 'deposit) 40)))
63+
(check-exn (regexp "Incorrect password") (lambda () ((acc3 'invalid-password 'deposit) 40)))
64+
(check-exn (regexp "Incorrect password") (lambda () ((acc3 'invalid-password 'deposit) 40)))
65+
(check-exn (regexp "Incorrect password") (lambda () ((acc3 'invalid-password 'deposit) 40)))
66+
(check-exn (regexp "Incorrect password") (lambda () ((acc3 'invalid-password 'deposit) 40)))
67+
(check-exn (regexp "Incorrect password") (lambda () ((acc3 'invalid-password 'deposit) 40)))
68+
(check-exn (regexp "Incorrect password") (lambda () ((acc3 'invalid-password 'deposit) 40)))
69+
;; call-the-cops after consecutive 7 failed attempts
70+
(check-exn (regexp "Calling 911") (lambda () ((acc3 'invalid-password 'deposit) 40)))
71+
)
72+
)
73+
74+
(run-tests module-test))

0 commit comments

Comments
 (0)