Exercice 3

Exercice 3#

On réalise un programme de gestion des réservations d’un parc d’appareils électriques sans fils. Les appareils sont numérotés de \(0\) à \(n-1\). On représente les réservations par un tableau de type vector<int>.
Il contient \(0\) pour les appareils libres (disponibles à la réservation), \(1\) pour les appareils en charge (non disponibles à la réservation) et un nombre entier strictement supérieur à \(1\) identifiant l’utilisateur pour les appareils réservés (non disponibles à la réservation). Voici par exemple un tableau de réservations pour un parc de dix visseuses dont quatre sont réservées et deux sont en charge :

vector<int> réservations = { 0,3,2,0,8,0,0,8,1,1};

Un deuxième tableau enregistre le dernier niveau de charge connu des appareils sous la forme d’un entier entre 0 (vide) et 9 (complètement chargé). Par exemple, avec le tableau niveauxDeCharge suivant, les appareils 3 et 9 sont chargé à un peu plus de la moitié et aucun appareil n’est vide, ni plein :

vector<int> niveauxDeCharge    = { 2,3,3,5,4,4,4,4,3,5};

Lorsqu’un utilisateur rend un appareil en cours de journée, il libère sa réservation et le niveau de charge de l’appareil est mis à jour à la main selon le niveau de batterie restant pour une réservation ultérieure.

Question 1

Considérons la fonction autonomieGlobale suivante :

int autonomieGlobale (vector<int> niveaux){
    int charge = 0;
    for (int i = 0; i < niveaux.size(); i++) {
        charge += niveaux[i];
    }
    return charge;
}
  1. Quel est le type de l’expression autonomieGlobale(niveauxDeCharge)?

    BEGIN SOLUTION int END SOLUTION

  2. Lors de l’appel autonomieGlobale(niveauxDeCharge), combien de fois la variable interne charge change t-elle de valeur après son initialisation? Pourquoi?

    BEGIN SOLUTION charge est modifié dix fois car l’algorithme parcoure les dix éléments du tableau niveauxDeCharge. END SOLUTION

  3. Modifiez ci-dessus le code de la fonction autonomieGlobale pour utiliser une boucle for each.

  4. On considère l’expression suivante apparaissant dans une fonction main :

    cout << autonomieGlobale({1,2,3,4,5,6,7,8,9})
    

    Cochez la ou les bonnes réponses parmi les cinq proposées ci-dessous :

    1. L’expression calcule l’empreinte carbone du parc d’appareils sur la journée.

    2. Elle affiche 45.

    3. Elle affiche la chaîne de caractères autonomieGlobale({1,2,3,4,5,6,7,8,9}).

    4. Elle affiche 9.

    5. Elle ne compile que si #include <iostream> et using namespace std; la précède.

Question 2

Définissez la fonction documentée et testée ci-dessous.

/** chargeTous rend et met en charge tous les appareils réservés par un utilisateur
 * @param un tableau: le tableau de réservation des appareils
 * @param un entier: l'identifiant de l'utilisateur
 * @return le tableau de réservations mis à jour
 **/
CHECK( chargeTous(réservations, 8) == vector<int>({0,3,2,0,1,0,0,1,1,1}) );
tableau chargeTous(vector<int> réservations, int utilisateur) {
    /// BEGIN SOLUTION
    for ( int i = 0; i < réservations.size(); i++ ) {
        if ( réservations[i] == utilisateur)
            réservations[i] = 1;
    }
    return réservations;
    /// END SOLUTION
}
Question 3

Proposez un nom de fonction plus parlant ainsi qu’une documentation pour la fonction suivante :

/// BEGIN SOLUTION
/** choisisAppareilÀRéserver Renvoie la premier appareil disponible satisfaisant le besoin de l'utilisateur
 * @param réservations: un tableau, les réservations
 * @param niveaux: un tableau, les niveaux de charge
 * @param niveau: un entier, le niveau de charge exigé au minimum
 * @return le numéro de l'appareil, ou -1 si aucun appareil disponible
 **/
/// END SOLUTION

int mystère(vector<int> H , vector<int> C, int N) {
    for ( int i = 0; i< H.size(); i++ ){
        if( H[i] == 0 and C[i] >= N )
            return i;
    }
    return -1;
}

Question 4

Définissez la fonction réserve qui réserve le premier appareil disponible avec un niveau de charge suffisant. Si aucun appareil ne convient, aucune réservation n’est faite.

/** Réserve un appareil pour un utilisateur 
 * @param réservations: un tableau, les réservations d'appareil
 * @param niveaux: un tableau, les niveaux de charge des appareils
 * @param utilisateur: un entier, l'identifiant de l'utilisateur
 * @param niveau: un entier, le niveau de charge exigé
 * @return le tableau des réservations mis à jour
 **/
