代码改变世界

《how to design programs》第11章自然数

2013-11-12 19:12  youxin  阅读(347)  评论(0编辑  收藏  举报

这章让我明白了原来自然数的定义本来就是个递归的过程。

我们通常用枚举的方式引出自然数的定义:0,1,2,3,等等(etc).最后的等等是什么意思?唯一能把等等从描述自然数的枚举方法中去除的方法是自引用,第一种尝试是:

0 is a natural number. 
If n is a natural number, then one more than n is one, too.

虽然这种描述并不是十分严格,但对于scheme格式的数据定义来说,他是一个很好的开始:

natural-number(自然数是以下2者之一

1。0

2.(add1 n) 如果n个自然数

 

0是第一个自然数

(add1 0)是下一个,接着就明显了:

(add1 (add1 0))

(add1 (add1 (add1 0)))

这些例子让我们想到了表的构造过程,我们从empty出发,通过cons连接更多的元素,构造出表。现在我们从0出发,通过(不断地)使用add1加上1,构造出自然数。

处理自然数的函数必须能够提取构造自然数时所使用的数,就像处理表的函数能够提取cons结构中的元素一样,执行这种提取操作的被称为sub1,它的运算规则是:

(sub1 (add1 n) )= n

它与cdr操作的运算规则类似:

(cdr (cons a-value a-list))= a-list

习题11.2.1:设计一个函数repeat,该函数读入一个自然数n个一个符号,返回包含n个符号的表:

;; repeat : natural-number -> list-of-symbols
(define (repeat n a-symbol)
  (cond
    [(zero? n) empty]
    [else (cons a-symbol (repeat (sub1 n) a-symbol))]))

;; Examples
(repeat 0 'doll) "should be" empty
(repeat 2 'rocket) "should be" (cons 'rocket (cons 'rocket empty))

 

习题11.2.2:

  Develop the function tabulate-f, which tabulates the values of

;; f : number  ->  number
(define (f x)
  (+ (* 3 (* x x)) 
     (+ (* -6 x)
        -1)))

for some natural numbers. Specifically, it consumes a natural number n and produces a list of n posns. The first one combines n with (f n), the second one n-1 with (f n-1), etc. 

设计函数,把函数f应用于一些由自然数值组成的表,其中f是上面的函数。

具体地说,函数读取自然数n,返回有n个posn结构体组成表,表的第一个元素是点(n (f n)),第二个为(n-1 (f n-1)),以此类推。

;; a list-of-posns is either:
;;  - empty
;;  - (cons posn list-of-posns)

;; f : number -> number
(define (f x) 
  (+ (* 3 (* x x)) 
     (+ (* -6 x) 
        -1)))

;; tabulate-f : number -> list-of-posns
;; produces a list of posns of length n. Each
;; posn's x coordinate is a number, from 0 to n, and each
;; posn's y coordinate is the result of f on the same posn's
;; x coordinate.

#|
;; TEMPLATE
(define (tabulate-f n)
  (cond
    [(zero? n) ...]
    [else (tabulate-f (sub1 n)) ...]))
|#

(define (tabulate-f n)
  (cond
    [(zero? n) empty]
    [else (cons (make-posn n (f n))
                (tabulate-f (sub1 n)))]))

;; EXAMPLES AS TESTS
(tabulate-f 0) "should be" empty
(tabulate-f 4) "should be"
(cons (make-posn 4 23)
      (cons (make-posn 3 8)
            (cons (make-posn 2 -1)
                  (cons (make-posn 1 -4)
                        empty))))

 

11.2.4 

 Lists may contain lists that contain lists and so on. Here is a data definition that takes this idea to an extreme:

deep-list is either

  1. s where s is some symbol or

  2. (cons dl empty), where dl is a deep list.

 

Develop the function depth, which consumes a deep list and determines how many times cons was used to construct it.

Develop the function make-deep, which consumes a symbol s and a natural number and produces a deep list containing s and constructed with nconses.

表的成员也可以是表,可以嵌套多层,下面就是这种思想的一个极端定义:

deep-list深层表示下列之一:

1.s其中s是symbol

2. (cons dl emtpy) dl是深层表。

设计函数depth,该函数读取一个深层表,测定这个表用了多少次cons来构成。设计函数make-deep,该函数读取符号s和自然数n,

返回包含s,使用n次cons构造的表。

;; depth : deep-list -> natural-number
;; counts the number of cons's used to create this deep list.
;depth:deep-list->number
(define (depth a-dl)
  (cond
    [(symbol? a-dl) 0]
    [else (+ 1 (depth (car a-dl))) ]
    ))

(depth 'bottom) "should be" 0
(depth (cons (cons (cons (cons 'bottom empty) empty) empty) empty)) "should be" 4
(define (make-deep n s)
  (cond
    [(zero? n) s]
    [else (cons (make-deep (sub1 n) s) empty)]))

(make-deep 0 'bottom) "should be" 'bottom
(make-deep 4 'bottom) "should be" 
(cons (cons (cons (cons 'bottom empty) empty) empty) empty)
DRracekt输出:'((((bottom))))
可以看到,很直观的表示4层嵌套。

 

自然数的另一种数据定义:

自然数(>=20)是系列之一:

1.20

2.(add 1 n)如果n是自然数。

说白了第一种定义时减法,第二种定义时加法。

计算从20(不包括20)到n(包括n)的乘积:

 ;计算n*(n-1)...21*1
 (define (product-from-20 n-above-20)
   (cond
     [(= n-above-20 20) 1]
     [else (* n-above-20 (product-from-20 (sub1 n-above-20)) )]
     ))
 (product-from-20 22) ;462