%%%
% Quatrido
%%%
\def\filedateQuatrido{2026/03/24}%
\def\fileversionQuatrido{0.1c}%
\message{-- \filedateQuatrido\space v\fileversionQuatrido}%
%
\setKVdefault[Quatrido]{Creation,Taille=6,Graine={},Cible={},Potentiel=false,Titre={},Echelle=1,Indications,AfficheSolutions=false,NombreSol={},Exemples=false}

\NewDocumentCommand\QuatridoReponse{smmmm}{%
  \mplibforcehmode%
  \IfBooleanTF{#1}{%
    \begin{mplibcode}
      trace (cercles((0,0),0.5u) xscaled 1.5) shifted(u*(-1,0.5));
      trace u*(0,0.25)--(0,0)--u*(1,0)--u*(1,0.25);
      trace (u*(1.25,0)--u*(4.75,0)) dashed evenly;
      trace polygone(u*(5,0),u*(6,0),u*(6,1),u*(5,1));
    \end{mplibcode}%
  }{%
    \begin{mplibcode}
      trace (cercles((0,0),0.5u) xscaled 1.5) shifted(u*(-1,0.5));
      trace u*(0,0.25)--(0,0)--u*(1,0)--u*(1,0.25);
      trace (u*(1.25,0)--u*(4.75,0)) dashed evenly;
      trace polygone(u*(5,0),u*(6,0),u*(6,1),u*(5,1));
      label(TEX("\Large\bfseries"&#2),u*(-1,0.5));
      label.top(TEX(#3),u*(0.5,0));
      label.urt(TEX(#4),u*(1.25,0));
      label(TEX("\large\bfseries"&#5),u*(5.5,0.5));
    \end{mplibcode}%
  }%
}%

\NewDocumentCommand\Quatrido{om}{%
  \useKVdefault[Quatrido]%
  \setKV[Quatrido]{#1}%
  \ifboolKV[Quatrido]{Creation}{%
    \ifboolKV[Quatrido]{Exemples}{%
      \openin\myread=PfCQuatridoNbExemples.tex%
      \read\myread to \PfCQuatridoNbExemples%
      \openin\myread PfCQuatridoExemples.tex%
      \xintFor* ##1 in{\xintSeq{1}{\PfCQuatridoNbExemples}}\do{%
        \read\myread to \PfCQuatridoTypeCouleur%
        \read\myread to \PfCQuatridoAbscisse%
        \read\myread to \PfCQuatridoOrdonnee%
        \read\myread to \PfCQuatridoCalcul%
        \setcounter{PfCTrash}{\PfCQuatridoOrdonnee}%
        \IfStrEqCase{\fpeval{\PfCQuatridoTypeCouleur}}{%
          {1}{\QuatridoReponse{"\useKV[Quatrido]{Cible}"}{"\Alph{PfCTrash}\PfCQuatridoAbscisse"}{"{\color{blue}\PfCQuatridoCalcul}"}{"4"}}%
          {2}{\QuatridoReponse{"\useKV[Quatrido]{Cible}"}{"\Alph{PfCTrash}\PfCQuatridoAbscisse"}{"{\color{red}\PfCQuatridoCalcul}"}{"4"}}%
          {3}{\QuatridoReponse{"\useKV[Quatrido]{Cible}"}{"\Alph{PfCTrash}\PfCQuatridoAbscisse"}{"{\color{Maroon}\PfCQuatridoCalcul}"}{"4"}}%
          {4}{\QuatridoReponse{"\useKV[Quatrido]{Cible}"}{"\Alph{PfCTrash}\PfCQuatridoAbscisse"}{"{\color{DarkGreen}\PfCQuatridoCalcul}"}{"4"}}%
        }\par
      }%
    }{%
      \ifboolKV[Quatrido]{AfficheSolutions}{%
        \ifemptyKV[Quatrido]{NombreSol}{\openin\myread=PfCQuatridoNbSolutionCible.tex%
            \read\myread to \PfCNbSolutionQuatridoCible}{\xdef\PfCNbSolutionQuatridoCible{\useKV[Quatrido]{NombreSol}}}%
       \openin\myread PfCQuatridoSolutionCible.tex%
        \begin{itemize}
        \xintFor* ##1 in{\xintSeq{1}{\PfCNbSolutionQuatridoCible}}\do{%
        \item%
        \read\myread to \PfCQuatridoAbscisse%
        \read\myread to \PfCQuatridoOrdonnee%
        \read\myread to \PfCQuatridoCalcul%
        \setcounter{PfCTrash}{\PfCQuatridoOrdonnee}%
        \QuatridoReponse{"\useKV[Quatrido]{Cible}"}{"\Alph{PfCTrash}\PfCQuatridoAbscisse"}{"\PfCQuatridoCalcul"}{"4"}%
      }%
      \end{itemize}
    }{
    \ifemptyKV[Quatrido]{Graine}{}{\PfCGraineAlea{\useKV[Quatrido]{Graine}}}%
    \edef\PfCQuatTaille{\useKV[Quatrido]{Taille}}%
    \edef\PfCListeQuatAMelanger{1}%
    \xintFor* ##1 in{\xintSeq{2}{\PfCQuatTaille}}\do{%
      \edef\PfCListeQuatAMelanger{\PfCListeQuatAMelanger,##1}%
    }%
    \MelangeListe{\PfCListeQuatAMelanger}{\PfCQuatTaille}%
    \edef\PfCListeQuatMel{\faa}%
    \MelangeListe{\PfCListeQuatAMelanger}{\PfCQuatTaille}%
    \edef\PfCListeQuatRotCol{\faa}%
    \MelangeListe{\PfCListeQuatAMelanger}{\PfCQuatTaille}%
    \edef\PfCListeQuatRotLig{\faa}%
    \edef\PfCGraineRetenue{\PfCGraineAAfficher}%
    \BuildQuatridoCreation{\PfCListeQuatMel}{\PfCListeQuatRotCol}{\PfCListeQuatRotLig}%
    \ifemptyKV[Quatrido]{Graine}{}{\PfCGraineAlea{\PfCGraineRetenue}}%
      \PfCQuadridoCibleSeules%
    \ifboolKV[Quatrido]{Potentiel}{%
      \PfCQuadridoCiblePotentielles%
      \setsepchar{,}\ignoreemptyitems%
      \readlist*\ListeQuatridoSolutions{\PfCSolutionQuatridoRemove}%
      \reademptyitems%
      Au minimum, les cibles potentielles de cette grille sont : \xintFor* ##1 in{\xintSeq{1}{\ListeQuatridoSolutionslen}}\do{%
        \ListeQuatridoSolutions[##1]\xintifForLast{.}{, }%
      }%
    }{}%
    }%
    }%
  }{%
%    \BuildQuatrido{#2}%
  }%
}%

\ExplSyntaxOn
\NewDocumentCommand\PfCQuadridoCiblePotentielles{}{%
  \openin\myread=PfCQuatridoSolution.tex
  \read\myread to \PfCSolutionQuatrido
  \clist_set:Ne \l_tmpa_clist {\PfCSolutionQuatrido}%
  \clist_remove_duplicates:N \l_tmpa_clist
  \clist_sort:Nn \l_tmpa_clist
  {
    \str_compare:nNnTF { ##1 } > { ##2 }
    { \sort_return_swapped: }
    { \sort_return_same: }
  }
  \edef\PfCSolutionQuatridoRemove{\clist_use:N \l_tmpa_clist}
}%
\NewDocumentCommand\PfCQuadridoCibleSeules{}{%
  \openin\myread=PfCQuatridoSolutionCiblesSeules.tex
  \read\myread to \PfCSolutionQuatridoCiblesSeules
  \clist_set:Ne \l_tmpa_clist {\PfCSolutionQuatridoCiblesSeules}%
  \clist_remove_duplicates:N \l_tmpa_clist
  \clist_sort:Nn \l_tmpa_clist
  {
    \str_compare:nNnTF { ##1 } > { ##2 }
    { \sort_return_swapped: }
    { \sort_return_same: }
  }
  \xdef\PfCSolutionQuatridoCiblesSeulesRemove{\clist_use:N \l_tmpa_clist}
}%
\ExplSyntaxOff

\NewDocumentCommand\BuildQuatridoCreation{mmm}{%
  \mplibforcehmode%
  \mplibnumbersystem{double}%
  \begin{mplibcode}
    u:=\useKV[Quatrido]{Echelle}*1cm;
    boolean Solution,Cibles,RetourCible,Titre,Indications,RetourCiblage;
    Indications:=\useKV[Quatrido]{Indications};
    RetourCible=false;
    RetourCiblage=false;
    \ifemptyKV[Quatrido]{Cible}{Cibles=false;}{Cibles=true;ValeurCible=\useKV[Quatrido]{Cible};}%
    \ifemptyKV[Quatrido]{Titre}{Titre=false;}{Titre=true;}%
    nbsoltrouvees=0;
    if Cibles:
      vardef TestCible=
%        if Cible[nbcible]=ValeurCible:
          RetourCible:=true;
          SensRetenu:=sensparcours;
          AfficheOp:=RetiensOp;
          nbsoltrouvees:=nbsoltrouvees+1;
          write decimal(PfCQuatridoAbscisse) to "PfCQuatridoSolutionCible.tex";
          write decimal(PfCQuatridoOrdonnee) to "PfCQuatridoSolutionCible.tex";
          write AfficheOp to "PfCQuatridoSolutionCible.tex";
        %else:
        %  RetourCible:=false;
%        fi;
      enddef;
    else:
      def TestCible=enddef;
    fi;
    pair A[][],Pind[];
    numeric M[][],Mrotcol[][],Mrotlig[][],Mfinal[][];
    path Case;
    Case=unitsquare scaled u;
    largeur=0;
    for p_=#1:
      M[0][largeur]=p_;
      largeur:=largeur+1;
    endfor;
    largeura:=largeur-1;
    % Reperage horizontal et vertical
    for k=1 upto largeur:
      label.top(TEX(decimal(k)),u*((k-1),0.5));
      label.lft(TEX("\setcounter{PfCTrash}{"&decimal(k)&"}\Alph{PfCTrash}"),u*(-0.5,-(k-1)));
    endfor;
    % Titre
    if Titre:
    label(TEX("\Huge\useKV[Quatrido]{Titre}"),u*(largeura/2,2));
    fi;
    % Tracé du terrain de jeu
    for k=0 upto largeura:
      for l=0 upto largeura:
        A[k][l]=u*(l,-k);
        trace Case shifted (A[k][l]-center Case);
%        label.lft(TEX("\tiny"&decimal(M[0][l])),A[k][l]);
      endfor;
    endfor;
%    dotlabel("",(0,0));  
    % On crée les lignes par rotations circulaires des colonnes
    klig:=0;  
    for p_=#2:
      for k=0 upto largeura:
        Mrotlig[klig][k]=M[0][(k+p_-1) mod largeur];
%        label.top(TEX("\tiny"&decimal(Mrotlig[klig][k])),A[klig][k]);
      endfor;
      klig:=klig+1;  
    endfor;
    % On permute les lignes :)
    kcol:=0;  
    for p_=#3:
      for k=0 upto largeura:
        Mfinal[kcol][k]=Mrotlig[p_-1][k];
        Num[kcol][k]=Mfinal[kcol][k];
        % label.rt(TEX("\tiny"&decimal(Mfinal[kcol][k])),A[kcol][k]);
%        if Solution:
%          drawoptions(withcolor CoulSol);
          label(TEX(decimal(Mfinal[kcol][k])),A[kcol][k]);
%        fi;
      endfor;
      kcol:=kcol+1;
    endfor;
    % La recherche des cibles
    numeric Cible[],Quantite[];
    nbcible=0;
    string RetiensOp,AfficheOp;
    %
    if Cibles:
      vardef TestCiblage=
        RetourCiblage:=false;
        if Ciblage=ValeurCible:
          RetourCiblage:=true;
        fi;
      enddef;
    else:
      vardef TestCiblage=
        RetourCiblage:=false;
        if (Ciblage>9) and (Ciblage<70):
          RetourCiblage:=true;
        fi;
      enddef;
    fi;
    %
    vardef Test(expr aa,bb,cc,dd)=
      Ciblage:=aa+bb+cc+dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa+bb+cc+dd;
        RetiensOp:="$"&decimal(aa)&"+"&decimal(bb)&"+"&decimal(cc)&"+"&decimal(dd)&"$";
        TestCible; 
        if unknown Quantite[Cible[nbcible]]:
          Quantite[Cible[nbcible]]=1;
        else:
          Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=aa+bb+cc-dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa+bb+cc-dd;
        RetiensOp:="$"&decimal(aa)&"+"&decimal(bb)&"+"&decimal(cc)&"-"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
          Quantite[Cible[nbcible]]=1;
        else:
          Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=aa+bb-cc-dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa+bb-cc-dd;
        RetiensOp:="$"&decimal(aa)&"+"&decimal(bb)&"-"&decimal(cc)&"-"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
          Quantite[Cible[nbcible]]=1;
        else:
          Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
         fi;
      fi;
      Ciblage:=aa-bb+cc-dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa-bb+cc-dd;
        RetiensOp:="$"&decimal(aa)&"-"&decimal(bb)&"+"&decimal(cc)&"-"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=aa-bb-cc+dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa-bb-cc+dd;
        RetiensOp:="$"&decimal(aa)&"-"&decimal(bb)&"-"&decimal(cc)&"+"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=aa*bb+cc+dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa*bb+cc+dd;
        RetiensOp:="$"&decimal(aa)&"\times"&decimal(bb)&"+"&decimal(cc)&"+"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=aa+bb*cc+dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa+bb*cc+dd;
        RetiensOp:="$"&decimal(aa)&"+"&decimal(bb)&"\times"&decimal(cc)&"+"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=aa*bb+cc*dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa*bb+cc*dd;
        RetiensOp:="$"&decimal(aa)&"\times"&decimal(bb)&"+"&decimal(cc)&"\times"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=aa*(bb+cc)*dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa*(bb+cc)*dd;% Mistral ko
        RetiensOp:="$"&decimal(aa)&"\times("&decimal(bb)&"+"&decimal(cc)&")\times"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=(aa+bb)*(cc-dd);
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=(aa+bb)*(cc-dd);
        RetiensOp:="$("&decimal(aa)&"+"&decimal(bb)&")\times("&decimal(cc)&"-"&decimal(dd)&")$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=(aa+bb)*(cc+dd);
      TestCiblage;
      if RetourCiblage:
      nbcible:=nbcible+1;
        Cible[nbcible]=(aa+bb)*(cc+dd);
        RetiensOp:="$("&decimal(aa)&"+"&decimal(bb)&")\times("&decimal(cc)&"+"&decimal(dd)&")$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;  
      fi;
      Ciblage:=aa*(bb-cc)*dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa*(bb-cc)*dd;%Mistral ko
        RetiensOp:="$"&decimal(aa)&"\times("&decimal(bb)&"-"&decimal(cc)&")\times"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=(aa*bb+cc)*dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=(aa*bb+cc)*dd;% M KO
        RetiensOp:="$("&decimal(aa)&"\times"&decimal(bb)&"+"&decimal(cc)&")\times"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=(aa*bb-cc)*dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=(aa*bb-cc)*dd;% M KO
        RetiensOp:="$("&decimal(aa)&"\times"&decimal(bb)&"-"&decimal(cc)&")\times"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=aa*(bb+cc*dd);
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa*(bb+cc*dd);% M KO
        RetiensOp:="$"&decimal(aa)&"\times("&decimal(bb)&"+"&decimal(cc)&"\times"&decimal(dd)&")$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=aa*bb*cc+dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa*bb*cc+dd;
        RetiensOp:="$"&decimal(aa)&"\times"&decimal(bb)&"\times"&decimal(cc)&"+"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=aa*bb*cc*dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa*bb*cc*dd;%M KO
        RetiensOp:="$"&decimal(aa)&"\times"&decimal(bb)&"\times"&decimal(cc)&"\times"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=aa*bb+cc-dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa*bb+cc-dd;
        RetiensOp:="$"&decimal(aa)&"\times"&decimal(bb)&"+"&decimal(cc)&"-"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=aa+bb*cc-dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa+bb*cc-dd;
        RetiensOp:="$"&decimal(aa)&"+"&decimal(bb)&"\times"&decimal(cc)&"-"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
        fi;
        Ciblage:=aa*bb-cc*dd;
        TestCiblage;
        if RetourCiblage:
          nbcible:=nbcible+1;
          Cible[nbcible]=aa*bb-cc*dd;
          RetiensOp:="$"&decimal(aa)&"\times"&decimal(bb)&"-"&decimal(cc)&"\times"&decimal(dd)&"$";
          TestCible;
          if unknown Quantite[Cible[nbcible]]:
          Quantite[Cible[nbcible]]=1;
          else:
          Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
          fi;
      fi;
      Ciblage:=aa*bb*cc-dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa*bb*cc-dd;
        RetiensOp:="$"&decimal(aa)&"\times"&decimal(bb)&"\times"&decimal(cc)&"-"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=aa*bb*(cc-dd);
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa*bb*(cc-dd);%M KO
        RetiensOp:="$"&decimal(aa)&"\times"&decimal(bb)&"\times("&decimal(cc)&"-"&decimal(dd)&")$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=aa+bb-cc+dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa+bb-cc+dd;
        RetiensOp:="$"&decimal(aa)&"+"&decimal(bb)&"-"&decimal(cc)&"+"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=aa-bb+cc+dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa-bb+cc+dd;%
        RetiensOp:="$"&decimal(aa)&"-"&decimal(bb)&"+"&decimal(cc)&"+"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=aa*bb-cc+dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa*bb-cc+dd;
        RetiensOp:="$"&decimal(aa)&"\times"&decimal(bb)&"-"&decimal(cc)&"+"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=aa*bb-cc-dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa*bb-cc-dd;
        RetiensOp:="$"&decimal(aa)&"\times"&decimal(bb)&"-"&decimal(cc)&"-"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=(aa+bb)*cc+dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=(aa+bb)*cc+dd;
        RetiensOp:="$("&decimal(aa)&"+"&decimal(bb)&")\times"&decimal(cc)&"+"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=(aa+bb)*cc-dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=(aa+bb)*cc-dd;
        RetiensOp:="$("&decimal(aa)&"+"&decimal(bb)&")\times"&decimal(cc)&"-"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=(aa-bb)*cc+dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=(aa-bb)*cc+dd;
        RetiensOp:="$("&decimal(aa)&"-"&decimal(bb)&")\times"&decimal(cc)&"+"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=(aa-bb)*cc-dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=(aa-bb)*cc-dd;
        RetiensOp:="$("&decimal(aa)&"-"&decimal(bb)&")\times"&decimal(cc)&"-"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=aa*(bb+cc)+dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa*(bb+cc)+dd;
        RetiensOp:="$"&decimal(aa)&"\times("&decimal(bb)&"+"&decimal(cc)&")+"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=aa*(bb+cc)-dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa*(bb+cc)-dd;
        RetiensOp:="$"&decimal(aa)&"\times("&decimal(bb)&"+"&decimal(cc)&")-"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=aa*(bb-cc)+dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa*(bb-cc)+dd;
        RetiensOp:="$"&decimal(aa)&"\times("&decimal(bb)&"-"&decimal(cc)&")+"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=aa*(bb-cc)-dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa*(bb-cc)-dd;
        RetiensOp:="$"&decimal(aa)&"\times("&decimal(bb)&"-"&decimal(cc)&")-"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=aa+bb+cc*dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa+bb+cc*dd;
        RetiensOp:="$"&decimal(aa)&"+"&decimal(bb)&"+"&decimal(cc)&"\times"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=aa+bb-cc*dd;
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=aa+bb-cc*dd;
        RetiensOp:="$"&decimal(aa)&"+"&decimal(bb)&"-"&decimal(cc)&"\times"&decimal(dd)&"$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
      Ciblage:=(aa-bb)*(cc+dd);
      TestCiblage;
      if RetourCiblage:
        nbcible:=nbcible+1;
        Cible[nbcible]=(aa-bb)*(cc+dd);
        RetiensOp:="$("&decimal(aa)&"-"&decimal(bb)&")\times("&decimal(cc)&"+"&decimal(dd)&")$";
        TestCible;
        if unknown Quantite[Cible[nbcible]]:
        Quantite[Cible[nbcible]]=1;
        else:
        Quantite[Cible[nbcible]]:=Quantite[Cible[nbcible]]+1;
        fi;
      fi;
    enddef;
    decalexemple:=0;
    NBExemples:=0;
    % Tests verticaux
    numcible=0;
     for l=0 upto largeura:
       for k=0 upto (largeura-3):
         PfCQuatridoAbscisse:=l+1;
         PfCQuatridoOrdonnee:=k+1;
         sensparcours:=1;
         Test(Mfinal[k][l],Mfinal[k+1][l],Mfinal[k+2][l],Mfinal[k+3][l]);
         sensparcours:=2;
         PfCQuatridoAbscisse:=l+1;
         PfCQuatridoOrdonnee:=k+3+1;
         Test(Mfinal[k+3][l],Mfinal[k+2][l],Mfinal[k+1][l],Mfinal[k][l]);
         if RetourCible:
           if numcible=0:
             drawoptions(withcolor blue);
             if Indications:
             if SensRetenu=1:
               PfCQuatridoAbscisse:=l+1;
               PfCQuatridoOrdonnee:=k+1;
               dotlabel("",1/10[A[k][l],A[k+1][l]] shifted(u*(0.25,0)));
               drawarrow (chemin(1/10[A[k][l],A[k+1][l]],9/10[A[k+2][l],A[k+3][l]])) shifted(u*(0.25,0)) withpen pencircle scaled 1.5;
             else:
               PfCQuatridoAbscisse:=l+1;
               PfCQuatridoOrdonnee:=k+3+1;
              dotlabel("",1/10[A[k+3][l],A[k+2][l]] shifted(u*(0.25,0)));
              drawarrow (chemin(1/10[A[k+3][l],A[k+2][l]],9/10[A[k+1][l],A[k][l]])) shifted(u*(0.25,0)) withpen pencircle scaled 1.5;
            fi;
            trace segment(u*(largeur,0),u*(largeur+1,decalexemple)) withpen pencircle scaled 1.5;
            label.rt(TEX(AfficheOp),u*(largeur+1,decalexemple));
            else:
              draw (chemin(1/10[A[k+3][l],A[k+2][l]],9/10[A[k+1][l],A[k][l]])) shifted(u*(0.25,0)) withpen pencircle scaled 1.5;
            fi;
            write decimal(1) to "PfCQuatridoExemples.tex";
            write decimal(PfCQuatridoAbscisse) to "PfCQuatridoExemples.tex";
            write decimal(PfCQuatridoOrdonnee) to "PfCQuatridoExemples.tex";
            write AfficheOp to "PfCQuatridoExemples.tex";
            numcible:=1;
            NBExemples:=NBExemples+1;
            drawoptions();
          fi;
        fi;
      endfor;
    endfor;
    % Tests horizontaux
    numcible:=0;
    RetourCible:=false;
    for l=0 upto (largeura-3):
      for k=0 upto largeura:
        PfCQuatridoAbscisse:=l+1;
        PfCQuatridoOrdonnee:=k+1;
        sensparcours:=1;
        Test(Mfinal[k][l],Mfinal[k][l+1],Mfinal[k][l+2],Mfinal[k][l+3]);
        PfCQuatridoAbscisse:=l+3+1;
        PfCQuatridoOrdonnee:=k+1;
        sensparcours:=2;
        Test(Mfinal[k][l+3],Mfinal[k][l+2],Mfinal[k][l+1],Mfinal[k][l]);
        if RetourCible:
          if numcible=0:
            decalexemple:=decalexemple-1;
            drawoptions(withcolor red);
            if Indications:
            if SensRetenu=1:
              PfCQuatridoAbscisse:=l+1;
              PfCQuatridoOrdonnee:=k+1;
              dotlabel("",1/10[A[k][l],A[k][l+1]] shifted(u*(0,-0.25)));
              drawarrow (chemin(1/10[A[k][l],A[k][l+1]],9/10[A[k][l+2],A[k][l+3]])) shifted(u*(0,-0.25)) withpen pencircle scaled 1.5;
            else:
              PfCQuatridoAbscisse:=l+3+1;
              PfCQuatridoOrdonnee:=k+1;
              dotlabel("",1/10[A[k][l+3],A[k][l+2]] shifted(u*(0,-0.25)));
              drawarrow (chemin(1/10[A[k][l+3],A[k][l+2]],9/10[A[k][l+1],A[k][l]])) shifted(u*(0,-0.25)) withpen pencircle scaled 1.5;
            fi;
            trace segment(u*(largeur,decalexemple),u*(largeur+1,decalexemple)) withpen pencircle scaled 1.5;
            label.rt(TEX(AfficheOp),u*(largeur+1,decalexemple));
            else:
            draw (chemin(1/10[A[k][l+3],A[k][l+2]],9/10[A[k][l+1],A[k][l]])) shifted(u*(0,-0.25)) withpen pencircle scaled 1.5;
            fi;
            write decimal(2) to "PfCQuatridoExemples.tex";
            write decimal(PfCQuatridoAbscisse) to "PfCQuatridoExemples.tex";
            write decimal(PfCQuatridoOrdonnee) to "PfCQuatridoExemples.tex";
            write AfficheOp to "PfCQuatridoExemples.tex";
            numcible:=1;
            NBExemples:=NBExemples+1;
            drawoptions();
          fi;
        fi;
      endfor;
    endfor;
    % Test Diag descendantes
    numcible:=0;
    RetourCible:=false;
    for l=0 upto (largeura-3):
      for k=0 upto (largeura-3):
        PfCQuatridoAbscisse:=l+1;
        PfCQuatridoOrdonnee:=k+1;
        sensparcours:=1;
        Test(Mfinal[k][l],Mfinal[k+1][l+1],Mfinal[k+2][l+2],Mfinal[k+3][l+3]);
        sensparcours:=2;
        PfCQuatridoAbscisse:=l+3+1;
        PfCQuatridoOrdonnee:=k+3+1;
        Test(Mfinal[k+3][l+3],Mfinal[k+2][l+2],Mfinal[k+1][l+1],Mfinal[k][l]);
        if RetourCible:
          if numcible=0:
            decalexemple:=decalexemple-1;
            drawoptions(withcolor Maroon);
            if Indications:
            if SensRetenu=1:
              PfCQuatridoAbscisse:=l+1;
              PfCQuatridoOrdonnee:=k+1;
              dotlabel("",1/10[A[k][l],A[k+1][l+1]] shifted(u*(0.15,0.15)));
              drawarrow (chemin(1/10[A[k][l],A[k+1][l+1]],9/10[A[k+2][l+2],A[k+3][l+3]])) shifted(u*(0.15,0.15)) withpen pencircle scaled 1.5;
            else:
              PfCQuatridoAbscisse:=l+3+1;
              PfCQuatridoOrdonnee:=k+3+1;
              dotlabel("",1/10[A[k+3][l+3],A[k+2][l+2]] shifted(u*(0.15,0.15)));
              drawarrow (chemin(1/10[A[k+3][l+3],A[k+2][l+2]],9/10[A[k+1][l+1],A[k][l]])) shifted(u*(0.15,0.15)) withpen pencircle scaled 1.5;
            fi;
            trace segment(u*(largeur,decalexemple),u*(largeur+1,decalexemple)) withpen pencircle scaled 1.5;
            label.rt(TEX(AfficheOp),u*(largeur+1,decalexemple));
            else:
            draw (chemin(1/10[A[k+3][l+3],A[k+2][l+2]],9/10[A[k+1][l+1],A[k][l]])) shifted(u*(0.15,0.15)) withpen pencircle scaled 1.5;
            fi;
            write decimal(3) to "PfCQuatridoExemples.tex";
            write decimal(PfCQuatridoAbscisse) to "PfCQuatridoExemples.tex";
            write decimal(PfCQuatridoOrdonnee) to "PfCQuatridoExemples.tex";
            write AfficheOp to "PfCQuatridoExemples.tex";
            numcible:=1;
            NBExemples:=NBExemples+1;
            drawoptions();
          fi;
        fi;
      endfor;
    endfor;
%    % Test Diag montantes
    numcible:=0;
    RetourCible:=false;
    for l=0 upto (largeura-3):
      for k=3 upto largeura:
        sensparcours:=1;
        PfCQuatridoAbscisse:=l+1;
        PfCQuatridoOrdonnee:=k+1;
        Test(Mfinal[k][l],Mfinal[k-1][l+1],Mfinal[k-2][l+2],Mfinal[k-3][l+3]);
        sensparcours:=2;
        PfCQuatridoAbscisse:=l+3+1;
        PfCQuatridoOrdonnee:=k-3+1;
        Test(Mfinal[k-3][l+3],Mfinal[k-2][l+2],Mfinal[k-1][l+1],Mfinal[k][l]);
        if RetourCible:
          if numcible=0:
            decalexemple:=decalexemple-1;
            drawoptions(withcolor DarkGreen);
            if Indications:
            if SensRetenu=1:
              PfCQuatridoAbscisse:=l+1;
              PfCQuatridoOrdonnee:=k+1;
              dotlabel("",1/10[A[k][l],A[k-1][l+1]] shifted(u*(-0.15,0.15)));
              drawarrow (chemin(1/10[A[k][l],A[k-1][l+1]],9/10[A[k-2][l+2],A[k-3][l+3]])) shifted(u*(-0.15,0.15)) withpen pencircle scaled 1.5;
            else:
              PfCQuatridoAbscisse:=l+3+1;
              PfCQuatridoOrdonnee:=k-3+1;
              dotlabel("",1/10[A[k-3][l+3],A[k-2][l+2]] shifted(u*(-0.15,0.15)));
              drawarrow (chemin(1/10[A[k-3][l+3],A[k-2][l+2]],9/10[A[k-1][l+1],A[k][l]])) shifted(u*(-0.15,0.15)) withpen pencircle scaled 1.5;
            fi;
            trace segment(u*(largeur,decalexemple),u*(largeur+1,decalexemple)) withpen pencircle scaled 1.5;
            label.rt(TEX(AfficheOp),u*(largeur+1,decalexemple));
            else:
            draw (chemin(1/10[A[k-3][l+3],A[k-2][l+2]],9/10[A[k-1][l+1],A[k][l]])) shifted(u*(-0.15,0.15)) withpen pencircle scaled 1.5;
            fi;
            write decimal(4) to "PfCQuatridoExemples.tex";
            write decimal(PfCQuatridoAbscisse) to "PfCQuatridoExemples.tex";
            write decimal(PfCQuatridoOrdonnee) to "PfCQuatridoExemples.tex";
            write AfficheOp to "PfCQuatridoExemples.tex";
            numcible:=1;
            NBExemples:=NBExemples+1;
            drawoptions();
          fi;
        fi;
      endfor;
    endfor;
    write EOF to "PfCQuatridoExemples.tex";
    write decimal(NBExemples) to "PfCQuatridoNbExemples.tex";
    write EOF to "PfCQuatridoNbExemples.tex";
    write EOF to "PfCQuatridoSolutionCible.tex";
    write decimal(nbsoltrouvees) to "PfCQuatridoNbSolutionCible.tex";
    write EOF to "PfCQuatridoNbSolutionCible.tex";
    string RetiensLAssemblage,RetiensLAssemblageSolutionsCiblees;
    RetiensLAssemblage="";
    RetiensLAssemblageSolutionsCiblees="";
    for k=1 upto nbcible:
    if (Cible[k]>9) and (Cible[k]<70):
    RetiensLAssemblage:=RetiensLAssemblage&decimal(Cible[k])&" ("&decimal(Quantite[Cible[k]])&"),";
    if Quantite[Cible[k]]>8:
    RetiensLAssemblageSolutionsCiblees:=RetiensLAssemblageSolutionsCiblees&decimal(Cible[k])&",";
    fi;
    fi;
    endfor;
    write RetiensLAssemblage to "PfCQuatridoSolution.tex";
    write EOF to "PfCQuatridoSolution.tex";
    write RetiensLAssemblageSolutionsCiblees to "PfCQuatridoSolutionCiblesSeules.tex";
    write EOF to "PfCQuatridoSolutionCiblesSeules.tex";
  \end{mplibcode}%
  \mplibnumbersystem{scaled}%
}%

\begin{comment}
%aa + bb + cc + dd
%aa + bb + cc - dd
%aa + bb - cc + dd
%aa + bb - cc - dd
%aa - bb + cc + dd
%aa - bb + cc - dd
%aa - bb - cc + dd
%aa - bb - cc - dd
%aa * bb + cc + dd
%aa * bb + cc - dd
%aa * bb - cc + dd
%aa * bb - cc - dd
%aa + bb * cc + dd
%aa + bb * cc - dd
%aa - bb * cc + dd
%aa - bb * cc - dd
%aa * bb * cc + dd
%aa * bb * cc - dd
%(aa + bb) * cc + dd
%(aa + bb) * cc - dd
%(aa - bb) * cc + dd
%(aa - bb) * cc - dd
%aa * (bb + cc) + dd
%aa * (bb + cc) - dd
%aa * (bb - cc) + dd
%aa * (bb - cc) - dd
%aa + bb + cc * dd
%aa + bb - cc * dd
aa - bb + cc * dd
aa - bb - cc * dd
%aa * bb + cc * dd
%aa * bb - cc * dd
%(aa + bb) * (cc + dd)
%(aa + bb) * (cc - dd)
(aa - bb) * (cc + dd)
(aa - bb) * (cc - dd)
\end{comment}