/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        C O M B I N A I S O N S   D E   Q U A T R E   N O M B R E S  :                                                             */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*        Author of '$xtc/combinaisons.01$vv$c' :                                                                                    */
/*                                                                                                                                   */
/*                    Jean-Francois Colonna (LACTAMME, 20140704120117).                                                              */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

#include  "INCLUDES.01.I"

extern    double    pow();

#define   RESULTAT_ATTENDU                                                                                                              \
                    24

#define   nNOMBRES                                                                                                                      \
                    4
enum      ListeDesNombres
          {
           N1=1
          ,N2=3
          ,N3=4
          ,N4=6
           };

typedef   struct
          {
          int       Numerateur;
          int       Denominateur;
          }
          Fraction;
                                        /* Definition d'une fraction (nombre rationnel).                                             */
#define   UNITE                                                                                                                         \
                    1
#define   Numer(fraction)                                                                                                               \
                    (fraction.Numerateur)
#define   Denom(fraction)                                                                                                               \
                    (fraction.Denominateur)
#define   EGAL(fraction,numerateur,denominateur)                                                                                        \
                    {                                                                                                                   \
                    Numer(fraction) = numerateur;                                                                                       \
                    Denom(fraction) = denominateur;                                                                                     \
                    }

enum      NomDesOperateurs
          {
           ADDITION=0
          ,SOUSTRACTION
          ,MULTIPLICATION
          ,DIVISION
          ,EXPONENTIATION
          ,nOPERATEURS
           };

#define   UNDEF                                                                                                                         \
                    4444719

int       FaireCommeSiTousLesOperateursEtaientNonCommutatifs=FAUX;
int       AccepterLesMultiplicationsParUn=VRAI;
int       AccepterLesDivisionsParUn=VRAI;
int       AccepterLesExponentiationsParUn=VRAI;
int       PouvoirUtiliserPlusieursFoisChaqueNombre=FAUX;
                                        /* Divers indicateurs de controle du fonctionnement de la fonction 'operation(...)'.         */

int       ListeOperators[nOPERATEURS]=     { ADDITION,      SOUSTRACTION,  MULTIPLICATION,     DIVISION,      EXPONENTIATION      };
int       ListeUtilises[nOPERATEURS]=      { VRAI,          VRAI,          VRAI,               VRAI,          FAUX                };
int       ListeCommutativites[nOPERATEURS]={ VRAI,          FAUX,          VRAI,               FAUX,          FAUX                };
                                        /* Liste des 'nOPERATEURS' operateurs autorises et utilisables 0, 1, 2,... fois.             */

int       ListeNombresEntiers[nNOMBRES]={N1,N2,N3,N4};
Fraction  ListeNombres[nNOMBRES];
                                        /* Liste des 'nNOMBRES' nombres autorises et obligatoires une seule fois...                  */

#define   ri                                                                                                                            \
                    (INDEX0-UNDEF)

