Épreuve Pratique 2026

Les 23 sujets officiels — exercices interactifs + guide méthodologique

23
Sujets officiels
1/23
Chance par sujet
~1h
Durée épreuve
16 pts
Sur 20 au bac

Comment réussir l'épreuve pratique

0–5 min
Lire tout
Parcourir les 2 exercices avant d'écrire
5–30 min
Exercice 1
Du plus simple au plus dur
30–55 min
Exercice 2
Même approche
55–60 min
Relecture
Lancer les tests fournis

Structure d'un sujet

  • 2 exercices indépendants (~30 min chacun)
  • 3 à 5 questions par exercice
  • Types : implémenter, débugger, tester
  • Code fourni à compléter (jamais repartir de zéro)
  • Tests assert inclus → utiliser comme guide

Les 3 types de questions

  • Implémenter : remplacer pass par du code fonctionnel
  • Débugger : trouver + corriger un bug volontaire dans une fonction fournie
  • Tester : écrire des assert qui révèlent un bug

Méthode — Implémenter

  • Lire la docstring : elle dit EXACTEMENT quoi retourner
  • Regarder les tests assert fournis → valider ton code
  • Commencer par les cas simples/limites (liste vide, None)
  • Nommer les variables clairement
  • Si bloqué : écrire la logique en commentaire d'abord

Méthode — Débugger

  • Lire la docstring + les tests pour savoir le comportement attendu
  • Tracer manuellement sur un exemple simple
  • Chercher : opérateur wrong (- au lieu de +), indice off-by-one, condition inversée (< vs <=), boucle sur mauvais range
  • Ne modifier QUE la ligne fautive

Méthode — Tester (assert)

  • Écrire ≥3 assertions qui échouent sur la version buggée
  • Tester les cas limites : liste vide, un seul élément, valeur max/min
  • Tester le cas "normal" ET le cas "limite"
  • Format : assert f(entrée) == sortie_attendue

Erreurs classiques à éviter

  • Modifier une liste pendant qu'on l'itère avec for
  • Oublier return (retourner None silencieusement)
  • range(1, 12) au lieu de range(1, 13) (décembre exclu)
  • Division par zéro si liste vide
  • Comparer des strings à des entiers sans convertir

Modifier une liste pendant iteration : for x in liste: if ...: liste.remove(x) → certains éléments sautés. Toujours créer une nouvelle liste ou itérer sur une copie.

Bug derniere_vaccination (sujet 15) : comparer dates comme strings. "20241024" < "20251125" fonctionne en ASCII uniquement si format AAAAMMJJ. Faire attention à l'ordre de comparaison (cherche max, pas min).

Si les tests assert fournis passent mais que quelque chose semble faux : lire la docstring mot à mot. Souvent la fonction doit gérer None ou une liste vide.

Patterns récurrents dans les 23 sujets

Ces patterns apparaissent dans de nombreux sujets. Les maîtriser garantit de résoudre la majorité des questions.

Filtrer une liste → nouvelle liste

# Apparaît dans : 04, 10, 12, 17, 19, 20
def filtrer(elements, condition):
    return [e for e in elements if condition(e)]

# OU version explicite
def filtrer(elements, seuil):
    resultat = []
    for e in elements:
        if e["valeur"] > seuil:
            resultat.append(e)
    return resultat

Accumuler dans un dictionnaire

# Apparaît dans : 02, 17, 18, 19, 20
def par_categorie(elements):
    result = {}
    for e in elements:
        cle = e["categorie"]
        if cle not in result:
            result[cle] = 0
        result[cle] += e["valeur"]
    return result

K plus proches voisins (KNN)

# Apparaît dans : 02, 11
from math import sqrt

def distance(a, b):
    return sqrt(sum((a[k]-b[k])**2
               for k in a))

def k_proches(k, cible, liste):
    dists = [(distance(cible, x), x)
             for x in liste]
    dists.sort(key=lambda t: t[0])
    return [x for _, x in dists[:k]]

Récursivité sur dict imbriqué

# Apparaît dans : 05
def total_rec(d):
    total = 0
    for v in d.values():
        if isinstance(v, dict):
            total += total_rec(v)
        else:
            total += v
    return total

Lecture CSV

# Apparaît dans : 12, 13, 16, 17
import csv

