2009-12-21 35 views
9

Các tội phạm là một trong A, B, C và D.Giải quyết một câu đố Logic sử dụng Prolog

Một nói: "Nó không phải là tôi"
B nói: "Đó là D"
C nói: "Đó là B"
D nói: "Không phải tôi"

Và chúng tôi biết rằng chỉ một trong số họ nói sự thật.

Ai là người? Tôi muốn giải quyết nó bằng cách sử dụng Prolog.

Đó là câu hỏi phỏng vấn.

+0

Ý của tôi nhận được rằng đúng: một là một tên tội phạm, nhưng ba là kẻ nói dối ?! – ThomasH

Trả lời

23

giải pháp One-liner

?- 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 Điều này thật thú vị. – ThomasH

+0

Nếu tội phạm có thể là hai của một, b, c, d thì sao? – user198729

+0

@ user198729: Sau đó kết thúc điều khoản bằng A + B + C + D =: = 1; A + B + C + D =: = 2. –

17

Disclaimer: Đây là Xonix 'giải pháp. Nếu bạn thích nó, hãy bỏ phiếu số anh ta. Nhưng vì nó đã cho tôi một số đầu gãi để tìm ra những gì đang xảy ra, tôi nghĩ rằng tôi cũng có thể cung cấp ý kiến ​​của tôi để những người khác có thể được hưởng lợi.

Lúc đầu, đây là giải pháp của mình như là một điều khoản thích hợp:

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. 

Và nó đi như thế này:

Lúc đầu, ông chạy qua danh sách các cá nhân (phải là trường hợp thấp hơn, vì vậy chúng không phải là biến). K được khởi tạo cho từng người trong số họ lần lượt.

Với mỗi giá trị có thể có của K, anh ta chạy qua phần còn lại của mệnh đề. K có thể được hiểu là giả thuyết là tội phạm. 4 dòng tiếp theo là cung cấp các ràng buộc cho mỗi biến A, B, C và D. Bạn có thể đọc chúng như thế này: Theo giả định rằng a không phải là hình sự, một cách trung thực nếu không thì không. Theo giả định rằng d là tội phạm, b là trung thực nếu không thì không. Asf. Đó là, các biến A, B, ... nắm bắt được tính trung thực của cá nhân điều chỉnh, đưa ra một tội phạm cụ thể.

Như một ràng buộc đã biết là thực tế chỉ có một trong số đó là trung thực, tổng giá trị chân lý của chúng phải là 1. Trên backtracking, Prolog tạo liên kết tiếp theo cho K và chạy lại nó. Hóa ra ràng buộc chỉ thỏa mãn nếu a là tội phạm (và d là nói sự thật, nếu tôi không nhầm). Dễ thương.

8

Đây là một giải pháp khác mà tôi thấy khó hiểu hơn một chút so với Xonix's. Được thử nghiệm trong 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). 

Cách sử dụng Ví dụ:

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

Một vấn đề tương tự và giải pháp tương ứng cũng có thể được tìm thấy ở đây:

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

Giống như các giải pháp đăng bởi Kaarel, có thể yêu cầu một lý giải/giải thích cho giải pháp tìm thấy.

+0

Vui lòng không cung cấp [link only answers] (http://meta.stackoverflow.com/tags/link-only-answers/info), viết thêm điều gì đó. –

3

Tôi chạy qua vấn đề này và muốn cho nó một 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)). 
Các vấn đề liên quan