/* Three-in-a-row puzzle in Picat. http://stackoverflow.com/questions/36202351/3-in-a-row-logic-puzzle-optimisation-for-sequence-constraints-in-lists-arrays """ In the following puzzle we try and fill the grid with blue and white squares in such a way that: - A 3-in-a-row (or column) of the same colour is not allowed. - Each row and column has an equal number of blue and white squares. [Example_puzzle] If we now represent white with a 0 and blue with a 1, we get: 0 _ _ _ 1 _ _ 0 _ _ _ _ _ _ _ _ _ 0 1 _ _ 0 _ _ _ _ 1 1 _ _ _ 0 _ _ 1 _ And we can pretty quickly verify that 0 1 0 0 1 1 0 0 1 1 0 1 1 1 0 1 0 0 1 1 0 0 1 0 0 0 1 1 0 1 1 0 1 0 1 0 is the solution for this example. """ This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ import smt. % import sat. % import cp. main => go. go => % puzzle(1,X), puzzle(2,X), X :: 0..1, Rows = X.len, Cols = X[1].len, foreach(I in 1..Rows) S = [X[I,J] : J in 1..Cols], sum(S) #= Rows div 2, sequence(S,3,0,2) end, foreach(J in 1..Cols) S = [X[I,J] : I in 1..Rows], sum(S) #= Cols div 2, sequence(S,3,0,2) end, println(solve), solve($[ffd,updown],X.vars()), foreach(Row in X) println(Row) end, nl, % fail, nl. % % sequence(?X,+Length,?LBound,?UBound) % % Ensures that all sums of every subsequence of length Length % in array X is between LBound and UBound % sequence(X,Length, LBound,UBound) => foreach(I in 1..X.len-Length+1) Sum #= sum([X[J] : J in I..I+Length-1]), Sum #>= LBound, Sum #=< UBound end. puzzle(1,X) => X = { {0,_,_,_,1,_}, {_,0,_,_,_,_}, {_,_,_,_,_,0}, {1,_,_,0,_,_}, {_,_,1,1,_,_}, {_,0,_,_,1,_} }. puzzle(2,X) => X = new_array(18,18), L = [(1,3,0),(1,9,0),(1,10,0),(1,12,0),(1,14,0),(1,18,1),(2,4,0),(2,7,1),(2,8,1),(3,2,1),(3,6,0),(3,16,0),(3,17,0),(4,2,1),(4,4,1),(4,10,1),(4,13,1),(4,18,1),(5,8,1),(5,10,1),(5,15,0),(5,16,1),(6,12,1),(7,3,0),(7,4,0),(7,6,1),(7,9,0),(7,12,1),(7,17,0),(8,1,1),(8,4,0),(8,8,1),(8,15,1),(8,16,1),(9,7,0),(9,10,0),(9,14,0),(10,2,1),(10,4,1),(10,6,1),(10,13,1),(11,7,0),(11,10,1),(12,1,1),(12,4,1),(12,7,1),(12,15,1),(12,16,1),(13,1,1),(13,6,0),(13,8,1),(13,10,0),(13,16,1),(14,5,1),(14,10,0),(14,13,1),(15,1,1),(15,3,1),(15,12,0),(15,13,1),(15,15,0),(16,2,1),(16,4,0),(16,12,0),(16,18,0),(17,9,0),(17,15,0),(17,18,0),(18,2,1),(18,8,1),(18,11,1),(18,15,1),(18,16,1)], foreach((I,J,Val) in L) X[I,J] := Val end.