def lire_csv(nom):
    donnees = []
    with open(nom, 'r', encoding='utf-8') as f:
        lecteur = csv.DictReader(f)
        for ligne in lecteur:
            donnees.append(dict(ligne))
    return donnees

Méthode OOP avec attribut liste

# Apparaît dans : 06, 07, 09, 12, 14, 21
class Conteneur:
    def __init__(self):
        self.elements = []

    def ajouter(self, e):
        self.elements.append(e)

    def filtrer(self, cond):
        return [e for e in self.elements
                if cond(e)]

Bugs volontaires courants dans les sujets :

Type de bugExemple concretCorrection
Opérateur inversésomme - dico["écart"] (sujet 16)somme + dico["écart"]
Range incompletrange(1, 12) (sujet 17 — décembre exclu)range(1, 13)
Condition < vs <=if k < 0 au lieu de if k < len(...)Ajuster la borne
Division par mauvais dénominateur/ (len(lst)-1) (sujet 19)/ len(lst)
Décennie mal calculéeannee // 10 donne 201 au lieu de 2010(annee // 10) * 10
Comparaison ordre max/min inverséCherche derniere mais stocke la plus ancienneInverser condition <>
Return trop tôt dans bouclereturn alerte_valeur_aberrante(val, lim) → sort au premier dictStocker résultat, retourner à la fin
Accès mauvaise clé du tupleif distance['presence_renard'] au lieu de caracteristiquesUtiliser la bonne variable
Variable non initialisée avant usaged2 utilisé sans être défini (sujet 14)Calculer d2 avant
Modification liste en cours d'itérationfor m in lst: if ...: lst.remove(m) (sujet 04)Construire une nouvelle liste

Exemples de bugs à détecter

Exercice : identifier la ligne buggée, expliquer pourquoi, proposer la correction.

Bug 1 — Signe inversé (warming stripes)

def moyenne_ecarts(debut, fin, datas):
    somme = 0
    compteur = 0
    for dico in datas:
        if debut <= dico["année"] <= fin:
            # BUG ICI ↓
            somme = somme - dico["écart"]
            compteur += 1
    return somme / compteur

Correction : somme + dico["écart"]

Bug 2 — Range manque décembre

def solde_annuel(mouvements):
    total = 0
    # BUG : range(1, 12) exclut le mois 12
    for m in range(1, 12):
        total += solde_mensuel(mouvements, m)
    return total

Correction : range(1, 13)

Bug 3 — Division dénominateur incorrect

def volume_moyen(reservoirs):
    somme = 0
    for r in reservoirs:
        somme += r["volume"]
    # BUG : -1 faux
    return somme / (len(reservoirs)-1)

Correction : / len(reservoirs)

Bug 4 — Return prématuré dans récursion

def alerte(empreinte, limite):
    for cat, val in empreinte.items():
        if isinstance(val, dict):
            # BUG : return interrompt après 1er dict
            return alerte(val, limite)
        else:
            if val > limite:
                return True
    return False

Correction : if alerte(val, limite): return True

Les 23 sujets officiels

01
Compression RLE — Images
AlgorithmiqueListesFichiers binaires

Concept

Run-Length Encoding : compresser une suite d'octets en paires (occurrences, valeur). Ex : [255,255,0,255,255,255][2,255,1,0,3,255].

Questions

  • Q1 : La fonction codage_rle est fournie. Implémenter decodage_rle(liste_rle) qui fait l'inverse.
  • Q2 : Tester sur une image PNG.

Solution decodage_rle

def decodage_rle(liste_rle):
    resultat = []
    i = 0
    while i < len(liste_rle):
        occ = liste_rle[i]
        val = liste_rle[i + 1]
        resultat.extend([val] * occ)
        i += 2
    return resultat
02
Analyse salaires & KNN
K-NNAlgorithmiqueDictsBug

Concept

Analyse de données salariales + algorithme KNN pour prédire un salaire en fonction de l'expérience, du niveau d'études et du sexe.

Questions

  • Q1 : Implémenter salaire_moyen_condition(employes, champ, valeur) → moyenne des salaires où employe[champ]==valeur. Retourner None si 0 employés.
  • Q2 : Implémenter effectif_par_sexe(employes) → dict {'F': n, 'M': m}
  • Q3 : Bug dans calcul_ecart_sexesalaire_moyen_condition('employes', ...) passe une string au lieu de la variable.
  • Q4 : k_plus_proches et salaire_par_proximite sont fournis, les utiliser.

