sicp 4.3.2部分习题

4.38,谜题就有翻译错误,问题更是错的离谱。原题是这样的:
Baker, Cooper, Fletcher, Miller, and Smith live on different floors of an apartment house
that contains only five floors. Baker does not live on the top floor. Cooper does not live on
the bottom floor. Fletcher does not live on either the top or the bottom floor. Miller lives on
a higher floor than does Cooper. Smith does not live on a floor adjacent to Fletcher's.
Fletcher does not live on a floor adjacent to Cooper's. Where does everyone live?

其中说Miller住的比Cooper高,却翻译成了Miller住的比Cooper高一层,如果按照这个翻译来谜题是没有答案的。
回到4.38,题目是这样的:
Modify the multiple-dwelling procedure to omit the requirement that Smith and Fletcher do
not live on adjacent floors. How many solutions are there to this modified puzzle?

翻译却成了增加Smith和Fletcher不住在相邻层这个条件,谜题本来就是如此,何来的增加?错将omit翻译成了“增加”。
这道题很简单咯,将

(require (not (= (abs (- smith fletcher)) 1)))

注释掉即可,答案增加到5个:

> (multiple-dwelling)
((baker 1) (cooper 2) (fletcher 4) (miller 3) (smith 5))
> (amb)
((baker 1) (cooper 2) (fletcher 4) (miller 5) (smith 3))
>  (amb)
((baker 1) (cooper 4) (fletcher 2) (miller 5) (smith 3))
>  (amb)
((baker 3) (cooper 2) (fletcher 4) (miller 5) (smith 1))
>  (amb)
((baker 3) (cooper 4) (fletcher 2) (miller 5) (smith 1))

4.39,约束条件的顺序肯定是有影响的,能缩小搜索范围的强约束条件排在前面,弱约束条件排在后面,可以减少整体的判断次数。在DrScheme中,可以启用profile来分析顺序带来的影响,打开language->R5RS->Show Details,选择Debugging and Profiling 即可。运行scheme程序,然后在View->Show Profile中查看具体分析结果,在该视图中将详细列出各个函数调用的时间和次数。
在没有调整顺序前:
Msec      Calls      Function
40            1               multiple-dwelling
0              1716         require
4              2524          distinct?

说明multiple-dwelling调用了一次,花费了40毫秒,而require和distinct?函数分别被调用了1716次和2524次。
然后我将
(require
     (distinct? (list baker cooper fletcher miller smith)))

这个我认为弱约束条件放到了最后,测试的结果并不让人满意:
Msec      Calls      Function
44            1               multiple-dwelling
4              6035         require
0              129          distinct?

并没有大的提高,甚至反而所下降。猜测问题在于我使用的amb实现是call/cc、宏实现的,待俺完成amb求值器再测试一下。

4.40,题目都提示咯,嵌套let语句,我的解答:

