2009-12-21 14 views
9

El criminal es uno de A, B, C y D.Resolver un rompecabezas de la lógica utilizando Prolog

A dice: "No soy yo"
B dice: "Es D"
C dice: "es B"
D dice: "no soy yo"

Y sabemos que sólo uno de ellos dice la verdad.

¿Quién es el indicado? Quiero resolverlo usando Prolog.

Es una pregunta de la entrevista.

+0

he llegado hasta ese derecho: uno es un criminal, pero tres son mentirosos ?! – ThomasH

Respuesta

23

solución de una sola línea

?- 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 Esto es interesante. – ThomasH

+0

¿Qué pasa si los delincuentes pueden ser dos de a, b, c, d? – user198729

+0

@ user198729: A continuación, finalice la cláusula con A + B + C + D =: = 1; A + B + C + D =: = 2. –

17

de exención de responsabilidad: Este es Xonix 'solución. Si te gusta vota él arriba. Pero como me tomó un buen esfuerzo averiguar qué estaba pasando, pensé que sería mejor que ofreciera mis comentarios para que otros pudieran beneficiarse.

En primer lugar, aquí es su solución como una cláusula adecuada:

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. 

Y dice así:

En un primer momento, que corre a través de la lista de personas (tienen que estar en minúsculas, entonces no son variables). K se instancia a cada uno de ellos sucesivamente.

Con cada posible valor de K, él repasa el resto de la cláusula. K se puede interpretar como la hipótesis de quién es el criminal. Las siguientes 4 líneas son para proporcionar enlaces a cada una de las variables A, B, C y D. Puedes leerlas así: bajo el supuesto de que a no es el criminal, a es veraz o no. Bajo la suposición de que d es el criminal, b es veraz o no. Asf. Es decir, las variables A, B, ... capturan la veracidad del individuo correspondiente, dado un criminal específico.

Como una restricción conocida es el hecho de que solo uno de ellos es veraz, la suma de sus valores de verdad debe ser 1. Al retroceder, Prolog realiza el siguiente enlace para K y lo vuelve a ejecutar. Resulta que la restricción solo se cumple si a es el criminal (y d está diciendo la verdad, si no me equivoco). Linda.

8

Aquí hay otra solución que me resulta un poco menos críptica que la de Xonix. Probado en SWI-Prolog. ejemplo

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

Uso:

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

Un problema similar y solución correspondiente también se puede encontrar aquí:

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

igual que la solución Publicado por Kaarel, es posible solicitar una justificación/explicación de la solución encontrada.

+0

No proporcione [solo respuestas de enlace] (http://meta.stackoverflow.com/tags/link-only-answers/info), escriba algo más. –

3

me encontré con este problema y quería darle un tiro:

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