/* ------------------------------------------*/
/*tableaux de caractères et codes ASCII */
/*LG le 15 octobre 2004*/
/* ------------------------------------------*/

/*bibliotheques et constantes*/
#include <stdio.h>
#include<stdlib.h>
#include<time.h>

#define MAX 20
#define bool int
#define VRAI 1
#define FAUX 0


/* donne un entier au hasard entre binf et bsup comprises*/
int hasard(int binf, int bsup)
{
  int rando = rand();
  return (binf + rando %(bsup - binf +1));
}

/* tirage d'un caractère entre 'a' et 'z'*/
char caract_alea(void)
{
  int h = hasard(97,122);
  return(h);
}

/*initialisation aleatoire du tab de cacracteres*/
void initialise(char tab[MAX])
{
  int i;
  for (i=0;i<MAX;i++)
    {
      tab[i] = caract_alea();
    }
}

/*affichage des donnees du tableau et majuscules*/
void affiche_majuscules(char tab[MAX])
{
  int i;
  for (i=0;i<MAX;i++)
    {
      printf("c[%d] = '%c' code = %d maj = '%c'\n",i,tab[i],tab[i],tab[i]-32);
    }

}

/*affiche le mini par ordre alphabetique */
/*on parcourt le tableau comme un tableau d'entier en gardant le min */
/* ensuite on affiche cet entier sous forme caractère */
void affiche_mini(char tab[MAX])
{
  int i;
  int mini = tab[0];
  for (i=1;i<MAX;i++)
    {
      if (tab[i]<mini)
	{
	  mini = tab[i];
	}
    }
  printf("La plus petite lettre est '%c' \n",mini);
}

/* affiche les occurences des differentes lettres sans tableau*/
/* on remarquera qu'on ne peut faire "cette lettre n'apparait pas" */
/* puisqu'on affiche les indices au fur et à mesure*/
void cherche_une_lettre_et_affiche_occs(char tab[MAX])
{
  int i=0;
  int cpt = 0;
  char c;

  printf("Donnez une lettre\n");
  c = getchar();;
  getchar(); /*pour vider le buffer*/

  printf("On trouve la lettre '%c' dans les cases ",c);

  while (i<MAX)
    {
      if (tab[i] == c)
	{
	  printf(" %d,",i);
	  cpt = cpt+1;
	}
      i = i + 1;
    }
  printf(".\nLa lettre '%c' apparait donc %d fois.\n",c,cpt);
}

/*compte et retourne le nb d'occ du caractere dont le code */
/*est stocké dans la variable c*/
int compte_occ(char tab[MAX], int c)
{
  int i = 0;
  int cpt = 0;
  while (i<MAX)
    {
      if (tab[i] == c)
	{
	  cpt = cpt+1;
	}
      i = i + 1;
    }
  return cpt;
}

/*donne l'indice de la premiere occurrence*/
/*retourne -1 si pas trouve*/
int retourne_premiere_occ(char tab[MAX], int c)
{
  int cpt = 0;
  bool continuer = VRAI;
  int res = -1;

  while (continuer && cpt <MAX)
    {
      if (tab[cpt] == c)
	{
	  res = cpt;
	  continuer = FAUX;
	}
      cpt = cpt+1;
    }
  return res;
}

/*affiche les indices de premieres apparitions de 'a' a 'z'*/
void afficher_premieres_apparitions(char tab[MAX])
{
  int res;
  int i;
  for (i=97;i<=122;i=i+1)
    {
      res = retourne_premiere_occ(tab,i);
      if (res == -1)
	{
	  printf("'%c' n'apparait jamais\n",i);
	}
      else
	{
	  printf("'%c' apparait pour la 1ere fois en position %d \n",i,res);
	}
    }
}

/* initialisation du tableau occurrences*/
/* la case 0 correspond a 'a', ie code = 97 */
/* on parcourt tab, et on maj le tableau occ à chaque coup */
void initialiser_occurrences(char tab[MAX], int occ[26])
{
  int i;
  int lettre;
  /*mise a zero des cases de occurences*/
  for (i=0;i<26;i++)
    {
      occ[i] = 0;
    }

  /*on commence ...*/
  for (i=0;i<MAX;i++)
    {
      lettre = tab[i];
      occ[lettre - 97] = occ[lettre - 97] + 1;
    }
}

/*affichage du contenu du tableau occ*/
/*on suppose que occ a ete initilialise*/
void affiche_occ_avec_tableau(int occ[26])
{
  int i;
  for (i=0;i<26;i++)
    {
      printf("La lettre '%c' apparait %d fois\n",i+97,occ[i]);
    }
}

/*affichage alphabetique */
/*idem on suppose que occ a ete initialise*/
void affiche_alphabetique(int occ[26])
{
  int i;
  int j;
  for (i=0;i<26;i=i+1)
    {
      for (j=0;j<occ[i];j=j+1)
	{
	  printf("%c ,",i+97);
	}
    }
  printf("\n");
}


/*fonction d'impression du tableau tab*/
void afficher_tabc(char tab[MAX])
{
  int i;
  printf("[");
  for (i=0;i<MAX;i=i+1)
    {
      printf("%c ,",tab[i]);
    }
  printf("]\n");
}

/*fonction d'impression du tableau occ*/
void afficher_occ(int occ[26])
{
  int i;
  printf("[");
  for (i=0;i<26;i=i+1)
    {
      printf("%d ,",occ[i]);
    }
  printf("]\n");
}


/*trie le tableau tab */
/*ecrase les lettres de tab a l'aide de occ*/
void trier(char tab[MAX], int occ[26])
{
  int index; /*indice courant dans le tableau tab*/
  index = 0;
  int i;
  int nb_occ;

  for (i=0;i<26;i=i+1)
    {
      nb_occ = occ[i];
      //      printf("%d : %c ; nb occ : %d \n",i,i+97,nb_occ);
      while (nb_occ > 0)
	{
	  tab[index] = i+97;
	  index = index + 1;
	  nb_occ = nb_occ - 1;
	}
    }
}

/*fonction principale*/
int main(void)
{
  char tab[MAX];
  int occurrences[26];

  srand(time(NULL));

  initialise(tab);
  affiche_majuscules(tab);
  affiche_mini(tab);
  cherche_une_lettre_et_affiche_occs(tab);
  afficher_premieres_apparitions(tab);

  initialiser_occurrences(tab,occurrences);
  afficher_occ(occurrences);
  affiche_occ_avec_tableau(occurrences);  
  affiche_alphabetique(occurrences);
  trier(tab,occurrences);
  afficher_tabc(tab);

  return 0;
}
