Programme de Révision NSI - Structures Python

Préparation pour l'évaluation du vendredi - 7 jours de révision intensive

Objectif : Maîtriser les fonctions, boucles, parcours séquentiels, chaînes de caractères et tests

Jour 1
Fonctions & Tests
Jour 2
Boucles & Parcours
Jour 3
Chaînes de caractères
Jour 4
Exercices combinés
Jour 5
Algorithmes de base
Jour 6
Révision complète
Jour 7
Simulation d'examen

Jour 1 : Fonctions et Structures de Tests

📚 Théorie

Une fonction en Python est un bloc de code réutilisable qui effectue une tâche spécifique. Elle est définie avec le mot-clé def.

Les structures de tests permettent d'exécuter du code conditionnellement avec if, elif et else.

Syntaxe de base d'une fonction :

def nom_fonction(parametre1, parametre2):
    """Documentation de la fonction (docstring)"""
    # Corps de la fonction
    resultat = parametre1 + parametre2
    return resultat

Syntaxe de base d'un test :

if condition1:
    # code exécuté si condition1 est vraie
elif condition2:
    # code exécuté si condition2 est vraie
else:
    # code exécuté si aucune condition n'est vraie

💻 Exercice 1 : Fonction de vérification de parité

Écrivez une fonction est_pair(n) qui prend un entier en paramètre et retourne True si le nombre est pair, False sinon.

Indice : Utilisez l'opérateur modulo % qui donne le reste de la division.

Solution :

def est_pair(n):
    """Retourne True si n est pair, False sinon"""
    if n % 2 == 0:
        return True
    else:
        return False

# Version simplifiée :
def est_pair_simple(n):
    return n % 2 == 0

# Tests
print(est_pair(4))   # Affiche True
print(est_pair(7))   # Affiche False

💻 Exercice 2 : Fonction avec plusieurs conditions

Écrivez une fonction categorie_age(age) qui retourne une chaîne de caractères selon l'âge :

  • "Enfant" si age < 12
  • "Adolescent" si 12 ≤ age < 18
  • "Adulte" si 18 ≤ age < 60
  • "Senior" sinon

Solution :

def categorie_age(age):
    """Retourne la catégorie d'âge correspondante"""
    if age < 12:
        return "Enfant"
    elif age < 18:
        return "Adolescent"
    elif age < 60:
        return "Adulte"
    else:
        return "Senior"

# Tests
print(categorie_age(8))   # Affiche "Enfant"
print(categorie_age(15))  # Affiche "Adolescent"
print(categorie_age(30))  # Affiche "Adulte"
print(categorie_age(65))  # Affiche "Senior"

💡 Conseils pour l'évaluation :

  • Pensez toujours à tester vos fonctions avec plusieurs valeurs
  • Utilisez des noms de variables explicites
  • Ajoutez des docstrings pour expliquer ce que fait votre fonction

Jour 2 : Boucles et Parcours Séquentiels

📚 Théorie

Les boucles permettent de répéter une action plusieurs fois :

  • for : pour parcourir une séquence (liste, chaîne, range...)
  • while : tant qu'une condition est vraie

Les parcours séquentiels consistent à examiner chaque élément d'une séquence dans l'ordre.

Boucle for avec range :

# Parcours de 0 à 4
for i in range(5):
    print(i)  # Affiche 0, 1, 2, 3, 4

# Parcours de 2 à 8 avec un pas de 2
for i in range(2, 9, 2):
    print(i)  # Affiche 2, 4, 6, 8

Parcours d'une liste :

ma_liste = [10, 20, 30, 40]
for element in ma_liste:
    print(element)  # Affiche 10, 20, 30, 40

# Avec l'indice
for i in range(len(ma_liste)):
    print(f"Indice {i} : {ma_liste[i]}")

💻 Exercice 1 : Somme des éléments d'une liste

Écrivez une fonction somme_liste(liste) qui calcule et retourne la somme de tous les éléments d'une liste de nombres.

Solution :

