:- use_module(library(clpfd)).

sudoku(Rows) :-
    length(Rows, 9),
    maplist(same_length(Rows), Rows),
    append(Rows, Vs), Vs ins 1..9,
    maplist(all_distinct, Rows),
    transpose(Rows, Columns),
    maplist(all_distinct, Columns),
    Rows = [A,B,C,D,E,F,G,H,I],
    blocks(A, B, C),
    blocks(D, E, F),
    blocks(G, H, I),
    maplist(label, Rows).

blocks([], [], []).
blocks([A,B,C|Bs1], [D,E,F|Bs2], [G,H,I|Bs3]) :-
    all_distinct([A,B,C,D,E,F,G,H,I]),
    blocks(Bs1, Bs2, Bs3).

print_sudoku([]).
print_sudoku([Row|Rows]) :-
    write(Row), nl,
    print_sudoku(Rows).

% Example: the "AI Escargot" puzzle
% Run with:  ?- example.
example :-
    Puzzle = [[1,_,_,_,_,7,_,9,_],
              [_,3,_,_,2,_,_,_,8],
              [_,_,9,6,_,_,5,_,_],
              [_,_,5,3,_,_,9,_,_],
              [_,1,_,_,8,_,_,_,2],
              [6,_,_,_,_,4,_,_,_],
              [3,_,_,_,_,_,_,1,_],
              [_,4,_,_,_,_,_,_,7],
              [_,_,7,_,_,_,3,_,_]],
    sudoku(Puzzle),
    print_sudoku(Puzzle).
