Pages

samedi 29 octobre 2011

Mini projet en langage C : les signaux de fumée


vous savez sûrement que les indiens communiquent à l'aide de petits nuages de fumée. Les nuages de fumée se voient de loin (surtout dans les grandes plaines américaines), et en utilisant plusieurs faiseurs de nuages qui reproduisent les signaux qu'ils observent, un message peut parcourir des dizaines de kilomètres en très peu de temps. Quand on y pense, c'était un moyen de communication plutôt efficace (du temps où il fallait choisir entre de la fumée ou des pigeons).
En fait, le seul vrai problème avec les signaux de fumée, c'est le mauvais temps, qui réduit considérablement la visibilité des signaux.



 
1.Cahier de charge :

Vous êtes le chef de la tribu, et vous souhaitez prévoir précisement le nombre de membres de votre tribu que vous ne pourrez pas joindre les jours de mauvais temps.
Vous disposez d'un plan de la région (une carte 2D) qui indique la position exacte de tous les faiseurs de nuages de votre tribu, dont celui qui se trouve à côté de vous dans le camp principal, et à qui vous dictez les messages à transmettre.
Lorsqu'un faiseur de nuages voit un signal de fumée, il le réémet immédiatement, afin de transmettre le message à d'autres camps.
Grâce aux pouvoirs du grand Chamane de votre tribu, vous disposez de prédictions météo pour les jours qui viennent. Chaque prédiction est donnée sous la forme d'un nombre entier : la distance maximale à laquelle un signal de fumée pourra être vu ce jour là.
Votre objectif est de déterminer, pour chaque jour pour lequel vous disposez de ces prédictions, le nombre de faiseurs de nuages qui ne recevront pas vos messages ce jour là (directement ou indirectement).

Remarque :
 le faiseur de fumée correspondant au camp principal est le premier des faiseurs de fumée que l'on vous donne sur l'entrée standard.
un faiseur de fumée se trouvant exactement à la distance maximale d'un deuxième, voit les signaux de celui-ci (et réciproquement).
LIMITES DE TEMPS ET DE MEMOIRE:
  • Temps     : 1 s sur une machine à 1Ghz.
  • Mémoire : 32000 Ko. 
2. Partie Analyse :                                                              
2.1.Les explications:
L'image ci-dessous représente les positions des 6 faiseurs de nuages de l'exemple, numérotés de 1 à 6,et chaque faiseur il a des coordonnées  X et Y .


2 . 1 .1 .Exemple 1:   (le ciel est dégagé)


le ciel est dégagé, et la distance à laquel un signal peut être vu est de 17km. Le message émis par le faiseur de fumée 1 peut être vu directement par les numéros 2 et 3. Le numéro 4 peut voir le message retransmis par le numéro 2. Le numéro 5 voit alors le message retransmis par le 4. Le 3 et le 5 retransmettent aussi leur message, mais ce n'est pas suffisant pour qu'il soit vu par le faiseur de fumée 6. C'est le seul faiseur de nuages qui ne reçoit pas le message.

2 . 1 .2. Exemple 2:  (le ciel est assez nuageux)

 
le ciel est assez nuageux, et les signaux ne peuvent être vus que jusqu'à une distance de 10km. le numéro 2 et 3 reçoivent le message. Ils le réémet, mais personne d'autre que le 1 ne peut voir ses signaux. Il reste donc 3 faiseurs de nuages qui ne reçoivent rien.

2.2.Analyse du probleme :
2.2.1 .Les objets d'entrées :

N           : le nombre de faiseur de fumée  (2 <= N <= 1 000)                         
X et Y   : se  sont les coordonnées entières ( -65 000 <= X,Y <= 65 000)
M    : est le nombre de jours pour lesquels nous disposons de     prédictions  météorologiques. (0<= M <=10000)                    
Di          : la distance de visibilité pour chaque jour i  ( 0 <= D <= 200000)
 
2.2.2. Les objets de sorties :

Nous devons  afficher le nombre de faiseurs de nuages injoignables  s pour chaque jour i dans l'ordre de l'entrée.

2.2.3. Les objets intermédiares :

T: tableau de taille N pour memorise les faiseur qui ont vus les signaux de fumées.

2.2.4. Les formules :

L'equation d'une cercle de centre (xi , yi) et de rayon r :
(xi – x0)² + (yi – y0)² ≤ r ²

2.3. Commentaire : 

