% Autor:
% Datum: 07.02.2015
:- use_module(library(pce)).
:- use_module(library(clpfd)).
:- use_module(library(apply)).

puzzle([[A1,IB11],[A2,IB12],[A3,IB13], [A4,IB14],[A5,IB15],[A6,IB16],[A7,IB17],[A8,IB18],[A9,IB19],
      [B1,IB21],[B2,IB22],[B3,IB23], [B4,IB24],[B5,IB25],[B6,IB26],[B7,IB27],[B8,IB28],[B9,IB29],
       [C1,IB31],[C2,IB32],[C3,IB33], [C4,IB34],[C5,IB35],[C6,IB36],[C7,IB37],[C8,IB38],[C9,IB39],

       [D1,IB41],[D2,IB42],[D3,IB43], [D4,IB44],[D5,IB45],[D6,IB46],[D7,IB47],[D8,IB48],[D9,IB49],
       [E1,IB51],[E2,IB52],[E3,IB53], [E4,IB54],[E5,IB55],[E6,IB56],[E7,IB57],[E8,IB58],[E9,IB59],
       [F1,IB61],[F2,IB62],[F3,IB63], [F4,IB64],[F5,IB65],[F6,IB66],[F7,IB67],[F8,IB68],[F9,IB69],

       [G1,IB71],[G2,IB72],[G3,IB73], [G4,IB74],[G5,IB75],[G6,IB76],[G7,IB77],[G8,IB78],[G9,IB79],
       [H1,IB81],[H2,IB82],[H3,IB83], [H4,IB84],[H5,IB85],[H6,IB86],[H7,IB87],[H8,IB88],[H9,IB89],
       [I1,IB91],[I2,IB92],[I3,IB93], [I4,IB94],[I5,IB95],[I6,IB96],[I7,IB97],[I8,IB98],[I9,IB99]]) :-
        print('ERGEBNIS \n'),
       %CHECK ROWS
  %      pruefen([[A1,IB11],[A2,IB12],[A3,IB13], [A4,IB14],[A5,IB15],[A6,IB16],[A7,IB17],[A8,IB18],[A9,IB19]]),
        pruefen([[B1,IB21],[B2,IB22],[B3,IB23], [B4,IB24],[B5,IB25],[B6,IB26],[B7,IB27],[B8,IB28],[B9,IB29]]),
   %     pruefen([[C1,IB31],[C2,IB32],[C3,IB33], [C4,IB34],[C5,IB35],[C6,IB36],[C7,IB37],[C8,IB38],[C9,IB39]]),
    %    pruefen([[D1,IB41],[D2,IB42],[D3,IB43], [D4,IB44],[D5,IB45],[D6,IB46],[D7,IB47],[D8,IB48],[D9,IB49]]),
     %   pruefen([[E1,IB51],[E2,IB52],[E3,IB53], [E4,IB54],[E5,IB55],[E6,IB56],[E7,IB57],[E8,IB58],[E9,IB59]]),
      %  pruefen([[F1,IB61],[F2,IB62],[F3,IB63], [F4,IB64],[F5,IB65],[F6,IB66],[F7,IB67],[F8,IB68],[F9,IB69]]),
       % pruefen([[G1,IB71],[G2,IB72],[G3,IB73], [G4,IB74],[G5,IB75],[G6,IB76],[G7,IB77],[G8,IB78],[G9,IB79]]),
        %pruefen([[H1,IB81],[H2,IB82],[H3,IB83], [H4,IB84],[H5,IB85],[H6,IB86],[H7,IB87],[H8,IB88],[H9,IB89]]),
        %pruefen([[I1,IB91],[I2,IB92],[I3,IB93], [I4,IB94],[I5,IB95],[I6,IB96],[I7,IB97],[I8,IB98],[I9,IB99]]),
        %CHECK COLUMNS