Solutions clés

def salaire_moyen_condition(employes, champ, valeur):
    filtres = [e for e in employes if e[champ] == valeur]
    if len(filtres) == 0:
        return None
    return sum(e['salaire'] for e in filtres) / len(filtres)

def effectif_par_sexe(employes):
    return {
        'F': sum(1 for e in employes if e['sexe'] == 'F'),
        'M': sum(1 for e in employes if e['sexe'] == 'M')
    }
# Bug Q3 : remplacer 'employes' (string) par employes (variable)
03
Cycle menstruel — Dates
AlgorithmiqueDatesConditions

Concept

Manipulation de dates sous forme de tuples (jour, mois, annee). Fonctions ajouter_jours et jours_dans_mois fournies.

Questions

  • Q1 : Implémenter est_bissextile(annee) → True si divisible par 4 ET (pas par 100 OU par 400).
  • Q2 : Implémenter determiner_phase(date_regles, date) → phase du cycle (règles, folliculaire, ovulation, lutéale) selon le nb de jours écoulés.
  • Q3/4 : calendrier_cycles est fournie, utiliser et tester.
def est_bissextile(annee):
    return (annee % 4 == 0 and
            (annee % 100 != 0 or annee % 400 == 0))
04
Cultures de plantes & mesures
AlgorithmiqueDictsBug itération

Concept

Traitement de listes de plantes et mesures de température. Bug classique : suppression pendant itération.

Questions

  • Q1 : Implémenter croissance_moyenne(plantes)
  • Q2 : Implémenter dictionnaire_mesure(plantes, mesures)
  • Q3 : Analyser purger_mesures_extremes — elle retire des éléments d'une liste pendant qu'on l'itère → éléments sautés.
  • Q4 : Corriger le bug.
# Bug : modifie liste_mesures pendant le for
# Correction : construire une nouvelle liste
def purger_mesures_extremes(liste_mesures):
    return [m for m in liste_mesures
            if 20 <= m['temperature'] <= 25]
05
Empreinte carbone — Récursivité JSON
RécursivitéJSONBug récursion

Concept

Calcul d'empreinte carbone dans un dict potentiellement imbriqué. Nécessite récursion pour les sous-catégories.

Questions

  • Q1 : total_simple(empreinte) — dict plat, sommer les valeurs.
  • Q2 : total_rec(empreinte) — dict imbriqué, récursion si valeur est dict.
  • Q3 : Bug dans alerte_valeur_aberrantereturn alerte(...) sort dès le premier sous-dict, même si la valeur n'est pas aberrante. Corriger : if alerte(...): return True
def total_simple(empreinte):
    return sum(empreinte.values())

def total_rec(empreinte):
    total = 0
    for v in empreinte.values():
        if isinstance(v, dict):
            total += total_rec(v)
        else:
            total += v
    return total

# Correction alerte_valeur_aberrante :
# remplacer "return alerte_valeur_aberrante(valeur, limite)"
# par "if alerte_valeur_aberrante(valeur, limite): return True"
06
Boutique Smoothies — OOP
OOPMéthodesListes

Concept

Classe Boutique_smoothie avec attribut liste_fruits_disponibles et un dict de recettes. Méthodes à compléter.

Questions

  • Q1 : smoothie_possible(nom) → True si tous les fruits de la recette sont dans liste_fruits_disponibles.
  • Q2 : liste_smoothies_possibles() → liste des smoothies réalisables.
  • Q3 : Écrire test_score_proximite() avec des assertions.
  • Q4/5 : plus_proche_possible est fournie mais bugguée — regarder si elle inclut le smoothie lui-même.
def smoothie_possible(self, nom):
    fruits_recette = self.db_smoothies[nom]
    for fruit in fruits_recette:
        if fruit not in self.liste_fruits_disponibles:
            return False
    return True

def liste_smoothies_possibles(self):
    return [nom for nom in self.db_smoothies
            if self.smoothie_possible(nom)]
07
Simulation coccinelles — OOP
OOPSimulationrandom

Concept

Simulation d'écosystème : classe Coccinelle et fonction evolution fournies. Écrire des fonctions d'analyse de la simulation.

