【算法】 用Prolog解决谁是凶手问题

2024-02-21 10:10:31 浏览数 (3)

四、谁是凶手

下面看一个比较有趣的逻辑题。

Boddy 先生死于谋杀,现有六个嫌疑犯,每个人在不同的房间,每间房间各有一件可能的凶器,但不知道嫌疑犯、房间、凶器的对应关系。请根据下面的条件和线索,找出谁是凶手。

已知条件:六个嫌疑犯是三男(George、John、Robert)三女(Barbara、Christine、Yolanda)。

代码语言:javascript复制
man(george). man(john). man(robert).
woman(barbara). woman(christine). woman(yolanda).

为了后面解题的方便,需要把"男人"和"女人"都定义为"人"。

代码语言:javascript复制
person(X):- man(X).
person(X):- woman(X).

六个嫌疑犯分别待在六个房间:浴室(Bathroom)、饭厅(Dining Room)、厨房(Kitchen)、起居室(Living Room)、 储藏室(Pantry)、书房(Study)。每间房间都有一件可疑的物品,可以当作凶器:包(Bag)、火枪(Firearm)、煤气(Gas)、刀(Knife)、毒药(Poison)、绳索(Rope)。

代码语言:javascript复制
location(bathroom). location(dining). location(kitchen).
location(livingroom). location(pantry). location(study).
weapon(bag). weapon(firearm). weapon(gas). 
weapon(knife). weapon(poison). weapon(rope).

下面声明一条规则,每个房间的人都是不一样的。

代码语言:javascript复制
uniq_ppl(A,B,C,D,E,F):- 
  person(A), person(B), person(C), 
  person(D), person(E), person(F),  
   A=B,  A=C,  A=D,  A=E,  A=F, 
   B=C,  B=D,  B=E,  B=F, 
   C=D,  C=E,  C=F, 
   D=E,  D=F, 
   E=F.

然后,定义一个表达式murderer(X),变量X就是凶手。该表达式只有满足以下所有条件,才可能为true

代码语言:javascript复制
murderer(X) :-
   uniq_ppl(Bathroom, Dining, Kitchen, Livingroom, Pantry, Study),
   uniq_ppl(Bag, Firearm, Gas, Knife, Poison, Rope),

注意,上面代码中BathroomBag这样的字符串,都是大写字母开头,所以都是变量,代表对应的人。至于具体是谁,就要通过推理得到。

线索一:厨房里面是一个男人,那里的凶器不是绳索、刀子、包和火枪。

代码语言:javascript复制
man(Kitchen), 
    Kitchen=Rope,  Kitchen=Knife,  Kitchen=Bag,  Kitchen=Firearm,

线索二:Barbara 和 Yolanda 在浴室和书房。

代码语言:javascript复制
woman(Bathroom), woman(Study), 
   christine=Bathroom,  christine=Study, 
   barbara=Dining,  barbara=Kitchen, 
   barbara=Livingroom,  barbara=Pantry,
   yolanda=Dining,  yolanda=Kitchen, 
   yolanda=Livingroom,  yolanda=Pantry,

线索三:带包的那个人不是 Barbara 和 George,也不在浴室和饭厅。

代码语言:javascript复制
 barbara=Bag,  george=Bag, 
 Bag=Bathroom,  Bag=Dining,

线索四:书房里面是一个带绳子的女人。

代码语言:javascript复制
woman(Rope), Rope=Study,

线索五:起居室里面那件凶器,与 John 或 George 在一起。

代码语言:javascript复制
man(Livingroom),  Livingroom=robert,

线索六:刀子不在饭厅。

代码语言:javascript复制
 Knife=Dining,

线索七:书房和食品储藏室里面的凶器,没跟 Yolanda 在一起。

代码语言:javascript复制
 yolanda=Pantry,  yolanda=Study,

线索八:George 所在的那间屋子有火枪。

代码语言:javascript复制
Firearm=george,

线索九:Boddy 先生死在食品储藏室里,那里的凶器是煤气。

代码语言:javascript复制
Pantry=Gas, Pantry=X, Gas=X,

线索就是上面这些,然后把写好的所有表达式放在一起,组成一个完整的脚本crime.pl,代码看这里。

加载这个脚本,执行murderer(X)函数,由于条件复杂,运算时间较长,最终会显示凶手是谁。

代码语言:javascript复制
?- [crime].
true.

?- murderer(X).
KILLER IS :christine
Bathroom: yolanda
Dining: george
Livingroom: john
Pantry: christine
Study: barbara
Kitchen: robert
Knife: yolanda
Gas: christine
Rope: barbara
Bag: john
Poison: robert
Firearm: george
X = christine ;

0 人点赞