/* Grid puzzle in Picat. Riddle in Prolog http://stackoverflow.com/questions/9955366/riddle-in-prolog """ I've got a problem. I must solve a riddle in Prolog, but I haven't got any idea how to do this. Maybe can you help me, give me some hint or something. First I haven't real name of this riddle, it's calld simply "ABC". At the beggining they give me size of board (n x m) and n, m = (1,10) and one letter, for example C, so I can use in ma solution only letters form A to C. Then I get some threes in form (i,j,k) , i <= n, j<=m and k belong to (A,C). For example board it the beggining look like this: _ _ B A B _ _ C C _ _ _ _ A _ _ To every empty boxe I must type the letters A,B,C in such a way, that when i finish typing they must meet the following conditions: * if in a row (column) are different letters, every of letter is appearing in this row (column) same number of times * at least in one row (column) all letters are the same. Have you any idea how to solve this kind of riddle? Maybe this puzzle has its own name and I can read somewhere about it? I'll be very grateful for every help! ... Little correct: In only one row OR column all letters are the same, not in both. Solution for my example is: B A B A B C B C C C C C C A C A """ In numeric representation 2 1 2 1 2 3 2 3 3 3 3 3 3 1 3 1 Note: Without any hints at all, there are 864 different solutions with n=4 and m=3 (A,B,C) This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ import cp. main => go. go ?=> N = 4, M = 3, % A..C data(1,Grid), [A,B,C] = [1,2,3], Str = ["A","B","C"], S = [I : I in 1..M], % decision variables X = new_array(N,N), X :: 1..M, % Note: I make these global for debuggin purposes GccRows = new_array(N,M), GccRows :: 0..N, GccCols = new_array(N,M), GccCols :: 0..N, % hints foreach(I in 1..N, J in 1..N) if Grid[I,J] > 0 then X[I,J] #= Grid[I,J] end end, println("Grid:"), foreach(Row in Grid) println(Row) end, nl, foreach(I in 1..N) global_cardinality2([X[I,J] : J in 1..N], [GccRows[I,K] : K in 1..M]), same_except_0([GccRows[I,K] : K in 1..M]) end, foreach(J in 1..N) % Note: we transpose gcc_cols to be row based global_cardinality2([X[I,J] : I in 1..N], [GccCols[J,K] : K in 1..M]), same_except_0([GccCols[J,K] : K in 1..M]) end, % % Exact one occurrence where all are the same value in x % sum([B1+B2 : I in 1..N, same([X[I,J] : J in 1..N],B1), same([X[J,I] : J in 1..N],B2)]) #= 1, Vars = X.vars ++ GccRows ++ GccCols, solve(Vars), println("Solution:"), foreach(Row in X) println(Row) end, nl, foreach(Row in X) println([Str[V] : V in Row]) end, println(gccRows=GccRows), println(gccCols=GccCols), nl, fail, nl. go => true. % all values > 0 must be the same same_except_0(V) => N = V.len, foreach(I in 1..N, J in 1..N) (V[I] #> 0 #/\ V[J] #> 0) #=> (V[I] #= V[J]) end. % alternative version same_except_0_b(X) => N = X.len, foreach(I in 1..N, J in 1..N) X[I] #= X[J] #\/ X[I] #= 0 #\/ X[J] #= 0 end. % all values must be the same % same(V) => % foreach(I in 2..V.len) % V[I] #= V[I-1] % end. % with a boolean same(V,B) => N = V.len, B :: 0..1, sum([V[I] #= V[I-1] : I in 2..N]) #= N-1 #<=> B#=1. % % global_cardinality(A, Gcc) % % This version is bidirectional but limited: % % Both A and Gcc are (plain) lists. % % The list A can contain only values 1..Max (i.e. the length of Gcc). % This means that the caller must know the max values of A. % Or rather: if A contains another values they will not be counted. % global_cardinality2(A, Gcc) => Len = length(A), Max = length(Gcc), Gcc :: 0..Len, foreach(I in 1..Max) count(I,A,#=,Gcc[I]) end. data(1,Grid) => [A,B,C] = [1,2,3], Grid = [ [0, 0, B, A], [B, 0, 0, C], [C, 0, 0, 0], [0, A, 0, 0] ].