Questions

  • Q1/2 : Analyser et comprendre les méthodes chasser, reproduction, a_survecu.
  • Q3 : Écrire une fonction qui simule N jours et retourne l'historique des populations.
  • Q4 : Analyser quand la population s'éteint.
def simuler(population_initiale, nb_proies_init, nb_jours):
    pop = population_initiale[:]
    proies = nb_proies_init
    historique = []
    for _ in range(nb_jours):
        pop, proies = evolution(pop, proies)
        historique.append((len(pop), proies))
    return historique
08
Arithmétique BCD — Binaire
BinaireAlgorithmiqueConversion

Concept

BCD (Binary Coded Decimal) : chaque chiffre décimal encodé sur 4 bits. 9 → '1001', 0 → '0000'. Problème des flottants IEEE 754.

Questions

  • Q1 : Montrer le problème des flottants (0.1 + 0.2 ≠ 0.3). Écrire calcul_recettes() qui illustre.
  • Q2 : Implémenter convertir_BCD_vers_decimal(liste_quartets).
  • Q3 : Compléter aligner_quartets pour égaliser les longueurs.
  • Q4 : Tester additionner_nombres_format_BCD.
def convertir_BCD_vers_decimal(liste_quartets):
    # convention : virgule avant les 2 derniers quartets
    chaine = ""
    for i, q in enumerate(liste_quartets):
        if i == len(liste_quartets) - 2:
            chaine += "."
        chaine += str(int(q, 2))
    return float(chaine)

def aligner_quartets(q1, q2):
    while len(q1) < len(q2):
        q1 = ['0000'] + q1
    while len(q2) < len(q1):
        q2 = ['0000'] + q2
    return q1, q2
09
Objets 3D — Multi-classes
OOPGéométrie 3Dmatplotlib

Concept

3 classes : Sommet(x,y,z), Face(sommets), Objet3D. Notion de sommets adjacents (partagent une face).

Questions

  • Q1 : Comprendre la structure Sommet/Face/Objet3D.
  • Q2 : Implémenter sommets_adjacents(s1, s2) → True si les deux sommets appartiennent à une même face.
  • Q3/4 : Utiliser pour calculer la plus longue arête.
  • Q5 : Bug dans transformer — crée de nouveaux Sommet mais les faces référencent encore les anciens.
def sommets_adjacents(self, s1, s2):
    for face in self.faces:
        if s1 in face.sommets and s2 in face.sommets:
            return True
    return False

# Bug transformer : mettre à jour self.sommets ET les faces
# Solution : modifier les coordonnées in-place
def transformer(self, rapport):
    for s in self.sommets:
        s.x *= rapport
        s.y *= rapport
        s.z *= rapport
10
Analyse consommation eau
AlgorithmiqueListesBug moyenne

Concept

Analyse de consommation d'eau chaude/froide par jour. Détection de fuite (consommation la nuit). Bug dans la moyenne glissante.

Questions

  • Q1 : total_conso(donnees, jour) → total chaude + froide pour un jour donné.
  • Q2 : fuite_possible(donnees, jour) → True si consommation entre 1h et 5h du matin.
  • Q3 : Bug dans lissage_conso — cas milieu : divise par 2 au lieu de 3.
  • Q4 : Écrire des tests qui révèlent le bug.
def total_conso(donnees, jour):
    return sum(d['chaude'] + d['froide']
               for d in donnees if d['jour'] == jour)

def fuite_possible(donnees, jour):
    for d in donnees:
        if d['jour'] == jour:
            h = int(d['heure'][:2])
            if 1 <= h <= 5 and (d['chaude']>0 or d['froide']>0):
                return True
    return False
# Bug lissage : "/ 2" → "/ 3" pour le cas milieu
11
Prédiction habitat — KNN renards
K-NNDistance euclidienneBug clé

Concept

KNN pour prédire la présence de renards dans un habitat selon 4 caractéristiques. Bug : accès à la mauvaise clé du tuple.

Questions

  • Q1 : distance(habitat_1, habitat_2) → distance euclidienne sur 4 attributs.
  • Q2 : distance_d_un_habitat(habitat, habitats) → liste de tuples (distance, habitat).
  • Q3 : Bug dans presence_renard : distance['presence_renard'] au lieu de caracteristiques['presence_renard'].
def distance(h1, h2):
    cles = ['vegetation', 'proximite_eau',
            'densite_urbaine', 'disponibilite_proies']
    return sqrt(sum((h1[k]-h2[k])**2 for k in cles))

