Correction de l'examen de TD

Exercice 1

Complexité de l'algorithme de recherche dichotomique de la position d'une valeur entière dans un tableau trié de valeurs entières.

Cet algorithme de recherche est construit au moyen d'une simple boucle tant que. Sa complexité sera de l'ordre du nombre d'exécution du contenu de la boucle.
A chaque exécution de la boucle, l'intervalle de recherche voit sa taille divisée par deux. L'algorithme s'exécute jusqu'à ce que cet intervalle soit de taille 1. Le nombre de fois où un nombre n doit être divisé par deux pour arriver à 1 est de l'ordre de log2(n).

Exercice 2

001  Action algo(tab,val)
002    Données-Résultats tab : Tableau [N] 
de entier
003    Données           val : entier
004    Locales g,d : entier           { Indices de parcours gauche et droit }
005            temp : entier          { Variable auxiliaire de permutation }
006    g := 0
007    d := N-1
008    tant que g < d faire
009      tant que g < N et tab[g] <= val faire
010        g := g+1
011      fait
012      tant que d >= 0 et tab[d] > val faire
013        d := d+1
014      fait
015      si g < d alors
016        temp := tab[g]
017        tab[g] := tab[d]
018        tab[d] := temp
019      fsi
020    fait
021  fin action

/* Auteur: Nicolas JANEY          */
/* nicolas.janey@univ-fcomte.fr   */
/* Fevrier 2005                   */

import java.io.*;

public class Complexite {
  static BufferedReader flux = new BufferedReader(new InputStreamReader(System.in));
  
  /* Fonction de creation d'un tableau d'entiers          */
  /* tires au hasard dans l'intervalle [0,99]             */
  /* n : nombre d'entiers du tableau                      */
  /* Resultat fonction : Tableau de n entiers             */
  
  public static int [] creationTableauAleatoire(int n) {
    int [] m = new int[n];
    for ( int i = 0 ; i < n ; i++ )
      m[i] =(int) (Math.random()*(100));
    return(m);
  }

  /* Fonction d'affichage d'un tableau d'entiers          */
  /* t : Tableau d'entier a afficher                      */
  
  public static void affichageTableau(int [] t) {
    for ( int i = 0 ; i < t.length ; i++ )
      System.out.print(" "+t[i]);
    System.out.println();
  }

  /* Fonction de traitement d'un tableau d'entiers vis    */
  /* a vis d'une valeur v de maniere a regrouper dans     */
  /* la partie gauche toutes les valeurs plus petite      */
  /* que v et dans la partie droite toutes les valeurs    */
  /* plus grandes que v                                   */
  /* t : Tableau d'entiers a traiter                      */
  /* v : Valeur de borne a traiter sur le tableau t       */
  
  public static void traitement(int [] t,int v) {
    int g = 0;
    int d = t.length-1;
      System.out.println(g+" "+d);
    while ( g < d ) {
      while ( ( g < t.length ) && ( t[g] <= v ) )
        g++;
      while ( ( d >= 0 ) && ( t[d] > v ) )
        d--;
      System.out.println(g+" "+d);
      if ( g < d ) {
        int temp = t[g]; 
        t[g] = t[d];
        t[d] = temp; } }
  }

  /* Fonction principale                                  */

  public static void main(String [] args) throws IOException {
  /* Initialisation du tableau de l'examen et de val      */
    int [] tab = { 7,8,2,3,6 };
    int val = 4;
  /* Affichage du tableau tab                             */
    System.out.println("Le tableau initial est :");
    affichageTableau(tab);
  /* Traitement                                           */
    traitement(tab,val);
  /* Affichage du resultat de l'execution de l'algorithme */
    System.out.println("Apres traitement :");
    affichageTableau(tab);
  /* Lecture au clavier de la taille du tableau           */
    System.out.print("Taille du tableau : ");
    int n = Integer.valueOf(flux.readLine()).intValue();
  /* Lecture au clavier de la valeur de traitement        */
    System.out.print("Valeur            : ");
    int v = Integer.valueOf(flux.readLine()).intValue();
  /* Creation d'un tableau de n entiers aleatoires        */
    int [] m = creationTableauAleatoire(n);
  /* Affichage de ma matice m                             */
    System.out.println("Le tableau initial est :");
    affichageTableau(m);
  /* Traitement                                           */
    traitement(m,v);
  /* Affichage du resultat de l'execution de l'algorithme */
    System.out.println("Apres traitement :");
    affichageTableau(m);
  }
}