def somme_liste(liste):
    """Retourne la somme des éléments d'une liste"""
    somme = 0
    for nombre in liste:
        somme += nombre
    return somme

# Version avec range
def somme_liste_range(liste):
    somme = 0
    for i in range(len(liste)):
        somme += liste[i]
    return somme

# Tests
print(somme_liste([1, 2, 3, 4, 5]))  # Affiche 15
print(somme_liste([]))               # Affiche 0

💻 Exercice 2 : Recherche du maximum

Écrivez une fonction maximum(liste) qui retourne le plus grand élément d'une liste de nombres. Si la liste est vide, retournez None.

Solution :

def maximum(liste):
    """Retourne le maximum d'une liste de nombres"""
    if len(liste) == 0:
        return None
    
    max_val = liste[0]
    for nombre in liste:
        if nombre > max_val:
            max_val = nombre
    return max_val

# Tests
print(maximum([3, 7, 2, 9, 1]))  # Affiche 9
print(maximum([]))               # Affiche None

💻 Exercice 3 : Comptage d'occurrences

Écrivez une fonction compter_occurrences(liste, valeur) qui compte combien de fois une valeur apparaît dans une liste.

Solution :

def compter_occurrences(liste, valeur):
    """Compte le nombre d'occurrences de valeur dans liste"""
    compteur = 0
    for element in liste:
        if element == valeur:
            compteur += 1
    return compteur

# Tests
print(compter_occurrences([1, 2, 3, 2, 4, 2, 5], 2))  # Affiche 3
print(compter_occurrences([1, 2, 3], 4))              # Affiche 0

💡 Conseils pour l'évaluation :

  • Pensez aux cas limites : liste vide, valeur absente, etc.
  • Utilisez range(len(liste)) quand vous avez besoin de l'indice
  • Pour les boucles while, assurez-vous que la condition d'arrêt sera atteinte

Jour 3 : Chaînes de Caractères

📚 Théorie

Les chaînes de caractères (strings) sont des séquences de caractères délimitées par des guillemets simples ou doubles.

Propriétés importantes :

  • Indexation : chaine[0] donne le premier caractère
  • Slicing : chaine[2:5] donne les caractères de l'indice 2 à 4
  • Longueur : len(chaine) donne le nombre de caractères
  • Immuabilité : une chaîne ne peut pas être modifiée

Méthodes utiles :

chaine = "Bonjour le monde"
print(chaine.upper())      # "BONJOUR LE MONDE"
print(chaine.lower())      # "bonjour le monde"
print(chaine.split())      # ["Bonjour", "le", "monde"]
print(chaine.replace("le", "la"))  # "Bonjour la monde"
print(chaine.find("jour")) # 3 (indice où commence "jour")

Parcours d'une chaîne :

chaine = "Python"
for caractere in chaine:
    print(caractere)  # Affiche P, y, t, h, o, n

# Avec l'indice
for i in range(len(chaine)):
    print(f"Caractère {i} : {chaine[i]}")

💻 Exercice 1 : Inverser une chaîne

Écrivez une fonction inverser_chaine(chaine) qui retourne la chaîne inversée sans utiliser la fonction reversed() ou le slicing avec pas négatif.

Solution :

def inverser_chaine(chaine):
    """Retourne la chaîne inversée"""
    resultat = ""
    for i in range(len(chaine)-1, -1, -1):
        resultat += chaine[i]
    return resultat

# Version avec parcours direct
def inverser_chaine2(chaine):
    resultat = ""
    for caractere in chaine:
        resultat = caractere + resultat  # Ajout au début
    return resultat

# Tests
print(inverser_chaine("Python"))      # Affiche "nohtyP"
print(inverser_chaine("NSI"))         # Affiche "ISN"

💻 Exercice 2 : Compter les voyelles

Écrivez une fonction compter_voyelles(chaine) qui compte et retourne le nombre de voyelles (a, e, i, o, u, y) dans une chaîne, sans distinction de casse.

Solution :

