son siempre sencillos resueltos operaciones los listas jóvenes funciones explicados estudiantes ejercicios ejemplos ejemplo conocimiento con prolog puzzle

siempre - prolog ejemplos sencillos



Resolviendo un acertijo lógico usando Prolog (5)

Aquí hay otra solución que encuentro un poco menos críptica que la de Xonix. Probado en 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).

Ejemplo de uso:

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

El criminal es uno de A, B, C y D.

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

Y sabemos que solo uno de ellos dice la verdad.

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

Es una pregunta de entrevista.


Me encontré con este problema y quería intentarlo:

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


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.



Descargo de responsabilidad : esta es la solución de Xonix . Si te gusta, vótalo. 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.

Al principio, aquí está 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í:

Al principio, examina la lista de individuos (tiene que ser minúsculas, por lo que no son variables). K se crea una instancia para cada uno de ellos a su vez.

Con cada valor posible de K , recorre el resto de la cláusula. K puede interpretarse 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 la suposición de que a no es el criminal, a es veraz o no. Bajo el supuesto de que d es el criminal, b es veraz, de lo contrario, 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 hace 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.