/* Sally Rooney Hat Puzzle in Picat. https://www.theguardian.com/science/2024/dec/09/can-you-solve-it-that-sally-rooney-hat-puzzle """ Can you solve it? That Sally Rooney hat puzzle Midway though the new Sally Rooney novel, Intermezzo, two of the characters discuss a puzzle about hats. I thought it would make a perfect puzzle for this column, so here it is. A liar who always lies says "All my hats are green." Can we conclude that he has some hats? In fact, I would like to extend the puzzle by making it multiple choice. Which, if any, of the following statements can we conclude from what the liar has said? A) The liar has at least one hat. B) The liar has only one green hat. C) The liar has no hats. D) The liar has at least one green hat. E) The liar has no green hats. Note: this question was originally set in a maths exam, so the answer assumes some basic assumptions about formal logic. A liar is someone who only says false statements. """ Solution: https://www.theguardian.com/science/2024/dec/09/did-you-solve-it-that-sally-rooney-hat-puzzle """ Solution A If the liar says "All my hats are green" then the statement "All my hats are green" is false. In other words, it is not the case that all of the liar’s hats are green. We cannot conclude B because it is possible that the liar has, say, one red and two green hats. (It may be the case that the liar has a single green hat, but we cannot conclude it with 100 per cent certainty.) We cannot conclude D because it is possible the liar has a single red hat and no green hats. We cannot conclude E because it is possible that the liar has a green and a red hat. So, either A is true or C is true – either the liar has some hats or he has no hats. And here is where we get to the crux of the problem, the notion of vacuous truth. Imagine I have a shelf with no books on it. The statement ‘I have read all the books on my shelf’ is technically true, although it is meaningless because there are no books. Likewise, the statement ‘I have read none of the books on my shelf’ is also technically true and meaningless for the same reason. A logician would call both of these statements vacuously true. They are true, but say nothing. Now back to the liar. Imagine he has no hats. If he has no hats, then the statement "All my hats are green" is true (and vacuous). Which contradicts the fact that he only says false statements. The liar must have some hats, thus A is the right answer. I hope you enjoyed today’s puzzle. (I do recommend the Rooney book BTW.) """ Here is the output of this model (go/0): [hats = [0,1],numHats = 1,greenHats = [0,0],numGreenHats = 0,statement = 0] [hats = [0,1],numHats = 1,greenHats = [1,0],numGreenHats = 0,statement = 0] [hats = [1,0],numHats = 1,greenHats = [0,0],numGreenHats = 0,statement = 0] [hats = [1,0],numHats = 1,greenHats = [0,1],numGreenHats = 0,statement = 0] [hats = [1,1],numHats = 2,greenHats = [0,0],numGreenHats = 0,statement = 0] [hats = [1,1],numHats = 2,greenHats = [0,1],numGreenHats = 1,statement = 0] [hats = [1,1],numHats = 2,greenHats = [1,0],numGreenHats = 1,statement = 0] I.e. for all solutions, there is at least one hat. We cannot tell if the hats are green or not or the number of green hats. Another take on this: Showing if the statements A..E are true (1) or not (0): [a = 1,b = 0,c = 0,d = 0,e = 1] [a = 1,b = 0,c = 0,d = 0,e = 1] [a = 1,b = 0,c = 0,d = 0,e = 1] [a = 1,b = 0,c = 0,d = 0,e = 1] [a = 1,b = 0,c = 0,d = 0,e = 1] [a = 1,b = 1,c = 0,d = 1,e = 0] [a = 1,b = 1,c = 0,d = 1,e = 0] Again, statement A (The liar has at least one hat) is the only statement that is true in all solutions. HT to @iamreddave (Twitter/X) This program was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ import cp. main => go. go ?=> N = 2, % number of hats in the universe % Does the person own this hats: Hats[I]? Hats = new_list(N), Hats :: 0..1, % Is the hat Hats[I] green? GreenHats = new_list(N), GreenHats :: 0..1, NumHats #= sum(Hats), % number of hats NumGreenHats #= sum([Hats[I]*GreenHats[I] : I in 1..N]), % Number of owned hats that are green % The liar says : All my hats are green (the number of my hats = number of my green hats) Statement #= 1 #<=> NumHats #= NumGreenHats, % But it's a lie Statement #= 0, % A) The liar has at least one hat. A #<=> NumHats #>= 1, % B) The liar has only one green hat. B #<=> NumGreenHats #= 1, % C) The liar has no hats. C #<=> NumHats #= 0, % D) The liar has at least one green hat. D #<=> NumGreenHats #>= 1, % E) The liar has no green hats. E #<=> NumGreenHats #= 0, Vars = Hats ++ GreenHats, solve(Vars), println([hats=Hats,numHats=NumHats,greenHats=GreenHats, numGreenHats=NumGreenHats,statement=Statement]), println([a=A,b=B,c=C,d=D,e=E]), nl, fail, nl. go => true. /* Checks all the solutions and prints the solution(s) that are true in all solutions. Here are the output for number of hats in the universe: N=2..10. Number of hats in the universe: 2 num_solutions = 7 Correct statement(s): A Number of hats in the universe: 3 num_solutions = 37 Correct statement(s): A Number of hats in the universe: 4 num_solutions = 175 Correct statement(s): A Number of hats in the universe: 5 num_solutions = 781 Correct statement(s): A Number of hats in the universe: 6 num_solutions = 3367 Correct statement(s): A Number of hats in the universe: 7 num_solutions = 14197 Correct statement(s): A Number of hats in the universe: 8 num_solutions = 58975 Correct statement(s): A Number of hats in the universe: 9 num_solutions = 242461 Correct statement(s): A Number of hats in the universe: 10 num_solutions = 989527 Correct statement(s): A */ go2 ?=> member(N,2..10), garbage_collect(200_000_000), % N = 10, % number of hats in the universe printf("Number of hats in the universe: %d\n",N), AllSolutions = hat_puzzle(N), Map = new_map(), foreach(_=Sol in AllSolutions) foreach({Statement,Answer} in zip("ABCDEF",Sol)) if Answer == 1 then Map.put(Statement,Map.get(Statement,0)+1) end end end, NumSolutions = AllSolutions.len, println(num_solutions=NumSolutions), println("Correct statement(s):"), println([Answer : Answer=Num in Map, Num==NumSolutions]), nl, fail, nl. go2 => true. % For go2/0 hat_puzzle(N) = AllSolutions => % Does the person own this hats: Hats[I]? Hats = new_list(N), Hats :: 0..1, % Is the hat Hats[I] green? GreenHats = new_list(N), GreenHats :: 0..1, NumHats #= sum(Hats), % number of hats NumGreenHats #= sum([Hats[I]*GreenHats[I] : I in 1..N]), % Number of owned hats that are green % The liar says : All my hats are green (the number of my hats = number of my green hats) Statement #= 1 #<=> NumHats #= NumGreenHats, % But it's a lie Statement #= 0, % A) The liar has at least one hat. A #<=> NumHats #>= 1, % B) The liar has only one green hat. B #<=> NumGreenHats #= 1, % C) The liar has no hats. C #<=> NumHats #= 0, % D) The liar has at least one green hat. D #<=> NumGreenHats #>= 1, % E) The liar has no green hats. E #<=> NumGreenHats #= 0, AllSolutions = solve_all(Hats++GreenHats=[A,B,C,D,E]).