Pour chaque jour i :
On va initialiser un tableau de taille N a 0 sauf  le premier element qu'on va initialiser a 1, car toujours le premier faiseur c'est celui qui va transmettre le premier signal, ce tableau sert a memorise les faiseur qui ont vu les fumées, on affecte la valeur 1 au faiseur qui a recu le message et la valeur 0 au faiseur qui n'a pas vu les fumées.
Apres  on  declanche une boucle repeter – jusqu'à allant de i=0 jusqu'à n et pour chaque element i en va tester est ce que l'element t[i]=1  c-a –dire est ce qu il a déjà recu le message si oui  on  va declencher une autre boucle  repeter-tantque qui va chercher les faiseur qui n'ont pas recu le message et on  teste est ce que leurs coordonnées (X[j],Y[j]) appartiennent au cercle de centre (X[i],Y[i]) et de rayon D[r] on utilise l'equation du cercle qui definie comme suit :
Un point (X[j],Y[j]) appartienne au cercle de centre (X[i],Y[i]) et de rayon D[r] seulement si :
(X[J]- X[i])² + (Y[j] -Y[i])² <=D[r],
si les coordonnées verifie cette equation on va affecter a t[j] la valeur 1   c-a-dire il a recu le message parce qu'il est se trouve au long d'une distance qui le permet de voir les fumées ; et en méme temps en mémorise la position de j la plus petite qu'on a trouver dans une autre variable qui s'appelle  trouve , apres la fin de la boucle repeter –tantque si trouve <i on va revenir a cette position car peut etre que ce faiseur pouvra transmettre leur message a des autres faiseurs qu'on a deppassé dans la boucle repeter-jusqu'à  si tous ces cas ne sont pas verifiés  on va incrimenter le i .

2.4. L'algorithme:


algorithme faiseur_fumee;

var

 

  X,Y,t: tableaux [1 .. 1000] d'entiers long;

  i,j,h,N,r,s,trouve : entiers;

  M    : long entier;

  D    : tableau [1..10000] d'entier long;

  auxi : double;