Complexite.java

Question 1

En deux itérations du tant que g < d, deux permutations sont réalisées entre les couples de valeurs d'indice 0 et 3, et 1 et 2 pour obtenir en fin d'exécution le tableau { 3, 2, 8, 7, 6 }.
Cet algorithme réorganise les valeurs d'un tableau de telle manière que toutes les valeurs inférieures à val soient placées dans la partie gauche du tableau et toutes les valeurs supérieures à val soit placées dans la partie gauche. Dans ces deux parties, les valeurs ne sont pas triées.

Question 2

N est le nombre de valeurs du tableau.

Dans le meilleur des cas, aucune permutation ne sera réalisée. Ce cas se produit lorsque la répartition gauche-droite est déjà réalisée dans le tableau initial.
-> L'expression conditionnelle du "si" est évaluée au mieux 1 fois et conduit à 0 affectations.
Pour les deux "tant que" internes, 2*(N+2) expressions conditionnelles sont réalisées ainsi que N affectations.
Pour le "tant que" global, 2 expressions conditionnelles sont réalisées.
On ajoute les 2 affectations initiales.
Au total : N+2 affectations et 2*N+7 tests

Dans le pire des cas, le nombre de permutations est de l'ordre N/2. En effet, la cas le plus défavorable se produit lorsqu'une permutation se produit autant de fois que possible. Or une permutation à l'itération i entraine obligatoirement un déplacement des indices g et d vers les indice g+1 et d-1 à l'itération i+1 car, à cette itération, les valeurs en g et d sont correctement placées. Une permutation à une itération est donc synonyme de convergence d'au minimum 2 valeurs d'indice (exactement 2 dans le cas défavorable) de g et d à l'itération suivante.
-> N/2 permutations au maximum (N nombre de valeurs du tableau).
-> L'expression conditionnelle du "si" est évaluée au pire (N/2)+1 fois et conduit à 3*(N/2) affectations.
Pour les deux "tant que" internes, 2*N+(N/2+1)*2*2 expressions conditionnelles sont réalisées ainsi que N affectations.
Pour le "tant que" global, (N/2)+1+1 expressions conditionnelles sont réalisées.
On ajoute les 2 affectations initiales.
Au total : 3*(N/2)+N+2 affectations et 6*(N/2)+2*N+7 tests

Exercice 3

Question 1

L'ensemble du planning est parcouru (2 boucles "pour"imbriquées). A chaque créneau occupé, une variable compteur entière est incrémentée. A l'issue du parcours, cette variable contient le nombre total de créneaux occupés.
Le pourcentage est obtenu en divisant cette valeur par le nombre total de créneaux du planning (nombre de jours x nombre de créneaux par jour) et en multipliant par 100. On prêtera attention à effectuer les calculs en réel pour éviter les problèmes éventuels liés aux divisions entières.

001  Fonction pourcentageReservation(p) : reel
002    Données p : Tableau [NBJ][NBC] 
de booleen
003    Locale  cpt : entier      { Compteur de creneaux affectes }
004            j,c : entier      { Indices de parcours du planning }
005            res : reel        { Resultat de la fonction }
006    cpt := 0
007    pour j 
de 0 à NBJ-1 faire
008      pour c 
de 0 à NBC-1 faire
009        si p[j][c] alors
010          cpt := cpt+1
011        fsi
012      fait
013    fait
014    res = (cpt*100.0)/(NBJ*NBC)
015    Resultat : res
016  fin fonction

