//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
const AnsiString CA_tiret="-";
const AnsiString CA_nihil="";
const AnsiString CA_espace=" ";
const AnsiString CA_separ="------------------------------";
const AnsiString CA_ajout="Ajout n°";
const AnsiString CA_lien=" : lien ";
const char Cc_espace=' ';
const char Cc_tiret='-';
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// Composants gérés par l'EDI
   TMemo *Memo1;
   TButton *Button1;
   TLabel *Label1;
   void __fastcall Button1Click(TObject *Sender);
   void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
private:	// Déclarations utilisateur
public:		// Déclarations utilisateur
int compteur, niveau;
bool nouveau_lien;
AnsiString A_pred,A_succ;
AnsiString A_pred_syr,A_succ_syr;
AnsiString couple;

// contient l'arborescence en construction
TStringList *SYR;

__fastcall TForm1(TComponent* Owner);

int succ_syr(int);
void suivant();
bool ajout(int,int);
bool ajout10();
void insert(int,int);
void insert10(int,int);
void insert20(int,int);
void insert30(int,int,int);

void Aff_memo();

void traite(AnsiString);

AnsiString traite10(AnsiString);
AnsiString supp_coupl(AnsiString);

void traite_couple();
AnsiString extrait_P(AnsiString);
AnsiString extrait_S(AnsiString);

