|
| 1 | +#lang racket |
| 2 | + |
| 3 | +(define (count-pairs x) |
| 4 | + (let ((seen '())) |
| 5 | + (define (helper v) |
| 6 | + (cond ((not (pair? v)) |
| 7 | + 0) |
| 8 | + ((memq v seen) |
| 9 | + 0) |
| 10 | + (else (set! seen (cons v seen)) |
| 11 | + (+ (helper (car v)) |
| 12 | + (helper (cdr v)) |
| 13 | + 1)))) |
| 14 | + (helper x))) |
| 15 | + |
| 16 | +(module+ test |
| 17 | + (require rackunit) |
| 18 | + |
| 19 | + (test-case "Test for count-pairs return 3, without shared" |
| 20 | + (define a (list '1 '2 '3)) |
| 21 | + (check-equal? (count-pairs a) 3)) |
| 22 | + |
| 23 | + (test-case "Test for count-pairs return 3, with shared cons" |
| 24 | + (define shared (cons 1 2)) |
| 25 | + (define b (cons shared (cons shared '()))) |
| 26 | + (check-equal? (count-pairs b) 3)) |
| 27 | + |
| 28 | + (test-case "Test for count-pairs return 3, with multiple shared cons" |
| 29 | + (define shared (cons 1 2)) |
| 30 | + (define c (cons shared shared)) |
| 31 | + (define d (cons c c)) |
| 32 | + (check-equal? (count-pairs d) 3) |
| 33 | + ) |
| 34 | + |
| 35 | + (test-case "Test for circular reference - mutable version" |
| 36 | + ;; racket 不支持 Scheme set-cdr! 操作, 只支持针对 mutable 对象的 |
| 37 | + ;; set-mcdr!, 但如果要使用 set-mcdr!, 就需要使用相应的 mpair?, |
| 38 | + ;; mcdr, mcar 函数, 那干脆在定义一个 mutable 版本的 count-pairs |
| 39 | + (define (mcount-pairs x) |
| 40 | + (let ((seen '())) |
| 41 | + (define (helper v) |
| 42 | + (cond ((not (mpair? v)) |
| 43 | + 0) |
| 44 | + ((memq v seen) |
| 45 | + 0) |
| 46 | + (else (set! seen (cons v seen)) |
| 47 | + (+ (helper (mcar v)) |
| 48 | + (helper (mcdr v)) |
| 49 | + 1)))) |
| 50 | + (helper x))) |
| 51 | + |
| 52 | + (define cycle (mcons 1 (mcons 2 null))) |
| 53 | + (set-mcdr! (mcdr cycle) cycle) |
| 54 | + (check-equal? (mcount-pairs cycle) 2)) |
| 55 | + ) |
| 56 | + |
| 57 | + |
| 58 | + |
0 commit comments