{************************************************
                 Hugo Eti‚vant
     http://www.multimania.com/cyberzoide/
      e-mail : cyberzoide@multimania.com
      (pour une aide en Turbo Pascal 7.0)
*************************************************}

program tableaux;

uses crt;

const n1=-5; {rang minimum d'un ‚l‚ment de TABLEAU}
      n2=5; {rang maximun du tableau}

type tableau=array[n1..n2] of integer;
{ATTENTION : le type TABLEAU est utilis‚ par tous les sous-programmes}

{
**************************************************************************
**  DESCRIPTION : Dichotomie it‚rative qui renvoit l'indice             **
**  correspondant … la position de l'‚l‚ment entier X dans un tableau   **
**  d'entiers … une seule dimension d'indice variant de N1 … N2.        **
**  ATTENTION : suppose que le tableau est tri‚ dans l'odre croissant ! **
**  EN CAS D'ERREUR : renvoit N2+1 si le tableau ne contient pas X.     **
**                                                                      **
**  SYNTAXE : Dichoto(Tableau,BorneInf,BorneSup,El‚ment);               **
**  avec Tableau:TABLEAU  -> votre tableau de recherche                 **
**       BorneInf:Integer -> indice de la borne inf‚rieure du tableau   **
**       BorneSup:Integer -> indice de la borne sup‚rieure du tableau   **
**       El‚ment:Integer  -> valeur de l'‚l‚ment dont on cherche        **
**                           l'indice par dichotomie                    **
**                                                                      **
**  EXEMPLE :                                                           **
**    x:=Dichoto(mon_tab,-100,100,30);                                  **
**    x prend la valeur de l'indice de la case (ou de l'une des cases)  **
**    du tableau "mon_tab" contenant la valeur 30. Ce tableau est       **
**    consid‚r‚ pour les bornes [-100..100]                             **
**                                                                      **
**  AUTEUR : Hugo ETIEVANT  <cyberzoide@multimania.com>                 **
**  URL : http://www.multimania.com/cyberzoide                          **
**************************************************************************
}
function dichoto(tab:tableau; n1,n2,x:integer):integer;
var test,test1,test2:boolean;  {'TRUE' si ‚l‚ment X trouv‚}
    g,d,m:integer; {pointeurs vers Gauche, Droite ou Milieu de l'intervalle}
begin
test:=false; {initialisation … 'FALSE' par d‚faut}
test1:=(n2-n1)>=0;
test2:=(tab[n1]<=x) and (tab[n2]>=x);
if test1 then
begin
if test2 then  {si X est dans le tableau ordonn‚}
   begin
   g:=n1; d:=n2; {initialisation des bornes Gauche et Droite}
   while (g<=d) and not(test) do
         begin
         m:=(g+d) div 2; {calcul de la borne Milieu}
         if tab[m]=x then  test:=true  {‚l‚ment X trouv‚}
                     else if tab[m]>x then d:=m-1 {changement des bornes}
                                    else g:=m+1;
         end;
   end;
end;
if not(test2) then writeln('Erreur dans <Dichoto> : l''‚l‚ment n''est pas compris entre les extrema du tableau.');
if not(test1) then writeln('Erreur dans <Dichoto> : les bornes du tableau sont invalides.');
if test then dichoto:=m else dichoto:=n2+1; {r‚sultat de la fonction}
end;

{
**************************************************************************
**  DESCRIPTION : Tri it‚ratif d'un tableau d'entiers … une dimension   **
**  dans l'ordre croissant.                                             **
**  NOTE : on peux ne trier qu'un intervalle pr‚cis du tableau !        **
**                                                                      **
**  SYNTAXE : Tri(Tableau,BorneInf,BorneSup);                           **
**  avec Tableau:TABLEAU  -> tableau … trier                            **
**       BorneInf:Integer -> borne inf‚rieure du tableau                **
**       BorneSup:Integer -> borne sup‚rieure du tableau                **
**                                                                      **
**  AUTEUR : Hugo ETIEVANT  <cyberzoide@multimania.com>                 **
**  URL : http://www.multimania.com/cyberzoide                          **
**************************************************************************
}
procedure tri(var tab:tableau; n1,n2:integer);
var i,j,x:integer;
begin
for i:=n1 to n2-1 do  {compare l'‚l‚ment d'indice I ...}
    begin
    for j:=i+1 to n2 do {... … celui d'indice J}
        begin
        if tab[i]>tab[j] then  {permutation des 2 ‚l‚ments}
           begin
           x:=tab[i];
           tab[i]:=tab[j];
           tab[j]:=x;
           end;
        end;
    end;
end;

{
**************************************************************************
**  DESCRIPTION : Initialisation d'un tableau[BorneInf..BorneSup] … une **
**  dimension en donnant soit la valeur z‚ro … toutes les cases soit    **
**  une valeur al‚atoire comprise dans l'intervalle [A..B] indiqu‚ en   **
**  paramŠtre.                                                          **         
**                                                                      **
**  SYNTAXE : Init(Tableau,Boul‚en,BorneInf,BorneSup,RandMin,RandMax);  **
**  avec Tableau:TABLEAU  -> votre tableau … initialiser                **
**       Bool‚en:Boolean  -> TRUE pour mettre … z‚ro                    **
**                           FALSE pour l'initialisation al‚atoire      **
**       BorneInf:Integer -> borne inf‚rieure du tableau                **
**       BorneSup:integer -> borne sup‚rieure du tableau                **
**       RandMin:Integer  -> borne inf‚rieure de l'intervalle al‚atoire **
**       RandMax:Integer  -> borne sup‚rieure de l'intervalle al‚atoire **
**                                                                      **
**  EXEMPLE 1 :                                                         **
**    Init(mon_tab,true,0,100,0,0);                                     **
**    Initialisation … z‚ro du tableau "mon_tab" d'indice [0..100]      **
**  EXEMPLE 2 :                                                         **
**    Init(mon_tab,false,1,10,-20,20);                                  **
**    Initalisation al‚atoire du tableau "mon_tab" d'indice [1..10]     **
**    ces ‚l‚ments entiers nouvellement cr‚‚s appartiennent …           **
**    l'intervalle [-20..20]                                            **             
**                                                                      **
**  AUTEUR : Hugo ETIEVANT  <cyberzoide@multimania.com>                 **
**  URL : http://www.multimania.com/cyberzoide                          **
**************************************************************************
}
procedure init(var tab:tableau; test:boolean; n1,n2,a,b:integer);
var i:integer;
    test1,test2:boolean;
begin
test1:=(n2-n1)>=0;
test2:=(b-a)>=0;
 if (test1 and test2) then
  begin
  if test then for i:=n1 to n2 do tab[i]:=0 {initialisation … z‚ro}
          else
              begin   {initialisation al‚atoire}
              randomize;
              for i:=n1 to n2 do tab[i]:=random(b-a+1)+a;
              end;
  end;
if not(test2) then writeln('Erreur dans <Init> : l''intervalle al‚atoire est invalide.');
if not(test1) then writeln('Erreur dans <Init> : les bornes du tableau sont invalides.');
end;

procedure pause; {pause pour l'affichage}
begin
writeln('Appuyez sur une touche pour continuer...');
repeat until keypressed;
clrscr;
end;

procedure affichage(tab:tableau; n1,n2:integer); {affichage des ‚l‚ments
                                                  du tableau}
var i,j:integer;
begin
if (n2-n1)>=0 then
begin
j:=0;
for i:=n1 to n2 do
    begin
    writeln('Case nø',i,'=',tab[i]);
    inc(j);
    if (j mod 20) =0 then pause;
    end;
end
else writeln('Erreur dans <affichage> : le tableau ne contient aucun ‚l‚ment.');
end;


{
**************************************************************************
**  DESCRIPTION : Suppression d'un ‚l‚ment d'un tableau. La case vide   **
**  qui en r‚sulte prend soit la valeur z‚ro (Boul‚en=TRUE) soit une    **
**  valeur al‚atoire (Boul‚en=FALSE) comprise dans l'intervalle         **
**  [RandMin..RandMax]                                                  **
**                                                                      **
**  SYNTAXE :                                                           **
**    Suppr(Tableau,BorneInf,BorneSup,Rang,Boul‚en,RandMin,RandMax);    **
**  avec Tableau:TABLEAU  -> votre tableau                              **
**       BorneInf:Integer -> borne inf‚rieure du tableau                **
**       BorneSup:integer -> borne sup‚rieure du tableau                **
**       Rang:Integer     -> rang (ou indice) de l'‚l‚ment … supprimer  **
**       Bool‚en:Boolean  -> TRUE pour mettre … z‚ro l'‚l‚ment final    **
**                           vide qui en r‚sulte ou FALSE pour y mettre **
**                           un nombre al‚atoire compris entre RandMin  **
**                           et Randmax                                 **
**       RandMin:Integer  -> borne inf‚rieure de l'intervalle al‚atoire **
**       RandMax:Integer  -> borne sup‚rieure de l'intervalle al‚atoire **
**                                                                      **
**  EXEMPLE 1 :                                                         **
**    Suppr(mon_tab,1,10,5,TRUE,0,0);                                   **
**    Suppression de l'‚l‚ment de rand 5 du tableau "mon_tab" dont les  **
**    bornes sont [1..10]. TRUE signifie que l'espace vide final prend  **
**    z‚ro pour valeur.                                                 **
**  EXEMPLE 2 :                                                         **
**    Suppr(mon_tab,1,10,5,FALSE,-100,100);                             **
**    Suppression de l'‚l‚ment de rand 5 du tableau "mon_tab" dont les  **
**    bornes sont [1..10]. FALSE signifie que l'espace vide final prend **
**    une valeur al‚atoire entiŠre comprise entre -100 et 100.          **
**                                                                      **
**  AUTEUR : Hugo ETIEVANT  <cyberzoide@multimania.com>                 **
**  URL : http://www.multimania.com/cyberzoide                          **
**************************************************************************
}
procedure Suppr(var tab:tableau; n1:integer; n2:integer; rang:integer; test:boolean; a,b:integer);
var i:integer;
begin
if (n2-n1)>=0 then    { s'il y a au moins 1 ‚l‚ment dans le tableau}
begin
if (rang IN [n1..n2]) then {si le rang n'est pas hors du tableau}
   begin
   for i:=rang to (n2-1) do tab[i]:=tab[i+1];
   if test then tab[n2]:=0 {valeur z‚ro ou ...}
           else
               begin      {... ou al‚atoire entre A et B}
               randomize;
               tab[n2]:=random(b-a+1)+a;
               end;
   end
else writeln('Erreur dans <Suppr> : l''indice sp‚cifi‚ est hors du tableau.');
end
else writeln('Erreur dans <Suppr> : le tableau ne contient aucun ‚l‚ment.');
end;

{
**************************************************************************
**  DESCRIPTION : Insertion d'un ‚l‚ment d'un tableau. La case finale   **
**  en trop est tout simplement perdue !                                **
**                                                                      **
**  SYNTAXE : Inser(Tableau,BorneInf,BorneSup,Rang,Valeur);             **
**  avec Tableau:TABLEAU  -> votre tableau                              **
**       BorneInf:Integer -> borne inf‚rieure du tableau                **
**       BorneSup:integer -> borne sup‚rieure du tableau                **
**       Rang:Integer     -> rang (ou indice) de l'‚l‚ment … ins‚rer    **
**       Valeur:Integer   -> valeur du nouvel ‚l‚ment                   **
**                                                                      **
**  EXEMPLE :                                                           **
**    Inser(mon_tab,-10,10,i,sqr(i));                                   **
**    insert dans la tableau "mon_tab" la valeur du carr‚ de "i" …      **
**    l'indice "i". Le tableau ‚tant consid‚r‚ avec les bornes          **
**    [-10..10]                                                         **
**                                                                      **
**  AUTEUR : Hugo ETIEVANT  <cyberzoide@multimania.com>                 **
**  URL : http://www.multimania.com/cyberzoide                          **
**************************************************************************
}
procedure Inser(var tab:tableau; n1:integer; n2:integer; rang,valeur:integer);
var i:integer;
begin
if (rang IN [n1..n2]) then  {si le rang n'est pas en dehors du tableau...}
   begin
   for i:=n2 downto rang do tab[i]:=tab[i-1];
   tab[rang]:=valeur;
   end
else writeln('Erreur dans <Inser> : l''indice sp‚cifi‚ est hors du tableau.');
end;


var tab:tableau;
    x,i:integer;

BEGIN
init(tab,false,n1,n2,0,10); {initialisation al‚atoire (car FALSE)
                             du tableau TAB du rang N1 … N2
                             dans le domaine [0..10] }


tri(tab,n1,n2);  {tri du tableau TAB du rang N1 … N2 }

writeln('---------------');
affichage(tab,n1,n2); {affichage du tableau du rang N1 … N2}
suppr(tab,n1,n2,0,FALSE,200,2000);
inser(tab,n1,n2,0,666);
affichage(tab,n1,n2); {affichage du tableau du rang N1 … N2}
write('Entrez la valeur de l''‚l‚ment … rechercher : ');
readln(x);
writeln('L''indice de l''‚l‚ment ',x,' est ',dichoto(tab,n1,n2,x));

END.