//---------------------------------------------------------------------------
#pragma hdrstop
//---------------------------------------------------------------------------
#pragma argsused
//---------------------------------------------------------------------------
#include <stdio.h>
#include <System.hpp>
#include <SysUtils.hpp>
#include <ShellApi.hpp>
//---------------------------------------------------------------------------
#define NBLETTRES   8
#define NBCHIFFRES 10
//---------------------------------------------------------------------------
#define NEUF "NEUF"
#define DEUX "DEUX"
#define ONZE "ONZE"
//---------------------------------------------------------------------------
const char LettresUtilisees[NBLETTRES]={'D','E','F','N','O','U','X','Z'};
//---------------------------------------------------------------------------
char LettreChiffre[NBCHIFFRES]={'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'};
//---------------------------------------------------------------------------
void VideLettreChiffre()
 {
  for(int i=0; i<NBCHIFFRES; i++)
   LettreChiffre[i]='\0';
 }
//---------------------------------------------------------------------------
bool Point4Respecte(FILE *f, const char Lettre, const int Chiffre, const AnsiString asEspace)
 {
  const AnsiString asFormatMessage="%s%s formant %s ne peut correspondre à %d (Point 4).<BR>\n";

  switch(Lettre)
   {
    case 'E':
     if (Chiffre==1)
      {
       fprintf(f, Format(asFormatMessage, ARRAYOFCONST((asEspace, Lettre, ONZE, Chiffre))).c_str());
       return false;
      }
    case 'U':
     if (Chiffre==2)
      {
       fprintf(f, Format(asFormatMessage, ARRAYOFCONST((asEspace, Lettre, DEUX, Chiffre))).c_str());
       return false;
      }
    case 'F':
     if (Chiffre==9)
      {
       fprintf(f, Format(asFormatMessage, ARRAYOFCONST((asEspace, Lettre, NEUF, Chiffre))).c_str());
       return false;
      }
     break;

    case 'N':
     if (Chiffre==9)
      {
       fprintf(f, Format(asFormatMessage, ARRAYOFCONST((asEspace, Lettre, NEUF, Chiffre))).c_str());
       return false;
      }
    case 'O':
    case 'Z':
     if (Chiffre==1)
      {
       fprintf(f, Format(asFormatMessage, ARRAYOFCONST((asEspace, Lettre, ONZE, Chiffre))).c_str());
       return false;
      }
     break;
    case 'D':
    case 'X':
     if (Chiffre==2)
      {
       fprintf(f, Format(asFormatMessage, ARRAYOFCONST((asEspace, Lettre, DEUX, Chiffre))).c_str());
       return false;
      }
     break;

   }
  return true;
 }