/// BEGIN SOLUTION
tableau réserve(vector<int> réservations, vector<int> niveaux, int utilisateur, int niveau) {
    int i = mystère(réservations, niveaux, niveau);
    if ( i >= 0 ) {
        réservations[i] = utilisateur;
    }
    return réservations;
}
/// END SOLUTION

Afin d’optimiser la réutilisation des appareils, on souhaite attribuer un appareil de charge minimale mais suffisante pour le besoin demandé. Pour cela, la fonction chargeMin déclarée ci-dessous renvoie l’identifiant d’un tel appareil de numéro minimal, ou \(-1\) si aucun appareil ne convient.

int chargeMin(vector<int> réservations, vector<int> capacités, int niveau);
Question 5

En utilisant les tableaux réservations et niveauxDeCharge définis au début de l’énoncé, écrivez les tests pour cette fonction pour des besoins en niveau de charge de 3, 4, 5 et 6 respectivement.

/// BEGIN SOLUTION
CHECK( chargeMin(réservations, niveauxDeCharge, 6) == -1 );
CHECK( chargeMin(réservations, niveauxDeCharge, 5) ==  3 );
CHECK( chargeMin(réservations, niveauxDeCharge, 4) ==  5 );
CHECK( chargeMin(réservations, niveauxDeCharge, 3) ==  5 );
/// END SOLUTION

On suppose définie la fonction metsÀJourCharge déclarée et testée ci-dessous qui met automatiquement à jour les niveaux de charge de chacun des appareils à disposition dans le parc et laisse inchangé celui des appareils dont la réservation est en cours.

vector<int> metsÀJourCharge( vector<int> reservations, vector<int> charge);
CHECK ( metsÀJourCharge(réservations, niveauxDeCharge)
        == vector<int>( {2,3,3,5,4,4,4,4,9,9} )) ;
CHECK ( metsÀJourCharge({0,0,0,1,1,1,2,2,2}, {0,5,9,0,5,9,0,5,9})
        == vector<int>(  {0,5,9,9,9,9,0,5,9} ) ) ;

En observant le niveau de charge du parc, on définit un seuil de branchement seuilB à partir duquel les appareils disponibles doivent être branchés et un seuil de charge seuilC à partir duquel les appareils redeviennent disponibles.

Question 6

\(\clubsuit\) Définissez ci-dessous la fonction metsÀJourRéservation qui commence par un appel à la fonction metsÀJourCharge puis déclare disponibles à la réservation tous les appareils de charge supérieure à seuilC et en charge tous les appareils de charge inférieure à seuilB qui ne sont pas déjà réservés, comme dans le test qui suit :

/// BEGIN SOLUTION
tableau metsÀJourRéservation(vector<int> réservations, vector<int> niveaux,
                             int seuilC, int seuilB) {
    vector<int> charge = metsÀJourCharge(réservations, niveaux);
    for ( int i = 0; i < réservations.size(); i++ ) {
        if ( réservations[i] == 1
             and charge[i] > seuilC ) {
            réservations[i] = 0;
        }
        if ( réservations[i] == 0
             and charge[i] < seuilB ) {
            réservations[i] = 1;
        }
    }
    return réservations;
}
/// END SOLUTION
CHECK ( metsÀJourRéservation({0,0,0,1,1,1,2,2,2}, {0,5,9,0,5,9,0,5,9}, 2, 3 )
        == vector<int>({1,0,0,0,0,0,2,2,2}) ) ;

Question 7

Pour conserver une trace de l’utilisation des appareils, chaque emprunt et chaque rendu est enregistré sous la forme d’une ligne dans un fichier log.txt. La ligne est formée de l’identifiant de l’utilisateur, du mot emprunte (respectivement rend), du numéro de l’appareil et du niveau de charge de l’appareil lors de l’emprunt (respectivement du rendu). Voici un exemple:

135 emprunte 1 9
120 emprunte 2 9
120 rend 2 5
...

En supposant que le fichier existe et est cohérent, définissez une fonction qui prend en paramètres le nom du fichier et l’identifiant d’un utilisateur et compte le nombre d’appareils que cet utilisateur doit rendre :

/// BEGIN SOLUTION 
int nbARendre (string f, int i){
    int id;
    string action;
    int appareil; 
    int charge; 
    int cumul = 0; 
    ifstream flux.
	flux.open(f);
    while ( flux >> id >> action >> appareil >> charge ) {
        if (id == i)
            if (action == "emprunte") {cumul ++;}
            if (action == "retour"  ) {cumul --;}
        }
    }
    fichier.close();
    return cumul;
}
///END SOLUTION