:- module(sudoku, [do/1], [clpfd]).
% Written by MCL (mcarro_at_fi_dot_upm_dot_es)

% Adapted by Jose F. Morales to recent changes in the implementation,
% added labeling options as parameter of do/1.

:- use_module(engine(runtime_control), [statistics/2]).
:- use_module(library(format), [format/2]).
:- use_module(engine(io_basic), [nl/0]).
:- use_module(library(write), [write/1]).

:- use_module(library(clpfd/clpfd_stats)).

setup(T, Tt, Squares):-
 %% From El Mundo, Sat. 23
 %%         C1=     [_,_,_,1,_,3,8,_,_],
 %%         C2=     [_,_,6,2,_,_,_,5,3],
 %%         C3=     [7,_,9,_,5,_,_,1,_],
 %%         C4=     [3,_,_,5,7,_,_,_,_],
 %%         C5=     [_,_,_,_,_,_,_,_,_],
 %%         C6=     [_,4,_,_,_,_,1,_,7],
 %%         C7=     [9,5,7,8,_,_,6,_,_],
 %%         C8=     [_,_,_,_,_,2,_,_,_],
 %%         C9=     [_,_,8,_,1,_,_,_,9],

%% From http://www.sciencenews.org/articles/20050618/mathtrek.asp
%% It is said to be difficult

 %%         C1=     [_,_,_,1,_,_,7,4,_],
 %%         C2=     [_,5,_,_,9,_,_,3,2],
 %%         C3=     [_,_,6,7,_,_,9,_,_],
 %%         C4=     [4,_,_,8,_,_,_,_,_],
 %%         C5=     [_,2,_,_,_,_,_,1,_],
 %%         C6=     [_,_,_,_,_,9,_,_,5],
 %%         C7=     [_,_,4,_,_,7,3,_,_],
 %%         C8=     [7,3,_,_,2,_,_,6,_],
 %%         C9=     [_,6,5,_,_,4,_,_,_],


%% From The Times online: "very hard"

    C1=     [_,4,3,_,8,_,2,5,_],
    C2=     [6,_,_,_,_,_,_,_,_],
    C3=     [_,_,_,_,_,1,_,9,4],
    C4=     [9,_,_,_,_,4,_,7,_],
    C5=     [_,_,_,6,_,8,_,_,_],
    C6=     [_,1,_,2,_,_,_,_,3],
    C7=     [8,2,_,5,_,_,_,_,_],
    C8=     [_,_,_,_,_,_,_,_,5],
    C9=     [_,3,4,_,9,_,7,1,_],


    T = [C1,C2,C3,C4,C5,C6,C7,C8,C9],
    C1 = [V11, V12, V13, V14, V15, V16, V17, V18, V19],
    C2 = [V21, V22, V23, V24, V25, V26, V27, V28, V29],
    C3 = [V31, V32, V33, V34, V35, V36, V37, V38, V39],
    C4 = [V41, V42, V43, V44, V45, V46, V47, V48, V49],
    C5 = [V51, V52, V53, V54, V55, V56, V57, V58, V59],
    C6 = [V61, V62, V63, V64, V65, V66, V67, V68, V69],
    C7 = [V71, V72, V73, V74, V75, V76, V77, V78, V79],
    C8 = [V81, V82, V83, V84, V85, V86, V87, V88, V89],
    C9 = [V91, V92, V93, V94, V95, V96, V97, V98, V99],

    S1 = [V11, V12, V13, V21, V22, V23, V31, V32, V33],
    S2 = [V14, V15, V16, V24, V25, V26, V34, V35, V36],
    S3 = [V17, V18, V19, V27, V28, V29, V37, V38, V39],

    S4 = [V41, V42, V43, V51, V52, V53, V61, V62, V63],
    S5 = [V44, V45, V46, V54, V55, V56, V64, V65, V66],
    S6 = [V47, V48, V49, V57, V58, V59, V67, V68, V69],

    S7 = [V71, V72, V73, V81, V82, V83, V91, V92, V93],
    S8 = [V74, V75, V76, V84, V85, V86, V94, V95, V96],
    S9 = [V77, V78, V79, V87, V88, V89, V97, V98, V99],

    Squares = [S1,S2,S3,S4,S5,S6,S7,S8,S9],
    trans_m(T, Tt).

do(Opts) :-
    statistics(runtime,_),
%       fd_chain_stats(_),
    setup(T, Tt, Squares),
    all_vars(T, V),
    every_list_diff(T),
    every_list_diff(Tt),
    every_list_diff(Squares),
    statistics(runtime, [_, BuildT]),
%        labeling(V),
    labeling(Opts, V),
    write_lists(T),
    statistics(runtime,[_, Time]),
%       fd_chain_stats(ChainCalls),
%       format("~d ms in labeling ~d ms in constraining (~p reexecutions)~n", [Time, BuildT, ChainCalls]).
    format("~d ms in labeling ~d ms in constraining~n", [Time, BuildT]),
    clpfd_stats,
    fail.
do(_Opts).

trans_m([[]|_],[]).
trans_m(M,[C1|Cn]):- trans_v(M,C1,R), trans_m(R,Cn).

trans_v([],[],[]).
trans_v([[C11|C1n]|C],[C11|X],[C1n|Y]):- trans_v(C,X,Y).

every_list_diff([]).
every_list_diff([L|Ls]):-
    clpfd_rt:all_different(L),
    every_list_diff(Ls).

write_lists([]).
write_lists([L|Ls]):-
    write(L), nl,
    write_lists(Ls).

all_vars([], []).
all_vars([N|R], V):- nonvar(N), N = [], !, all_vars(R, V).
all_vars([[X|Xs]|Rs], [X|Ys]):-
    X in 1..9,
    all_vars([Xs|Rs], Ys).