Question 2

La ligne du planning correspondant au jour testé est parcourue à la recherche d'un créneau occupé. Si aucun créneau n'est occupé, vrai est rendu, sinon faux.
Un "tant que" est utilisé de manière à rendre possible l'interuption du parcours lorsqu'un créneau réservé est trouvé.

001  Fonction estLibre(p,j) : booleen
002    Données p : Tableau [NBJ][NBC] 
de booleen
003            j : entier
004    Locales c : entier       { Indice de parcours des creneaux }
005                             { du jour j du planning p }
006            b : booleen      { Resultat de la fonction }
007    c := 0
008    b := vrai
009    tant que b et ( c < NBC ) faire
010      si p[j][c] alors
011        b := faux
012      fsi
013      c := c+1
014    fait
015    Resultat : b
016  fin fonction

Question 3

Une action doit être développée car deux paramètres sont des résultats dont un par ailleurs est en données.
Le compteur entier en paramètre est initialisé à O.
Un "tantque" est utilisé pour parcourir le tableau des demandes de réservation. Deux conditions d'arrêt sont implantées:
- Tous le tableau a été parcouru.
- On a trouvé un -1 en indice 0 de la ligne courante.
Si le créneau correspondant à une demande de réservation est libre, on le réserve, sinon le compteur du nombre de réservation non satisfaites est incrémenté de 1.

001  Action reservation(p,r,cpt) : entier
002    Données-Résultats p : Tableau [NBJ][NBC] 
de booleen
003    Données           r : Tableau [MAX][2] 
de entier
004    Résultats         cpt : entier
005    Locales cpt : entier      { Compteur de reservation non realisees }
006            i : entier        { Indice de parcours du tableau }
007                              { de demandes de reservation }
008    cpt := 0
009    i := 0
010    tant que ( i < MAX ) et ( r[i][0] != -1 ) faire
011      si p[r[i][0]][r[i][1]] alors
012        cpt := cpt+1
013        sinon
014        p[r[i][0]][r[i][1]] := vrai
015      fsi
016      i := i+1
017    fait
018  fin action

Implantation complète en Java

/* Auteur: Nicolas JANEY          */
/* nicolas.janey@univ-fcomte.fr   */
/* Fevrier 2005                   */

import java.io.*;

public class ReservationSalle {
  static BufferedReader flux = new BufferedReader(new InputStreamReader(System.in));
  
  /* Fonction de creation d'un planning                   */
  /* initialise avec des booleens aleatoires              */
  /* nbj : Nombre de jours du planning                    */
  /* nbc : Nombre de creneaux du planning                 */
  /* v : reel coefficient de chance qu'un creneau         */
  /* soit affecte                                         */
  /* Resultat fonction : Matrice de booleens              */

  public static boolean [][] creationPlanningAleatoire(int nbj,int nbc,double v) {
  /* Allocation de la matrice                             */
    boolean [][] p = new boolean[nbj][nbc];
  /* Pour tous les jours du planning a initialiser        */                                    
    for ( int j = 0 ; j < nbj ; j++ )
  /* Pour tous les creneaux du planning a initialiser     */                                    
      for ( int c = 0 ; c < nbc ; c++ )
  /* Initialisation avec un booleen aleatoire             */
        p[j][c] = (Math.random() < v);
  /* Resultat de la fonction                              */
    return(p);
  }

  /* Fonction de creation d'une matrice de reservations   */
  /* initialisee avec des valeurs aleatoires              */
  /* t : Nombre de reservations possibles de la matrice   */
  /* nb : Nombre de reservations effectives               */
  /* nbj : Nombre de jours de reservation                 */
  /* nbc : Nombre de creneaux de reservation              */
  /* Resultat fonction : Matrice d'entiers                */