(define (multiple-dwelling2)
  (let ((baker   (amb 1 2 3 4 5)))
     (require (not (= baker 5)))
      (let ((cooper  (amb 1 2 3 4 5)))
        (require (not (= cooper 1)))
        (let ((fletcher (amb 1 2 3 4 5)))
          (require (not (= fletcher 5))) 
          (require (not (= fletcher 1)))
          (require (not (= (abs (- fletcher cooper)) 1)))
          (let ((miller (amb 1 2 3 4 5)))
             (require (> miller cooper))
             (let ((smith   (amb 1 2 3 4 5)))
                (require (not (= (abs (- smith fletcher)) 1)))
                (require (distinct? (list baker cooper fletcher miller smith)))
                (list (list 'baker baker)
                      (list 'cooper cooper)
                      (list 'fletcher fletcher)
                      (list 'miller miller)
                      (list 'smith smith))))))))

profile一下,multiple-dwelling2的调用时间缩小到8毫秒,require和distinct?的调用次数分别降低到了404和129次。

4.42,说谎者谜题,
五个女生参加一个考试,她们的家长对考试结果过分关注。为此她们约定,在给家里写信谈到考试的时候,每个姑娘都要写一句真话和一句假话。下面是从她们的信里摘抄出来的句子:
Betty : kitty考第二,我只考了第三
Ethel : 你们应该很高兴听到我考了第一,joan第二
joan :   我考第三,可怜的Ethel垫底
kitty:  我第二,marry只考了第四
marry: 我是第四,Betty的成绩最高。
这五个姑娘的实际排名是什么?

将题目翻译成代码就OK了,说明性编程真是舒坦:

(define (liars-puzzle)
  (let ((betty (amb 1 2 3 4 5))
        (ethel (amb 1 2 3 4 5))
        (joan (amb 1 2 3 4 5))
        (kitty (amb 1 2 3 4 5))
        (marry (amb 1 2 3 4 5)))
    (require
       (distinct? (list betty ethel joan kitty marry)))
    (require (or (= kitty 2) (= betty 3)))
    (require (not (and (= kitty 2) (= betty 3))))
    (require (or (= ethel 1) (= joan 2)))
    (require (not (and (= ethel 1) (= joan 2))))
    (require (or (= joan 3) (= ethel 5)))
    (require (not (and (= joan 3) (= ethel 5))))
    (require (or (= kitty 2) (= marry 4)))
    (require (not (and (= kitty 2) (= marry 4))))
    (require (or (= marry 4) (= betty 1)))
    (require (not (and (= marry 4) (= betty 1))))
    (list (list 'betty betty)
          (list 'ethel ethel)
          (list 'joan joan)
          (list 'kitty kitty)
          (list 'marry marry))))

答案是:
((betty 3) (ethel 5) (joan 2) (kitty 1) (marry 4))

4.43.也很有趣的题目,游艇迷题,
   Mary Ann Moore的父亲有一条游艇,他的四个朋友Colonel Dowing、Mr.Hall、Sir Barnacle Hood和Dr.Parker也各有一条。这五个人都有一个女儿,每个人都用另一个人的女儿的名字来为自己的游艇命名。Sir Barnacle的游艇叫Gabrielle,Mr.Moore拥有Lorna,Mr.Hall的游艇叫Rosalind,Melissa属于Colonel Downing(取自Sir Barnacle的女儿的名字),Garielle的父亲的游艇取的是Dr.Parker的女儿的名字。请问,谁是Lorna的父亲。

先说下结果,Lorna的父亲是Downing。
具体解答如下,先定义辅助过程:

(define (father yacht daughter)
     (cons yacht daughter))
(define (yacht father)
  (car father))
(define (daughter father)
  (cdr father))

然后翻译题目为代码即可,暂不考虑效率问题:

(define (yacht-puzzle)
  (let ((moore (father 'lorna 'mary))  ;;Mr.Moore
        (downing (father 'melissa (amb 'mary 'melissa 'gabrielle 'rosalind 'lorna))))  ;;Colonel Downing
    (require (not (equal? (yacht downing) (daughter downing))))
    (let ((hall (father 'rosalind (amb 'mary 'melissa 'gabrielle 'rosalind 'lorna))))  ;;Mr.Hall
       (require (not (equal? (yacht hall) (daughter hall))))
       (let ((barnacle (father 'gabrielle 'melissa))   ;;Sir Barnacle Hood
             (parker (father (amb 'mary 'melissa 'gabrielle 'rosalind 'lorna) (amb 'mary 'melissa 'gabrielle 'rosalind 'lorna))))         ;;Dr.Parker
         (require (not (equal? (yacht parker) (daughter parker))))
         (let ((gabrielle-father (amb moore downing hall barnacle parker))) ;;Garielle's Father
           (require (equal? (daughter gabrielle-father) 'gabrielle))   
           (require (equal? (yacht gabrielle-father) (daughter parker)))
           (require (distinct? (map daughter (list moore downing hall barnacle parker))))
           (require (distinct? (map yacht (list moore downing hall barnacle parker))))
           (list 
              (list 'moore (yacht moore) (daughter moore))
              (list 'downing (yacht downing) (daughter downing))
              (list 'hall (yacht hall) (daughter hall))
              (list 'barnacle (yacht barnacle) (daughter barnacle))
              (list 'parker (yacht parker) (daughter parker))))))))

运行(yacht-puzzle)的结果为:
((moore lorna mary) (downing melissa lorna) (hall rosalind gabrielle) (barnacle gabrielle melissa) (parker mary rosalind))

三元组:父亲名、游艇名、女儿名,因此lorna的父亲是Downing。Garielle的父亲是Mr.Hall,Mr.Hall的游艇名叫做Rosalind,正是Dr.Parker的女儿名字。

延伸题目,如果没有Mary Ann姓Moore这个条件,答案将有三个,分别是:
((moore lorna mary) (downing melissa lorna) (hall rosalind gabrielle) (barnacle gabrielle melissa) (parker mary rosalind))
((moore lorna gabrielle) (downing melissa rosalind) (hall rosalind mary) (barnacle gabrielle melissa) (parker mary lorna))
((moore lorna lorna) (downing melissa mary) (hall rosalind gabrielle) (barnacle gabrielle melissa) (parker mary rosalind))

文章转自庄周梦蝶  ,原文发布时间

时间: 2024-09-21 10:52:18

sicp 4.3.2部分习题的相关文章

sicp 4.4.1小节习题

本节开始进入第4章最后一部分--逻辑程序设计.scheme将实现一种查询语言,非常类似prolog.由于解释器的实现在后面,还未读到,前面的习题我都将用prolog做测试,当然也给出scheme版本的解答,待以后测试.     首先给出依照书中所述写出的prolog事实库: address('BitDiddle Ben','Slumerville','Ridge Road',10). address('Hacker Alyssa P','Cambridge','Mass Ave',78). ad

sicp 3.1.1小节习题尝试解答

这一节主要是介绍局部状态变量,介绍了set!和begin的语法,看来ruby使用!号来表示改变变量值不是什么新鲜主意.    习题3.1,不解释了 ;习题3.1 (define (make-accumulator init)   (define (accumulator num)     (set! init (+ init num))     init)   accumulator) 习题3.2,非常有趣的例子,在内部维持一个计数的变量即可,如果传入的参数是特定的符号就返回计数或者清0,如果不

sicp 4.3.3小节习题

  本节实现了amb求值器,题目都是扩展这个求值器,引入一些特殊的过程.我的尝试解答从4.51开始 习题4.51,要求实现permanent-set!,这个过程的副作用在遇到失败时不撤销,实现如下: ;扩充analyze  ((permanent-assignment? exp)          (analyze-permanent-assignment exp)) ;实现 (define (permanent-assignment? exp)   (tagged-list? exp 'per

sicp 习题3.6-3.8试解

习题3.6,我的实现如下: (define rand   (let ((x 3))      (lambda(arg)       (cond((eq? arg 'generate)             ((lambda()(set! x (rand-update x)) x)))            ((eq? arg 'reset)             (lambda(init) (set! x init) (set! x (rand-update x)) x))         

sicp 2.3小结习题尝试解答

 习题2.2没有全部做,我读书的速度远远超过做习题的进度,没办法,时间有限,晚上的时间基本用来看书了,习题也都是在工作间隙做的,慢慢来了,前两章读完再总结下.回到2.3节,这一节在前几节介绍数值型符号数据的基础上引入了符号数据,将任意符号作为数据的能力非常有趣,并给出了一个符号求导的例子,实在是太漂亮了. 习题2.53,直接看结果: > (list 'a 'b 'c)(a b c)> (list (list 'george))((george))> (cdr '((x1 x2) (y1 

sicp习题2.33-2.39尝试解答

这一节的内容非常有趣,通过将序列作为interface,在此基础上进而提取出各种高阶操作(map,filter,accumulate,enumerate等),由此引出模块化设计的讨论.模块化设计带来复杂性的降低,同时可能引入性能上的损失,比如书中对sum-odd-squares过程的两种写法,原来的写法枚举列表元素的过程散落在累积.过滤.映射的过程中,主要一次循环就够了,而通过三个高阶过程来操作反而需要3次的遍历. 习题2.33,将map,append,length基本过程用累积操作重新定义,联

sicp 5.1节习题尝试解答

5.1 图就不画在机器上了,麻烦 5.2 用寄存器语言描述5.1题中的阶乘机器,加上了读取和打印,这里的解答全部在实际的寄存机器中验证过,但是仍然按照该节的表示法表示. (controller   fac-loop    (assign n (op read))    (assign product (const 1))    (assign counter (const 1))   iter-loop    (test (op >) (reg counter) (reg n))    (bra

sicp 3.12 3.13 3.14习题解答

习题3.12,append不是改变函数,不会改变x的结构.append!是改变函数,显然第一个response是(b),第二个就是(b c d).图就不画了,画了一次太麻烦了. 习题3.13,利用set-cdr!形成环,比较有意思: (define z (make-cycle (list 'a 'b 'c 'd))) z在DrScheme上表示为: #0=(a b c d . #0#) 形象地展示了一个环,显然运行(last-pair z)将陷入无限递归,因为(null? (cdr x))永远不

sicp 4.2.2小节部分习题

4.27, ;;; L-Eval input: (define count 0) ;;; L-Eval value: ok ;;; L-Eval input: (define (id x)   (set! count (+ 1 count))   x) ;;; L-Eval value: ok ;;; L-Eval input: (define w (id (id 10))) ;;; L-Eval value: ok ;;; L-Eval input: count ;;; L-Eval valu