使用 Prolog 解决逻辑难题

发布于 2024-09-04 09:25:42 字数 197 浏览 6 评论 0原文

犯罪者属于 A、B、C、D 之一。

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

我们知道他们中只有一个人说的是实话。

到底是谁呢?我想用Prolog来解决这个问题。

这是一道面试题。

The criminal is one of A, B, C and D.

A says: "It's not me"
B says: "It's D"
C says: "It's B"
D says: "It's not me"

And we know that only one of them tells the truth.

Who is the one? I want to solve it by using Prolog.

It's an interview question.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

我恋#小黄人 2024-09-11 09:25:43

免责声明:这是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是真实的,否则不是。阿斯夫。也就是说,变量 A、B……捕捉了给定特定罪犯的相应个体的真实性。

由于已知约束条件是只有其中一个是真实的,因此它们的真值之和必须为 1。回溯时,Prolog 为 K 进行下一个绑定,并再次运行它。事实证明,只有当 a 是罪犯时(并且 d 说的是实话,如果我没记错的话),这个约束才被满足。可爱的。

Disclaimer: This is Xonix' solution. If you like it vote him up. But as it took me some head-scratching to figure out what was going on, I thought I might just as well offer my comments so others could benefit.

At first, here is his solution as a proper clause:

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.

And it goes like this:

At first, he runs through the list of individuals (have to be lower case, so they're not variables). K is instantiated to each of them in turn.

With each possible value of K he runs through the rest of the clause. K can be interpreted as the hypothesis who the criminal is. The next 4 lines are to provide bindings to each of the variables A, B, C and D. You can read them like this: Under the assumption that a is not the criminal, a is truthful otherwise not. Under the assumption that d is the criminal, b is truthful otherwise not. Asf. That is, the variables A, B, ... capture the truthfulness of the corrsponding individual, given a specific criminal.

As a known constraint is the fact that only one of them is truthful, the sum of their truth values must be 1. On backtracking, Prolog makes the next binding for K, and runs through it again. Turns out the constraint is only satisfied if a is the criminal (and d is telling the truth, if I'm not mistaken). Cute.

浅暮の光 2024-09-11 09:25:43

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

Here is another solution which I find a bit less cryptic than Xonix's.
Tested in 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).

Usage example:

?- criminal_and_truthteller(Criminal, Truthteller).
Criminal = a,
Truthteller = d ;
false.
不一样的天空 2024-09-11 09:25:43

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

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

I ran across this problem and wanted to give it a shot :

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)).
当梦初醒 2024-09-11 09:25:43

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

https: //github.com/LogtalkDotOrg/logtalk3/blob/master/examples/puzzles/jam_thief.lgt

与 Kaarel 发布的解决方案一样,可以请求对找到的解决方案进行论证/解释。

A similar problem and corresponding solution can also be found here:

https://github.com/LogtalkDotOrg/logtalk3/blob/master/examples/puzzles/jam_thief.lgt

Like the solution posted by Kaarel, is possible to request a justification/explanation for the solution found.

愛上了 2024-09-11 09:25:42

单线解决方案

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

One-liner solution

?- 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.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文