用Prolog解决逻辑难题

用Prolog解决逻辑难题,prolog,puzzle,Prolog,Puzzle,罪犯是A、B、C和D中的一个 A说:“不是我” B说:“是D” C说:“是B” D说:“不是我” 我们知道他们中只有一个人说了实话 那个人是谁?我想用Prolog来解决这个问题 这是一个面试问题。一行解决方案 ?- 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 ;

罪犯是A、B、C和D中的一个

A说:“不是我”
B说:“是D”
C说:“是B”
D说:“不是我”

我们知道他们中只有一个人说了实话

那个人是谁?我想用Prolog来解决这个问题

这是一个面试问题。

一行解决方案

?- 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.
一行解决方案

?- 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.

免责声明:这是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
说的是实话),约束才得到满足。可爱。

免责声明:这是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
说的是实话),约束才得到满足。可爱。

这是另一个解决方案,我发现它比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.

这是另一个解决方案,我发现它没有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.

类似的问题和相应的解决方案也可以在这里找到:


与Kaarel发布的解决方案一样,可以要求对发现的解决方案进行理由/解释。

类似的问题和相应的解决方案也可以在此处找到:


就像Kaarel发布的解决方案一样,可以要求对找到的解决方案进行理由/解释。

我遇到了这个问题,想尝试一下:

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)).

我遇到了这个问题,想试一试:

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)).

我说得对吗:一个是罪犯,但三个是骗子?!我说得对吗:一个是罪犯,但三个是骗子?!如果罪犯可以是a,b,c,d中的两个呢?@user198729:然后用a+b+c+d=:=1结束这个子句;A+B+C+D=:=2。@CharlesStewart我不太确定。通过这种方式添加
A+B+C+D=:=2
,你只允许两个人说出真相,而不是两个人是罪犯。你可能需要更多的信息来解决这个问题,例如,每个人都会对两个人发表声明,而不仅仅是一个人。如果罪犯可以是a、b、c、d中的两个呢?@user198729:然后以a+b+c+d=:=1结束该子句;A+B+C+D=:=2。@CharlesStewart我不太确定。通过这种方式添加
A+B+C+D=:=2
,你只允许两个人说出真相,而不是两个人是罪犯。你可能需要更多的信息来解决这个问题,例如,每个人都会对两个人发表声明,而不仅仅是一个人。请不要提供,多写一些。请不要提供,多写一些。