/* Latin Squares (Groza) in Picat. From Adrian Groza "Modelling Puzzles in First Order Logic" """ Puzzle 88. Latin square Latin square is an n × n array filled with n different values. Each value occurs exactly once in each row and exactly once in each column. How many Latin squares are there for n = 3? A Latin square is normalised or in standard form if both its first row and its first column are in their natural order (i.e. 0, 1, 2). How many normalised Latin squares are for n = 3? What about n = 4? After you solved the above puzzle, think also at the following one. Albert is a scientist that wants to test four different drugs (called A, B, C, and D) on four volunteers. He decides that every volunteer has to be tested with a different drug each week, but no two volunteers are allowed the same drug at the same time. """ Cf latin_squares.pi This program was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ import util. import cp. main => go. go => N = 4, latin_square(N,X,true), foreach(Row in X) println(Row.to_list) end, nl, fail, nl. /* How many different solutions? normalized = false 1 = 1 2 = 2 3 = 12 4 = 576 5 = 161280 normalized = true 1 = 1 2 = 1 3 = 1 4 = 4 5 = 56 */ go2 => member(Normalized,[false,true]), nl, println(normalized=Normalized), member(N,1..6), C = count_all(latin_square(N,_,Normalized)), println(N=C), fail, nl. /* Op.cit: """ After you solved the above puzzle, think also at the following one. Albert is a scientist that wants to test four different drugs (called A, B, C, and D) on four volunteers. He decides that every volunteer has to be tested with a different drug each week, but no two volunteers are allowed the same drug at the same time. """ ABCD BADC CDAB DCBA ABCD BADC CDBA DCAB ABCD BCDA CDAB DABC ABCD BDAC CADB DCBA */ go3 => N = 4, Drugs = ['A','B','C','D'], latin_square(N,X,true), foreach(Row in X) println([Drugs[I] : I in Row]) end, nl, false, nl. latin_square(N,X,Normalized) => X = new_array(N,N), X :: 1..N, foreach(I in 1..N) all_different([X[I,J] : J in 1..N]), all_different([X[J,I] : J in 1..N]), end, if Normalized then increasing([X[1,J] : J in 1..N]), increasing([X[I,1] : I in 1..N]) end, solve(X).