SICP 2.2节习题(1)

第二章 构造数据抽象

2.2 层次性数据和闭包性质

EX 2.17

1
2
3
4
5
;返回列表尾元素
(define (last-pair x)
(if (null? (cdr x))
x
(last-pair (cdr x))))
1
2
;测试
(last-pair (list 1 2 3 4))

EX 2.18

1
2
3
4
5
6
7
;反转列表
(define (reverse x)
(define (iter remain result)
(if (null? remain)
result
(iter (cdr remain) (cons (car remain) result))))
(iter x '()))

EX 2.19

题目本身并不难,只要看过“换零钱”的程序,根据分治思想,分成使用的币种和为未使用的币种,两部分分别是list的car和cdr

1
2
3
4
5
6
;源程序
(define (cc amount coin-values)
(cond ((= amount 0) 1)
((or (< amount 0) (no-more? coin-values)) 0)
(else (+ (cc amount (except-first-denomination coin-values))
(cc (- amount (first-denomination coin-values)) coin-values)))))
1
2
3
4
5
6
7
;补全程序
(define (first-denomination coin-values)
(car coin-values))
(define (except-first-denomination coin-values)
(cdr coin-values))
(define (no-more? coin-values)
(null? coin-values))

EX 2.20

一般的思路是利用循环遍历列表,逐个判断元素的奇偶性,当该项符合要求时加入新的list中
这里的思路是抽象出一种通用的过程filter,体现了动态语言的特性,将过程(函数)作为参数传递

1
2
3
4
5
6
;P78 filter的定义
(define (filter predicate sequence)
(cond ((null? sequence) '())
((predicate (car sequence))
(cons (car sequence) (filter predicate (cdr sequence))))
(else (filter predicate (cdr sequence)))))
1
2
3
4
5
6
7
8
9
10
11
12
;一种same-parity  
(define (same-parity x . y)
(cond ((odd? x) (filter odd? (cons x y)))
((even? x) (filter even? (cons x y)))
(else (display "x error"))))

;一种same-parity的简洁定义
(define (same-parity x . y)
(filter (if (odd? x)
odd?
even?)
(cons x y)))

EX 2.21

不难补全代码
第一种定义:对car项做平方,cdr项继续迭代回过程中
第二种定义:根据map的定义,形式参数是操作类型和被操作的项即可

1
2
3
4
5
6
;一种square-list的定义
(define (square-list1 items)
(if (null? items)
'()
(cons (square (car items))
(square-list1 (cdr items)))))
1
2
3
;另一种square-list的定义
(define (square-list2 items)
(map square items))

EX 2.22

1
2
3
4
5
6
7
8
9
;原始程序(未交换cons参数)
(define (square-list items)
(define (iter things answer)
(if (null? things)
answer
(iter (cdr things)
(cons (square (car things))
answer))))
(iter items '()))

分析如下:

(square-list (list 1 2 3))                    ->
(iter (1 2 3) '())                            ->
(iter (2 3) (cons 1 '()))                    ->
(iter (3) (cons 4 (cons 1 '())))            ->
(iter '() (cons 9 (cons 4 (cons 1 '()))))    ->    (cons 9 (cons 4 (cons 1 '())))) = (list 9 4 1)
(9 4 1)
1
2
3
4
5
6
7
8
9
;原始程序(交换cons参数)
(define (square-list items)
(define (iter things answer)
(if (null? things)
answer
(iter (cdr things)
(cons answer
(square (car things))))))
(iter items '()))

分析如下:

(square-list (list 1 2 3))                    ->
(iter (1 2 3) '())                             ->
(iter (2 3) (cons '() 1))                    ->
(iter (3) (cons (cons '() 1) 4))            ->
(iter '() (cons (cons (cons '() 1) 4) 3))    ->    (cons (cons (cons '() 1) 4) 3) = (((() . 1) . 4) . 9)
(((() . 1) . 4) . 9)
1
2
3
4
5
6
7
8
9
;正确程序
(define (square-list items)
(define (iter things answer)
(if (null? things)
(reverse answer)
(iter (cdr things)
(cons (square (car things))
answer))))
(iter items '()))

分析如下:

(square-list (list 1 2 3))                    ->
(iter (1 2 3) '())                            ->
(iter (2 3) (cons 1 '()))                    ->
(iter (3) (cons 4 (cons 1 '())))            ->
(iter '() (cons 9 (cons 4 (cons 1 '()))))    ->    (cons 9 (cons 4 (cons 1 '()))) = (list 9 4 1)
(list 1 4 9)

EX 2.23

1
2
3
4
5
6
;类似于map的定义,返回逻辑值
(define (for-each proc items)
(if (null? items)
#f
(cons (proc (car items))
(for-each proc (cdr items)))))