Un corrigé pédagogique pour comprendre et justifier vos réponses. Les conseils de rédaction ne constituent pas un barème officiel détaillé.
Application
Usages numériques, émissions et pourcentages d’écart
L’application estime une empreinte mensuelle à partir de quantités d’activités numériques. On utilise exclusivement les coefficients du sujet, exprimés en gCO₂e par unité : ce sont les paramètres de ce modèle pédagogique, pas une estimation actualisée universelle des usages. Les dictionnaires d’utilisateurs peuvent omettre des activités ; les comparaisons considèrent alors une quantité nulle.
| Activité | Coefficient du sujet | Quantité utilisateur 1 | Émission (gCO₂e) |
|---|---|---|---|
emails_simples | 4 par email | 150 | 600 |
emails_pj | 19 par email | 20 | 380 |
streaming_sd | 36 par heure | 10 | 360 |
streaming_hd | 100 par heure | 25 | 2500 |
| recherches | 7 par recherche | 500 | 3500 |
stockage_cloud | 10 parGo et par mois | 15 | 150 |
Le dossier comporte le sujet et les fichiers listés dans les téléchargements. Les codes de départ sont reproduits ci-dessous. Travaillez sur une copie. Les appels professeur signalés dans les questions servent à présenter votre démarche ; vous pouvez aussi demander de l’aide en cas de difficulté.
Code fourni : code_empreinte.py
# Données d'émissions en gCO2e par unité
EMISSIONS = {
'emails_simples': 4, # par email
'emails_pj': 19, # par email avec pièce jointe
'streaming_sd': 36, # par heure
'streaming_hd': 100, # par heure
'recherches': 7, # par recherche
'stockage_cloud': 10 # par Go par mois
}
# Exemples d'utilisateurs pour les tests
utilisateur1 = {
'emails_simples': 150,
'emails_pj': 20,
'streaming_sd': 10,
'streaming_hd': 25,
'recherches': 500,
'stockage_cloud': 15
}
utilisateur2 = {
'streaming_hd': 15,
'emails_simples': 100,
'recherches': 10
}
utilisateur3 = {
'emails_simples': 50,
'emails_pj': 5,
'streaming_sd': 30,
'streaming_hd': 5,
'recherches': 200,
'stockage_cloud': 5
}
utilisateur4 = {
'emails_simples': 100,
'recherches': 50
}
utilisateur5 = {
'emails_simples': 50,
'recherches': 100
}
utilisateur6 = {}
#############################################################################
# Écrire le code de la fonction calculer_empreinte de la question 1 #
#############################################################################
#############################################################################
# Écrire le code de la fonction classer_par_impact de la question 2 #
#############################################################################
#############################################################################
# Fonction fournie pour la question 3 #
#############################################################################
def comparer(u1, u2):
"""Compare les émissions de deux utilisateurs pour toutes les activités.
Renvoie un dictionnaire avec, pour chaque activité, la différence des
émissions (émissions de l’utilisateur 2 moins celles de l’utilisateur 1).
Si une activité est absente chez un utilisateur, on considère que
son émission vaut 0."""
differences = {}
for activite in EMISSIONS:
quantite1 = 0
quantite2 = 0
if activite in u1:
quantite1 = u1[activite]
if activite in u2:
quantite2 = u2[activite]
emission1 = quantite1 * EMISSIONS[activite]
emission2 = quantite2 * EMISSIONS[activite]
differences[activite] = emission2 - emission1
return differences
def test_comparer():
diff = comparer(utilisateur4, utilisateur5)
assert diff['emails_simples'] == -200 # (50-100) * 4
assert diff['recherches'] == 350 # (100-50) * 7
# Ajouter vos tests ci-dessous avec justifications
#############################################################################
# Fonction fournie pour la question 4 #
#############################################################################
def comparer_v2(u1, u2):
"""Compare les émissions de deux utilisateurs pour toutes les activités.
Renvoie un dictionnaire avec, pour chaque activité, l'écart des émissions
sous forme de pourcentage, en proportion de la première émission."""
ecarts = {}
for activite in EMISSIONS:
quantite1 = 0
quantite2 = 0
if activite in u1:
quantite1 = u1[activite]
if activite in u2:
quantite2 = u2[activite]
emission1 = quantite1 * EMISSIONS[activite]
emission2 = quantite2 * EMISSIONS[activite]
ecarts[activite] = (emission2 - emission1)/emission1 * 100
return ecarts
Question 1
#Écrire calculer_empreinte(utilisateur) : renvoyer l’empreinte mensuelle totale entière en gCO₂e. utilisateur 1 doit donner 7490.
Indice
La quantité seule n’est pas une émission.
Comprendre la correction
def calculer_empreinte(utilisateur):
total = 0
for activite, quantite in utilisateur.items():
total += quantite * EMISSIONS[activite]
return totalChaque quantité est multipliée par le coefficient correspondant, puis les contributions s’additionnent. Les données du sujet utilisent des quantités et coefficients entiers, donc le résultat reste entier sans conversion artificielle. Le total de l’utilisateur 1 est 600+380+360+2500+3500+150=7490 gCO₂e. Une activité absente ne contribue pas ; un dictionnaire vide produit 0.
assert calculer_empreinte(utilisateur1) == 7490
assert calculer_empreinte({}) == 0
assert calculer_empreinte({'streaming_hd': 2}) == 200Question 2
#Écrire classer_par_impact : renvoyer trois clés fort, moyen, faible associées aux noms d’activités. Fort si émission≥1000 ; moyen si 200≤émission<1000 ; faible si émission<200. Pour utilisateur 2, attendre fort:[streaming_hd], moyen:[emails_simples], faible:[recherches].
PythonClasser une activité selon son émission réelleÉcrivez votre solution et mettez-la à l’épreuve
Écrivez classer_par_impact(utilisateur). Multipliez la quantité de chaque activité présente par son coefficient dans EMISSIONS, fourni. Classez son nom dans fort pour au moins 1000 gCO₂e, moyen entre 200 inclus et 1000 exclu, faible sous 200. Les trois clés doivent toujours exister avec des listes indépendantes. N’ajoutez pas les activités absentes de l’utilisateur.
def classer_par_impact(utilisateur):
# À vous de jouer
pass
Les cas de test proposés :
- Utilisateur 2 du sujet : Les émissions valent 1500, 400 et 70, et non les seules quantités.
- Exactement 200 : 200 appartient à la catégorie moyenne.
- Exactement 1000 : 1000 appartient à la catégorie forte.
- Juste en dessous des seuils : 49 × 4 = 196 reste faible ; 99 × 10 = 990 reste moyen.
- Une quantité nulle mais présente : Une activité présente à zéro se classe faible, sans ajouter toutes les activités absentes.
- Listes indépendantes pour un utilisateur vide : Créer les trois clés avec une même liste partagerait les ajouts entre catégories.
Indice
Multiplier avant de comparer aux seuils.
Comprendre la correction
def classer_par_impact(utilisateur):
classes = {'fort': [], 'moyen': [], 'faible': []}
for activite, quantite in utilisateur.items():
emission = quantite * EMISSIONS[activite]
if emission >= 1000:
classes['fort'].append(activite)
elif emission >= 200:
classes['moyen'].append(activite)
else:
classes['faible'].append(activite)
return classesOn classe les activités présentes chez l’utilisateur, comme le montre l’exemple. Parcourir toutes les clés de EMISSIONS ajouterait des activités absentes à la catégorie faible et ne correspondrait plus au résultat demandé. Les trois listes doivent être créées séparément. Tester d’abord le seuil le plus élevé permet au elif d’exprimer l’intervalle 200 à 999 sans répéter sa borne supérieure.
assert classer_par_impact(utilisateur2) == {
'fort':['streaming_hd'],'moyen':['emails_simples'],'faible':['recherches']}
assert classer_par_impact({'streaming_hd':2})['moyen'] == ['streaming_hd']
assert classer_par_impact({'streaming_hd':10})['fort'] == ['streaming_hd']Question 3
#Compléter test_comparer avec au moins deux tests pertinents et leur justification. comparer renvoie, pour chaque activité, émission 2−émission 1, avec zéro pour une activité absente.
Comprendre la correction
# Identité : aucune activité ne doit varier.
assert all(v == 0 for v in comparer(utilisateur1,utilisateur1).values())
# Absence chez le premier utilisateur : hausse positive.
assert comparer({}, {'emails_simples':3})['emails_simples'] == 12
# Absence chez le second : disparition, donc différence négative.
assert comparer({'emails_simples':3}, {})['emails_simples'] == -12
# Aucune donnée : les six clés existent, chacune à zéro.
assert comparer({}, {}) == {activite:0 for activite in EMISSIONS}Ces tests vérifient plusieurs aspects distincts : signe, valeurs par défaut, identité et structure du dictionnaire. Le test initial utilisateur 4 vers utilisateur 5 donne déjà−200 pour les emails et 350 pour les recherches. Une différence positive représente une hausse chez le second utilisateur, pas une économie.
Question 4
#Identifier les cas qui font échouer comparer_v 2, où le pourcentage est(émission 2−émission 1)/émission 1×100, et corriger.
Indice
Chercher quand le dénominateur devient nul.
Comprendre la correction
Une activité absente ou de quantité nulle chez le premier utilisateur donne une émission de référence nulle. La division provoque ZeroDivisionError, y compris lorsque les deux émissions sont nulles. Le pourcentage relatif à zéro n’est pas défini : aucune valeur numérique universelle ne peut le remplacer. Nous choisissons explicitement None pour ces cas, afin de ne pas inventer 0% ou 100%.
def comparer_v2(u1, u2):
ecarts = {}
for activite in EMISSIONS:
emission1 = u1.get(activite, 0) * EMISSIONS[activite]
emission2 = u2.get(activite, 0) * EMISSIONS[activite]
if emission1 == 0:
ecarts[activite] = None
else:
ecarts[activite] = (emission2 - emission1) / emission1 * 100
return ecartsassert comparer_v2({}, {'emails_simples':3})['emails_simples'] is None
assert comparer_v2({}, {})['emails_simples'] is None
assert comparer_v2({'emails_simples':3}, {})['emails_simples'] == -100.0
assert comparer_v2({'emails_simples':2},{'emails_simples':3})['emails_simples'] == 50.0Pour une référence non nulle, la formule est inchangée. utilisateur 1 vers utilisateur 2 donne notamment−40% pour le streamingHD et−98% pour les recherches. Un affichage peut traduire None par « référence nulle, pourcentage non défini » et afficher en complément la différence absolue fournie par comparer. Cette convention est un choix documenté de la correction, car le sujet ne fixe pas de valeur de remplacement.
Le dénominateur fixe le point de vue. Passer de 100 à 150 représente +50%, mais revenir de 150 à 100 représente environ −33,33%, car la référence a changé. Les pourcentages ne sont donc pas simplement opposés lorsque l’on échange les utilisateurs, contrairement aux différences absolues. Tester les deux sens aide à vérifier que le programme divise par l’émission du premier utilisateur. Lorsque cette émission est nulle, ce raisonnement n’a plus de base numérique : afficher la différence absolue accompagne utilement la mention de pourcentage indéfini.
Lire un pourcentage sans lui inventer de valeurUn atelier pour expérimenter
Choisissez une réponse puis confrontez votre intuition à l’explication. Vous pouvez modifier vos choix.
Lire les réponses et leurs explications
- Passer de 0 à 12 gCO₂e correspond à…
Un pourcentage relatif non défini.. La variation absolue est 12, mais pas le pourcentage.
- Passer de 12 à 0 gCO₂e correspond à…
−100%.. La référence 12 est non nulle : (0−12)/12=−1.
Appuyez votre explication sur les valeurs et les conditions exactes du programme.
Variation absolue et relative des emailsUn atelier pour expérimenter
Modifiez les quantités mensuelles d’emails simples. Le coefficient reste 4 gCO₂e par email, comme dans le sujet. Explorez surtout une quantité initiale nulle.
Lire le résultat de l’expérience initiale
Variation absolue : 200gCO₂e ; relative : 50.00%.
Le pourcentage divise par la première émission. Le coefficient commun se simplifie lorsque cette référence est non nulle.
| Utilisateur | Quantité | Émission |
|---|---|---|
| 1 | 100 | 400 |
| 2 | 150 | 600 |
Un nombre manquant parce que la formule est indéfinie est plus honnête qu’un pourcentage inventé.
Revoir les notions de cet exercice
Du sujet à la méthode
Votre prochaine séance de révision
- Définir l’unité avant de totaliser ou classer.
- Conserver une différence absolue lorsque la variation relative est indéfinie.
Retrouver ces notions dans d’autres sujets
Toutes les annales de NSI · Le guide pour préparer le bac NSI 2027
Énoncé : sujet 26_BCG_NSI_20 (PDF). Corrigé et explications pédagogiques proposés par Sofien.
