/* Logic puzzl in Picat. CP version of this puzzle https://swi-prolog.discourse.group/t/similar-einstein-riddle/5142 """ Friends: Jarek, Frank, Stefanie, Albert, Simon, Robert, Marcin they live in one building, each on a different level (0, 1, 2, …). Each of them has a different animal: dog, a cat, a fish, hamster, parrot, snake, canary. In which floort each of them lives and what kind of animal does it have when bellow sentences are true? Franek lives lower than Albert. The owner of the parrot lives on floor 6. The canary owner lives on floor 0. Franek has no snake. The snake owner lives on floor 1. Albert doesn’t have a canary. Jarek doesn’t have a parrot. Simon has no snake. Robert has no hamsters. The hamster owner lives on floor 3. Robert lives lower than Stefan. Szymon lives lower than Marcin. Marcin has no fish. The owner of the fish lives on floor 4. Franek doesn’t have a hamster. Albert lives lower than Stefan. The cat owner lives on floor 5. The dog owner lives on floor 2. Szymon lives lower than Jarek. Robert lives higher than Albert. Albert doesn’t have a dog. Franek doesn’t have a dog. Stefan doesn’t have a canary. Franek doesn’t have a cat. Marcin lives higher than Jarek. Stefan doesn’t have a parrot. Franek lives lower than Marcin. Marcin doesn’t have a snake. Marcin lives higher than Albert. Franek has no fish. Szymon lives higher than Stefan. Robert has no fish. Stefan lives higher than Franek. Simon lives higher than Albert. Robert doesn’t have a cat. Marcin lives higher than Robert. Franek lives lower than Szymon. Franek lives lower than Robert. Stefan lives lower than Jarek. Stefan doesn’t have a cat. Jarek lives higher than Franek. Stefan doesn’t have a dog. Jarek lives higher than Robert. Franek doesn’t have a parrot. Stefan has no snake. Albert has no fish. Robert lives lower than Simon. Jarek lives higher than Albert. Albert doesn’t have a cat. Stefan lives lower than Marcin. Albert doesn’t have a parrot. Stefan has no fish. Simon doesn’t have a parrot. Simon doesn’t have a cat. Albert doesn’t have a hamster. Jarek doesn’t have a dog. Simon doesn’t have a hamster. Marcin doesn’t have a dog. Simon doesn’t have a canary. Simon doesn’t have a dog. """ Cf my SWI-Prolog model: http://hakank.org/swi_prolog/friends_at_different_floors.pl This model was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ import v3_utils. import cp. main => go. % This is joeblog's solution % row(Frank,0,canary) % row(Albert,1,snake) % row(Robert,2,dog) % row(Stefanie,3,hamster) % row(Simon,4,fish) % row(Jarek,5,cat) % row(Marcin,6,parrot) % % 0.001..0.003s % go ?=> joeblog_solution(Table), foreach(Row in Table) println(Row) end, fail, nl. go => true. % This is my solution: % floor = [1,0,5,6,2,4,3] % owns = [2,1,5,7,6,3,4] % Floor: 0 frank canary % Floor: 1 albert snake % Floor: 2 robert dog % Floor: 3 stefanie hamster % Floor: 4 simon fish % Floor: 5 jarek cat % Floor: 6 marcin parrot % % 0.0..0.001s % go2 ?=> Animals = [canary,snake,dog,hamster,fish,cat,parrot], People = [albert,frank,jarek,marcin,robert,simon,stefanie], % sorted hakank_solution(Floor,Owns,OwnsA), println(floor=Floor), println(owns=Owns), println(ownsA=OwnsA), foreach(F in 1..7) printf("Floor: %d %w %w\n",F-1,People[OwnsA[F]],Animals[F]) end, nl, fail, nl. go2 => true. % % This is joeblog's program (with some changes for Picat) % joeblog_solution(Table) :- Table = $[row(_, 0, canary), % The canary owner lives on floor 0. row(_, 1, snake), % The snake owner lives on floor 1. row(_, 2, dog), % The dog owner lives on floor 2. row(_, 3, hamster), % The hamster owner lives on floor 3. row(_, 4, fish), % The owner of the fish lives on floor 4. row(_, 5, cat), % The cat owner lives on floor 5. row(_, 6, parrot)], % The owner of the parrot lives on floor 6. % hakank: Here we have to use member/2 since it's a generator member($row('Frank', LFrank, AFrank), Table), member($row('Albert', LAlbert, AAlbert), Table), member($row('Robert', LRobert, ARobert), Table), member($row('Stefanie', LStefanie, AStefanie), Table), member($row('Simon', LSimon, ASimon), Table), member($row('Jarek', LJarek, AJarek), Table), member($row('Marcin', LMarcin, AMarcin), Table), % Frank has no snake. % Frank doesn’t have a dog. % Frank doesn’t have a hamster. % Franek has no fish. % Frank doesn’t have a cat. % Franek doesn’t have a parrot. % hakank: Here we just tests for membership and can use membchk \+ membchk(AFrank, [snake, dog, hamster, fish, cat, parrot]), % Albert doesn’t have a canary. % Albert doesn’t have a dog. % Albert doesn’t have a hamster. % Albert has no fish. % Albert doesn’t have a cat. % Albert doesn’t have a parrot. not membchk(AAlbert, [canary, dog, hamster, fish, cat, parrot]), % Robert has no hamsters. % Robert has no fish. % Robert doesn’t have a cat. not membchk(ARobert, [hamster, fish, cat]), % Stefan doesn’t have a canary. % Stefan has no snake. % Stefan doesn’t have a dog. % Stefan has no fish. % Stefan doesn’t have a cat. % Stefan doesn’t have a parrot. not membchk(AStefanie, [canary, snake, dog, fish, cat, parrot]), % Simon doesn’t have a canary. % Simon has no snake. % Simon doesn’t have a dog. % Simon doesn’t have a hamster. % Simon doesn’t have a cat. % Simon doesn’t have a parrot. not membchk(ASimon, [canary, snake, dog, hamster, cat, parrot]), % Jarek doesn’t have a dog. % Jarek doesn’t have a parrot. not membchk(AJarek, [dog, parrot]), % Marcin doesn’t have a snake. % Marcin doesn’t have a dog. % Marcin has no fish. not membchk(AMarcin, [snake, dog, fish]), LFrank < LAlbert, % Frank lives lower than Albert. LFrank < LRobert, % Franek lives lower than Robert. LFrank < LStefanie, % Stefan lives higher than Franek. LFrank < LSimon, % Franek lives lower than Szymon. LFrank < LJarek, % Jarek lives higher than Franek. LFrank < LMarcin, % Franek lives lower than Marcin. LAlbert < LRobert, % Robert lives higher than Albert. LAlbert < LStefanie, % Albert lives lower than Stefan. LAlbert < LSimon, % Simon lives higher than Albert. LAlbert < LJarek, % Jarek lives higher than Albert. LAlbert < LMarcin, % Marcin lives higher than Albert. LRobert < LStefanie, % Robert lives lower than Stefan. LRobert < LSimon, % Robert lives lower than Simon. LRobert < LJarek, % Jarek lives higher than Robert. LRobert < LMarcin, % Marcin lives higher than Robert. LStefanie < LSimon, % Szymon lives higher than Stefan. LStefanie < LJarek, % Stefan lives lower than Jarek. LStefanie < LMarcin, % Stefan lives lower than Marcin. LSimon < LJarek, % Szymon lives lower than Jarek. LSimon < LMarcin, % Szymon lives lower than Marcin. LJarek < LMarcin. % Marcin lives higher than Jarek. % % CP version, a little less verbose approach. % hakank_solution(Floor,Owns,OwnsA) :- N = 7, % The canary owner lives on floor 0. % The snake owner lives on floor 1. % The dog owner lives on floor 2. % The hamster owner lives on floor 3. % The owner of the fish lives on floor 4. % The cat owner lives on floor 5. % The owner of the parrot lives on floor 6. Animals = 1..N, [Canary,Snake,Dog,Hamster,Fish,Cat,Parrot] = Animals, % Floor order People = 1..N, % Sorted names [Albert,Frank,Jarek,Marcin,Robert,Simon,Stefanie] = People, % What animal does person P owns? Owns = new_list(N), Owns :: Animals, % The inverse of Owns so we can just plug in the floor.. OwnsA = new_list(N), OwnsA :: 1..N, % Which Floor does person P lives at Floor = new_list(N), Floor :: 0..N-1, all_different(Owns), all_different(Floor), assignment(Owns,OwnsA), NoOwns = [[Frank, [Snake, Dog, Hamster, Fish, Cat, Parrot]], [Albert, [Canary, Dog, Hamster, Fish, Cat, Parrot]], [Robert, [Hamster, Fish, Cat]], [Stefanie, [Canary, Snake, Dog, Fish, Cat, Parrot]], [Simon, [Canary, Snake, Dog, Hamster, Cat, Parrot]], [Jarek, [Dog, Parrot]], [Marcin, [Snake, Dog, Fish]] ], foreach([P, NotOwned] in NoOwns) foreach(A in NotOwned) Owns[P] #!= A end end, Lesses = [ [Frank, [Albert,Robert,Stefanie,Simon,Jarek,Marcin]], [Albert, [Robert,Stefanie,Simon,Jarek,Marcin]], [Robert, [Stefanie,Simon,Jarek,Marcin]], [Stefanie, [Simon,Jarek,Marcin]], [Simon, [Jarek,Marcin]], [Jarek, [Marcin]] ], foreach([P,Ps] in Lesses) foreach(P2 in Ps) Floor[P] #< Floor[P2] end end, println(solve), solve(Owns ++ Floor).