  public static int [][] creationAleatoireReservations(int t,int nb,int nbj,int nbc) {
  /* Allocation de la matrice                             */
    int [][] r = new int[t][2];
  /* Pour toutes les reservations a initialiser           */                                    
    for ( int i = 0 ; i < nb ; i++ ) {
  /* Initialisation d'une reservation                     */
      r[i][0] =(int) (Math.random()*nbj);
      r[i][1] =(int) (Math.random()*nbc); }
  /* Pour toutes les reservations restantes possibles     */
  /* dans r                                               */
    for ( int i = nb ; i < t ; i++ ) {
  /* Initialisation d'une reservation a libre             */
      r[i][0] = -1; }
  /* Resultat de la fonction                              */
    return(r);
  }

  /* Fonction d'affichage d'un planning                   */
  /* p : Planning a afficher                              */

  public static void affichagePlanning(boolean [][] p) {
  /* Pour tous les jours du planning                      */
    for ( int j = 0 ; j < p.length ; j++ ) {
  /* Pour tous les creneaux du jour courant               */
      for ( int c = 0 ; c < p[j].length ; c++ )
  /* Si le creneau courant du jour courant est libre      */
        if ( p[j][c] )
  /* On affiche sans retour a la ligne le caractere V     */
          System.out.print(" V");
          else
  /* Sinon, on affiche F sans retour a la ligne           */
          System.out.print(" F");
  /* On va a la ligne quand les creaneaux d'un jour       */
  /* sont tous affiches                                   */
      System.out.println(); }
  }

  /* Fonction d'affichage d'une matrice de demandes       */
  /* de reservations                                      */
  /* r : Tableau de reservations a afficher               */

  public static void affichageDemandesReservation(int [][] r) {
  /* Definition et initialisation a 0 d'un indice         */
  /* de parcours de la matrice des reservations           */
    int i = 0;
  /* Tant que tous le tableau des reservations n'est pas  */
  /* parcouru et que la reservation courante est valide   */
    while ( ( i < r.length ) && ( r[i][0] != -1 ) ) {
  /* Affichage de la demande de reservation courante      */
      System.out.println(r[i][0]+" "+r[i][1]);
  /* L'indice de parcours du tableau des demandes         */
  /* de reservation est incremente de 1                   */
      i++; }
  }

  /* Fonction de calcul du pourcentage de reservation     */
  /* de l'ensemble des creneaux d'un planning             */
  /* p : Planning a traiter                               */
  /* Resultat fonction : Reel (pourcentage de creneaux    */
  /* reserves)                                            */

  public static double pourcentageReservation(boolean [][] p) {
  /* Definition et initialisation a 0 d'un compteur       */
    int cpt = 0;
  /* Pour tous les jours du planning                      */
    for ( int j = 0 ; j < p.length ; j++ ) {
  /* Pour tous les creneaux du jour courant               */
      for ( int c = 0 ; c < p[j].length ; c++ )
  /* Si le creneau courant du jour courant est reserve    */
        if ( p[j][c] )
  /* Le compteur est incremente de 1                      */
          cpt++; }
  /* Resultat fonction : Compteur/nombre de creneaux      */
  /* total du planning * 100                              */
    return((double) cpt/p.length/p[0].length*100.0);
  }

  /* Fonction de determination si tous les creneaux       */
  /* d'un jour d'un planning sont libres                  */
  /* p : Planning a traiter                               */
  /* j : Jour a tester                                    */
  /* Resultat fonction : Booleen (vrai si tous            */
  /* sont libres, faux sinon)                             */

  public static boolean estLibre(boolean [][] p,int j) {
  /* Definition et initialisation a 0 d'un indice         */
  /* de parcours des creneaux du jour j du planning p     */
    int c = 0;
  /* Pour tous les creneaux du jour j                     */
    while ( c < p[j].length ) {
  /* Si le creneau c du jour j est reserve                */
      if ( p[j][c] )
  /* La fonction est terminee avec pour resultat faux     */
        return(false);
  /* l'indice de parcours des creneaux est incremente     */
  /* de 1                                                 */
      c++; }
  /* Resultat fonction : Si la fonction ne s'est pas      */
  /* terminee avec pour resultat faux, le resultat        */
  /* est vrai                                             */
    return(true);
  }