%       pruefen([[A1,IB11],[B1,IB21],[C1,IB31], [D1,IB41],[E1,IB51],[F1,IB61],[G1,IB71],[H1,IB81],[I1,IB91]]),
%        pruefen([[A2,IB12],[B2,IB22],[C2,IB32], [D2,IB42],[E2,IB52],[F2,IB62],[G2,IB72],[H2,IB82],[I2,IB92]]),
%        pruefen([[A3,IB13],[B3,IB23],[C3,IB33], [D3,IB43],[E3,IB53],[F3,IB63],[G3,IB73],[H3,IB83],[I3,IB93]]),
%        pruefen([[A4,IB14],[B4,IB24],[C4,IB34], [D4,IB44],[E4,IB54],[F4,IB64],[G4,IB74],[H4,IB84],[I4,IB94]]),
%        pruefen([[A5,IB15],[B5,IB25],[C5,IB35], [D5,IB45],[E5,IB55],[F5,IB65],[G5,IB75],[H5,IB85],[I5,IB95]]),
%        pruefen([[A6,IB16],[B6,IB26],[C6,IB36], [D6,IB46],[E6,IB56],[F6,IB66],[G6,IB76],[H6,IB86],[I6,IB96]]),
%        pruefen([[A7,IB17],[B7,IB27],[C7,IB37], [D7,IB47],[E7,IB57],[F7,IB67],[G7,IB77],[H7,IB87],[I7,IB97]]),
%        pruefen([[A8,IB18],[B8,IB28],[C8,IB38], [D8,IB48],[E8,IB58],[F8,IB68],[G8,IB78],[H8,IB88],[I8,IB98]]),
%        pruefen([[A9,IB19],[B9,IB29],[C9,IB39], [D9,IB49],[E9,IB59],[F9,IB69],[G9,IB79],[H9,IB89],[I9,IB99]]),
        List=[[A1,IB11],[A2,IB12],[A3,IB13], [A4,IB14],[A5,IB15],[A6,IB16],[A7,IB17],[A8,IB18],[A9,IB19],
       [B1,IB21],[B2,IB22],[B3,IB23], [B4,IB24],[B5,IB25],[B6,IB26],[B7,IB27],[B8,IB28],[B9,IB29],
       [C1,IB31],[C2,IB32],[C3,IB33], [C4,IB34],[C5,IB35],[C6,IB36],[C7,IB37],[C8,IB38],[C9,IB39],

       [D1,IB41],[D2,IB42],[D3,IB43], [D4,IB44],[D5,IB45],[D6,IB46],[D7,IB47],[D8,IB48],[D9,IB49],
       [E1,IB51],[E2,IB52],[E3,IB53], [E4,IB54],[E5,IB55],[E6,IB56],[E7,IB57],[E8,IB58],[E9,IB59],
       [F1,IB61],[F2,IB62],[F3,IB63], [F4,IB64],[F5,IB65],[F6,IB66],[F7,IB67],[F8,IB68],[F9,IB69],

       [G1,IB71],[G2,IB72],[G3,IB73], [G4,IB74],[G5,IB75],[G6,IB76],[G7,IB77],[G8,IB78],[G9,IB79],
       [H1,IB81],[H2,IB82],[H3,IB83], [H4,IB84],[H5,IB85],[H6,IB86],[H7,IB87],[H8,IB88],[H9,IB89],
       [I1,IB91],[I2,IB92],[I3,IB93], [I4,IB94],[I5,IB95],[I6,IB96],[I7,IB97],[I8,IB98],[I9,IB99]],
%       exclude(isBlack,List,ExcludedList),
%       createOneDimensionalForLabeling(ExcludedList,Variablen),
       %labeling([ff],[B1,B2,B6,B7]),
       print([B1,B2,B6,B7]),
       drucken(List).


  %check rows and columns
  pruefen(L):-
  %exclude black and undefined lists
  exclude(isBlackAndEmpty,L,NewList),
  %Constraint 1 and 2, every list ins 1..9 and all different(list)
  constraintsFestlegen(NewList),
  %get list groups and set constraint(every white block cutted by black boxes has to be gapless)
  listGroupConstraints(L).


  %ausstiegspunkt für eine leere liste
  listGroupConstraints([]).
  
  %for a list with a black field
  listGroupConstraints(List):-
  append(Prefix, [[_,1]|Rest],List),
  %creates one dimensional list
  createOneDimensional(Prefix,OneDimensionalList),
  %rekursiv
  listGroupConstraints(Rest).

   %for a list without a black field
  listGroupConstraints(List):-
  %convert to one dimensional list
  createOneDimensional(List,OneDimensionalList),
  %set constraint for one dimensional list
  setGroupConstraints(OneDimensionalList).

  %set group constraints for white fields
  setGroupConstraints([]).
  setGroupConstraints([Variable]),
  Variable in 1..9.
  setGroupConstraints(Gruppe):-
  listl(Gruppe).



  %set constraints for whole list(black and undefined excluded)
  constraintsFestlegen(L) :-
      variablenListeErstellen(L,Variablen).


  %set constraints for whole list(black and undefined excluded)
  variablenListeErstellen([],Variablen):-
      %jede Liste darf nur aus Zahlen von 1..9 bestehen
      Variablen ins 1..9,
      %es dürfen in der Liste keine Zahlen doppelt vorkommen
      %bibliothek von SWI-Prolog Bibliothek clpfd
      all_different(Variablen),
      print('\nListenconstraints:'),
      print(Variablen).

  %create one dimensional list for constraint 1 and 2
  variablenListeErstellen([X|Rest],Variablen):-
  listeInListe(X,Variable,IsBlack),
  append(Variablen,[Variable],Herbert),
  variablenListeErstellen(Rest,Herbert).

  %helper
  %create one dimensional list from two dimensional list for constraint 3
  %get the first variables from list
  createOneDimensional([],Variablen):-
  setGroupConstraints(Variablen).
  createOneDimensional([X|Rest],Variablen):-
  listeInListe(X,Variable,IsBlack),
  append(Variablen,[Variable],MyList),
  createOneDimensional(Rest,MyList).
  
    %create one dimensional list from two dimensional list for labeling all
  %get the first variables from list
  createOneDimensionalForLabeling([],Variablen):-
  print(Variablen),
  labeling([ff],Variablen).
  createOneDimensionalForLabeling([X|Rest],Variablen):-
  listeInListe(X,Variable,IsBlack),
  append(Variablen,[Variable],MyList),
  createOneDimensionalForLabeling(Rest,MyList).

  %for the filter (exclude) excluse if field is black and undefined
  isBlackAndEmpty([Variable|IsBlack]):-
  IsBlack=:=1,
  var(Variable).

  %check if black
  isBlack([Variable|IsBlack]):-
  IsBlack=:=1.

  %get the first element from list
  listeInListe([Variable|IsBlack],Variable,IsBlack).

  %check if group is gapless,
  listl(L) :-
    [Fst,Lst] ins 1..9,
    Fst #=< Lst,
    Len #= Lst - Fst + 1,
    length(L, Len),
    label([Fst,Lst]),
    L ins Fst..Lst,
    all_different(L),
    print('\n'),
    print(L).



