% % ECLiPSe sample code % under Creative Commons Attribution 4.0 International License. % Author: Joachim Schimpf, Coninfer Ltd, 2019 % % This implements the model suggested in % https://stackoverflow.com/questions/56265708/constraints-for-a-3x3-block % The problem is modelled in terms of a matrix of Y-coordiates, such % that Ys[X,K]=Y iff the cell [X,Y] on the Sudoku board has the value K. % % ?- solve(1). % Y-Matrix % 7 3 1 5 6 2 8 4 9 % 1 7 6 8 3 5 2 9 4 % 5 4 8 2 9 7 6 3 1 % 2 9 3 4 5 8 1 6 7 % 6 1 5 9 7 3 4 8 2 % 8 5 9 3 2 4 7 1 6 % 9 8 2 1 4 6 5 7 3 % 4 2 7 6 1 9 3 5 8 % 3 6 4 7 8 1 9 2 5 % % Board % 3 6 2 8 4 5 1 7 9 % 1 7 5 9 6 3 2 4 8 % 9 4 8 2 1 7 6 3 5 % 7 1 3 4 5 8 9 6 2 % 2 9 6 7 3 1 5 8 4 % 8 5 4 6 2 9 7 1 3 % 4 3 9 5 7 6 8 2 1 % 5 2 7 1 8 4 3 9 6 % 6 8 1 3 9 2 4 5 7 % % Yes (0.05s cpu) :- lib(ic). :- lib(ic_global). :- import alldifferent/1 from ic_global. solve(Name) :- problem(Name, Board), board_to_ys(Board, Ys), model(Ys), labeling(Ys), writeln("Y-Matrix"), print_matrix(Ys), ys_to_board(Ys, Board), writeln("Board"), print_matrix(Board). model(Ys) :- dim(Ys, [N,N]), % Ys[X,K]=Y means K at position [X,Y] NB is integer(sqrt(N)), % number of blocks Ys #:: 1..N, ( for(I,1,N), param(Ys) do alldifferent(Ys[I,*]), alldifferent(Ys[*,I]) ), ( multifor([B,K],1,[NB,N]), param(Ys,NB) do ( for(X,(B-1)*NB+1,B*NB), foreach(Colour,Colours), param(Ys,K,NB) do Colour #:: 0..NB-1, Offset #:: 1..NB, Ys[X,K] #= Colour*NB + Offset ), alldifferent(Colours) ). board_to_ys(Board, Ys) :- dim(Board, [N,N]), dim(Ys, [N,N]), ( foreachelem(K,Board,[X,Y]), param(Ys) do ( var(K) -> true ; arg([X,K], Ys, Y) ) ). ys_to_board(Ys, Board) :- dim(Ys, [N,N]), dim(Board, [N,N]), ( foreachelem(Y,Ys,[X,K]), param(Board) do arg([X,Y], Board, K) ). print_matrix(Board) :- dim(Board, [N,N]), ( for(I,1,N), param(Board,N) do ( for(J,1,N), param(Board,I) do X is Board[I,J], ( var(X) -> write(" _") ; printf(" %2d", [X]) ) ), nl ), nl. problem(small, []( [](4,_,_,_), [](_,_,1,_), [](_,_,3,1), [](_,_,_,_))). problem(1, []( [](_, _, 2, _, _, 5, _, 7, 9), [](1, _, 5, _, _, 3, _, _, _), [](_, _, _, _, _, _, 6, _, _), [](_, 1, _, 4, _, _, 9, _, _), [](_, 9, _, _, _, _, _, 8, _), [](_, _, 4, _, _, 9, _, 1, _), [](_, _, 9, _, _, _, _, _, _), [](_, _, _, 1, _, _, 3, _, 6), [](6, 8, _, 3, _, _, 4, _, _))).