/* Lady and Tigers puzzle in logic programming in Picat. Here are the Lady and Tigers puzzles from chapter 5 in Adrian Groza "Modelling Puzzles in First Order Logic" using plain logic programming. Cf the constraint models for Chapter 5 Lady and Tigers at http://hakank.org/picat/#groza_puzzles This program was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ main => go. go ?=> member(P,37..47), PuzzleS = "puzzle_" ++ P.to_string, bp.atom_chars(Puzzle,PuzzleS), println(Puzzle), Puzzle, nl, fail, nl. go => true. go2 ?=> puzzle_48, fail, nl. go2 => true. % % Truthfulness of the room. % says(Sign,What) :- ( (Sign,What) ; (not Sign, not What)). /* """ Puzzle 37. Ladies and tigers in jail Each of the two rooms contains either a lady or a tiger. There could be tigers in both rooms or ladies in both rooms. There is a sign on each room. One of the signs is true and the other is false. Which door to open in order to find the lady, marry her, and get half of the kingdom as compensation? (adapted from Smullyan 2009) Room 1: In this room there is a lady and in the other room there is a tiger. Room 2: In one of these rooms there is a lady and in one of these rooms there is a tiger. """ Who 1:tiger Who 2:lady Room 1:false Room 2:true Cf ladies_and_tigers_in_jail.pi */ puzzle_37 ?=> % Truth of the room signs member(Room1,[true,false]), member(Room2,[true,false]), % Who is in the room member(Who1,[lady,tiger]), member(Who2,[lady,tiger]), % (Room1 = true, Room2 = false) ; (Room1 = false, Room2 = true), ((Room1 = true, Room2 = false) -> true ; (Room1 = false, Room2 = true) -> true ; false ), % Signs of the rooms says(Room1,(Who1 == lady, Who2 == tiger)), says(Room2,((Who1 == lady, Who2 == tiger) ; (Who1 == tiger, Who2 == lady) )), % says(Room2,(Who1 != Who2)), printf("Who 1:%w Who 2:%w Room 1:%w Room 2:%w\n",Who1,Who2,Room1,Room2), fail, nl. puzzle_37 => true. /* """ Puzzle 38. The trials of the second day Each of the two rooms contains either a lady or a tiger. There could be tigers in both rooms or ladies in both rooms. There is a sign on each room. The signs are either both true or both false. Which door to open in order to find the lady, marry her, and get half of the kingdom as compensation? (Smullyan 2009) Room 1: At least one of these rooms contains a lady. Room 2: A tiger is in the other room. """ Who 1:tiger Who 2:lady Room 1:true Room 2:true Cf lady_and_tiger_the_trials_of_the_second_day.pi */ puzzle_38 ?=> % Truth of the room signs member(Room1,[true,false]), member(Room2,[true,false]), % Who is in the room member(Who1,[lady,tiger]), member(Who2,[lady,tiger]), % The signs are either both true or both false. Room1 == Room2, % ((Room1 = true, Room2 = true) -> true % ; % (Room1 = false, Room2 = false) -> true % ; % false % ), % Signs of the rooms says(Room1,(Who1 == lady ; Who2 == lady)), says(Room2,(Who1 == tiger)), printf("Who 1:%w Who 2:%w Room 1:%w Room 2:%w\n",Who1,Who2,Room1,Room2), nl, fail, nl. puzzle_38 => true. /* """ Puzzle 39. Ladies only Each of the two rooms contains either a lady or a tiger. There could be tigers in both rooms or ladies in both rooms. There is a sign on each room. The signs are either both true of both false. Which door to open in order to find the lady, marry her, and get half of the kingdom as compensation? (Smullyan 2009) Room 1: Either a tiger is in this room or a lady is in the other room. Room 2: A lady is in the other room. """ Who 1:lady Who 2:lady Room 1:true Room 2:true Cf lady_and_tiger_ladies_only.pi */ puzzle_39 ?=> % Truth of the room signs member(Room1,[true,false]), member(Room2,[true,false]), % Who is in the room member(Who1,[lady,tiger]), member(Who2,[lady,tiger]), Room1 == Room2, % Signs of the rooms says(Room1,(Who1 == tiger ; Who2 == lady)), says(Room2,(Who1 == lady)), printf("Who 1:%w Who 2:%w Room 1:%w Room 2:%w\n",Who1,Who2,Room1,Room2), nl, fail, nl. puzzle_39 => true. /* """ Puzzle 40. Fourth day: Ladies are honest but tigers are liars Each of the two rooms contains either a lady or a tiger. There could be tigers in both rooms or ladies in both rooms. There is a sign on each room. If a lady is in room 1, then the sign on the door is true. If a tiger is in room 1, then the sign on the door is false. For room 2, the situation is opposite. If a lady is in room 2, then the sign on the door is false. If a tiger is in room 2, then the sign on the door is true. The signs are either both true or both false. Which door to open in order to find the lady, marry her, and get half of the kingdom as compensation? (Smullyan 2009) Room 1: Both rooms contains ladies. Room 2: Both rooms contain ladies. """ Who 1:tiger Who 2:lady Room 1:false Room 2:false Cf lady_and_tiger_fourth_day_ladies_are_honest_but_tigers_are_liars.pi */ puzzle_40 ?=> % Truth of the room signs member(Room1,[true,false]), member(Room2,[true,false]), % Who is in the room member(Who1,[lady,tiger]), member(Who2,[lady,tiger]), % The signs are either both true or both false. Room1 == Room2, % Signs of the rooms says(Room1,(Who1 == lady, Who2 == lady)), says(Room2,(Who1 == lady, Who2 == lady)), % If a lady is in room 1, then the sign on the door is true. % If a tiger is in room 1, then the sign on the door is false. (Who1 == lady -> Room1 == true ; true), (Who1 == tiger -> Room1 == false ; true), % For room 2, the situation is opposite. If a lady is in room 2, then the sign on the % door is false. If a tiger is in room 2, then the sign on the door is true. (Who2 == lady -> Room2 == false ; true), (Who2 == tiger -> Room2 == true ; true), printf("Who 1:%w Who 2:%w Room 1:%w Room 2:%w\n",Who1,Who2,Room1,Room2), nl, fail, nl. puzzle_40 => true. /* """ Puzzle 41. Fifth day Each of the two rooms contains either a lady or a tiger. There could be tigers in both rooms or ladies in both rooms. There is a sign on each room. If a lady is in room 1, then the sign on the door is true. If a tiger is in room 1, then the sign on the door is false. For room 2, the situation is opposite. If a lady is in room 2, then the sign on the door is false. If a tiger is in room 2, then the sign on the door is true. The signs are either both true of both false. Which door to open in order to find the lady, marry her, and get half of the kingdom as compensation? (Smullyan 2009) Room 1: At least one room contains a lady Room 2: The other room contains a lady """ Who 1:lady Who 2:tiger Room 1:true Room 2:true Cf lady_and_tiger_fifth_day.pi */ puzzle_41 ?=> % Truth of the room signs member(Room1,[true,false]), member(Room2,[true,false]), % Who is in the room member(Who1,[lady,tiger]), member(Who2,[lady,tiger]), % The signs are either both true or both false. Room1 == Room2, % Signs of the rooms says(Room1,(Who1 == lady ; Who2 == lady)), says(Room2,(Who1 == lady)), % If a lady is in room 1, then the sign on the door is true. % If a tiger is in room 1, then the sign on the door is false. (Who1 == lady -> Room1 == true ; true), (Who1 == tiger -> Room1 == false ; true), % For room 2, the situation is opposite. If a lady is in room 2, then the sign on the % door is false. If a tiger is in room 2, then the sign on the door is true. (Who2 == lady -> Room2 == false ; true), (Who2 == tiger -> Room2 == true ; true), printf("Who 1:%w Who 2:%w Room 1:%w Room 2:%w\n",Who1,Who2,Room1,Room2), nl, fail, nl. puzzle_41 => true. /* """ Puzzle 42. Sixth day Each of the two rooms contains either a lady or a tiger. There could be tigers in both rooms or ladies in both rooms. There is a sign on each room. If a lady is in room 1, then the sign on the door is true. If a tiger is in room 1, then the sign on the door is false. For room 2, the situation is opposite. If a lady is in room 2, then the sign on the door is false. If a tiger is in room 2, then the sign on the door is true. The signs are either both true of both false. Which door to open in order to find the lady, marry her, and get half of the kingdom as compensation? (Smullyan 2009) Room 1: It make no difference which room you pick Room 2: The other room contains a lady """ Who 1:tiger Who 2:lady Room 1:false Room 2:false Cf lady_and_tiger_sixth_day.pi */ puzzle_42 ?=> % Truth of the room signs member(Room1,[true,false]), member(Room2,[true,false]), % Who is in the room member(Who1,[lady,tiger]), member(Who2,[lady,tiger]), % The signs are either both true or both false. Room1 == Room2, % Signs of the rooms says(Room1,(Who1 == Who2)), says(Room2,(Who1 == lady)), % If a lady is in room 1, then the sign on the door is true. % If a tiger is in room 1, then the sign on the door is false. (Who1 == lady -> Room1 == true ; true), (Who1 == tiger -> Room1 == false ; true), % For room 2, the situation is opposite. If a lady is in room 2, then the sign on the % door is false. If a tiger is in room 2, then the sign on the door is true. (Who2 == lady -> Room2 == false ; true), (Who2 == tiger -> Room2 == true ; true), printf("Who 1:%w Who 2:%w Room 1:%w Room 2:%w\n",Who1,Who2,Room1,Room2), nl, fail, nl. puzzle_42 => true. /* """ Puzzle 43. Seventh day Each of the two rooms contains either a lady or a tiger. There could be tigers in both rooms or ladies in both rooms. There is a sign on each room. If a lady is in room 1, then the sign on the door is true. If a tiger is in room 1, then the sign on the door is false. For room 2, the situation is opposite. If a lady is in room 2, then the sign on the door is false. If a tiger is in room 2, then the sign on the door is true. The signs are either both true of both false. Which door to open in order to find the lady, marry her, and get half of the kingdom as compensation? (Smullyan 2009) Room 1: It makes a difference which room you pick Room 2: You are better off choosing the other room. """ Who 1:lady Who 2:tiger Room 1:true Room 2:true Cf lady_and_tiger_seventh_day.pi */ puzzle_43 ?=> % Truth of the room signs member(Room1,[true,false]), member(Room2,[true,false]), % Who is in the room member(Who1,[lady,tiger]), member(Who2,[lady,tiger]), % The signs are either both true or both false. Room1 == Room2, % Signs of the rooms says(Room1,(Who1 != Who2)), says(Room2,(Who1 == lady)), % If a lady is in room 1, then the sign on the door is true. % If a tiger is in room 1, then the sign on the door is false. (Who1 == lady -> Room1 == true ; true), (Who1 == tiger -> Room1 == false ; true), % For room 2, the situation is opposite. If a lady is in room 2, then the sign on the % door is false. If a tiger is in room 2, then the sign on the door is true. (Who2 == lady -> Room2 == false ; true), (Who2 == tiger -> Room2 == true ; true), printf("Who 1:%w Who 2:%w Room 1:%w Room 2:%w\n",Who1,Who2,Room1,Room2), nl, fail, nl. puzzle_43 => true. /* """ Puzzle 44. Eighth day Each of the two rooms contains either a lady or a tiger. There could be tigers in both rooms or ladies in both rooms. There is a sign on each room. If a lady is in room 1, then the sign on the door is true. If a tiger is in room 1, then the sign on the door is false. For room 2, the situation is opposite. If a lady is in room 2, then the sign on the door is false. If a tiger is in room 2, then the sign on the door is true. Now, the prob- lem is that signs are not already put on the doors. That is, the two messages can appear either on the first door or on the second one. The signs are either both true of both false. Which door to open in order to find the lady, marry her, and get half of the king- dom as compensation? (Smullyan 2009) Sign 1 (Room 1 or Room 2): This room contains a tiger Sign 2 (Room 1 or Room 2): Both rooms contain tigers """ Who 1:tiger Who 2:lady Room 1:false Room 2:false Sign1:room2 Sign2:room1 Cf lady_and_tiger_eighth_day.pi */ puzzle_44 ?=> % Truth of the room signs member(Room1,[true,false]), member(Room2,[true,false]), % Who is in the room member(Who1,[lady,tiger]), member(Who2,[lady,tiger]), member(Sign1,[room1,room2]), member(Sign2,[room1,room2]), % The signs are either both true or both false. Room1 == Room2, Sign1 != Sign2, % Signs of the rooms (Sign1 == room1 -> says(Room1,(Who1 == tiger)) ; true), (Sign1 == room2 -> says(Room1,(Who1 == tiger, Who2 == tiger)) ; true), (Sign2 == room1 -> says(Room1,(Who2 == tiger)) ; true), (Sign2 == room2 -> says(Room1,(Who1 == tiger, Who2 == tiger)) ; true), % If a lady is in room 1, then the sign on the door is true. % If a tiger is in room 1, then the sign on the door is false. (Who1 == lady -> Room1 == true ; true), (Who1 == tiger -> Room1 == false ; true), % For room 2, the situation is opposite. If a lady is in room 2, then the sign on the % door is false. If a tiger is in room 2, then the sign on the door is true. (Who2 == lady -> Room2 == false ; true), (Who2 == tiger -> Room2 == true ; true), printf("Who 1:%w Who 2:%w Room 1:%w Room 2:%w Sign1:%w Sign2:%w\n",Who1,Who2,Room1,Room2,Sign1,Sign2), nl, fail, nl. puzzle_44 => true. /* """ Puzzle 45. Ninth day: three rooms One room contains a lady and the other two contain tigers. At most one of the three signs is true. Which door to open in order to find the lady, marry her, and get half of the kingdom as compensation? (Smullyan 2009) Room 1: A tiger is in this room Room 2: A lady is in this room Room 3: A tiger is in room 2 """ Who 1:lady Who 2:tiger Who3:tiger Room 1:false Room 2:false Room 3:true Cf lady_and_tiger_ninth_day_three_rooms.pi */ puzzle_45 ?=> % Truth of the room signs member(Room1,[true,false]), member(Room2,[true,false]), member(Room3,[true,false]), % Who is in the room member(Who1,[lady,tiger]), member(Who2,[lady,tiger]), member(Who3,[lady,tiger]), % One room contains a lady and the other two contain tigers. ( (Who1 == lady, Who2 == tiger, Who3 == tiger) ; (Who1 == tiger, Who2 == lady, Who3 == tiger) ; (Who1 == tiger, Who2 == tiger, Who3 == lady) ), % At most one of the three signs is true. ( (Room1 == true, Room2 == false, Room3 == false) ; (Room1 == false, Room2 == true, Room3 == false) ; (Room1 == false, Room2 == false, Room3 == true) ), % Signs of the rooms says(Room1,(Who1 == tiger)), says(Room2,(Who2 == lady)), says(Room3,(Who2 == tiger)), printf("Who 1:%w Who 2:%w Who3:%w Room 1:%w Room 2:%w Room 3:%w\n",Who1,Who2,Who3,Room1,Room2,Room3), nl, fail, nl. puzzle_45 => true. /* """ Puzzle 46. A lady and two tigers One room contains a lady and the other two contain tigers. The sign on the door con- taining the lady is true and at least one of the other two signs is false. Which door to open in order to find the lady, marry her, and get half of the kingdom as compensa- tion? (Smullyan 2009) Room 1: A tiger is in room 2 Room 2: A tiger is in this room Room 3: A tiger is in room 1 """ Who 1:lady Who 2:tiger Who3:tiger Room 1:true Room 2:true Room 3:false Cf lady_and_tiger_a_lady_and_two_tigers.pi */ puzzle_46 ?=> % Truth of the room signs member(Room1,[true,false]), member(Room2,[true,false]), member(Room3,[true,false]), % Who is in the room member(Who1,[lady,tiger]), member(Who2,[lady,tiger]), member(Who3,[lady,tiger]), % One room contains a lady and the other two contain tigers. ( (Who1 == lady, Who2 == tiger, Who3 == tiger) ; (Who1 == tiger, Who2 == lady, Who3 == tiger) ; (Who1 == tiger, Who2 == tiger, Who3 == lady) ), % The sign on the door containing the lady is true % and at least one of the other two signs is false (Who1 == lady -> (Room1 == true, (Room2 == false ; Room3 == false)) ; true), (Who2 == lady -> (Room2 == true, (Room1 == false ; Room3 == false)) ; true), (Who3 == lady -> (Room3 == true, (Room1 == false ; Room3 == false)) ; true), % Signs of the rooms says(Room1,(Who2 == tiger)), says(Room2,(Who2 == tiger)), says(Room3,(Who1 == tiger)), printf("Who 1:%w Who 2:%w Who3:%w Room 1:%w Room 2:%w Room 3:%w\n",Who1,Who2,Who3,Room1,Room2,Room3), nl, fail, nl. puzzle_46 => true. /* """ Puzzle 47. A lady, a tiger, and an empty room One room contains a lady, another a tiger, and the third room is empty. The sign of the door containing a lady is true. The sign of the door containing a tiger is false. The sign of the empty room can be either true or false. Which door to open in order to find the lady, marry her, and get half of the kingdom as compensation? (Smullyan 2009) Room 1: Room 3 is empty Room 2: The tiger is in room 1 Room 3: This room is empty """ Who 1:lady Who 2:tiger Who3:empty Room 1:true Room 2:false Room 3:true Cf lady_and_tiger_a_lady_a_tiger_and_an_empty_room.pi */ puzzle_47 ?=> % Truth of the room signs member(Room1,[true,false]), member(Room2,[true,false]), member(Room3,[true,false]), % Who is in the room member(Who1,[lady,tiger,empty]), member(Who2,[lady,tiger,empty]), member(Who3,[lady,tiger,empty]), % One room contains a lady, another a tiger, and the third room is empty. ( (Who1 == lady, ((Who2 == tiger, Who3 == empty) ; (Who2 == empty, Who3 == tiger))) ; (Who2 == lady, ((Who1 == tiger, Who3 == empty) ; (Who1 == empty, Who3 == tiger))) ; (Who3 == lady, ((Who1 == tiger, Who2 == empty) ; (Who1 == empty, Who2 == tiger))) ), % The sign of the door containing a lady is true. (Who1 == lady -> (Room1 == true) ; true), (Who2 == lady -> (Room2 == true) ; true), (Who3 == lady -> (Room3 == true) ; true), % The sign of the door containing a tiger is false. (Who1 == tiger -> (Room1 == false) ; true), (Who2 == tiger -> (Room2 == false) ; true), (Who3 == tiger -> (Room3 == false) ; true), % The sign of the empty room can be either true or false. % Signs of the rooms says(Room1,(Who3 == empty)), says(Room2,(Who1 == tiger)), says(Room3,(Who3 == empty)), printf("Who 1:%w Who 2:%w Who3:%w Room 1:%w Room 2:%w Room 3:%w\n",Who1,Who2,Who3,Room1,Room2,Room3), nl, fail, nl. puzzle_47 => true. /* """ Puzzle 48. A logic labyrinth There are nine rooms. Only one room contains the lady. Each of the other eight con- tains a tiger or they are empty. The sign on the door containing a lady is true. The signs on the doors containing tigers are false. The signs on the empty rooms can be either true or false. You studied the situation for a long while: "The problem is unsolvable!" "I know" laughed the king. "Now, at least give me a decent clue: is Room 8 empty or not?". The king was decent enough to tell whether Room 8 was empty or not, and you are then able to deduce where the lady is. Which door to open in order to find the lady, marry her, and get half of the kingdom as compensation? (Smullyan 2009) Room 1: Room 2: Room 3: Lady is (in) and odd This room Either sign 5 is right numbered room is empty or sign 7 is wrong Room4: Room 5: Room 6: Sign 1 is wrong Either sign 2 Sign 3 is wrong or sign 4 is right Room 7: Room 8: Room 9: Lady is not in This room This room contains a room 1 contains a tiger and sign 6 tiger and is wrong room 9 is empty """ Here is the total number of different solutions, the combination of scenario and what room the lady is 32 who8_empty = lady_is_in_room = [1] 4 who8_empty = lady_is_in_room = [3] 12 who8_empty = lady_is_in_room = [4] 4 who8_empty = lady_is_in_room = [5] 20 who8_empty = lady_is_in_room = [7] 8 who8_not_empty = lady_is_in_room = [7] I.e. when Room 8 is encoded as not empty there are 8 solutions, all stating that the lady is in room 7. Here are all these 8 solutions: who8_not_empty = lady_is_in_room = [7] rooms = [true,false,false,false,false,true,true,false,false] whos = [empty,tiger,tiger,tiger,tiger,empty,lady,tiger,tiger] who8_not_empty = lady_is_in_room = [7] rooms = [true,false,false,false,false,true,true,false,false] whos = [empty,tiger,tiger,tiger,empty,empty,lady,tiger,tiger] who8_not_empty = lady_is_in_room = [7] rooms = [true,false,false,false,false,true,true,false,false] whos = [empty,tiger,tiger,empty,tiger,empty,lady,tiger,tiger] who8_not_empty = lady_is_in_room = [7] rooms = [true,false,false,false,false,true,true,false,false] whos = [empty,tiger,tiger,empty,empty,empty,lady,tiger,tiger] who8_not_empty = lady_is_in_room = [7] rooms = [true,false,false,false,false,true,true,false,false] whos = [empty,tiger,empty,tiger,tiger,empty,lady,tiger,tiger] who8_not_empty = lady_is_in_room = [7] rooms = [true,false,false,false,false,true,true,false,false] whos = [empty,tiger,empty,tiger,empty,empty,lady,tiger,tiger] who8_not_empty = lady_is_in_room = [7] rooms = [true,false,false,false,false,true,true,false,false] whos = [empty,tiger,empty,empty,tiger,empty,lady,tiger,tiger] who8_not_empty = lady_is_in_room = [7] rooms = [true,false,false,false,false,true,true,false,false] whos = [empty,tiger,empty,empty,empty,empty,lady,tiger,tiger] As mentioned in lady_and_tiger_a_logic_labyrinth.pi, these two hints are a little dubious: - Room 3: Either sign 5 is right or sign 7 is wrong - Room 5: Either sign 2 or sign 4 is right I would rather interpret these clues as XOR constraints, but that does not give the unique solution of which room the lady was located. But if they instead are interpreted as OR constraints then the intended solution are shown. Cf lady_and_tiger_a_logic_labyrinth.pi */ puzzle_48 ?=> N = 9, member(Scenario,[who8_empty,who8_not_empty]), println(scenario=Scenario), % Truth of the room signs Rooms = new_list(N), Rooms = [Room1,Room2,Room3,Room4,Room5,Room6,Room7,Room8,Room9], % Who are in each room? Whos = new_list(N), Whos = [Who1,Who2,Who3,_Who4,Who5,_Who6,Who7,Who8,Who9], foreach(R in 1..N) member(Rooms[R],[true,false]), member(Whos[R],[lady,tiger,empty]), % The sign of the door containing a lady is true. ( Whos[R] == lady -> Rooms[R] == true ; true), % The sign of the door containing a lady is false. ( Whos[R] == tiger -> Rooms[R] == false ; true) end, % Testing the scenarios (Scenario == who8_empty -> Who8 == empty ; true), (Scenario == who8_not_empty -> Who8 != empty ; true), [1 : R in 1..N, Whos[R] == lady].len == 1, % Room1: Lady is and odd numbered room % says(Room1, ([ 1 : I in 1..N, I mod 2 == 1, Whos[I] == lady].len == 1)), says(Room1,(Who1 == lady ; Who3 == lady ; Who5 == lady ; Who7 == lady ; Who9 == lady)), % Room 2: This room is empty says(Room2, Who2 == empty), % See comment above % Room 3: Either sign 5 is right or sign 7 is wrong says(Room3,(Room5 == true ; Room7 == false)), % Room 4: Sign 1 is wrong says(Room4, Room1 == false), % See comment above % Room 5: Either sign 2 or sign 4 is right says(Room5,(Room2 == true ; Room4 == true)), % Room 6: Sign 3 is wrong says(Room6, Room3 == false), % Room 7: Lady is not in room 1 says(Room7, Who1 != lady), % Room 8: This room contains a tiger and room 9 is empty says(Room8, (Who8 == tiger, Who9 == empty)), % Room 9: This room contains a tiger and sign 6 is wrong says(Room9, (Who9 == tiger, Room6 == false)), println(Scenario=lady_is_in_room=[R : R in 1..N, Whos[R] == lady]), if Scenario == who8_not_empty then println(rooms=Rooms), println(whos=Whos), nl end, fail, nl. puzzle_48 => true.