%for printing the solution
drucken([[A1,IB11],[A2,IB12],[A3,IB13], [A4,IB14],[A5,IB15],[A6,IB16],[A7,IB17],[A8,IB18],[A9,IB19],
       [B1,IB21],[B2,IB22],[B3,IB23], [B4,IB24],[B5,IB25],[B6,IB26],[B7,IB27],[B8,IB28],[B9,IB29],
       [C1,IB31],[C2,IB32],[C3,IB33], [C4,IB34],[C5,IB35],[C6,IB36],[C7,IB37],[C8,IB38],[C9,IB39],

       [D1,IB41],[D2,IB42],[D3,IB43], [D4,IB44],[D5,IB45],[D6,IB46],[D7,IB47],[D8,IB48],[D9,IB49],
       [E1,IB51],[E2,IB52],[E3,IB53], [E4,IB54],[E5,IB55],[E6,IB56],[E7,IB57],[E8,IB58],[E9,IB59],
       [F1,IB61],[F2,IB62],[F3,IB63], [F4,IB64],[F5,IB65],[F6,IB66],[F7,IB67],[F8,IB68],[F9,IB69],

       [G1,IB71],[G2,IB72],[G3,IB73], [G4,IB74],[G5,IB75],[G6,IB76],[G7,IB77],[G8,IB78],[G9,IB79],
       [H1,IB81],[H2,IB82],[H3,IB83], [H4,IB84],[H5,IB85],[H6,IB86],[H7,IB87],[H8,IB88],[H9,IB89],
       [I1,IB91],[I2,IB92],[I3,IB93], [I4,IB94],[I5,IB95],[I6,IB96],[I7,IB97],[I8,IB98],[I9,IB99]]):-
       print([[A1,IB11],[A2,IB12],[A3,IB13], [A4,IB14],[A5,IB15],[A6,IB16],[A7,IB17],[A8,IB18],[A9,IB19]]),
       print('\n'),
       print([[B1,IB21],[B2,IB22],[B3,IB23], [B4,IB24],[B5,IB25],[B6,IB26],[B7,IB27],[B8,IB28],[B9,IB29]]),
       print('\n'),
       print([[C1,IB31],[C2,IB32],[C3,IB33], [C4,IB34],[C5,IB35],[C6,IB36],[C7,IB37],[C8,IB38],[C9,IB39]]),
       print('\n'),
       print([[D1,IB41],[D2,IB42],[D3,IB43], [D4,IB44],[D5,IB45],[D6,IB46],[D7,IB47],[D8,IB48],[D9,IB49]]),
       print('\n'),
       print([[E1,IB51],[E2,IB52],[E3,IB53], [E4,IB54],[E5,IB55],[E6,IB56],[E7,IB57],[E8,IB58],[E9,IB59]]),
       print('\n'),
       print([[F1,IB61],[F2,IB62],[F3,IB63], [F4,IB64],[F5,IB65],[F6,IB66],[F7,IB67],[F8,IB68],[F9,IB69]]),
       print('\n'),
       print([[G1,IB71],[G2,IB72],[G3,IB73], [G4,IB74],[G5,IB75],[G6,IB76],[G7,IB77],[G8,IB78],[G9,IB79]]),
       print('\n'),
       print([[H1,IB81],[H2,IB82],[H3,IB83], [H4,IB84],[H5,IB85],[H6,IB86],[H7,IB87],[H8,IB88],[H9,IB89]]),
       print('\n'),
       print([[I1,IB91],[I2,IB92],[I3,IB93], [I4,IB94],[I5,IB95],[I6,IB96],[I7,IB97],[I8,IB98],[I9,IB99]]).