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))