def compter_voyelles(chaine):
    """Compte le nombre de voyelles dans une chaîne"""
    voyelles = "aeiouy"
    chaine = chaine.lower()  # Convertit en minuscules
    compteur = 0
    for caractere in chaine:
        if caractere in voyelles:
            compteur += 1
    return compteur

# Tests
print(compter_voyelles("Python"))        # Affiche 1 (o)
print(compter_voyelles("Informatique"))  # Affiche 6 (i, o, a, i, u, e)

💻 Exercice 3 : Vérification de palindrome

Un palindrome est un mot qui se lit de la même façon de gauche à droite et de droite à gauche. Écrivez une fonction est_palindrome(chaine) qui retourne True si la chaîne est un palindrome, False sinon. Ignorez la casse.

Solution :

def est_palindrome(chaine):
    """Vérifie si une chaîne est un palindrome"""
    chaine = chaine.lower()  # Ignore la casse
    n = len(chaine)
    for i in range(n // 2):
        if chaine[i] != chaine[n-1-i]:
            return False
    return True

# Version utilisant la fonction d'inversion du premier exercice
def est_palindrome2(chaine):
    chaine = chaine.lower()
    return chaine == inverser_chaine(chaine)

# Tests
print(est_palindrome("radar"))    # Affiche True
print(est_palindrome("Python"))   # Affiche False
print(est_palindrome("Ésope reste ici et se repose"))  # Affiche True (en ignorant les espaces et accents)

💡 Conseils pour l'évaluation :

  • N'oubliez pas que les chaînes sont immuables : vous ne pouvez pas faire chaine[0] = 'a'
  • Utilisez les méthodes de chaîne (lower(), upper(), strip(), etc.)
  • Pour vérifier si un caractère est dans une chaîne, utilisez if caractere in "aeiouy"

Jour 4 : Exercices Combinés

📚 Théorie

Aujourd'hui, nous combinons plusieurs concepts : fonctions, boucles, tests et chaînes de caractères pour résoudre des problèmes plus complexes.

Ces exercices sont typiques des évaluations NSI et demandent de bien structurer son code.

💻 Exercice 1 : FizzBuzz amélioré

Écrivez une fonction fizzbuzz(n) qui :

  • Pour les nombres de 1 à n :
  • Affiche "Fizz" si le nombre est divisible par 3
  • Affiche "Buzz" si le nombre est divisible par 5
  • Affiche "FizzBuzz" si le nombre est divisible par 3 et 5
  • Affiche le nombre sinon

La fonction doit retourner une liste des résultats.

Solution :

def fizzbuzz(n):
    """Implémentation du jeu FizzBuzz"""
    resultats = []
    for i in range(1, n+1):
        if i % 3 == 0 and i % 5 == 0:
            resultats.append("FizzBuzz")
        elif i % 3 == 0:
            resultats.append("Fizz")
        elif i % 5 == 0:
            resultats.append("Buzz")
        else:
            resultats.append(str(i))
    return resultats

# Tests
resultats = fizzbuzz(15)
for r in resultats:
    print(r)
# Affiche : 1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, 11, Fizz, 13, 14, FizzBuzz

💻 Exercice 2 : Analyse de texte

Écrivez une fonction analyser_texte(texte) qui retourne un dictionnaire contenant :

  • Le nombre de mots
  • Le nombre de caractères (espaces exclus)
  • Le mot le plus long
  • La fréquence de chaque voyelle

Solution :

def analyser_texte(texte):
    """Analyse un texte et retourne des statistiques"""
    # Initialisation des résultats
    resultat = {
        "nb_mots": 0,
        "nb_caracteres": 0,
        "mot_plus_long": "",
        "freq_voyelles": {"a": 0, "e": 0, "i": 0, "o": 0, "u": 0, "y": 0}
    }
    
    # Séparation en mots
    mots = texte.split()
    resultat["nb_mots"] = len(mots)
    
    # Analyse de chaque mot
    for mot in mots:
        # Nombre de caractères (sans espaces)
        resultat["nb_caracteres"] += len(mot)
        
        # Mot le plus long
        if len(mot) > len(resultat["mot_plus_long"]):
            resultat["mot_plus_long"] = mot
        
        # Fréquence des voyelles
        for lettre in mot.lower():
            if lettre in resultat["freq_voyelles"]:
                resultat["freq_voyelles"][lettre] += 1
    
    return resultat

# Tests
texte = "Le langage Python est puissant et intuitif"
stats = analyser_texte(texte)
print(stats)

💻 Exercice 3 : Tri par sélection (bonus)

Implémentez l'algorithme de tri par sélection qui trie une liste de nombres dans l'ordre croissant :

  1. Parcourez la liste pour trouver le plus petit élément
  2. Échangez-le avec le premier élément
  3. Répétez pour le reste de la liste

Solution :

def tri_selection(liste):
    """Tri une liste par l'algorithme de tri par sélection"""
    n = len(liste)
    
    for i in range(n-1):
        # Recherche de l'indice du minimum dans la sous-liste non triée
        indice_min = i
        for j in range(i+1, n):
            if liste[j] < liste[indice_min]:
                indice_min = j
        
        # Échange si nécessaire
        if indice_min != i:
            liste[i], liste[indice_min] = liste[indice_min], liste[i]
    
    return liste

# Tests
print(tri_selection([64, 25, 12, 22, 11]))  # Affiche [11, 12, 22, 25, 64]
print(tri_selection([5, 2, 8, 1, 9]))       # Affiche [1, 2, 5, 8, 9]

💡 Conseils pour l'évaluation :

  • Lisez attentivement l'énoncé et identifiez les sous-problèmes
  • Testez chaque partie de votre code au fur et à mesure
  • Utilisez des fonctions auxiliaires pour simplifier le code principal

Jour 5 : Algorithmes de Base

📚 Théorie

Les algorithmes de base sont des patterns récurrents en programmation. Les maîtriser vous aidera à résoudre de nombreux problèmes.

Algorithmes importants :

  • Recherche linéaire : parcourir une séquence jusqu'à trouver un élément
  • Recherche du minimum/maximum : parcourir en gardant la valeur extrême
  • Comptage : parcourir en incrémentant un compteur
  • Accumulation : parcourir en ajoutant à un total

💻 Exercice 1 : Recherche dichotomique

Implémentez l'algorithme de recherche dichotomique (binary search) qui recherche un élément dans une liste triée. L'algorithme compare l'élément recherché avec l'élément du milieu et élimine la moitié de la liste à chaque itération.

Solution :

def recherche_dichotomique(liste, element):
    """Recherche un élément dans une liste triée par dichotomie"""
    gauche = 0
    droite = len(liste) - 1
    
    while gauche <= droite:
        milieu = (gauche + droite) // 2
        
        if liste[milieu] == element:
            return milieu  # Élément trouvé, retourne l'indice
        elif liste[milieu] < element:
            gauche = milieu + 1  # Chercher dans la moitié droite
        else:
            droite = milieu - 1  # Chercher dans la moitié gauche
    
    return -1  # Élément non trouvé

# Tests
liste_triee = [2, 5, 8, 12, 16, 23, 38, 56, 72, 91]
print(recherche_dichotomique(liste_triee, 23))   # Affiche 5
print(recherche_dichotomique(liste_triee, 38))   # Affiche 6
print(recherche_dichotomique(liste_triee, 100))  # Affiche -1

💻 Exercice 2 : Calcul du PGCD (algorithme d'Euclide)

Écrivez une fonction pgcd(a, b) qui calcule le Plus Grand Commun Diviseur de deux nombres entiers positifs en utilisant l'algorithme d'Euclide :

  • Tant que b ≠ 0 :
  • Calculer r = a % b
  • a prend la valeur de b
  • b prend la valeur de r
  • Le résultat est a

Solution :

def pgcd(a, b):
    """Calcule le PGCD de a et b avec l'algorithme d'Euclide"""
    while b != 0:
        r = a % b
        a = b
        b = r
    return a

# Version récursive
def pgcd_recursif(a, b):
    if b == 0:
        return a
    return pgcd_recursif(b, a % b)

# Tests
print(pgcd(48, 18))     # Affiche 6
print(pgcd(1071, 1029)) # Affiche 21
print(pgcd(17, 13))     # Affiche 1 (nombres premiers entre eux)

💻 Exercice 3 : Crible d'Ératosthène

Implémentez l'algorithme du crible d'Ératosthène pour trouver tous les nombres premiers inférieurs à n :

  1. Créez une liste de booléens de taille n+1, tous initialisés à True
  2. Marquez 0 et 1 comme non premiers (False)
  3. Pour i de 2 à √n : si i est premier, marquez tous ses multiples comme non premiers
  4. Récupérez les indices qui sont encore True

Solution :

import math

def crible_eratosthene(n):
    """Retourne la liste des nombres premiers inférieurs à n"""
    if n < 2:
        return []
    
    # Initialisation : tous les nombres sont supposés premiers
    est_premier = [True] * (n+1)
    est_premier[0] = est_premier[1] = False
    
    # Crible
    limite = int(math.sqrt(n)) + 1
    for i in range(2, limite):
        if est_premier[i]:
            # Marquer les multiples de i comme non premiers
            for multiple in range(i*i, n+1, i):
                est_premier[multiple] = False
    
    # Récupérer les nombres premiers
    premiers = []
    for i in range(2, n+1):
        if est_premier[i]:
            premiers.append(i)
    
    return premiers

# Tests
print(crible_eratosthene(30))  # Affiche [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]

💡 Conseils pour l'évaluation :

  • Connaître les algorithmes classiques (recherche, tri, PGCD) est un atout
  • Entraînez-vous à les écrire sans aide pour être rapide le jour J
  • Comprenez la complexité des algorithmes (linéaire, logarithmique, quadratique)

Jour 6 : Révision Complète

📚 Révision des concepts clés

Aujourd'hui, nous revoyons l'ensemble des concepts en les combinant dans des exercices synthétiques.

Checklist de révision :

  • ✅ Fonctions : définition, paramètres, return, portée des variables
  • ✅ Tests : if/elif/else, conditions simples et composées
  • ✅ Boucles : for (avec range ou séquence), while, break/continue
  • ✅ Parcours séquentiels : liste, chaîne, indices
  • ✅ Chaînes de caractères : méthodes, slicing, immuabilité
  • ✅ Listes : méthodes, modification, parcours

💻 Exercice synthétique 1 : Statistiques d'une liste

Écrivez une fonction statistiques_liste(liste) qui retourne un dictionnaire contenant :

  • La somme des éléments
  • La moyenne
  • Le minimum et le maximum
  • La médiane (valeur centrale lorsque la liste est triée)
  • Le mode (élément le plus fréquent, en cas d'égalité retourner le plus petit)

Solution :

def statistiques_liste(liste):
    """Calcule diverses statistiques sur une liste de nombres"""
    if len(liste) == 0:
        return None
    
    # Tri de la liste pour certaines statistiques
    liste_triee = sorted(liste)
    n = len(liste)
    
    # Somme et moyenne
    somme = sum(liste)
    moyenne = somme / n
    
    # Minimum et maximum
    minimum = min(liste)
    maximum = max(liste)
    
    # Médiane
    if n % 2 == 1:
        mediane = liste_triee[n // 2]
    else:
        mediane = (liste_triee[n // 2 - 1] + liste_triee[n // 2]) / 2
    
    # Mode (élément le plus fréquent)
    freq = {}
    for element in liste:
        freq[element] = freq.get(element, 0) + 1
    
    # Recherche du mode
    mode = liste[0]
    freq_max = freq[mode]
    for element, frequence in freq.items():
        if frequence > freq_max or (frequence == freq_max and element < mode):
            mode = element
            freq_max = frequence
    
    return {
        "somme": somme,
        "moyenne": moyenne,
        "minimum": minimum,
        "maximum": maximum,
        "mediane": mediane,
        "mode": mode,
        "taille": n
    }

# Tests
liste_test = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3]
stats = statistiques_liste(liste_test)
for cle, valeur in stats.items():
    print(f"{cle}: {valeur}")

💻 Exercice synthétique 2 : Formateur de texte

Écrivez une fonction formater_texte(texte, largeur) qui formate un texte pour qu'il ne dépasse pas une certaine largeur (nombre de caractères par ligne). Le texte doit être justifié (ajouter des espaces entre les mots pour atteindre exactement la largeur), sauf pour la dernière ligne qui reste à gauche.

Indice : Construisez la ligne mot par mot, et quand vous ne pouvez plus ajouter de mot, justifiez la ligne en ajoutant des espaces.

Solution :

def formater_texte(texte, largeur):
    """Formate un texte avec justification à une largeur donnée"""
    mots = texte.split()
    lignes = []
    ligne_courante = []
    longueur_courante = 0
    
    for mot in mots:
        # Si le mot seul dépasse la largeur, on le met sur une ligne
        if len(mot) > largeur:
            if ligne_courante:
                lignes.append(" ".join(ligne_courante))
                ligne_courante = []
                longueur_courante = 0
            lignes.append(mot)
            continue
        
        # Vérifie si on peut ajouter le mot à la ligne courante
        if longueur_courante + len(mot) + (len(ligne_courante) if ligne_courante else 0) <= largeur:
            ligne_courante.append(mot)
            longueur_courante += len(mot)
        else:
            # Justifier la ligne courante (sauf si c'est une ligne d'un seul mot)
            if len(ligne_courante) == 1:
                lignes.append(ligne_courante[0])
            else:
                lignes.append(justifier_ligne(ligne_courante, largeur))
            
            # Commencer une nouvelle ligne avec le mot courant
            ligne_courante = [mot]
            longueur_courante = len(mot)
    
    # Dernière ligne (non justifiée)
    if ligne_courante:
        lignes.append(" ".join(ligne_courante))
    
    return "\n".join(lignes)

def justifier_ligne(mots, largeur):
    """Justifie une ligne en ajoutant des espaces entre les mots"""
    nb_mots = len(mots)
    if nb_mots == 1:
        return mots[0]
    
    # Nombre total d'espaces à ajouter
    longueur_mots = sum(len(mot) for mot in mots)
    espaces_totaux = largeur - longueur_mots
    
    # Répartition des espaces
    espaces_par_intervalle = espaces_totaux // (nb_mots - 1)
    espaces_supplementaires = espaces_totaux % (nb_mots - 1)
    
    # Construction de la ligne
    ligne = mots[0]
    for i in range(1, nb_mots):
        espaces = espaces_par_intervalle
        if i <= espaces_supplementaires:
            espaces += 1
        ligne += " " * espaces + mots[i]
    
    return ligne

# Tests
texte = "Python est un langage de programmation interprété, multi-paradigme et multiplateforme."
print(formater_texte(texte, 30))

💡 Stratégie pour l'évaluation :

  • Lisez l'énoncé en entier avant de commencer
  • Identifiez les sous-problèmes et traitez-les un par un
  • Testez votre code avec différents cas (normaux, limites, erreurs)
  • Commentez votre code pour expliquer votre raisonnement
  • Gérez votre temps : ne restez pas bloqué sur une question

Jour 7 : Simulation d'Examen

📚 Instructions pour la simulation

Considérez cet exercice comme un vrai examen :

  • Travaillez sans aide extérieure
  • Limitez-vous à 1h30 (temps typique d'une évaluation NSI)
  • Écrivez un code propre et commenté
  • Testez vos fonctions

Durée conseillée : 1h30 maximum

💻 Exercice 1 : Gestion des notes (4 points)

Écrivez une fonction moyenne_ponderee(notes, coefficients) qui calcule la moyenne pondérée d'un élève. Les paramètres sont deux listes de même longueur contenant les notes et leurs coefficients. La fonction doit retourner la moyenne ou None si les listes sont vides ou de tailles différentes.

Exemple : moyenne_ponderee([12, 15, 8], [1, 2, 1]) doit retourner 12.5 car (12×1 + 15×2 + 8×1) / (1+2+1) = 50/4 = 12.5

💻 Exercice 2 : Analyse de mots de passe (6 points)

Écrivez une fonction valider_mot_de_passe(mdp) qui vérifie si un mot de passe est valide selon ces critères :

  • Au moins 8 caractères
  • Au moins une lettre majuscule
  • Au moins une lettre minuscule
  • Au moins un chiffre
  • Au moins un caractère spécial parmi !@#$%^&*
  • Ne doit pas contenir d'espaces

La fonction doit retourner True si le mot de passe est valide, False sinon.

💻 Exercice 3 : Compression RLE (10 points)

La compression RLE (Run-Length Encoding) remplace les séquences de caractères identiques par le caractère suivi du nombre de répétitions.

Exemple : "aaabbccccd" devient "a3b2c4d1"

Écrivez deux fonctions :

  1. compresser_rle(texte) qui compresse une chaîne avec l'algorithme RLE
  2. decompresser_rle(texte_compresse) qui décompresse une chaîne compressée avec RLE

Attention : Gérer le cas où le nombre de répétitions dépasse 9 (ex: "aaaaaaaaaa" devient "a10")

Solutions :

Exercice 1 :
def moyenne_ponderee(notes, coefficients):
    """Calcule la moyenne pondérée des notes"""
    if len(notes) != len(coefficients) or len(notes) == 0:
        return None
    
    somme_notes = 0
    somme_coeffs = 0
    
    for i in range(len(notes)):
        somme_notes += notes[i] * coefficients[i]
        somme_coeffs += coefficients[i]
    
    return somme_notes / somme_coeffs
Exercice 2 :
def valider_mot_de_passe(mdp):
    """Valide un mot de passe selon plusieurs critères"""
    if len(mdp) < 8:
        return False
    
    if ' ' in mdp:
        return False
    
    # Vérification des critères
    majuscule = False
    minuscule = False
    chiffre = False
    special = False
    speciaux = "!@#$%^&*"
    
    for caractere in mdp:
        if caractere.isupper():
            majuscule = True
        elif caractere.islower():
            minuscule = True
        elif caractere.isdigit():
            chiffre = True
        elif caractere in speciaux:
            special = True
    
    return majuscule and minuscule and chiffre and special
Exercice 3 :
def compresser_rle(texte):
    """Compresse un texte avec l'algorithme RLE"""
    if not texte:
        return ""
    
    resultat = ""
    caractere_courant = texte[0]
    compteur = 1
    
    for i in range(1, len(texte)):
        if texte[i] == caractere_courant:
            compteur += 1
        else:
            resultat += caractere_courant + str(compteur)
            caractere_courant = texte[i]
            compteur = 1
    
    # Ne pas oublier le dernier caractère
    resultat += caractere_courant + str(compteur)
    return resultat

def decompresser_rle(texte_compresse):
    """Décompresse un texte compressé avec RLE"""
    if not texte_compresse:
        return ""
    
    resultat = ""
    i = 0
    
    while i < len(texte_compresse):
        caractere = texte_compresse[i]
        i += 1
        
        # Extraire le nombre (peut avoir plusieurs chiffres)
        nombre = ""
        while i < len(texte_compresse) and texte_compresse[i].isdigit():
            nombre += texte_compresse[i]
            i += 1
        
        # Ajouter le caractère répété
        resultat += caractere * int(nombre)
    
    return resultat

💡 Derniers conseils pour demain :

  • Reposez-vous bien cette nuit
  • Arrivez en avance pour être détendu
  • Lisez attentivement chaque question
  • Commencez par les questions que vous maîtrisez le mieux
  • Gardez du temps pour relire et tester votre code
  • Si vous êtes bloqué, passez à la question suivante et revenez plus tard
  • Vous êtes prêt ! Bonne chance pour votre évaluation ! 🍀