/* Knights and Knaves using plain logic programming in SWI-Prolog. Here I'm coding the Knights and Knaves puzzles from Adrian Groza "Modelling Puzzles in First Order Logic" using plain logic programming. This is a port of my Picat program http://hakank.org/picat/knights_and_knaves_lp.pi It required just some small changes to work in SWI-Prolog as well: - Picat's function type/1 -> type/2 - println/1 -> writeln/1 - not -> \+ Cf the Picat constraint models for Chapter 7 Island of Truth at http://hakank.org/picat/#groza_puzzles This program was created by Hakan Kjellerstrand, hakank@gmail.com See also my SWI-Prolog page: http://www.hakank.org/swi_prolog/ */ % Test all puzzles go :- between(61,72,P), atom_concat("puzzle_",P,Puzzle), writeln(Puzzle), call(Puzzle), nl, fail, nl. go. % % Who say what? % This is equivalent to % Who <=> What % says(Who,What) :- ( (Who,What) ; (\+ Who,\+ What)). % Atom version of the types type(true,'Knight') :- !. type(false,'Knave') :- !. type(X,X). % Everything else /* """ Puzzle 61. We are both knaves On the island of knights and knaves, knights always tell the truth, while knaves always lie. You are approached by two people. The first one says: "We are both knaves". What are they actually? (Smullyan 2011) """ [a = Knave,b = Knight] Cf knights_and_knaves_we_are_both_knaves.pi Puzzle 61. */ puzzle_61 :- Knave = false, Knight = true, member(A,[Knave,Knight]), member(B,[Knave,Knight]), says(A, (A == Knave, B == Knave)), maplist(type,[A,B],[AType,BType]), writeln([a=AType,b=BType]), fail, nl. puzzle_61. /* """ Puzzle 62. At least one of us is a knave On the island of knights and knaves, knights always tell the truth, while knaves always lie. You are approached by two people. The first one says: "At least one of us is a knave". What are they actually? (puzzle 28 from Smullyan (2011)) """ [a = Knight,b = Knave] Cf knights_and_knaves_at_least_one_of_us_is_a_knave.pi */ puzzle_62 :- Knave = false, Knight = true, member(A,[Knave,Knight]), member(B,[Knave,Knight]), says(A, (A == Knave ; B == Knave)), maplist(type,[A,B],[AType,BType]), writeln([a=AType,b=BType]), fail, nl. puzzle_62. /* """ Puzzle 63. Either I am a knave or b is a knight On the island of knights and knaves, knights always tell the truth, while knaves always lie. You are approached by two people. The first one says: "Either I am a knave or B is a knight.". What are they actually? (puzzle 29 from Smullyan (2011)) """ [a = Knight,b = Knight] Cf knights_and_knaves_either_i_am_a_knave_or_b_is_a_knight.pi */ puzzle_63 :- Knave = false, Knight = true, member(A,[Knave,Knight]), member(B,[Knave,Knight]), says(A, (A == Knave ; B == Knight)), maplist(type,[A,B],[AType,BType]), writeln([a=AType,b=BType]), fail, nl. puzzle_63. /* """ Puzzle 64. We are both the same On the island of knights and knaves, knights always tell the truth, while knaves always lie. You are approached by two people. The first one says: "We are the same". Is the other person a knight or a knave? (adapted from Smullyan (2011)) """ [a = Knave,b = Knight] [a = Knight,b = Knight] knights_and_knaves_we_are_both_the_same.pi */ puzzle_64 :- Knave = false, Knight = true, member(A,[Knave,Knight]), member(B,[Knave,Knight]), says(A, (A == B)), maplist(type,[A,B],[AType,BType]), writeln([a=AType,b=BType]), fail, nl. puzzle_64. /* """ Puzzle 65. Three inhabitants and two messages Again we have three people, A, B, C, each of them is either a knight or a knave. A and B make the following statements: A: "All of us are knaves". B: "Exactly one of us is a knight". What are A, B, C? (puzzle 31 from Smullyan (2011)) """ [a = Knave,b = Knight,c = Knave] Cf knights_and_knaves_three_inhabitants_and_two_messages.pi */ puzzle_65 :- Knave = false, Knight = true, member(A,[Knave,Knight]), member(B,[Knave,Knight]), member(C,[Knave,Knight]), says(A, (A == Knave, B == Knave, C == Knave)), % says(B, (sum([1 : T in [A,B,C], T == Knight]) == 1)), says(B, ( (A == Knight, B == Knave, C == Knave) ; (A == Knave, B == Knight, C == Knave) ; (A == Knave, B == Knave, C == Knight) )), maplist(type,[A,B,C],[AType,BType,CType]), writeln([a=AType,b=BType,c=CType]), fail, nl. puzzle_65. /* """ Puzzle 66. Three inhabitants and not enough information Suppose instead, A and B say the following: A: "All of us are knaves". B: "Exactly one of us is a knave". Can it be determined what B is? Can it be determined what C is? (puzzle 32 from Smullyan (2011)) """ [a = Knave,b = Knave,c = Knight] [a = Knave,b = Knight,c = Knight] I.e. - a is a Knave - c is a Knight - b can be either Cf knights_and_knaves_three_inhabitants_and_not_enough_information.pi */ puzzle_66 :- Knave = false, Knight = true, member(A,[Knave,Knight]), member(B,[Knave,Knight]), member(C,[Knave,Knight]), says(A, (A == Knave, B == Knave, C = Knave)), says(B, ( (A == Knave, B == Knight, C == Knight) ; (A == Knight, B == Knave, C == Knight) ; (A == Knight, B == Knight, C == Knave) )), maplist(type,[A,B,C],[AType,BType,CType]), writeln([a=AType,b=BType,c=CType]), fail, nl. puzzle_66. /* """ Puzzle 67. Three inhabitants and two of the same type Suppose instead, A and B say the following: A: "B is a knave". B: "A and C are of the same type". What is C? (puzzle 34 from Smullyan (2011)) """ [a = Knave,b = Knight,c = Knave] [a = Knight,b = Knave,c = Knave] I.e. c is a Knave, a anb b are unknown Cf knights_and_knaves_three_inhabitants_and_two_of_the_same_type.pi */ puzzle_67 :- Knave = false, Knight = true, member(A,[Knave,Knight]), member(B,[Knave,Knight]), member(C,[Knave,Knight]), says(A, (B == Knave)), says(B, (A == C)), maplist(type,[A,B,C],[AType,BType,CType]), writeln([a=AType,b=BType,c=CType]), fail, nl. puzzle_67. /* """ Puzzle 68. Jim, Jon, and Joe On the island of knights and knaves, knights always tell the truth, while knaves always lie. You are approached by three people: Jim, Jon, and Joe. Jim says: "Joe is a knave or I am a knight". Jon says, "Jim could claim that I am a knave". Joe says, "Neither Jim nor Jon are knights". What are they actually? (taken from Popular mechanics - www. popularmechanics.com/science/math) """ [jim = Knave,jon = Knave,joe = Knight] Cf knights_and_knaves_jim_jon_and_joe.pi */ puzzle_68 :- Knave = false, Knight = true, member(Jim,[Knave,Knight]), member(Jon,[Knave,Knight]), member(Joe,[Knave,Knight]), says(Jim, (Joe == Knave ; Jim == Knight)), says(Jon, ( (Jim == Knight, Jon == Knave ) ; (Jim == Knave, Jon == Knight ) ) ), says(Joe, (Jim \= Knight, Jon \= Knight)), maplist(type,[Jim,Jon,Joe],[JimType,JonType,JoeType]), writeln([jim=JimType,jon=JonType,joe=JoeType]), fail, nl. puzzle_68. /* """ Puzzle 69. A spy appears On the island of knights and knaves a new type on inhabitants has settled: spies. Spies can lie or tell the truth at will. You are approached by three people wearing different coloured clothes. You know that one is a knight, one is a knave, and one is a spy. They speak in the following order: The man wearing blue says, "I am a knight". The man wearing red says, "He speaks the truth". The man wearing green says, "I am a spy". Who is the knight, who is the knave, and who is the spy? (taken from Popular mechan- ics - www.popularmechanics.com/science/math) """ type = [blue = knight,red = spy,green = knave] truth = [blue = true,red = true,green = false] Cf knights_and_knaves_a_spy_appears.pi */ puzzle_69 :- Knave = knave, Knight = knight, Spy = spy, % Truthfulness member(BlueT,[false,true]), member(RedT,[false,true]), member(GreenT,[false,true]), % Types member(Blue,[Knave,Knight,Spy]), member(Red,[Knave,Knight,Spy]), member(Green,[Knave,Knight,Spy]), % All different Blue \= Red, Blue \= Green, Red \= Green, says(BlueT, (Blue == Knight)), says(RedT, (BlueT == true)), % says(RedT, (Blue == Knight)), says(GreenT, (Green == Spy)), % Connect truthfulness with the types (BlueT == true -> (Blue = Knight ; Blue = Spy) ; (Blue = Knave ; Blue = Spy)), (RedT == true -> (Red = Knight ; Red = Spy) ; (Red = Knave ; Red = Spy)), (GreenT == true -> (Green = Knight ; Green = Spy) ; (Green = Knave ; Green = Spy)), maplist(type,[Blue,Red,Green],[BlueType,RedType,GreenType]), writeln(type:[blue=BlueType,red=RedType,green=GreenType]), writeln(truth:[blue=BlueT,red=RedT,green=GreenT]), fail, nl. puzzle_69. /* """ Puzzle 70. Who is the spy? On the island of knights and knaves and spies, you come across three people. One wears blue, one wears red, and one wears green. You know that one is a knight, one is a knave, and one is a spy. "Who is the spy?" you ask. The man wearing blue says, "That man in red is the spy". The man wearing red says, "No, the man in green is the spy". The man wearing green says, "No, the man in red is in fact the spy". (taken from Popular mechanics - www.popularmechanics.com/science/math) """ type = [blue = knave,red = knight,green = spy] truth = [blue = false,red = true,green = false] Cf knights_and_knaves_who_is_the_spy.pi */ puzzle_70 :- Knave = knave, Knight = knight, Spy = spy, % Truthfulness member(BlueT,[false,true]), member(RedT,[false,true]), member(GreenT,[false,true]), % Types member(Blue,[Knave,Knight,Spy]), member(Red,[Knave,Knight,Spy]), member(Green,[Knave,Knight,Spy]), % All different Blue \= Red, Blue \= Green, Red \= Green, says(BlueT, (Red == Spy)), says(RedT, (Green == Spy)), says(GreenT, (Red == Spy)), % Connect truthfulness with the types (BlueT == true -> (Blue = Knight ; Blue = Spy) ; (Blue = Knave ; Blue = Spy)), (RedT == true -> (Red = Knight ; Red = Spy) ; (Red = Knave ; Red = Spy)), (GreenT == true -> (Green = Knight ; Green = Spy) ; (Green = Knave ; Green = Spy)), maplist(type,[Blue,Red,Green],[BlueType,RedType,GreenType]), writeln(type=[blue=BlueType,red=RedType,green=GreenType]), writeln(truth=[blue=BlueT,red=RedT,green=GreenT]), fail, nl. puzzle_70. /* """ Puzzle 71. The whole truth and nothing but the truth On a famous island in the Pacific Ocean (whose name I forgot) live three tribes: the Whites, who always tell the truth; the Blacks, who always tell lies; and the Greys, who lie and tell the truth alternatively (although their first answer may be either truth or lie). These natives always gather in groups of three, with one representative of each tribe in the group. I approached such a group of three natives, and had the following con- versation with the first native: "Are you the White, the Black, or the Grey?" "I am the Grey". "And what about your friend here?" "He is a Black". "So, your other friend is the White? " "Of course". Was the "other friend" a White, and if not, what was he? """ type = [a = black,b = white,c = grey] truth = [first = false,second = false,third = false] Cf knights_and_knaves_the_whole_truth_and_nothing_but_the_truth.pi */ puzzle_71 :- White = white, Black = black, Grey = grey, % Truthfulness member(FirstT,[false,true]), member(SecondT,[false,true]), member(ThirdT,[false,true]), % Types member(A,[White,Black,Grey]), member(B,[White,Black,Grey]), member(C,[White,Black,Grey]), % All different A \= B, A \= C, B \= C, says(FirstT, (A == Grey)), says(SecondT, (B == Black)), says(ThirdT, (C == White)), % Connect truthfulness with the types % (FirstT == true -> (A = White ; A = Grey) ; (A = Black ; A = Grey)), % (SecondT == true -> (A = White ; A = Grey) ; (A = Black ; A = Grey)), % (ThirdT == true -> (A = White ; A = Grey) ; (A = Black ; A = Grey)), % Whites: always tell the truth (A == White -> (FirstT = true, SecondT == true, ThirdT = true) ; true), % Blacks: always lies (A == Black -> (FirstT = false, SecondT = false, ThirdT = false) ; true), % Greys. lies/tell the truth alternatively (A == Grey -> ( (FirstT = true, SecondT = false, ThirdT = true) ; (FirstT = false, SecondT = true, ThirdT = false) ) ; true), maplist(type,[A,B,C],[AType,BType,CType]), writeln(type:[a=AType,b=BType,c=CType]), writeln(truth:[first=FirstT,second=SecondT,third=ThirdT]), nl, fail, nl. puzzle_71. /* """ Puzzle 72. Three goddesses Three goddesses were sitting in an old Indian temple. Their names were Truth (always telling the truth), Lie (always lying), and Wisdom (sometimes lying). A visitor asked the one on the left: "Who is sitting next to you?" "Truth", she answered. Then he asked the one in the middle: "Who are you?" "Wisdom". Last, he asked the one on the right: "Who is your neighbour?" "Lie", she replied. And then it became clear who was who. """ type = [left = wisdom,middle = lie,right = truth] truth = [left = false,middle = false,right = true] Cf knights_and_knaves_three_goddesses.pi */ puzzle_72 :- Truth = truth, Lie = lie, Wisdom = wisdom, % Truthfulness member(LeftT,[false,true]), member(MiddleT,[false,true]), member(RightT,[false,true]), % Types member(Left,[Truth,Lie,Wisdom]), member(Middle,[Truth,Lie,Wisdom]), member(Right,[Truth,Lie,Wisdom]), % All different Left \= Middle, Left \= Right, Middle \= Right, says(LeftT, (Middle == Truth)), says(MiddleT, (Middle == Wisdom)), says(RightT, (Middle == Lie)), % Connect truthfulness with the types (LeftT == true -> (Left = Truth ; Left = Wisdom) ; (Left = Lie ; Left = Wisdom)), (MiddleT == true -> (Middle = Truth ; Middle = Wisdom) ; (Middle = Lie ; Middle = Wisdom)), (RightT == true -> (Right = Truth ; Right = Wisdom) ; (Right = Lie ; Right = Wisdom)), maplist(type,[Left,Middle,Right],[LeftType,MiddleType,RightType]), writeln(type:[left=LeftType,middle=MiddleType,right=RightType]), writeln(truth:[left=LeftT,middle=MiddleT,right=RightT]), nl, fail, nl. puzzle_72.