didit(L) :- setof(P, suspect(P), L). person(P) :- says(P, _, _), forall((says(Q,_,_), P \= Q), says(_,_, didit(Q))). person(P) :- says(_, _, didit(P)). suspect(P) :- person(P), number_liars(P, NP), forall((person(Q), Q \= P), (number_liars(Q, NQ), NP =< NQ)). number_liars(P, N) :- liars(P, Liars), length(Liars, N). liars(P, Liars) :- validity(P, _, Lies), findall(X, (member(I, Lies), says(X, I, _)), Liars0), sort(Liars0, Liars). validity(P, Truths, Lies) :- findall(I, says(_, I, didit(P)), Truths0), findall(I, (says(_, I, didit(Q)), P \= Q), Lies0), validity(Truths0, Lies0, Truths, Lies). validity([], [], [], []). validity(Truths0, Lies0, Truths, Lies) :- (Truths0 \= []; Lies0 \= []), findall(I, (member(S, Truths0), says(_, I, true(S)); member(S, Lies0), says(_, I, false(S))), Truths1), findall(I, (member(S, Truths0), says(_, I, false(S)); member(S, Lies0), says(_, I, true(S))), Lies1), validity(Truths1, Lies1, Truths2, Lies2), append(Truths0, Truths2, Truths), append(Lies0, Lies2, Lies).