Fraction  operation(int xIndex,Fraction x,int IndexOperateur,Fraction y,int yIndex)
                                        /* Fonction calculant :                                                                      */
                                        /*                                                                                           */
                                        /*                  x.operateur.y                                                            */
                                        /*                                                                                           */
                                        /* Les arguments '?Index' indiquent si le nombre correspondant ('x' ou 'y') est l'un         */
                                        /* des nombres de la liste 'ListeNombres' (auquel cas c'est index superieur ou egal a        */
                                        /* 'INDEX0') ou bien un resultat anterieur (auquel cas il est inferieur a 'INDEX0').         */
          {
          Fraction  resultat;
          EGAL(resultat,UNDEF,UNDEF);
                                        /* La valeur 'UNDEF' est choisie de facon a ce qu'une operation la donnant comme resultat    */
                                        /* soit eliminee de la recherche ulterieurement...                                           */

          if        (         (ListeUtilises[IndexOperateur] == VRAI)
                    &&        (         (         (Numer(x) != UNDEF)
                                        &&        (Denom(x) != UNDEF)
                                        &&        (Numer(y) != UNDEF)
                                        &&        (Denom(y) != UNDEF)
                                         )
                               )
                    &&        (         (         (Denom(x) != 0)
                                        &&        (Denom(y) != 0)
                                         )
                               )
                    &&        (         (FaireCommeSiTousLesOperateursEtaientNonCommutatifs == VRAI)
                              ||        (ListeCommutativites[IndexOperateur] == FAUX)
                                        /* Cas ou l'operateur ne commute pas.                                                        */
                              ||        (         (ListeCommutativites[IndexOperateur] == VRAI)
                                        &&        (         (xIndex < INDEX0)
                                                  ||        (yIndex < INDEX0)
                                                   )
                                         )
                                        /* Cas ou l'operateur commute et porte sur deux nombres 'x' et 'y' dont l'un au moins des    */
                                        /* deux n'est pas elementaire.                                                               */
                              ||        (         (ListeCommutativites[IndexOperateur] == VRAI)
                                        &&        (         (xIndex >= INDEX0)
                                                  &&        (yIndex >= INDEX0)
                                                  &&        (xIndex < yIndex)
                                                   )
                                         )
                                        /* Cas ou l'operateur commute et porte sur deux nombres 'x' et 'y' elementaires tel que      */
                                        /* l'index du premier est inferieur a celui du second ; le cas 'xIndex>yIndex' n'a donc      */
                                        /* pas a etre teste a cause donc de la commutativite.                                        */
                               )
                     )
                    {
                    switch    (ListeOperators[IndexOperateur])
                              {
                              case      ADDITION:
                                        {
                                        EGAL(resultat
                                            ,(Numer(x)*Denom(y))+(Numer(y)*Denom(x))
                                            ,(Denom(x)*Denom(y))
                                             );
                                        break;
                                        }
                              case      SOUSTRACTION:
                                        {
                                        EGAL(resultat
                                            ,(Numer(x)*Denom(y))-(Numer(y)*Denom(x))
                                            ,(Denom(x)*Denom(y))
                                             );
                                        break;
                                        }
                              case      MULTIPLICATION:
                                        {
                                        if        (         (         (Numer(x) != Denom(x))
                                                            &&        (Numer(y) != Denom(y))
                                                             )
                                                  ||        (AccepterLesMultiplicationsParUn == VRAI)
                                                   )
                                                  {
                                                  EGAL(resultat
                                                      ,(Numer(x)*Numer(y))
                                                      ,(Denom(x)*Denom(y))
                                                       );
                                                  }
                                        else
                                                  {
                                        /* La multiplication par 1 est indeterminee de facon a l'exclure de la recherche.            */
                                                  }
                                        break;
                                        }
                              case      DIVISION:
                                        {
                                        if        (Numer(y) != 0)
                                                  {
                                                  if        (         (Numer(y) != Denom(y))
                                                            ||        (AccepterLesDivisionsParUn == VRAI)
                                                             )
                                                            {
                                                            EGAL(resultat
                                                                ,(Numer(x)*Denom(y))
                                                                ,(Denom(x)*Numer(y))
                                                                 );
                                                            }
                                                  else
                                                            {
                                        /* La division par 1 est indeterminee de facon a l'exclure de la recherche.                  */
                                                            }
                                                  }
                                        else
                                                  {
                                        /* La division par 0 est indeterminee de facon a l'exclure de la recherche.                  */
                                                  }
                                        break;
                                        }
                              case      EXPONENTIATION:
                                        {
                                        if        (         ((Numer(x)*Denom(x)) > 0)
                                                  &&        ((Numer(y)*Denom(y)) > 0)
                                                   )
                                                  if        (         (Numer(y) != Denom(y))
                                                            ||        (AccepterLesExponentiationsParUn == VRAI)
                                                             )
                                                            {
                                                            EGAL(resultat
                                                                ,pow(Numer(x),Numer(y)/Denom(y))
                                                                ,pow(Denom(x),Numer(y)/Denom(y))
                                                                 );
                                                            }
                                                  else
                                                            {
                                        /* L'exponentiation unitaire est indeterminee de facon a l'exclure de la recherche.          */
                                                            }
                                        else
                                                  {
                                        /* L'exponentiation negative ou nulle est indeterminee de facon a l'exclure de la recherche. */
                                                  }
                                        break;
                                        }
                              default:
                                        {
                                        fprintf(stderr,"L'operateur '%d' n'est pas reconnu\n",ListeOperators[IndexOperateur]);
                                        }
                              }
                    }
          else
                    {
                    }

          return(resultat);
          }

