/* Smullyan's Portia problem in Picat. From Raymond Smullyans "What is the name of this book?", Chapter 5 "The mystery of Portias Caskets". Problems 67a, 67b, 68a, and 68b. 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 => _ = findall(_,problem_67a), nl, _ = findall(_,problem_67b), nl, _ = findall(_,problem_68a), nl, _ = findall(_,problem_68b), nl, fail, nl. % % Problem 67a % Gold: The portrait is in this casket % Silver: The portrait is not in this casket % Lead: The portrait is not in the Gold casket % % Solution: The portraint is in the Silver casket % % This model: % portrait = [0,1,0] % inscription = [0,0,1] % The portrait is in the Silver casket. % problem_67a => println("problem_67a"), N = 3, % gold, silver, lead Portrait = new_list(N), Portrait :: 0..1, Inscription = new_list(N), Inscription :: 0..1, Boxes = ["Gold","Silver","Lead"], % Only one portrait sum(Portrait) #= 1, % At most one incription is correct sum(Inscription) #<= 1, % Gold inscription: The portrait is in this casket says(Inscription[1], Portrait[1]), % Silver inscription: The portrait is not in this casket says(Inscription[2], #~Portrait[2]), % Lead inscription: The portraint is in the Silver casket says(Inscription[3], #~Portrait[1]), Vars = Inscription ++ Portrait, solve(Vars), println(portrait=Portrait), println(inscription=Inscription), nth(Ix,Portrait,1), printf("The portrait is in the %w casket.\n", Boxes[Ix]), nl, fail, nl. % % Problem 67b % Gold: The portrait is not in the Silver casket % Silver: The portrait is not in this casket % Lead: The portrait is in this casket % % Solution: The portrait is in the Gold casket % % This model: % portrait = [1,0,0] % inscription = [1,1,0] % The portrait is in the Gold casket. % problem_67b => println("problem_67b"), N = 3, % gold, silver, lead Portrait = new_list(N), Portrait :: 0..1, Inscription = new_list(N), Inscription :: 0..1, Boxes = ["Gold","Silver","Lead"], % Only one portrait sum(Portrait) #= 1, % at least one incription is correct sum(Inscription) #>= 1, % at least one incription is false sum([#~Inscription[I] : I in 1..N]) #>= 1, % Gold inscription: The portrait is not in the Silver casket says(Inscription[1], #~Portrait[2]), % Silver inscription: The portrait is not in this casket says(Inscription[2], #~Portrait[2]), % Lead inscription: The portrait is in this casket says(Inscription[3], Portrait[3]), Vars = Inscription ++ Portrait, solve(Vars), println(portrait=Portrait), println(inscription=Inscription), nth(Ix,Portrait,1), printf("The portrait is in the %w casket.\n", Boxes[Ix]), nl, fail, nl. % % Problem 68a % % Each casket has two inscriptions, each contains no more than % one false statement. % Gold: 1) The portrait is not here % 2) The artist of the portrait is from Venice % Silver: 1) The portrait is not in the Gold casket % 2) The artist of the portrait is really from Florence % Lead: 1) The portrait is not in here % 2) The portrait is really in the Silver casket % % Solution: The portrait is in the Gold casket. % % This model yield 3 solutions, all state that the portrait is in % the Silver casket: % portrait = [0,1,0] % inscription = {{1,0},{1,0},{1,1}} % The portrait is in the Silver casket. % % portrait = [0,1,0] % inscription = {{1,0},{1,1},{1,1}} % The portrait is in the Silver casket. % % portrait = [0,1,0] % inscription = {{1,1},{1,0},{1,1}} % The portrait is in the Silver casket. % problem_68a => println("problem_68a"), N = 3, Inscription = new_array(N,2), Inscription :: 0..1, % gold, silver, lead Portrait = new_list(N), Portrait :: 0..1, Boxes = ["Gold","Silver","Lead"], % Only one portrait sum(Portrait) #= 1, % Gold: says(Inscription[1,1], #~Portrait[1]), % The portrait is not here % The artist of the portrait is from Venice % Silver: says(Inscription[2,1], #~Portrait[1]), % The portrait is not in the Gold casket % The artist of the portrait is really from Florence % At most one of second statements of inscriptions 1 and 2 can be true. Inscription[1,2] + Inscription[2,2] #<= 1, % Lead: says(Inscription[3,1], #~Portrait[3]), % The portrait is not in here says(Inscription[3,2], Portrait[2]), % The portrait is really in the Silver casket % No more than one false statement per inscription foreach(I in 1..N) sum([#~Inscription[I,J] : J in 1..2]) #<= 1 end, Vars = Inscription.vars ++ Portrait, solve(Vars), println(portrait=Portrait), println(inscription=Inscription), nth(Ix,Portrait,1), printf("The portrait is in the %w casket.\n", Boxes[Ix]), nl, fail, nl. % % Problem 68b % Each casket has two inscriptions, one has two correct statements, % one has two false statements and one has one true and one false % statements % Gold: 1) The portrait is not here % 2) The portrait is in the Silver casket % Silver: 1) The portrait is not in the Gold casket % 2) The portrait is in the Lead casket % Lead: 1) The portrait is not here % 2) It is in the Gold casket % % Solution: The portrait is in the Lead basket. % % This model: % portrait = [0,0,1] % inscription = {{1,0},{1,1},{0,0}} % sums = [1,2,0] % The portrait is in the Lead casket. % problem_68b => println("problem_68b"), N = 3, Inscription = new_array(N,2), Inscription :: 0..1, % gold, silver, lead Portrait = new_list(N), Portrait :: 0..1, Sums = new_list(N), Sums :: 0..2, Boxes = ["Gold","Silver","Lead"], % Only one portrait sum(Portrait) #= 1, % Gold says(Inscription[1,1], #~Portrait[1]), % The portrait is not here says(Inscription[1,2], Portrait[2]), % The portrait is in the Silver casket % Silver says(Inscription[2,1], #~Portrait[1]), % The portrait is not in the Gold casket says(Inscription[2,2], Portrait[3]), % The portrait is in the Lead casket % Lead says(Inscription[3,1], #~Portrait[3]), % The portrait is not here says(Inscription[3,2], Portrait[1]), % It is in the Gold casket % sum the number of true values foreach(I in 1..N) Sums[I] #= sum(Inscription[I]) end, all_different(Sums), Vars = Inscription.vars ++ Portrait ++ Sums, solve(Vars), println(portrait=Portrait), println(inscription=Inscription), println(sums=Sums), nth(Ix,Portrait,1), printf("The portrait is in the %w casket.\n", Boxes[Ix]), nl, fail, nl. says(Inscription, Placement) => Inscription #= Placement.