簡體   English   中英

使用Prolog解決邏輯難題

[英]Solving a logic puzzle using Prolog

罪犯是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.

免責聲明 :這是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.

我遇到了這個問題,想試一試:

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

在這里也可以找到類似的問題和相應的解決方案:

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

就像Kaarel發布的解決方案一樣,可以為找到的解決方案要求理由/解釋。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM