2009-12-21 33 views
9

逻辑谜题的罪犯是A,B,C和D.解决在使用的Prolog

之一

一说: “这不是我”
乙说: “这是d”
Ç说: “这是B”
d说:“这不是我”

而且我们知道,只有其中一人道出了实情。

谁是谁?我想通过使用Prolog解决它。

这是一个面试问题。

+0

难道我得到这个权利:一个是犯罪,但三是骗子? – ThomasH 2009-12-21 12:44:31

回答

23

一衬垫溶液

?- member(K,[a,b,c,d]),(K\=a->A=1;A=0),(K=d->B=1;B=0),(K=b->C=1;C=0),(K\=d->D=1;D=0),A+B+C+D=:=1. 
K = a, 
A = 0, 
B = 0, 
C = 0, 
D = 1 ; 
false. 
+0

+1这很有趣。 – ThomasH 2009-12-21 22:15:13

+0

如果犯罪分子可以是a,b,c,d中的两个,该怎么办? – user198729 2009-12-23 03:33:54

+0

@ user198729:然后以A + B + C + D =:= 1; A + B + C + D =:= 2结束子句。 – 2010-06-20 11:27:14

17

声明:这是Xonix'溶液。如果你喜欢它投了。但是,由于我花了一些脑筋想弄清楚发生了什么,我认为我可能会提出我的意见,以便其他人可以受益。

起初,这里是他作为一个适当的条款解决方案:

criminal(K):- 
    member(K,[a,b,c,d]), 
    (K\=a -> A=1;A=0), 
    (K=d -> B=1;B=0), 
    (K=b -> C=1;C=0), 
    (K\=d -> D=1;D=0), 
    A+B+C+D=:=1. 

它是这样的:

起初,他贯穿个人名单(必须是较低的情况下,所以它们不是变量)。 K被依次实例化给它们中的每一个。

对于K的每个可能的值,他会贯穿条款的其余部分。 K可以解释为罪犯是谁的假设。接下来的4行是为每个变量A,B,C和D提供绑定。你可以像这样读取它们:假设a不是罪犯,否则a是真实的。假设d是罪犯,否则b是真实的。 ASF。也就是说,变量A,B ......捕捉到了相应犯罪人的真实性。

由于已知的约束条件是只有其中一个是真实的,所以它们的真值总和必须为1.在回溯时,Prolog为K下一个绑定,并再次运行。原来,只有当a是犯罪分子才能满足约束条件(而d说的是实话,如果我没弄错的话)。可爱。

8

这是另一种解决方案,我发现它比Xonix更隐蔽。 在SWI-Prolog中测试。

% To find a criminal and the truthteller 
% 1. Pick a possible criminal 
% 2. Pick a possible truthteller and the remaining liars 
% 3. Assert that the truthteller's statement is the truth 
% 4. Assert that every liar's statement is not the truth 
% If both the assertions succeed 
% then we have found a criminal and the truthteller. 
criminal_and_truthteller(Criminal, Truthteller) :- 
    Group = [a, b, c, d], 
    member(Criminal, Group), 
    select(Truthteller, Group, Liars), 
    statement(Truthteller, Criminal, Truth), 
    Truth, 
    forall(
     member(Liar, Liars), 
     (statement(Liar, Criminal, Lie), \+ Lie) 
    ). 

% Statements 
% Arg 1: Who says 
% Arg 2: About whom 
% Arg 3: Which statement 
% e.g. "a claims that a is not a criminal" 
statement(a, C, a \= C). 
statement(b, C, d = C). 
statement(c, C, b = C). 
statement(d, C, d \= C). 

用例:

?- criminal_and_truthteller(Criminal, Truthteller). 
Criminal = a, 
Truthteller = d ; 
false. 
3

我跑过这个问题,想给它一个镜头:

a(K) :- K \== a. 
b(d). 
c(b). 
d(K) :- K \== d. 

solve(TruthTeller) :- 
    member(K, [a, b, c, d]), 
    xor([a(K), b(K), c(K), d(K)], Truth), 
    Truth =.. [TruthTeller|_]. 

xor([Head|Tail], Result) :- 
    ( call(Head) 
    -> forall(member(X, Tail), \+ call(X)), Result = Head 
    ; xor(Tail, Result)).