def distance_d_un_habitat(habitat, habitats):
    return [(distance(habitat, h), h) for h in habitats]

# Bug presence_renard :
# "if distance['presence_renard']"
# → "if caracteristiques['presence_renard']"
12
Refuge renards — OOP + CSV
OOPCSVClasses

Concept

Classes Renard et Refuge. Importation depuis CSV. Méthodes à compléter.

Questions

  • Q1 : Implémenter __init__ de Renard (attributs : id, nom, poids float, date_arrivee).
  • Q2 : Implémenter __str__ de Renard.
  • Q3 : Utiliser lister_peu_corpulents et pourcentage_peu_corpulents (fournies).
  • Q4 : Analyser les données du CSV importé.
def __init__(self, identifiant, nom, poids, date_arrivee):
    self.identifiant = identifiant
    self.nom = nom
    self.poids = float(poids)   # CSV = string → convertir
    self.date_arrivee = date_arrivee

def __str__(self):
    return (f"Renard {self.nom} (id={self.identifiant}, "
            f"{self.poids}kg, arrivée={self.date_arrivee})")
13
Étude climatique — Ballon sonde
CSVAlgorithmiqueConversion

Concept

Données CSV d'un ballon sonde (altitude, température K, longitude, latitude). Conversion Kelvin → Celsius. Recherche d'extrêmes.

Questions

  • Q1 : Analyser la structure du fichier CSV, comprendre recupere_donnees_fichier_csv.
  • Q2 : Corriger conversion_K_en_C(liste_temperatures) → soustraire 273.15.
  • Q3 : Implémenter altitude_la_plus_froide → retourner l'altitude associée au minimum de température.
def conversion_K_en_C(liste):
    return [t - 273.15 for t in liste]

def altitude_la_plus_froide(altitudes, temperatures):
    idx_min = temperatures.index(min(temperatures))
    return altitudes[idx_min]
14
Simulation évacuation — Grille 2D
OOPGrille 2DBug variable

Concept

Classe Piece avec grille 2D. Simulation d'évacuation vers des sorties. Plusieurs méthodes à compléter ou corriger.

Questions

  • Q1 : nb_occupants_restants() → somme de toutes les cases de la grille.
  • Q2 : evacuation(p) → boucler tant que des déplacements sont possibles, retourner le nb de tours.
  • Q3 : Compléter ajouter_sortie pour les directions S et E.
  • Q4 : Bug choix_sortie : if k < 0 (jamais vrai) → if d2 < distance. La variable d2 n'est jamais calculée.
def nb_occupants_restants(self):
    return sum(self.grille[i][j]
               for i in range(len(self.grille))
               for j in range(len(self.grille[i])))

def evacuation(p, silencieux=True):
    tours = 0
    while p.alerter(silencieux):
        tours += 1
    return tours

# ajouter_sortie S et E :
# elif direction == "S": self.sorties.append((self.i_max, position))
# elif direction == "E": self.sorties.append((position, self.j_max))

# Bug choix_sortie : calculer d2 et changer "if k < 0" :
# d2 = abs(i-autre_sortie[0]) + abs(j-autre_sortie[1])
# if d2 < distance:
15
Cabinet vétérinaire — SQLite
SQLsqlite3Bug comparaison

Concept

Base SQLite avec tables proprietaire, animal, consultation. Normalisation de numéros de téléphone + requêtes SQL.

Questions

  • Q1 : normalisation_tel(tel) → ne garder que les chiffres, enlever espaces/points/tirets/lettres.
  • Q2 : validation_tel(tel) est fournie, écrire ses tests.
  • Q3 : Écrire consultation_vaccination_chat(date) avec JOIN + WHERE + ORDER BY.
  • Q4 : Bug derniere_vaccination : stocke la plus ancienne (condition < inversée).
def normalisation_tel(tel):
    return ''.join(c for c in tel if c.isdigit())

-- SQL Q3 :
SELECT a.id, a.nom, p.telephone, c.date
FROM animal a
JOIN proprietaire p ON a.id_proprietaire = p.id
JOIN consultation c ON a.id = c.id_animal
WHERE a.espece = 'chat' AND c.type = 'vaccination'
  AND c.date > ?
ORDER BY a.id, c.date

