Solving a logic puzzle using Prolog

前端 未结 5 564
鱼传尺愫
鱼传尺愫 2020-12-13 16:27

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\"

5条回答
  •  难免孤独
    2020-12-13 16:51

    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.
    

提交回复
热议问题