//---------------------------------------------------------------------------
int main(int argc, char* argv[])
{

 const AnsiString asFormatMessagePoint2="&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%d est déjà affecté à %s (Point 2).<BR>\n",
                  asMessagePoint3=      "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Les premières lettres N, D et O ne peuvent être égales à ZÉRO (Point 3).<BR>\n",
                  asNomFichierDemonstration="NEUF+DEUX=ONZE.html",
                  asNomFichierSolutions="9+2=11.txt",
                  asChemin=ExtractFilePath(AnsiString(argv[0]));
 FILE *f=fopen(AnsiString(asChemin+asNomFichierDemonstration).c_str(), "wt");
 FILE *ff=fopen(AnsiString(asChemin+asNomFichierSolutions).c_str(), "wt");
 fprintf(f, "<HTML>\n\
<BODY>\n\
<TT>ÉNONCÉ DU PROBLÈME<BR>\n\
==================<BR>\n\
&nbsp;NEUF<BR>\n\
+DEUX<BR>\n\
-----<BR>\n\
&nbsp;ONZE<BR>\n\
<BR>\n\
1. Chaque lettre correspond à un seul chiffre.<BR>\n\
2. Si deux lettres sont différentes alors elles correspondent chacunes à deux chiffres différents.<BR>\n\
3. Les premiers chiffres sont significatifs.<BR>\n\
4. Si une lettre participe à la formation d'un mot qui est lui-même un nombre composé que d'un même chiffre,<BR>\n\
&nbsp;&nbsp;&nbsp;alors ce chiffre doit être différent de celui qui correspond à la lettre.<BR>\n\
5. Une fois les lettres remplacées par leurs chiffres respectifs, l'opération doit rester juste !<BR>\n\
6. Parmi toutes les solutions trouvées, on ne gardera que celle dont la somme n'aura qu'une possibilité.<BR><BR>\n\
RECHERCHE DES SOLUTIONS<BR>\n\
=======================<BR><BR>\n\
Point 3 => N, D et O ne peuvent correspondre au chiffre 0.<BR>\n\
Point 4 => N, E, U et F ne peuvent correspondre au chiffre 9 (NEUF).<BR>\n\
Point 4 => D, E, U et X ne peuvent correspondre au chiffre 2 (DEUX).<BR>\n\
Point 4 => O, N, Z et E ne peuvent correspondre au chiffre 1 (ONZE formé de 1).<BR>\n\
On choisit d'abord une valeur pour E puis pour U et on voit ce que ça implique...<BR>\n");
 for(int E=0; E<NBCHIFFRES; E++)
  {
   if (!E)
    {
     fprintf(f, "Tout d'abord, si E=0 => 2E>0 (car 2E=N et N>0) => 2U>8 => U>4.<BR>\n");
    }
   fprintf(f, "<BR>\n");
   fprintf(f, Format("On prend E=%d.<BR>\n", ARRAYOFCONST((E))).c_str());
   if (!Point4Respecte(f, 'E', E, "")) continue;
   for(int U=0; U<NBCHIFFRES; U++)
    {
     if ((E==U)||((!E)&&(U<5))) continue;
     fprintf(f, Format("&nbsp;· On prend U=%d.<BR>\n", ARRAYOFCONST((U))).c_str());
     if (!Point4Respecte(f, 'U', U, "&nbsp;&nbsp;&nbsp;")) continue;
     VideLettreChiffre();
     LettreChiffre[E]='E';
     LettreChiffre[U]='U';
     for(bool FPlusXSuperieurA9=false; FPlusXSuperieurA9<=true; FPlusXSuperieurA9++)
      {
       AnsiString asFPlusXEgal=FPlusXSuperieurA9?"F+X=1":"F+X=",
                  asContrainteFPlusX=FPlusXSuperieurA9?"On prend F+X>9 => ":"On prend F+X<10 => ";
       int FPlusX=10*FPlusXSuperieurA9+E;
       fprintf(f, Format("&nbsp;&nbsp;&nbsp;· "+asContrainteFPlusX+asFPlusXEgal+"%d.<BR>\n", ARRAYOFCONST((E))).c_str());
       int Z=(2*U+FPlusXSuperieurA9)%10;
       fprintf(f, Format(FPlusXSuperieurA9?"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2U=1+Z => Z=%d.<BR>\n":"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2U=Z => Z=%d.<BR>\n", ARRAYOFCONST((Z))).c_str());
       if (!Point4Respecte(f, 'Z', Z, "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;")) continue;
       if (LettreChiffre[Z]&&(LettreChiffre[Z]!='Z'))
        {
         fprintf(f, Format( asFormatMessagePoint2, ARRAYOFCONST((Z, AnsiString(LettreChiffre[Z])))).c_str());
         continue;
        }
       else LettreChiffre[Z]='Z';
       bool Retenue2U=(2*U+FPlusXSuperieurA9>9);
       AnsiString asDeuxEPlusRetenue=Retenue2U?"2E+1":"2E";
       int N=(2*E+Retenue2U)%10;
       fprintf(f, Format("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"+asDeuxEPlusRetenue+"=N => N=%d.<BR>\n", ARRAYOFCONST((N))).c_str());
       if (!N)
        {
         fprintf(f, asMessagePoint3.c_str());
         continue;
        }
       if (!Point4Respecte(f, 'N', N, "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;")) continue;
       if (LettreChiffre[N]&&(LettreChiffre[N]!='N'))
        {
         fprintf(f, Format( asFormatMessagePoint2, ARRAYOFCONST((N, AnsiString(LettreChiffre[N])))).c_str());
         continue;
        }
       else LettreChiffre[N]='N';
       bool Retenue2E=(2*E+Retenue2U>9);
       AnsiString asNPlusDPlusRetenue=Retenue2E?"N+D+1":"N+D";
       fprintf(f, Format("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"+asNPlusDPlusRetenue+"=O => O-D=%d.<BR>\n", ARRAYOFCONST((N+Retenue2E))).c_str());
       int OMoinsD=N+Retenue2E;
       for(int F=0; F<NBCHIFFRES; F++)
        {
         int X=FPlusX-F;
         if ((X<0)||(X>9)||
             (F==X)||
             (LettreChiffre[F])||
             (LettreChiffre[X])) continue;
         fprintf(f, Format("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;· On prend F=%d et X=%d.<BR>\n", ARRAYOFCONST((F,X))).c_str());
         if (!Point4Respecte(f, 'F', F, "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;")) continue;
         if (!Point4Respecte(f, 'X', X, "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;")) continue;
         LettreChiffre[F]='F';
         LettreChiffre[X]='X';
         for(int D=0; D<NBCHIFFRES; D++)
          {
           int O=OMoinsD+D;
           if ((O<0)||(O>9)||
               (D==O)||
               (LettreChiffre[D])||
               (LettreChiffre[O])) continue;
           fprintf(f, Format("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;· On prend D=%d; O=%d.<BR>\n", ARRAYOFCONST((D,O))).c_str());
           if (!D)
            {
             fprintf(f, AnsiString("     "+asMessagePoint3).c_str());
             continue;
            }
           if (!O)
            {
             fprintf(f, AnsiString("     "+asMessagePoint3).c_str());
             continue;
            }
           if (!Point4Respecte(f, 'D', D, "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;")) continue;
           if (!Point4Respecte(f, 'O', O, "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;")) continue;
          }
         LettreChiffre[F]='\x0';
         LettreChiffre[X]='\x0';
        }
       LettreChiffre[N]='\x0';
       LettreChiffre[Z]='\x0';
      }
    }
  }
 ShellExecute( NULL, "Open", asNomFichierDemonstration.c_str(), NULL, asChemin.c_str(), SW_SHOWNORMAL);
 ShellExecute( NULL, "Open", asNomFichierSolutions.c_str(),     NULL, asChemin.c_str(), SW_SHOWNORMAL);
 fclose(ff);
 fprintf(f, "\n</BODY></HTML>");
 fclose(f);
 return 0;
}
//---------------------------------------------------------------------------