# Bug Q4 : "elif date < derniere[id_animal][3]"
# → "elif date > derniere[id_animal][3]"
16
Warming Stripes — Températures
CSVRégressionBug signe

Concept

Données d'anomalies de température mondiale. Visualisation (warming stripes). Régression linéaire. Bug : signe inversé dans la somme.

Questions

  • Q1 : Implémenter ecart_temperature(datas, annee) → renvoyer l'écart pour une année donnée.
  • Q2 : derniere_annee_ecart_negatif est fournie, la comprendre (itère en décrémentant).
  • Q3 : Bug moyenne_ecarts : somme - dico["écart"]somme + dico["écart"].
  • Q4 : Compléter graphique : créer les listes annees et ordonnees.
def ecart_temperature(datas, annee):
    for d in datas:
        if d["année"] == annee:
            return d["écart"]
    return None

# Correction Q3 :
# somme = somme + dico["écart"]  (pas -)

# Q4 - compléter graphique :
annees = [d["année"] for d in datas]
ordonnees = [1] * len(datas)   # hauteur uniforme
17
Budget association — CSV
CSVCalculsBug range

Concept

Analyse de mouvements financiers (recettes/dépenses) d'une association. Calcul de soldes.

Questions

  • Q1 : Implémenter total_par_type(mouvements) → dict {'recette': x, 'dépense': y}.
  • Q2 : Écrire test_solde_annuel avec assertions. Bug : range(1, 12) exclut décembre.
  • Q3 : Corriger solde_annuelrange(1, 13).
def total_par_type(mouvements):
    result = {'recette': 0, 'dépense': 0}
    for m in mouvements:
        result[m['type']] += m['montant']
    return result

# Correction solde_annuel :
# range(1, 12) → range(1, 13)

# Tests qui révèlent le bug :
def test_solde_annuel():
    mvt = [
        {'type':'recette','catégorie':'a','montant':100.0,'mois':12},
        {'type':'dépense','catégorie':'b','montant':40.0,'mois':12},
    ]
    assert solde_annuel(mvt) == 60.0  # échoue si range(1,12)
18
Températures Polynésie
AlgorithmiqueDictsBug décennie

Concept

