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 1Considé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;
}
Quel est le type de l’expression
autonomieGlobale(niveauxDeCharge)
?BEGIN SOLUTION int END SOLUTION
Lors de l’appel
autonomieGlobale(niveauxDeCharge)
, combien de fois la variable internecharge
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 tableauniveauxDeCharge
. END SOLUTIONModifiez ci-dessus le code de la fonction
autonomieGlobale
pour utiliser une bouclefor each
.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 :
L’expression calcule l’empreinte carbone du parc d’appareils sur la journée.
Elle affiche 45.
Elle affiche la chaîne de caractères
autonomieGlobale({1,2,3,4,5,6,7,8,9})
.Elle affiche 9.
Elle ne compile que si
#include <iostream>
etusing namespace std
; la précède.
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
}
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;
}
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);
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.
\(\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}) ) ;
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