  /* Fonction de reservation dans un planning             */
  /* des demandes de reservation stockees dans un tableau */
  /* de reservations                                      */
  /* p : Planning a traiter                               */
  /* r : Tableau des reservations a traiter               */
  /* Resultat fonction : Entier (nombre de reservations   */
  /* non effectuees car non possibles                     */

  public static int reservation(boolean [][] p,int [][] r) {
  /* Definition et initialisation a 0 d'un compteur       */
  /* de reservations non effectuees                       */
    int cpt = 0;
  /* Definition et initialisation a 0 d'un indice         */
  /* de parcours de la matrice des reservations           */
    int i = 0;
  /* Tant que tous le tableau des reservations n'est pas  */
  /* parcouru et que la reservation courante est valide   */
    while ( ( i < r.length ) && ( r[i][0] != -1 ) ) {
  /* Si le creneau correspondant a la demande             */
  /* de reservation courante est deja reserve             */
      if ( p[r[i][0]][r[i][1]] )
  /* Le compteur de reservation est incremente de 1       */
        cpt++;
        else
  /* Sinon, la reservation est effectuee                  */
        p[r[i][0]][r[i][1]] = true;
  /* L'indice de parcours du tableau des demandes         */
  /* de reservation est incremente de 1                   */
      i++; }
  /* Resultat fonction : Entier (Nombre de reservations   */
  /* non effectuees                                       */
    return(cpt);
  }

  /* Fonction principale                                  */

  public static void main(String [] args) throws IOException {
  /* Lecture au clavier du nombre de jours du planning    */
    System.out.print("Nombre de jours             : ");
    int nbj = Integer.valueOf(flux.readLine()).intValue();
  /* Lecture au clavier du nombre de creneaux par jour    */
    System.out.print("Nombre de creneaux par jour : ");
    int nbc = Integer.valueOf(flux.readLine()).intValue();
  /* Lecture au clavier du facteur de reservation         */
    System.out.print("Facteur de reservation      : ");
    double f = Double.valueOf(flux.readLine()).doubleValue();
  /* Creation d'un tableau de n entiers aleatoires        */
    boolean [][] p = creationPlanningAleatoire(nbj,nbc,f);
  /* Affichage du planning                                */
    System.out.println("Le planning initial est :");
    affichagePlanning(p);
  /* Calcul et affichage du pourcentage de reservation    */
    System.out.println("Le pourcentage de reservation est : "+pourcentageReservation(p));
  /* Lecture au clavier du jour a tester                  */
    System.out.print("Jour a tester       : ");
    int j = Integer.valueOf(flux.readLine()).intValue();
  /* Calcul et affichage de la diponibilte entiere        */
  /* d'un jour                                            */
    System.out.println("Le jour "+j+" est libre : "+estLibre(p,j));
  /* Lecture au clavier de la taille du tableau           */
  /* des reservations                                     */
    System.out.print("Taille du tableau       : ");
    int t = Integer.valueOf(flux.readLine()).intValue();
  /* Lecture au clavier du nombre de reservations         */
    System.out.print("Nombre de reservations  : ");
    int nb = Integer.valueOf(flux.readLine()).intValue();
    int [][] re = creationAleatoireReservations(t,nb,nbj,nbc);
  /* Affichage de l'ensemble des demandes de reservation  */
    affichageDemandesReservation(re);
  /* Reservation et affichage du resultat                 */
    System.out.println("Le nombre de reservations non effectuees est : "+reservation(p,re));
  /* Affichage du planning apres reservations             */
    System.out.println("Le planning final est :");
    affichagePlanning(p);
  }
}

ReservationSalle.java

Auteur: Nicolas JANEY
UFR Sciences et Techniques
Université de Besançon
16 Route de Gray, 25030 Besançon
nicolas.janey@univ-fcomte.fr