#define   CONVERSION(operateur)                                                                                                         \
                    COND(operateur == ADDITION                                                                                          \
                        ,"+"                                                                                                            \
                        ,COND(operateur == SOUSTRACTION                                                                                 \
                             ,"-"                                                                                                       \
                             ,COND(operateur == MULTIPLICATION                                                                          \
                                  ,"*"                                                                                                  \
                                  ,COND(operateur == DIVISION                                                                           \
                                       ,"/"                                                                                             \
                                       ,COND(operateur == EXPONENTIATION                                                                \
                                            ,"^"                                                                                        \
                                            ,"?"                                                                                        \
                                             )                                                                                          \
                                        )                                                                                               \
                                   )                                                                                                    \
                              )                                                                                                         \
                         )

#define   FORMAT_s__                                                                                                                    \
                    "%s"
#define   FORMAT_ds_                                                                                                                    \
                    "%d%s"
#define   FORMAT_sd_                                                                                                                    \
                    "%s%d"
#define   FORMAT_dsd                                                                                                                    \
                    "(%d%s%d)"

#define   EDITION(sequence)                                                                                                             \
                    {                                                                                                                   \
                    arbre++;                                                                                                            \
                                                                                                                                        \
                    if        (         (Numer(R3) == RESULTAT_ATTENDU)                                                                 \
                              &&        (Denom(R3) == UNITE)                                                                            \
                               )                                                                                                        \
                              {                                                                                                         \
                              printf("arbre %d : ",arbre);                                                                              \
                              sequence;                                                                                                 \
                              printf(" = %d\n",Numer(R3));                                                                              \
                              }                                                                                                         \
                    else                                                                                                                \
                              {                                                                                                         \
                              }                                                                                                         \
                    }

#define   N1                                                                                                                            \
                    ListeNombres[n1]
#define   N2                                                                                                                            \
                    ListeNombres[n2]
#define   N3                                                                                                                            \
                    ListeNombres[n3]
#define   N4                                                                                                                            \
                    ListeNombres[n4]

#define   P1                                                                                                                            \
                    Numer(N1)
#define   P2                                                                                                                            \
                    Numer(N2)
#define   P3                                                                                                                            \
                    Numer(N3)
#define   P4                                                                                                                            \
                    Numer(N4)

#define   O1                                                                                                                            \
                    CONVERSION(ListeOperators[o1])
#define   O2                                                                                                                            \
                    CONVERSION(ListeOperators[o2])
#define   O3                                                                                                                            \
                    CONVERSION(ListeOperators[o3])