debut

   repeter

    lire(N);

   jusqu'a(N>=2 et N<=1000);



   pour i<-- 0 a N-1 faire

    repeter

    ecrire('entrez x',i,':');

    lire(X[i]);

    ecrire('entrez y',i,':');

    lire(Y[i]);

    jusqu'a(X[i]>-65000 et X[i]<65000 et Y[i]>-65000 Y[i]< 65000);

   fin pour i



  répéter  

  {

    Ecrire('entrez le nombre de jour pour laquelle vous

       voulez mettre des prédictions météorologiques :');

              

    lire(M);

  }

  jusqu'a(M>=0 et M=<10000);

 

  pour i<-- 0 a M faire

   répéter

    Lire (D[i]);

   jusqu'a (D[i]>=0 et D[i]<= 200000);

  Fin pour i



  Pour r<-- 0 a M-1 faire

   h <--  0;

   auxi<--  (D[r])^2;

    pour i=0 a N faire

     t[i]<-- 0;

    fin pour i

   t[0]<--  1;

   s <--  0;

  

   répéter

    trouve <-- s;                                     

    Si (t[s]=1)             

     Pour j<-- 1 a N

      Si (t[j]=0)                                           

       si (((X[j]-X[s])^2+(Y[j]-Y[s])^2)<=auxi)

         t[j] <--  1;

          Si (trouve>j)

            trouve <--  j;

          Finsi

   

       finsi

      finsi   

     fin pour j

    finsi

 

    Si (s=trouve)

     s <--  s+1;

    Sinon

      s <--  trouve;

    finsi

 

  jusqu'a (s>=N)

 

  pour i<-- 0 a N faire

    si(t[i]=0)

    h <--  h+1;

  fin pour i

 

  ecrire('le nombre de faiseur qui n'ont pas recus le'

           'message est :',h);



 jusqu'a (r>N)



  

Fin

 

3. Partie pratique :

3.1.Declarations des bibliothéques: 

     On va utiliser quatre  bibliothéque :
  <stdio.h>: pour les entrées et les sorties (scanf,printf….).
  <conio.h> : pour la fonction clrscr() qui permet d'effacer  l'ecran.        
 <string.h>: la fonction memset qui remplit  un nombre d' octet avec une   
                      valeur  donner.  
    <math.h>: pour la fonction mathematique  pow qui calcule la  
                       puissance.

 3.2.Declaration des variables:

Les variables
type
L'equivalent en c
X[],Y[],D[],M
Long entier
Long int (%ld)
i,j,h,N,r,s, t[],trouve
          entier
        int (%d)
auxi
double
Double (%lf)

3.3.Lecture des données:

En fait,il y'a deux façon pour lire les données en langage c soit avec l'entrée standard c-a-dire le clavier ou avec des fichiers.

3.3.1.Lecture a partir du clavier:
   
do
  {
    printf("entrez le nombre de faiseur (2<= n <= 1000) :");
    scanf("%d",&N);
  }
 while(N<2 || N>1000);

   for(i=0;i<N;i++)
  {
    do
    {
    printf("x%d=",i+1);
    scanf("%ld",&X[i]);
    printf("y%d=",i+1);
    scanf("%ld",&Y[i]);
    }
    while(X[i]<-65000 || X[i]>65000 || Y[i]<-65000 || Y[i]>65000);
 do
  {
    printf("entrez le nombre de jour pour lesquels vous disposez"
          " de predictions \nmeteorologiques (0<= m <=10000) :");    
    scanf("%ld",&M);
  }
 while(M<0 || M>10000);
 for(i=0;i<M;i++)
    {
    do
     {
     printf("entrez la distance de visibilite pour jour %d"
             :",i+1); 
     scanf("%ld",&D[i]);
     }
    while(D[i]<0 || D[i]>200000);}

    
3.3.2.Lecture a partir d'un fichier:

On suppose que le fichier est déjà créer et toutes les variable sont declaré au debut du programme, donc la lecture des  données a partir de ce fichier  va être comme suit :
   do
    {
     printf("Nom du fichier : ");
     scanf("%s",nom_fichier);
     f1 = fopen(nom_fichier, "r");
     if (!f1)
         printf("\aERREUR: Impossible d'ouvrir "
                "le fichier: %s.\n",nom_fichier);
    }
   while (!f1);
   fscanf(f1,"%d",&N);
   i=0;
   while (i<N)
    {
     fscanf(f1,"%d %d\n",&X[i],&Y[i]);
     i=i+1;
    }
   fscanf(f1,"%d",&M)

   while (!feof(f1))
    {
     fscanf(f1,"%d",&D[i]);
     i=i+1;
    }
   fclose(f1);

3.4.Le programme:

#include <stdio.h>

#include <conio.h>

#include<math.h>

#include<string.h>



int main()

{ long int X[1000],Y[1000],D[10000];

   int i,j,h,N,r,trouve=0,M,t[1000],;

    double auxi;

 

 do

  {

    printf("entrez le nombre de faiseur (2<= n <= 1000) :");

    scanf("%d",&N);

  }

 while(N<2 || N>1000);



   for(i=0;i<N;i++)

  {

    do

    {

    printf("x%d=",i+1);scanf("%ld",&X[i]);

    printf("y%d=",i+1);scanf("%ld",&Y[i]);

    }

    while(X[i]<-65000 || X[i]>65000 || Y[i]<-65000 || Y[i]>65000);

 do

  {

    printf("entrez le nombre de jour pour lesquels vous disposez"

          " de predictions \nmeteorologiques (0<= m <=10000) :");    

    scanf("%ld",&M);

  }

 while(M<0 || M>10000);

 for(i=0;i<M;i++)

    {   

    do

     {

     printf("entrez la distance de visibilite pour jour %d"

             :",i+1); 

     scanf("%ld",&D[i]);

     }

    while(D[i]<0 || D[i]>200000);}



 for(r=0;r<M;r++)

 {h=0;

 auxi=pow(D[r],2);





memset(t,0,N*sizeof(int));

   t[0]=1;

 s=0;

 do

 {

 trouve=s;                                                  

  if(t[s]==1)

  {              

  for(j=1;j<N;j++)

  {

    if(t[j]==0)

    {                                           

    if((pow((X[j]-X[s]),2)+pow((Y[j]-Y[s]),2))<=auxi)

    {

  t[j]=1;

  if(trouve>j)

    trouve=j;

    }

   

   }

  }

 }

 if(s==trouve)

 s++;

 else

 s=trouve;

}

 while(s<N);

  for(i=0;i<N;i++)

  {

    if(t[i]==0)

    h++;

  }

  printf("\n%d",h);

  printf("\n");

  }

  

  return 0;

  }

3.5.Exemple d'execution:





Aucun commentaire:

Enregistrer un commentaire

Partenaires

Computers Blogs

Contactez-nous

Nom

E-mail *

Message *

Tous droits resérvés-www.exercices-corriges.com Seo Blogger Templates