【问题标题】:Scheme - program to count the number of pairs (SICP ex 3.17) - is my solution correct?方案-计算对数的程序(SICP ex 3.17)-我的解决方案正确吗?
【发布时间】:2020-09-02 02:55:00
【问题描述】:
我需要设计一个程序来返回任何结构中不同对的数量。我的程序正确吗?我在网上找到的解决方案都大相径庭。
(define (count-pairs x)
(define (count-cdr x)
(if (not (pair? x))
0
(+ (count-pairs (car x))
(count-cdr (cdr x)))))
(if (not (pair? x))
0
(+ (count-pairs (car x))
(count-cdr (cdr x))
1)))
【问题讨论】:
标签:
list
scheme
lisp
sicp
【解决方案1】:
请注意,该问题要求 any 结构中 distinct 对的数量,因此我们必须小心并避免多次计算同一对,即使它在结构内的不同位置!还要注意提示:
遍历结构,维护一个辅助数据结构,用于跟踪哪些对已经被计数
您必须跟踪您找到的配对,并检查它们是否重复,您的解决方案完全忽略了提示。这对我有用:
(define (count-pairs x)
(let ((acc '()))
(define (count lst)
(cond ((or (not (pair? lst)) (memq lst acc)) 0)
(else (set! acc (cons lst acc))
(+ 1 (count (car lst)) (count (cdr lst))))))
(count x)))
这里有一些测试可以证明我的观点:
(define l1 (cons 1 (cons 2 (cons 3 null))))
(define x1 (cons null null))
(define y1 (cons x1 x1))
(define l2 (cons y1 null))
(define x2 (cons 1 (cons 2 null)))
(define l3 (cons x2 x2))
(define x3 (cons null null))
(define y3 (cons x3 x3))
(define l4 (cons y3 y3))
(count-pairs l1)
=> 3
(count-pairs l2)
=> 3
(count-pairs l3)
=> 3
(count-pairs l4)
=> 3
【解决方案2】:
这是我认为在 Scheme 中相当自然的方法。尽管人们(尤其是我)痴迷于使流程迭代而不是递归,而不是太多(为什么堆栈空间比这段代码创建的潜在巨大议程更有价值?),为这种类型编写迭代程序是相当不错的东西。
这个函数有两个列表:
- 它已经看过的配对列表,因此它可以知道它是否看过配对
- 它需要处理的事情的议程,在处理汽车之前,它会将它看到的新对的 cdr 推送到该议程上。
然后该过程是检查它正在看的东西是否是一对并且未被看到。如果这是真的,那么它将计数加一并处理这对汽车,将 cdr 推到议程上,并将整个车对推到已看到的列表中。如果这不是真的,那么它要么将某些事情从议程中拉出来进行处理,或者,如果没有议程,它就完成了,计数就是答案。
请注意,在现实生活中,cp-loop 将命名为 let,这使我认为迭代更加清晰。
(define (count-pairs thing)
(define (cp-loop it count agenda seen)
(cond
[(and (pair? it) (not (memq it seen)))
;; It's a pair, and we have not seen it, so:
;; - add one to the count
;; - loop on its car
;; - pushing its cdr onto the agenda
;; - note we've seen it
(cp-loop (car it)
(+ count 1)
(cons (cdr it) agenda)
(cons it seen))]
[(not (null? agenda))
;; Either it is not a pair, or we've seen it
;; But there is more to do, so:
;; - pick the first agenda item & try that
(cp-loop (first agenda)
count
(rest agenda)
seen)]
[else
;; it's not a pair or we have seen it
;; and there is no agenda: we are done
count]))
(cp-loop thing 0 '() '()))
现在:
> (define o1 '(1 . (2 . (3 . ()))))
> o1
'(1 2 3)
> (count-pairs o1)
3
> (define o2 '(1 . (2 . (3 . (4 . 5)))))
> o2
'(1 2 3 4 . 5)
> (count-pairs o2)
4
> (define o3 (cons o1 o1))
> (count-pairs o3)
4
> o3
'((1 2 3) 1 2 3)
> (count-pairs '((1 2 3) 1 2 3))
7