bool existe_couple(int,int);
bool existe_couple10(int,int);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// Étude sur Syracuse — Gilles Louïse — février 2024
// Création du début de l'arborescence syracusienne
// ne faisant intervenir que les nombres impairs
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
   : TForm(Owner)
{
// Création de la mémoire de l'arborescence
SYR=new TStringList;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
// Crée le début de l'arborescence
for(compteur=1;compteur<=50;compteur++) suivant();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
// Rend la mémoire au système
delete SYR;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//------------------   P R O C É D U R E S   --------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Renvoie le successeur impair unique
// selon la moulinete syracusienne
// du nombre impair n envoyé
int TForm1::succ_syr(int n)
{
n=3*n+1;
do n/=2; while((n%2)==0);
return n;
}
//---------------------------------------------------------------------------
// Calcule le lien suivant dans l'arborescence
void TForm1::suivant()
{
int p,s;
bool b;

// Calcul à partir du début de la liste virtuelle infinie
p=-1;
do
   {
   p+=2;
   s=succ_syr(p);

   // Si le couple p-s est dans l'arborescence,
   // il ne sera pas inséré puisqu'il y est déjà
   // sinon il est candidat pour y être ajouté
   // et c'est ajout10 qui dira
   // si on peut l'insérer quelque part
   if(existe_couple(p,s)) b=false; else b=ajout(p,s);
   }
while(!b);

// Le lien suivant p-s a été détecté
// comme insérable dans l'arborescence,
// donc on l'y insère
insert(p,s);

// Affichage de l'état actuel de l'arborescence
Aff_memo();
}
//---------------------------------------------------------------------------
// Vérifie si l'on peut ajouter le couple p-s dans l'arbosrecence
bool TForm1::ajout(int p, int s)
{
// mémorise le couple envoyé dans les variables générales
// A_pred et A_succ (liste virtuelle infinie)
A_pred=p;
A_succ=s;

// Si l'arborescence est vide, l'ajout peut se faire
//  sinon c'est ajout10 qui le dira
if(SYR->Count==0) return true; else return (ajout10());
}
//---------------------------------------------------------------------------
// On regarde s'il y a dans l'arborescence un couple
// dont le p correspond à A_succ
// (variable générale renseignée à ce stade)
// On sait ici que l'arborescence n'est pas vide
bool TForm1::ajout10()
{
int i;

// Pour chaque ligne de l'arborescence SYR
for(i=0;i<SYR->Count;i++)
   {
   // on traite la ligne i pour y tester les couples présents
   traite(SYR->Strings[i]);

   // si l'on peut placer A_succ dans l'arborescence SYR
   if(nouveau_lien)
      {
      // mémorise le niveau où l'insertion doit se faire,
      // sachant que cette insertion se fait à la ligne suivante
      // de celle actuellement visée par i.
      // Si i pointe la dernière ligne de l'arborescence,
      // on met niveau à -1 pour indiquer
      // la création d'une ligne à la suite de l'arborescence
      // pour y ajouter le couple p-s,
      // sinon l'ajout se fera à la ligne suivante qui existe
      if(i==SYR->Count-1) niveau=-1; else niveau=i+1;

      // sortie de boucle avec vrai pour insérer
      // le couple p-s au bon endroit dans l'arborescence
      return true;
      }
   }

// renvoie faux car on ne peut pas placer A_succ
// en l'état actuel de l'arborescence
return false;
}
//---------------------------------------------------------------------------
// Insère le couple p-s dans l'arborescence
void TForm1::insert(int p, int s)
{
if(SYR->Count==0) insert10(p,s); else insert20(p,s);
}
//---------------------------------------------------------------------------
// ici l'arborescence est vide,
// on y écrit le premier couple p-s donc 1-1
// (mais seul le premier 1 sera affiché
// dans ce cas particulier
// étant donné qu'il s'agit de la racine)
void TForm1::insert10(int p, int s)
{
SYR->Add((AnsiString)p+CA_tiret+s);
}
//---------------------------------------------------------------------------
// Ici on insère le couple p-s
void TForm1::insert20(int p, int s)
{
if(niveau==-1) insert10(p,s); else insert30(niveau,p,s);
}
//---------------------------------------------------------------------------
// insére le couple p-s à la ligne i de SYR
void TForm1::insert30(int i, int p, int s)
{
AnsiString A;

A=SYR->Strings[i];
A=A+CA_espace;
A=A+p;
A=A+CA_tiret;
A=A+s;
SYR->Strings[i]=A;
}
//---------------------------------------------------------------------------
// Affichage de l'arborescence et du couple p-s inséré
void TForm1::Aff_memo()
{
int i;
AnsiString A;

Memo1->Clear();
// affiche l'état actuel de l'arborescence
for(i=0;i<SYR->Count;i++)
   {
   A="Niveau ";
   A=A+i;
   A=A+" : ";
   // cas exceptionnel de la racine et cas général
   if(i==0) A=A+"1"; else A=A+SYR->Strings[i];

   Memo1->Lines->Add(A);
   }
// affichage du lien inséré dans l'arborescence
if(niveau==0)
   {
   A="Ajout ";
   A=A+compteur;
   A=A+" : racine 1";
   }
else
   {
   A="Ajout ";
   A=A+compteur;
   A=A+" : lien ";
   A=A+A_pred;
   A=A+CA_tiret;
   A=A+A_succ;
   A=A+" inséré au niveau ";
   A=A+niveau;
   }
Label1->Caption=A;
Application->ProcessMessages();
}
//---------------------------------------------------------------------------
// traite une ligne de l'arborescence
// renseigne la variable booléenne "nouveau_lien"
// qui dira si un nouveau lien a été détecté
void TForm1::traite(AnsiString A)
{
// pas de lien détecté par défaut
nouveau_lien=false;
do
   {
   // renseigne la variable générale "couple"
   // ainsi que A_pred_syr et A_succ_pred
   // et diminue la chaîne B de ce couple
   // pour qu'elle devienne vide
   A=traite10(A);

   // si un lien est possible ici
   if(A_succ==A_pred_syr)
      {
      // on renseigne la variable générale booléenne "nouveau_lien"
      nouveau_lien=true;

      // A=vide pour forcer la fin de la boucle
      A=CA_nihil;
      }
   }
while(A!=CA_nihil);
}
//---------------------------------------------------------------------------
// cherche le premier couple de l'AnsiString envoyé
// et renvoie la chaîne diminuée de ce couple
AnsiString TForm1::traite10(AnsiString A)
{
// renseigne la variable générale "couple"
// et supprime le couple de la chaîne
// pour qu'elle soit traitée
// jusqu'à ce qu'elle soit vide
A=supp_coupl(A);

// traite la variable générale "couple"
// i.e. extrait A_pred_syr et A_succ_syr
traite_couple();

return A;
}
//---------------------------------------------------------------------------
// Renseigne la variable générale "couple"
// et renvoie la chaîne diminuée de ce couple
AnsiString TForm1::supp_coupl(AnsiString A)
{
int i;
char c;
AnsiString B;

// AnsiString indicé à partir de 1
i=1;

// Ajout d'un espace en fin de chaîne comme délimiteur
A=A+CA_espace;

// chaîne de caractères jusqu'à espace détecté
// contenant les deux nombres p et s du couple
do
   {
   c=A[i];
   A[i++]=Cc_espace;
   B=B+(AnsiString)c;
   }
while(c!=Cc_espace);

couple=B;

// renvoie la chaîne de caractères dont on a supprimé
// les espaces à gauche et à droite s'il y en a
return Trim(A);
}
//---------------------------------------------------------------------------
// Extrait de la variable générale "couple"
// les deux variables générales A_pred_syr et A_succ_syr
void TForm1::traite_couple()
{
A_pred_syr=extrait_P(couple);
A_succ_syr=extrait_S(couple);
}
//---------------------------------------------------------------------------
// renvoie le premier nombre de la variable générale "couple"
AnsiString TForm1::extrait_P(AnsiString A)
{
int i;
char c;
bool b;
AnsiString B;

i=1;
do
   {
   c=A[i++];
   b=(c==Cc_tiret);
   if(!b) B=B+(AnsiString)c;
   }
while(!b);

return B;
}
//---------------------------------------------------------------------------
// renvoie le deuxième nombre de la variable générale "couple"
AnsiString TForm1::extrait_S(AnsiString A)
{
int i;
char c;
bool b;
AnsiString B;

// Ajout d'un espace en fin de chaîne comme délimiteur
A=A+CA_espace;

i=1;
do
   {
   c=A[i++];
   b=(c==Cc_tiret);
   }
while(!b);

do
   {
   c=A[i++];
   b=(c==Cc_espace);
   if(!b) B=B+(AnsiString)c;
   }
while(!b);

return B;
}
//---------------------------------------------------------------------------
// Renvoie vrai si le couple p-s est dans SYR, sinon renvoie faux
bool TForm1::existe_couple(int p, int s)
{
// si SYR est vide, le couple p-s ne s'y trouve pas
// sinon c'est existe_couple10 qui le dira
if(SYR->Count==0) return false; else return(existe_couple10(p,s));
}
//---------------------------------------------------------------------------
// Renvoie vrai si le couple p-s est déjà dans SYR,
// sinon renvoie faux
// SYR est non vide à ce stade
bool TForm1::existe_couple10(int p, int s)
{
int i;
AnsiString A;

// toute l'arborescence dans un seul AnsiString
for(i=0;i<SYR->Count;i++) A=A+SYR->Strings[i]+CA_espace;

do
   {
   // renseigne la variable générale "couple"
   // et supprime le couple de la chaîne
   A=supp_coupl(A);

   // traite la variable générale "couple"
   // i.e. extrait A_pred_syr et A_succ_syr
   traite_couple();

   // renvoie vrai si le couple est détecté dans SYR
   if((p==A_pred_syr) && (s==A_succ_syr)) return true;
   }
while(A!=CA_nihil);

// renvoie faux car le couple p-s ne se trouve pas dans l'arborescence
return false;
}
//---------------------------------------------------------------------------
//---------------------------   F I N   -------------------------------------
//---------------------------------------------------------------------------