Analyse de températures par zone et décennie. Bug : calcul de décennie incorrect (// 10 au lieu de // 10 * 10).

Questions

  • Q1 : temperature_moyenne(zone, donnees) → moyenne des températures pour une zone.
  • Q2 : detection_anomalies(zone, donnees, seuil) → liste des relevés dont la temp dépasse moyenne±seuil.
  • Q3 : Écrire 3 tests pour evolution_par_decennie qui révèlent le bug.
  • Q4 : Bug : decennie = (annee // 10)decennie = (annee // 10) * 10.
def temperature_moyenne(zone, donnees):
    releves = [r['temperature'] for r in donnees
               if r['zone'] == zone]
    if not releves: return None
    return sum(releves) / len(releves)

# Bug : decennie = (annee // 10)  → donne 201 pour 2015
# Correction : decennie = (annee // 10) * 10  → donne 2010

# Test révélateur :
def test_plusieurs_decennies():
    r = evolution_par_decennie('Societe', donnees_test)
    assert 2010 in r  # échoue si bug (clé serait 201)
    assert 2020 in r
19
Gestion réservoirs d'eau
AlgorithmiqueDictsBug division

Concept

Gestion de réservoirs par district. Détection de pénuries. Bug : division par len-1.

Questions

  • Q1 : est_en_penurie(reservoirs, nom) → True si le volume du réservoir nommé est 0.
  • Q2 : volume_par_district(reservoirs) → dict {district: volume_total}.
  • Q3 : Bug volume_moyen : / (len(reservoirs)-1)/ len(reservoirs).
  • Q4 : districts_vulnerables → liste des districts où tous les réservoirs sont en pénurie.
def est_en_penurie(reservoirs, nom):
    for r in reservoirs:
        if r["nom"] == nom:
            return r["volume"] == 0
    return False

def volume_par_district(reservoirs):
    result = {}
    for r in reservoirs:
        d = r["district"]
        result[d] = result.get(d, 0) + r["volume"]
    return result
20
Empreinte numérique CO₂
AlgorithmiqueDictsCalculs

Concept

Calcul d'empreinte carbone numérique à partir d'un dict d'usages. Classement par impact. Comparaison entre utilisateurs.

Questions

  • Q1 : calculer_empreinte(utilisateur) → somme de quantite * EMISSIONS[activite] pour chaque activité.
  • Q2 : classer_par_impact(utilisateur) → liste des (activite, emission) triée par émission décroissante.
  • Q3/4 : comparer et comparer_v2 sont fournis, ajouter des assertions de test. Bug potentiel comparer_v2 : division par zéro si emission1=0.
def calculer_empreinte(u):
    total = 0
    for activite, quantite in u.items():
        if activite in EMISSIONS:
            total += quantite * EMISSIONS[activite]
    return total

def classer_par_impact(u):
    impacts = []
    for a, q in u.items():
        if a in EMISSIONS:
            impacts.append((a, q * EMISSIONS[a]))
    impacts.sort(key=lambda x: x[1], reverse=True)
    return impacts
21
Cartes de révision — Leitner
OOPDatesBug algo

Concept

Système Leitner : carte avec niveau 0→4, date de prochaine révision. Si réponse juste → niveau+1, sinon → niveau 0.

Questions

  • Q1 : traiter_reponse(self, succes) : si succes → niveau+1 (max 4), date = aujourd'hui + DELAIS[niveau]. Sinon → niveau 0, date = aujourd'hui.
  • Q2 : extraire_cartes_du_jour(paquet) → cartes dont date_prochaine ≤ aujourd'hui.
  • Q3 : Bug extraire_cartes_a_renforcer : ajoute la carte après avoir mis à jour niveau_min, donc la première carte du nouveau minimum n'est pas dans la liste.
def traiter_reponse(self, succes):
    if succes:
        self.niveau = min(self.niveau + 1, 4)
    else:
        self.niveau = 0
    self.date_prochaine = date_future(DELAIS[self.niveau])

def extraire_cartes_du_jour(paquet):
    aujourd_hui = datetime.date.today()
    return [c for c in paquet
            if c.date_prochaine <= aujourd_hui]

# Bug extraire_cartes_a_renforcer :
# Quand niveau_min est mis à jour, la carte courante
# n'est pas ajoutée à a_renforcer avant reset.
# Correction : réinitialiser a_renforcer = [carte]
22
Décodage ASCII — Binaire
ASCIIBinaireListes

Concept

Table ASCII fournie. Décodage de listes de codes ASCII. Conversion binaire → entier → caractère. Gestion des codes hors table.

Questions

  • Q1 : Fonction binaire_vers_decimal(liste_bits) pour convertir une ligne de figure1.
  • Q2 : Décoder une liste de codes ASCII en chaîne de caractères.
  • Q3 : Gérer le cas d'un code absent de dict_ascii (ex: 233 = é, hors ASCII standard).
def binaire_vers_decimal(bits):
    # bits = tuple de 0 et 1
    val = 0
    for b in bits:
        val = val * 2 + b
    return val

def decoder(codes):
    result = ""
    for c in codes:
        if c in dict_ascii:
            result += dict_ascii[c]
        else:
            result += chr(c)   # fallback unicode
    return result
23
Transmission IoT — Trame binaire
BinaireOOPDécodage

Concept

Classe Transmission : décode une trame binaire (string de 0/1) contenant ID, température, humidité, checksum. int(s, 2) = conversion binaire→décimal.

Questions

  • Q1 : decoder_id fournie (bits 0–7). Implémenter decoder_temperature (bits 8–15, valeur décalée).
  • Q2 : Implémenter decoder_humidite (bits 16–23).
  • Q3 : Implémenter est_valide() → vérifier un checksum (somme des bytes ou XOR selon l'énoncé).
  • Q4 : Analyser le fichier data.txt : compter les transmissions valides/invalides.
def decoder_temperature(self):
    # Bits 8-15, valeur entière (ajuster selon énoncé)
    self._temperature = int(self._trame[8:16], 2)

def decoder_humidite(self):
    self._humidite = int(self._trame[16:24], 2)

# est_valide : lire l'énoncé pour la règle exacte
# Exemple checksum XOR :
def est_valide(self):
    n = len(self._trame) // 8
    octets = [int(self._trame[i*8:(i+1)*8], 2)
              for i in range(n-1)]
    xor = 0
    for o in octets: xor ^= o
    checksum = int(self._trame[-8:], 2)
    return xor == checksum