sicp 4.4.1小節(jié)習題
Posted on 2008-11-22 13:27 dennis 閱讀(1790) 評論(0) 編輯 收藏 所屬分類: 動態(tài)語言 、計算機科學與基礎本節(jié)開始進入第4章最后一部分——邏輯程序設計。scheme將實現(xiàn)一種查詢語言,非常類似prolog。由于解釋器的實現(xiàn)在后面,還未讀到,前面的習題我都將用prolog做測試,當然也給出scheme版本的解答,待以后測試。
首先給出依照書中所述寫出的prolog事實庫:
address('BitDiddle Ben','Slumerville','Ridge Road',10).
address('Hacker Alyssa P','Cambridge','Mass Ave',78).
address('Fect Cy D','Cambridge','Ames Street',3).
address('Tweakit Lem E','Boston','Bay State Road',22).
address('Reasoner Louis','Slumerville','Pine Tree Road',80).
address('Warbucks Oliver','Swellesley','Top Heap Road',unknown).
address('Scrooge Eben','Weston','Shady Lane',10).
address('Aull DeWitt','Slumerville','Onione Square',5).
address('Cratchet Robert','Allston','N Harvard Street',16).
job('BitDiddle Ben',computer,wizard).
job('Hacker Alyssa P',computer,programmer).
job('Fect Cy D',computer,programmer).
job('Tweakit Lem E',computer,technician).
job('Warbucks Oliver',administration,'big wheel').
job('Scrooge Eben',accounting,'chief accountant').
job('Aull DeWitt',administration,secretary).
job('Cratchet Robert',accounting,scrivener).
job('Reasoner Louis',computer,programmer,trainee).
salary('Hacker Alyssa P',40000).
salary('BitDiddle Ben',60000).
salary('Fect Cy D',35000).
salary('Tweakit Lem E',25000).
salary('Reasoner Louis',30000).
salary('Warbucks Oliver',150000).
salary('Scrooge Eben',75000).
salary('Cratchet Robert',18000).
salary('Aull DeWitt',25000).
supervisor('Hacker Alyssa P','BitDiddle Ben').
supervisor('Fect Cy D','BitDiddle Ben').
supervisor('Tweakit Lem E','BitDiddle Ben').
supervisor('Reasoner Louis','Hacker Alyssa P').
supervisor('BitDiddle Ben','Warbucks Oliver').
supervisor('Scrooge Eben','Warbucks Oliver').
supervisor('Cratchet Robert','Scrooge Eben').
supervisor('Aull DeWitt','Warbucks Oliver').
can_do(computer,wizard,computer,programmer).
can_do(computer,wizard,computer,technician).
can_do(administration,secretary,administration,'big wheel').
address('Hacker Alyssa P','Cambridge','Mass Ave',78).
address('Fect Cy D','Cambridge','Ames Street',3).
address('Tweakit Lem E','Boston','Bay State Road',22).
address('Reasoner Louis','Slumerville','Pine Tree Road',80).
address('Warbucks Oliver','Swellesley','Top Heap Road',unknown).
address('Scrooge Eben','Weston','Shady Lane',10).
address('Aull DeWitt','Slumerville','Onione Square',5).
address('Cratchet Robert','Allston','N Harvard Street',16).
job('BitDiddle Ben',computer,wizard).
job('Hacker Alyssa P',computer,programmer).
job('Fect Cy D',computer,programmer).
job('Tweakit Lem E',computer,technician).
job('Warbucks Oliver',administration,'big wheel').
job('Scrooge Eben',accounting,'chief accountant').
job('Aull DeWitt',administration,secretary).
job('Cratchet Robert',accounting,scrivener).
job('Reasoner Louis',computer,programmer,trainee).
salary('Hacker Alyssa P',40000).
salary('BitDiddle Ben',60000).
salary('Fect Cy D',35000).
salary('Tweakit Lem E',25000).
salary('Reasoner Louis',30000).
salary('Warbucks Oliver',150000).
salary('Scrooge Eben',75000).
salary('Cratchet Robert',18000).
salary('Aull DeWitt',25000).
supervisor('Hacker Alyssa P','BitDiddle Ben').
supervisor('Fect Cy D','BitDiddle Ben').
supervisor('Tweakit Lem E','BitDiddle Ben').
supervisor('Reasoner Louis','Hacker Alyssa P').
supervisor('BitDiddle Ben','Warbucks Oliver').
supervisor('Scrooge Eben','Warbucks Oliver').
supervisor('Cratchet Robert','Scrooge Eben').
supervisor('Aull DeWitt','Warbucks Oliver').
can_do(computer,wizard,computer,programmer).
can_do(computer,wizard,computer,technician).
can_do(administration,secretary,administration,'big wheel').
從習題4.55開始,
1)所有被Ben BitDiddle管理的人:
(supervisor ?x (BitDiddle Ben))
prolog測試:| ?- supervisor(Name,'BitDiddle Ben').
Name = 'Hacker Alyssa P' ? ;
Name = 'Fect Cy D' ? ;
Name = 'Tweakit Lem E' ? ;
no
Name = 'Hacker Alyssa P' ? ;
Name = 'Fect Cy D' ? ;
Name = 'Tweakit Lem E' ? ;
no
2)會計部所有的人的名字和工作:
(job ?name (accounting .?type))
prolog測試:
| ?- job(Name,accounting,Type).
Name = 'Scrooge Eben'
Type = 'chief accountant' ? ;
Name = 'Cratchet Robert'
Type = scrivener
yes
Name = 'Scrooge Eben'
Type = 'chief accountant' ? ;
Name = 'Cratchet Robert'
Type = scrivener
yes
3)在Slumerville居住所有人的名字和地址:
(address ?name (Slumerville ?where))
prolog測試:
| ?- address(Name,'Slumerville',Road,No).
Name = 'BitDiddle Ben'
No = 10
Road = 'Ridge Road' ? ;
Name = 'Reasoner Louis'
No = 80
Road = 'Pine Tree Road' ? ;
Name = 'Aull DeWitt'
No = 5
Road = 'Onione Square' ? ;
Name = 'BitDiddle Ben'
No = 10
Road = 'Ridge Road' ? ;
Name = 'Reasoner Louis'
No = 80
Road = 'Pine Tree Road' ? ;
Name = 'Aull DeWitt'
No = 5
Road = 'Onione Square' ? ;
習題4.56,
1)給出Ben Bitdiddle的所有下屬的名字,以及他們的地址:
(and
(supervisor ?name (Bitdiddle Ben))
(address ?name ?where))
prolog測試,注意prolog是用,號表示and的關系:(supervisor ?name (Bitdiddle Ben))
(address ?name ?where))
| ?- supervisor(Name,'BitDiddle Ben'),address(Name,City,Road,No).
City = 'Cambridge'
Name = 'Hacker Alyssa P'
No = 78
Road = 'Mass Ave' ? ;
City = 'Cambridge'
Name = 'Fect Cy D'
No = 3
Road = 'Ames Street' ? ;
City = 'Boston'
Name = 'Tweakit Lem E'
No = 22
Road = 'Bay State Road' ? ;
City = 'Cambridge'
Name = 'Hacker Alyssa P'
No = 78
Road = 'Mass Ave' ? ;
City = 'Cambridge'
Name = 'Fect Cy D'
No = 3
Road = 'Ames Street' ? ;
City = 'Boston'
Name = 'Tweakit Lem E'
No = 22
Road = 'Bay State Road' ? ;
2)所有工資少于Ben Bitdiddle的人,以及他們的工資和Ben Bitdiddle的工資
(and
(salary (Bitdiddle Ben) ?ben)
(salary ?person ?amount)
(lisp-value < ?amount ?ben)
)
(salary (Bitdiddle Ben) ?ben)
(salary ?person ?amount)
(lisp-value < ?amount ?ben)
)
prolog測試:
?-salary('BitDiddle Ben',Bensalary),salary(Person,Amount),Amount<Bensalary.
Amount = 40000
Bensalary = 60000
Person = 'Hacker Alyssa P' ? ;
Amount = 35000
Bensalary = 60000
Person = 'Fect Cy D' ? ;
Amount = 25000
Bensalary = 60000
Person = 'Tweakit Lem E' ? ;
Amount = 30000
Bensalary = 60000
Person = 'Reasoner Louis' ? ;
Amount = 18000
Bensalary = 60000
Person = 'Cratchet Robert' ? ;
Amount = 25000
Bensalary = 60000
Person = 'Aull DeWitt'
Amount = 40000
Bensalary = 60000
Person = 'Hacker Alyssa P' ? ;
Amount = 35000
Bensalary = 60000
Person = 'Fect Cy D' ? ;
Amount = 25000
Bensalary = 60000
Person = 'Tweakit Lem E' ? ;
Amount = 30000
Bensalary = 60000
Person = 'Reasoner Louis' ? ;
Amount = 18000
Bensalary = 60000
Person = 'Cratchet Robert' ? ;
Amount = 25000
Bensalary = 60000
Person = 'Aull DeWitt'
3)所有不是由計算機分部的人管理的人,以及他們的上司和工作:
(and (supervisor ?person ?boss)
(not (job ?boss (computer . ?type)))
(job ?boss?bossjob))
(not (job ?boss (computer . ?type)))
(job ?boss?bossjob))
prolog測試:
| ?- supervisor(Person,Boss),\+(job(Boss,computer,_)),job(Boss,BossJob1,BossJob2).
Boss = 'Warbucks Oliver'
BossJob1 = administration
BossJob2 = 'bit wheel'
Person = 'Ben BitDiddle' ? ;
Boss = 'Warbucks Oliver'
BossJob1 = administration
BossJob2 = 'bit wheel'
Person = 'Scrooge Eben' ? ;
Boss = 'Scrooge Eben'
BossJob1 = accounting
BossJob2 = 'chief accountant'
Person = 'Cratchet Robert' ? ;
Boss = 'Warbucks Oliver'
BossJob1 = administration
BossJob2 = 'bit wheel'
Person = 'Aull DeWitt'
Boss = 'Warbucks Oliver'
BossJob1 = administration
BossJob2 = 'bit wheel'
Person = 'Ben BitDiddle' ? ;
Boss = 'Warbucks Oliver'
BossJob1 = administration
BossJob2 = 'bit wheel'
Person = 'Scrooge Eben' ? ;
Boss = 'Scrooge Eben'
BossJob1 = accounting
BossJob2 = 'chief accountant'
Person = 'Cratchet Robert' ? ;
Boss = 'Warbucks Oliver'
BossJob1 = administration
BossJob2 = 'bit wheel'
Person = 'Aull DeWitt'
習題4.57
定義這個規(guī)則,用scheme實現(xiàn)是:
(rule (instead ?person ?insteadperson)
(and
(job ?person ?insteadedjob)
(job ?insteadperson ?job)
(not (same ?person ?insteadperson))
(or (can-do-job ?job ?insteadedjob)
(same ?job ?insteadedjob))))
(and
(job ?person ?insteadedjob)
(job ?insteadperson ?job)
(not (same ?person ?insteadperson))
(or (can-do-job ?job ?insteadedjob)
(same ?job ?insteadedjob))))
用prolog定義此規(guī)則:
instead(Person,InsteadPerson):-
job(Person,Part,Pos),
job(InsteadPerson,InsteadPart,InsteadPos),
Person\==InsteadPerson,
(can_do(InsteadPart,InsteadPos,Part,Pos);InsteadPart==Part,InsteadPos==Pos).
job(Person,Part,Pos),
job(InsteadPerson,InsteadPart,InsteadPos),
Person\==InsteadPerson,
(can_do(InsteadPart,InsteadPos,Part,Pos);InsteadPart==Part,InsteadPos==Pos).
a)找出能代替Cy D.Fect的人:
(instead (Fect Cy D) ?person)
prolog測試:
| ?- instead('Fect Cy D',InsteadPerson).
InsteadPerson = 'BitDiddle Ben' ? ;
InsteadPerson = 'Hacker Alyssa P' ? ;
InsteadPerson = 'BitDiddle Ben' ? ;
InsteadPerson = 'Hacker Alyssa P' ? ;
b)找出所有能夠代替某個工資比自己高的人的人,以及兩個人的工資:
(and (?person1 ?person2)
(salary ?person1 ?salary1)
(salary ?person2 ?salary2)
(lisp-value > ?salary1 ?salary2))
(salary ?person1 ?salary1)
(salary ?person2 ?salary2)
(lisp-value > ?salary1 ?salary2))
prolog測試:
| ?- instead(Person1,Person2),salary(Person1,Salary1),salary(Person2,Salary2),Salary1>Salary2.
Person1 = 'Hacker Alyssa P'
Person2 = 'Fect Cy D'
Salary1 = 40000
Salary2 = 35000 ? ;
Person1 = 'Warbucks Oliver'
Person2 = 'Aull DeWitt'
Salary1 = 150000
Salary2 = 25000 ? ;
Person1 = 'Hacker Alyssa P'
Person2 = 'Fect Cy D'
Salary1 = 40000
Salary2 = 35000 ? ;
Person1 = 'Warbucks Oliver'
Person2 = 'Aull DeWitt'
Salary1 = 150000
Salary2 = 25000 ? ;
習題4.58,
(rule (vip ?person)
(and
(job ?person (?part .?pos))
(or
(not (supervisor ?person ?boss))
(and
(?boss (?bosspart .?bosspos))
(not (same ?part ?bosspart))))))
(and
(job ?person (?part .?pos))
(or
(not (supervisor ?person ?boss))
(and
(?boss (?bosspart .?bosspos))
(not (same ?part ?bosspart))))))
用prolog實現(xiàn)并測試的結(jié)果:
vip(Person):-
job(Person,Part,Pos),
(\+(supervisor(Person,Boss));
(supervisor(Person,Boss),
job(Boss,BossPart,_),
Part\==BossPart)).
| ?- vip(Person).
Person = 'BitDiddle Ben' ? a
Person = 'Warbucks Oliver'
Person = 'Scrooge Eben'
job(Person,Part,Pos),
(\+(supervisor(Person,Boss));
(supervisor(Person,Boss),
job(Boss,BossPart,_),
Part\==BossPart)).
| ?- vip(Person).
Person = 'BitDiddle Ben' ? a
Person = 'Warbucks Oliver'
Person = 'Scrooge Eben'
習題4.59,增加4個事實到prolog程序中:
meeting(accounting,monday,am9).
meeting(administration,monday,am10).
meeting(computer,wednesday,pm3).
meeting(administration,friday,pm1).
meeting(whole-company,wednesday,pm4).
meeting(administration,monday,am10).
meeting(computer,wednesday,pm3).
meeting(administration,friday,pm1).
meeting(whole-company,wednesday,pm4).
a)查詢星期五的會議,scheme實現(xiàn):
(meeting ?part (Friady ?time))
prolog實現(xiàn)并測試:| ?- meeting(Part,friday,Time).
Part = administration
Time = pm1 ? ;
Part = administration
Time = pm1 ? ;
b)scheme實現(xiàn)查詢規(guī)則:
(rule (meeting-time ?person ?day-and-time)
(or (meeting whole-company ?day-and-time)
(and
(job ?person (?part . ?r))
(meeting ?part ?day-and-time))))
(or (meeting whole-company ?day-and-time)
(and
(job ?person (?part . ?r))
(meeting ?part ?day-and-time))))
prolog實現(xiàn)并測試
meeting_time(Person,Day,Time):-
meeting(whole-company,Day,Time);
(job(Person,Part,_),meeting(Part,Day,Time)).
| ?- meeting_time('BitDiddle',Day,Time).
Day = wednesday
Time = pm4 ? ;
no
| ?- meeting_time(Person,friday,Time).
Person = 'Warbucks Oliver'
Time = pm1 ? ;
Person = 'Aull DeWitt'
Time = pm1 ? ;
meeting(whole-company,Day,Time);
(job(Person,Part,_),meeting(Part,Day,Time)).
| ?- meeting_time('BitDiddle',Day,Time).
Day = wednesday
Time = pm4 ? ;
no
| ?- meeting_time(Person,friday,Time).
Person = 'Warbucks Oliver'
Time = pm1 ? ;
Person = 'Aull DeWitt'
Time = pm1 ? ;
c)Alyssa周三參加的會議:
(meeting-time (Hacker Alyssa P) (Wednesday ?time))
prolog測試:| ?- meeting_time('Hacker Alyssa P',wednesday,Time).
Time = pm4 ? ;
Time = pm3
Time = pm4 ? ;
Time = pm3
習題4.60,會重復是因為person1和person2都是查詢所有的address,而lives-near只規(guī)定
(not (same person1 person2))
而沒有定義兩者的順序,因此解決辦法就是強制加入一個固定順序即可去除重復,通過string>來比較兩個字符串。解釋器還未實現(xiàn),具體怎么寫留待后面,原理就是這樣了。
習題4.62,猜測實現(xiàn)如下,模式匹配,遞歸實現(xiàn):
(rule (last-pair (?x) (?x)))
(rule (last-pair (?v . ?u) (?z))
(last-pair ?u (?z))
(rule (last-pair (?v . ?u) (?z))
(last-pair ?u (?z))
習題4.63,這一題很簡單了,按照題意翻譯過來就是:
(rule (grandson ?g ?s)
(and
(son ?g ?f)
(son ?f ?s)))
(and
(son ?g ?f)
(son ?f ?s)))
(rule (son ?m ?s)
(and
(wife ?m ?w)
(son ?w ?s)))
看看prolog怎么解決:
son(adam,cain).
son(cain,enoch).
son(enoch,irad).
son(irad,mehujael).
son(mehujael,methushael).
son(methushael,lamech).
son(ada,jabal).
son(ada,jubal).
wife(lamech,ada).
son2(M,S):-
wife(M,W),
son(W,S).
grandson(G,S):-
son(F,S),
son(G,F).
son(cain,enoch).
son(enoch,irad).
son(irad,mehujael).
son(mehujael,methushael).
son(methushael,lamech).
son(ada,jabal).
son(ada,jubal).
wife(lamech,ada).
son2(M,S):-
wife(M,W),
son(W,S).
grandson(G,S):-
son(F,S),
son(G,F).
測試一下:
| ?- son2(lamech,jabal).
true ? ;
| ?- son2(lamech,jubal).
yes
| ?- grandson(adam,enoch).
true ? ;
true ? ;
| ?- son2(lamech,jubal).
yes
| ?- grandson(adam,enoch).
true ? ;