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).
這足以證明,羅伯特·遵循理髮(步驟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)貝爾納如下羅伯託和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的查詢顯示紅色是唯一的答案
?- 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的工作原理。我不能排除貝尼託是理髮師的情況。但我想發佈這個答案。
是不是肯定的是,理髮師是5名名爲男性中的一個?而「給定任何男性居民X」:你的意思是隻有5名男性中的任何一個? – mat 2012-04-22 14:13:44
唯一的顏色信息與這些人有關,所以如果理髮師不是其中之一,我們不能回答這個問題。 – 2012-04-22 14:25:46
理髮師是五個男性之一,這個謎題有一個合理的答案。 – 2012-04-22 16:56:52