我正在读Raymond Smullyan的“模仿一只知更鸟”。书中有一个这样的谜题:
这个故事的塞维利亚和塞维利亚之间的任何相似之处
西班牙著名的塞维利亚(实际上没有)纯粹是
巧合的。在这个神话般的塞维利亚小镇上,男性居民只有在那些人喜欢的时候戴假发。整日没有两个居民表现相似;也就是说,给定任何两个男性居民,至少有一天他们其中一个戴着假发,而另一天则没有。
给定任何男性居民X和Y,则说居民Y
如果Y在X的所有日子中都戴着假发,则成为X的追随者。
同样,给定居民X,Y和Z,居民Z被称为
如果Z整天戴着假发,则成为X和Y的追随者
X和Y都可以。
其中五个居民分别命名为Alfredo,Bernardo,Ben-
Ito,Roberto和Ramano。以下事实是已知的
关于他们:
事实1 ..贝尔纳多和贝尼托的假发相反,
养成习惯也就是说,在任何一天,其中一个戴着假发
另一个没有。
事实2:罗伯托和拉马诺同样是相反的。
事实三:拉玛诺在那些日子里只戴假发
当阿尔弗雷多(Alfredo)和贝尼托(Benito)都穿上一件时。
塞维利亚只有一名理发师,以下事实是
了解他:
事实四:贝尔纳多是阿尔弗雷多和理发师的追随者。
事实5:如果伯纳多(Bernardo)是一名男性居民,那么如果有任何男性居民X,
阿尔弗雷多(Alfredo)和X的较低者,那么理发师就是X的追随者
单独。
阿尔弗雷多只戴黑色假发。伯纳多只穿白色
假发贝尼托只戴灰色假发。罗伯托只穿红色
假发拉玛诺只戴棕色假发。
复活节的一个早晨,理发师戴着假发。
他穿什么颜色?
我发现在Prolog中解决这个问题会很有趣,但是我很早就陷入了困境:
isOpposite( bernardo, benito ).
isOpposite( benito , bernardo ).
isOpposite( roberto , ramano ).
isOpposite( ramano , roberto ).
wears( alfredo , black ).
wears( bernardo, white ).
wears( benito , gray ).
wears( roberto , red ).
wears( ramano , brown ).
whatWearsTheBarber( WigColor ) :-
member( Barber, [ alfredo, benito, bernardo, roberto, ramano ] ),
wears( Barber, WigColor ).
我不知道如何有效地编码某人跟随其他人,也不知道如何根据这些信息进行推理。我已经关注了Prolog中其他一些逻辑难题的解决方案,但是我无法找到解决方案。
编辑:这是从Smulyan的书中复制的解决方案:
步骤1:首先,我们证明Roberto是该品牌的追随者
理发师。
好吧,考虑一下理发师戴假发的任何一天。
那天阿尔弗雷多还是戴假发,或者不戴假发。假设
阿尔弗雷多做到了。然后那天贝尔纳多也戴假发,
因为贝尔纳多(Bernardo)是阿尔弗雷多(Alfredo)和理发师的追随者。所以
贝尼托那天不能戴假发,因为他在对面
到伯纳多。那一天Ramano不能戴假发
因为他只有在阿尔弗雷多(Alfredo)和
贝尼托都有,贝尼托今天没有。以来
拉玛诺今天没有戴假发,所以罗伯托必须
因为罗伯托(Roberto)与拉马诺(Ramano)对面。这证明了
理发师戴假发的任何一天,如果阿尔弗雷多也这样做,
罗伯托也是如此。
现在,那一天理发师戴假发
但是阿尔弗雷多不是吗?好吧,既然阿尔弗雷多(Alfredo)没有,那么它
当然,阿尔弗雷多和贝尼托都不都是这样。因此
根据事实3,拉马诺没有这样做,因此罗伯托这样做,
事实2。罗伯托在理发师戴的任何一天都戴假发
确实如此,而阿尔弗雷多的确如此,他整天都戴着假发
阿尔弗雷多没有,无论理发师。
这证明,在理发师穿着
假发,罗伯托也这么做,不管阿尔弗雷多是否
或当天不戴假发。所以罗伯托确实是一个
理发师的追随者。
最佳答案
Edit2:由于@ killy9999发布了本书中部分解决方案,因此我决定重写Prolog,以反映Smullyan的推理。原始的部分解决方案保留在下面。
首先是一些基本结构
person(alfredo).
person(benito).
person(roberto).
person(ramano).
person(bernardo).
day([_Alfredo,_Benito,_Bernardo,_Roberto,_Romano]).
% barber(alfredo). % Follows from Fact 4.
barber(benito).
% barber(bernardo). % Follows from Fact 4.
barber(roberto).
barber(romano).
wearsWig(alfredo,[1,_X,_Y,_Z,_W]).
wearsWig(benito,[_X,1,_Y,_Z,_W]).
wearsWig(bernardo,[_X,_Y,1,_Z,_W]).
wearsWig(roberto,[_X,_Y,_Z,1,_W]).
wearsWig(romano,[_X,_Y,_Z,_W,1]).
noWig(alfredo,[0,_X,_Y,_Z,_W]).
noWig(benito,[_X,0,_Y,_Z,_W]).
noWig(bernardo,[_X,_Y,0,_Z,_W]).
noWig(roberto,[_X,_Y,_Z,0,_W]).
noWig(romano,[_X,_Y,_Z,_W,0]).
然后,我们有两种类型的一致性条件。一个事实是,对方不会同时戴假发。另一个来自事实3和事实4。
consistent2(_D,[]).
consistent2(D,[(X,Y)|Os]):-wearsWig(X,D),noWig(Y,D),consistent2(D,Os).
consistent2(D,[(X,Y)|Os]):-noWig(X,D),wearsWig(Y,D),consistent2(D,Os).
consistent3(O,G):-consistent3(O,_D,G).
consistent3(_O,_D,[]).
consistent3(O,D,[(X,Y,Z)|Gs]):-
wearsWig(X,D),wearsWig(Y,D),wearsWig(Z,D),
consistent2(D,O),consistent3(O,D,Gs).
consistent3(O,D,[(_X,Y,_Z)|Gs]):-
noWig(Y,D),consistent2(D,O),consistent3(O,D,Gs).
consistent3(O,D,[(_X,_Y,Z)|Gs]):-
noWig(Z,D),consistent2(D,O),consistent3(O,D,Gs).
fact3(D):-wearsWig(romano,D),wearsWig(alfredo,D),wearsWig(benito,D).
fact3(D):-noWig(alfredo,D),noWig(romano,D).
fact3(D):-noWig(benito,D),noWig(romano,D).
这足以证明Roberto遵循理发师(步骤1):
?- person(Barber),barber(Barber),
O = [(benito,bernardo),(roberto,romano)],
G = [(bernardo,alfredo,Barber),(romano,alfredo,benito)],
consistent3(O,D,G),fact3(D),
wearsWig(Barber,D),noWig(roberto,D).
false.
因此排除了罗曼诺作为理发师。
我们还已经(步骤2)使Bernardo跟随Roberto和Alfredo:
?- person(Barber)barber(Barber),
O = [(benito,bernardo),(roberto,romano)],
G = [(bernardo,alfredo,Barber),(romano,alfredo,benito)],
consistent3(O,D,G),fact3(D),
wearsWig(alfredo,D),wearsWig(roberto,D),noWig(bernardo,D).
false.
下一步(第3步)需要使用事实5,这是一个通用声明(适用于塞维利亚的所有男性居民),并且很难在Prolog中进行编码。
consistent4(_D,_Barber,[]).
consistent4(D,Barber,[X|Xs]):-
wearsWig(X,D1),wearsWig(alfredo,D1),
noWig(bernardo,D1),consistent4(D,Barber,Xs).
consistent4(D,Barber,[X|Xs]):-
wearsWig(X,D),wearsWig(alfredo,D),
wearsWig(bernardo,D),wearsWig(Barber,D),
consistent4(D,Barber,Xs).
现在定义根谓词和奇特的颜色:
wears(alfredo, black).
wears(bernardo, white).
wears(benito, gray).
wears(roberto, red).
wears(ramano, brown).
whatWearsTheBarber(WigColor):-
person(Barber),
day(Easter),
barber(Barber),
wearsWig(Barber,Easter),
fact3(Easter),
G=[(bernardo,alfredo,Barber),(romano,alfredo,benito)],
O=[(benito,bernardo),(roberto,romano)],
consistent2(Easter,O),
consistent3(O,D,G),
X=[alfredo,benito,bernardo,roberto,romano],
consistent4(D,Barber,X),
wears(Barber, WigColor).
以下SWI-Prolog查询显示RED是唯一的答案
?- findall(WigColor,whatWearsTheBarber(WigColor),B),list_to_set(B,R).
B = [red, red, red, red, red, red, red, red, red|...],
R = [red].
感谢安德鲁·库克。我从他的回答中借来了。
下面的文本是最初发布并产生评论的答案。
编辑:这个难题实际上是非常困难的,因为一个人必须跟踪很多天,而不仅仅是特定的复活节。以下解决方案通过仅考虑当天的塞维利亚事务状态来大大减少搜索。
将塞维利亚市的情况视为一个未知关系,以列表形式表示,可能会更容易:
[ [WearsWig,IsBarber], ... , [WearsWig,IsBarber] ]
以目前的人口,我们可以说
seville(S) :-
S=[Benito,Bernardo,Roberto,Ramano,Alfredo],
opposite(Benito,Bernardo),
opposite(Roberto,Ramano),
fact3(Ramano,Alfredo,Benito),
fact4(Bernardo,Alfredo),
noBarber(Bernardo),noBarber(Alfredo),
onlyOneBarberWearsWig(S).
相关谓词定义如下:
noWig([0,_X]).
wearsWig([1,_X]).
isBarber([_X,1]).
noBarber([_X,0]).
opposite(X,Y):-noWig(X),wearsWig(Y).
opposite(X,Y):-noWig(Y),wearsWig(X).
fact3(X,Y,Z):-wearsWig(X),wearsWig(Y),wearsWig(Z).
fact3(X,Y,_Z):-noWig(X),noWig(Y).
fact3(X,_Y,Z):-noWig(X),noWig(Z).
fact4(X,Y):-wearsWig(X),wearsWig(Y),wearsWig(Z),isBarber(Z).
fact4(_X,Y):-noWig(Y).
onlyOneBarberWearsWig([X|Xs]):-isBarber(X),wearsWig(X),noBarbers(Xs).
onlyOneBarberWearsWig([X|Xs]):-noBarber(X),onlyOneBarberWearsWig(Xs).
noBarbers([]).
noBarbers([X|Xs]):-noBarber(X),noBarbers(Xs).
barbersWigColor([_X,_Y,_Z,_U,Alfredo],black):-isBarber(Alfredo).
barbersWigColor([_X,Bernardo,_Y,_Z,_U],white):-isBarber(Bernardo).
barbersWigColor([Benito,_X,_Y,_Z,_U],gray):-isBarber(Benito).
barbersWigColor([_X,_Y,Roberto,_Z,_U],red):-isBarber(Roberto).
barbersWigColor([_X,_Y,_Z,Ramano,_U],brown):-isBarber(Ramano).
whatWearsTheBarber(Color):-seville(X),barbersWigColor(X,Color).
通过以上定义,SWI可以快速返回:
?- seville(X).
X = [[0, 0], [1, 0], [1, 1], [0, 0], [0, 0]] ;
X = [[0, 0], [1, 0], [1, 1], [0, 0], [1, 0]] ;
X = [[0, 0], [1, 0], [1, 1], [0, 0], [0, 0]] ;
X = [[1, 1], [0, 0], [1, 0], [0, 0], [0, 0]] ;
X = [[1, 0], [0, 0], [1, 1], [0, 0], [0, 0]] ;
false.
?- whatWearsTheBarber(Color).
Color = red ;
Color = red ;
Color = red ;
Color = gray ;
Color = red ;
false.
我不太了解事实5的工作原理。我不能排除贝尼托是理发师的情况。但是,我想将其发布为答案。