main()
          {
          int       n1,n2,n3,n4;
                                        /* Index des 'nNOMBRES' nombres.                                                             */

          for       (n1=INDEX0 ; n1<nNOMBRES ; n1++)
                    {
                    EGAL(N1,ListeNombresEntiers[n1],UNITE);
                                        /* Conversion des nombres entiers N en nombres rationnels N/1.                               */
                    }

          for       (n1=INDEX0 ; n1<nNOMBRES ; n1++)
                    {
                    for       (n2=INDEX0 ; n2<nNOMBRES ; n2++)
                              {
                              for       (n3=INDEX0 ; n3<nNOMBRES ; n3++)
                                        {
                                        for       (n4=INDEX0 ; n4<nNOMBRES ; n4++)
                                                  {
                                                  if        (         (PouvoirUtiliserPlusieursFoisChaqueNombre == VRAI)
                                                            ||        (         (P1 != P2)
                                                                      &&        (P1 != P3)
                                                                      &&        (P1 != P4)
                                                                      &&        (P2 != P3)
                                                                      &&        (P2 != P4)
                                                                      &&        (P3 != P4)
                                                                       )
                                                             )
                                        /* Les 'nNOMBRES' nombres doivent etre tous utilises et ce une seule fois...                 */
                                                            {
                                                            int       o1,o2,o3;
                                        /* Index des 3 (=(nNOMBRES-1)) operateurs utiles (il en faut un de moins que de nombres...). */

                                                            for       (o1=INDEX0 ; o1<nOPERATEURS ; o1++)
                                                                      {
                                                                      for       (o2=INDEX0 ; o2<nOPERATEURS ; o2++)
                                                                                {
                                                                                for       (o3=INDEX0 ; o3<nOPERATEURS ; o3++)
                                                                                          {
                                                                                          int       arbre=0;
                                        /* Identification de l'arbre utilise (1,2,...).                                              */

                                                                                          Fraction  R1,R2,R3;

                                                                                          R1=operation(n1,N1,o1,N2,n2);
                                                                                          R2=operation(n3,N3,o3,N4,n4);
                                                                                          R3=operation(ri,R1,o2,R2,ri);

                                                                                          EDITION(
                                                                                                  {
                                                                                                  printf(FORMAT_dsd,P1,O1,P2);
                                                                                                  printf(FORMAT_s__,O2);
                                                                                                  printf(FORMAT_dsd,P3,O3,P4);
                                                                                                  }
                                                                                                  );
                                        /* Test de l'arbre symetrique ("1") :                                                        */
                                        /*                                                                                           */
                                        /*                  n1      n2   n3      n4                                                  */
                                        /*                    \    /       \    /                                                    */
                                        /*                     \  /         \  /                                                     */
                                        /*                      o1           o3                                                      */
                                        /*                     (R1)         (R2)                                                     */
                                        /*                        \        /                                                         */
                                        /*                         \      /                                                          */
                                        /*                          \    /                                                           */
                                        /*                           \  /                                                            */
                                        /*                            o2                                                             */
                                        /*                           (R3)                                                            */
                                        /*                                                                                           */
                                        /* soit :                                                                                    */
                                        /*                                                                                           */
                                        /*                  arbre 1 : (n1.o1.n2).o2.(n3.o3.n4)                                       */
                                        /*                                                                                           */

                                                                                          R1=operation(n1,N1,o1,N2,n2);
                                                                                          R2=operation(ri,R1,o2,N3,n3);
                                                                                          R3=operation(ri,R2,o3,N4,n4);

                                                                                          EDITION(
                                                                                                  {
                                                                                                  printf("(");
                                                                                                  printf(FORMAT_dsd,P1,O1,P2);
                                                                                                  printf(FORMAT_sd_,O2,P3);
                                                                                                  printf(")");
                                                                                                  printf(FORMAT_sd_,O3,P4);
                                                                                                  }
                                                                                                  );
                                        /* Test du premier arbre dissymetrique ("2") :                                               */
                                        /*                                                                                           */
                                        /*                  n1      n2                                                               */
                                        /*                    \    /                                                                 */
                                        /*                     \  /                                                                  */
                                        /*                      o1     n3                                                            */
                                        /*                     (R1)   /                                                              */
                                        /*                        \  /                                                               */
                                        /*                         o2     n4                                                         */
                                        /*                        (R2)   /                                                           */
                                        /*                           \  /                                                            */
                                        /*                            o3                                                             */
                                        /*                           (R3)                                                            */
                                        /*                                                                                           */
                                        /* soit :                                                                                    */
                                        /*                                                                                           */
                                        /*                  arbre 2 : ((n1.o1.n2).o2.n3).o3.n4                                       */
                                        /*                                                                                           */

                                                                                          R1=operation(n2,N2,o2,N3,n3);
                                                                                          R2=operation(n1,N1,o1,R1,ri);
                                                                                          R3=operation(ri,R2,o3,N4,n4);

                                                                                          EDITION(
                                                                                                  {
                                                                                                  printf("(");
                                                                                                  printf(FORMAT_ds_,P1,O1);
                                                                                                  printf(FORMAT_dsd,P2,O2,P3);
                                                                                                  printf(")");
                                                                                                  printf(FORMAT_sd_,O3,P4);
                                                                                                  }
                                                                                                  );
                                        /* Test du second arbre dissymetrique ("3") :                                                */
                                        /*                                                                                           */
                                        /*                                                                                           */
                                        /*                      n2      n3                                                           */
                                        /*                        \    /                                                             */
                                        /*                         \  /                                                              */
                                        /*                  n1      o2                                                               */
                                        /*                    \    (R1)                                                              */
                                        /*                     \  /                                                                  */
                                        /*                      o1     n4                                                            */
                                        /*                     (R2)   /                                                              */
                                        /*                        \  /                                                               */
                                        /*                         o3                                                                */
                                        /*                        (R3)                                                               */
                                        /*                                                                                           */
                                        /* soit :                                                                                    */
                                        /*                                                                                           */
                                        /*                  arbre 3 : (n1.o1.(n2.o2.n3)).o3.n4                                       */
                                        /*                                                                                           */

                                                                                          R1=operation(n3,N3,o3,N4,n4);
                                                                                          R2=operation(n2,N2,o2,R1,ri);
                                                                                          R3=operation(n1,N1,o1,R2,ri);

                                                                                          EDITION(
                                                                                                  {
                                                                                                  printf(FORMAT_ds_,P1,O1);
                                                                                                  printf("(");
                                                                                                  printf(FORMAT_ds_,P2,O2);
                                                                                                  printf(FORMAT_dsd,P3,O3,P4);
                                                                                                  printf(")");
                                                                                                  }
                                                                                                  );
                                        /* Test du troisieme arbre dissymetrique ("4") :                                             */
                                        /*                                                                                           */
                                        /*                                                                                           */
                                        /*                                                                                           */
                                        /*                                                                                           */
                                        /*                                                                                           */
                                        /*                          n3      n4                                                       */
                                        /*                            \    /                                                         */
                                        /*                             \  /                                                          */
                                        /*                      n2      o3                                                           */
                                        /*                        \    (R1)                                                          */
                                        /*                         \  /                                                              */
                                        /*                  n1      o2                                                               */
                                        /*                    \    (R2)                                                              */
                                        /*                     \  /                                                                  */
                                        /*                      o1                                                                   */
                                        /*                     (R3)                                                                  */
                                        /*                                                                                           */
                                        /* soit :                                                                                    */
                                        /*                                                                                           */
                                        /*                  arbre 4 : n1.o1.(n2.o2.(n3.o3.n4))                                       */
                                        /*                                                                                           */

                                                                                          R1=operation(n2,N2,o2,N3,n3);
                                                                                          R2=operation(ri,R1,o3,N4,n4);
                                                                                          R3=operation(n1,N1,o1,R2,ri);

                                                                                          EDITION(
                                                                                                  {
                                                                                                  printf(FORMAT_ds_,P1,O1);
                                                                                                  printf("(");
                                                                                                  printf(FORMAT_dsd,P2,O2,P3);
                                                                                                  printf(FORMAT_sd_,O3,P4);
                                                                                                  printf(")");
                                                                                                  }
                                                                                                  );
                                        /* Test du quatrieme arbre dissymetrique ("5") :                                             */
                                        /*                                                                                           */
                                        /*                                                                                           */
                                        /*                      n2      n3                                                           */
                                        /*                        \    /                                                             */
                                        /*                         \  /                                                              */
                                        /*                          o2     n4                                                        */
                                        /*                         (R1)   /                                                          */
                                        /*                            \  /                                                           */
                                        /*                      n1     o3                                                            */
                                        /*                       \    (R2)                                                           */
                                        /*                        \  /                                                               */
                                        /*                         o1                                                                */
                                        /*                        (R3)                                                               */
                                        /*                                                                                           */
                                        /* soit :                                                                                    */
                                        /*                                                                                           */
                                        /*                  arbre 5 : n1.o1.((n2.o2.n3).o3.n4)                                       */
                                        /*                                                                                           */
                                                                                          }
                                                                                }
                                                                      }
                                                            }
                                                  else
                                                            {
                                                            }
                                                  }
                                        }
                              }
                    }
          }



Copyright © Jean-François Colonna, 2021-2021.
Copyright © CMAP (Centre de Mathématiques APpliquées) UMR CNRS 7641 / Ecole Polytechnique, 2021-2021.