I'm programming some knight and knaves puzzles using both sat/1 and a more natural language approach using the custom propositions A says B and false().
Question 3 is stated as follows:
You meet three inhabitants, A, B and C.
A says: "All three of us are knaves".
B says: "Exactly one of us is a knight".
However, in my solutions that use custom propositions for some reason prolog is giving me Unknown procedure card/2. Here's the code (see question3_again proposition).
question3(A,B,C):- sat(A =:= card([0],[A,B,C])), sat(B =:= card([1],[A,B,C])).
% Now let's make it more intuitive to work with prolog by creating our own operator:
:- op(900,xfy,says).
knight says S :- S.
knave says S :- false(S).
false(A = B) :- dif(A,B).
false( (A ; B) ) :- false(A), false(B).
false( (A , B) ) :- false(A); false(B).
question3_again(A,B,C) :- A says ( A = knave, B = knave, C = knave ),
B says ( card( [1], [A = knight, B = knight, C = knight] ) ).
I tried counting the number of knights and using this solution below instead, but it gives me incorrect answers( I added false(A #= B) :- A #\= B.
so false could reason about integers):
false(A #= B) :- A #\= B.
counte(_,[],Count,Count).
counte(E,[H|T],C,Count) :- (E = H, CC is C+1 ; CC is C), counte(E,T,CC,Count).
counte(E,L,Count) :- counte(E,L,0,Count).
question3_again(A,B,C) :- counte(knight,[A,B,C],Knights),
A says ( Knights #= 0 ),
B says ( Knights #= 1 ).
Can someone give me a light?
Thank you in advance!
question3_again(A,B,C) :- A says ( A = knave, B = knave, C = knave ),
B says (permutation([A, B, C], [knave, knave, knight])).
?- question3_again(A, B, C).
A = C, C = knave,
B = knight
With permutation
you will get same solution multiple times. If you want to, you can avoid that with some thing like:
one_knight(X) :- nth0(_, X, knight, [knave, knave]).
?- one_knight(X).
X = [knight, knave, knave] ;
X = [knave, knight, knave] ;
X = [knave, knave, knight] ;
false.
permutation
would have given 6 choices.
Now your solution will be:
question3_again(A,B,C) :- A says ( A = knave, B = knave, C = knave ),
B says (one_knight([A, B, C])).