Chapitre 517 minIntermédiaire
Situation A : méthode et sujet corrigé
Par Josselyn C., prof de BTS SIO. Mis à jour le .
À la fin de ce chapitre, tu sauras
- organiser ton heure de préparation et tes 20 minutes d'oral ;
- vérifier ton travail avec les huit critères du référentiel ;
- traiter un sujet complet, du pseudo-code au jeu d'essai ;
- préparer les questions de l'entretien.
3 exercices corrigés1 schéma
La situation A est l'épreuve pratique d'algorithmique de l'E3 en CCF : une heure de préparation, 30 minutes sur table puis 30 minutes sur machine, suivie de 20 minutes d'oral avec le professeur qui t'a formé, pour un coefficient 1 sur 3. Ce chapitre résume la méthode en une page, puis la met en œuvre sur un sujet complet et corrigé, construit comme ceux de l'épreuve. Le cours d'algorithmique détaille chaque phase et chaque critère et propose trois autres sujets.
Le déroulement en bref
| Phase | Durée | Ce que tu fais | Ce qui est regardé |
|---|---|---|---|
| Préparation sur table | 30 min | Lire le sujet, écrire les algorithmes, préparer un jeu d'essai | Ta trace écrite, que la commission peut examiner |
| Préparation sur machine | 30 min | Programmer, tester, corriger ; l'aide syntaxique de l'environnement est permise | Ton programme et tes tests |
| Présentation | 10 min au plus | Expliquer ta démarche, ton code, faire tourner les tests | La clarté, la pertinence de la solution |
| Entretien | 10 min au plus | Répondre aux questions de la commission | Ta compréhension, ta capacité à corriger |
Les huit critères en une liste de contrôle
Le référentiel évalue la situation A sur huit critères. Avant de rendre ta trace écrite et avant de présenter, coche chaque ligne.
- Connaissances du module : les bonnes structures (boucle, condition, fonction, tableau) au bon endroit.
- Efficacité et pertinence de la solution : elle répond à la question posée, sans détour.
- Formalisme cohérent : mêmes conventions du début à la fin (affectation, indices, mots-clés).
- Lisibilité : indentation, noms parlants, commentaires, en-tête de chaque fonction.
- Efficacité de l'implémentation : pas de calcul répété inutilement, pas de boucle de trop.
- Composants fournis : tu les utilises au lieu de les réécrire, en respectant leurs paramètres.
- Tests de validation : un jeu d'essai avec des cas normaux et des cas limites, résultats attendus calculés à la main.
- Éléments de correction : tu sais expliquer et corriger une erreur, la tienne ou celle d'un algorithme fourni.
La méthode express
- Minutes 0 à 5. Lis tout le sujet. Souligne entrées, sorties et contraintes. Lis l'interface des composants fournis (nom, paramètres, valeur renvoyée).
- Minutes 5 à 25. Pour chaque question : une ligne « entrées → traitement → sortie », puis l'algorithme, proprement. Reconnais le motif : parcours, comptage, recherche, accumulation, conversion.
- Minutes 25 à 30. Le jeu d'essai, avec les résultats attendus calculés à la main.
- Minutes 30 à 55. Sur machine, une fonction à la fois : tu tapes, tu exécutes, tu testes. Garde tes tests dans le fichier.
- Minutes 55 à 60. Relis : noms, commentaires, en-têtes. Note les erreurs trouvées : ce sont d'excellents sujets pour l'oral.
Sujet type : à quel VLAN appartient cette adresse ?
Sujet d'entraînement construit sur le modèle de la situation A ; ce n'est pas un sujet officiel.
Contexte. Le réseau du siège de Sorbier Logistique est découpé en VLAN. Chaque VLAN a une adresse de réseau et un masque (cours de réseaux, TP d'adressage IP). Le technicien veut un petit programme qui dit à quel VLAN appartient une adresse IPv4, pour contrôler les adresses relevées dans les journaux.
Une adresse appartient à un réseau quand le ET bit à bit entre l'adresse et le masque, octet par octet, redonne l'adresse du réseau.
Composants fournis.
def octets(adresse):
"""Renvoie la liste des quatre entiers d'une adresse IPv4 écrite '192.168.10.71'."""
return [int(x) for x in adresse.split(".")]
VLANS = [
(10, "POSTES", "192.168.10.64", "255.255.255.192"),
(20, "SERVEURS", "192.168.10.176", "255.255.255.240"),
(21, "APPLIS", "192.168.21.0", "255.255.255.0"),
(30, "ENTREPOT", "192.168.10.128", "255.255.255.224"),
(40, "VISITEURS", "192.168.10.0", "255.255.255.192"),
(50, "TELEPHONIE", "192.168.10.160", "255.255.255.240"),
(60, "DMZ", "192.168.10.224", "255.255.255.240"),
(99, "ADMIN", "192.168.10.208", "255.255.255.240"),
]
Chaque élément de VLANS est un tuple (numéro, nom, adresse du réseau, masque). L'opérateur & de Python calcule le ET bit à bit de deux entiers : 71 & 192 vaut 64.
Sur table (30 minutes).
- Écris une fonction
binaire8(n)qui renvoie l'écriture binaire sur 8 bits d'un entier n compris entre 0 et 255, sous forme de chaîne, par divisions successives par 2 (sans utiliserbinniformat). - Écris une fonction
reseau(adresse, masque)qui renvoie l'adresse du réseau, sous forme de chaîne, en faisant le ET bit à bit octet par octet. - Écris une fonction
vlan_de(adresse)qui renvoie le numéro du VLAN qui contient l'adresse, ou 0 si aucun VLAN ne la contient. - Prépare un jeu d'essai pour
vlan_de: au moins six adresses, dont des cas limites, avec le résultat attendu.
Sur machine (30 minutes).
- Programme et teste les trois fonctions.
- Écris une fonction
hors_plan(adresses)qui reçoit une liste d'adresses et renvoie la liste de celles qui n'appartiennent à aucun VLAN du siège. - Pour aller plus loin. Écris une fonction
prefixe(masque)qui renvoie la longueur du préfixe d'un masque (26 pour 255.255.255.192), en réutilisantbinaire8.
Corrigé
Question 1. On divise par 2 huit fois ; chaque reste est un bit, que l'on place devant les bits déjà obtenus, puisque le premier reste est le bit de poids faible.
Fonction binaire8(n : entier) : chaîne
// n entre 0 et 255 ; renvoie ses 8 bits, poids fort à gauche
bits ← ""
Pour i allant de 1 à 8 faire
bits ← chaîne(n mod 2) + bits
n ← n div 2
Fin Pour
Renvoyer bits
Fin Fonction
La boucle « Pour » tourne exactement 8 fois : c'est ce qui garantit les zéros de tête (5 donne 00000101, pas 101).
Questions 2 et 3.
Fonction reseau(adresse : chaîne, masque : chaîne) : chaîne
a ← octets(adresse)
m ← octets(masque)
resultat ← ""
Pour i allant de 0 à 3 faire
resultat ← resultat + chaîne(a[i] ET m[i])
Si i < 3 alors
resultat ← resultat + "."
Fin Si
Fin Pour
Renvoyer resultat
Fin Fonction
Fonction vlan_de(adresse : chaîne) : entier
Pour chaque (numero, nom, adresse_reseau, masque) de VLANS faire
Si reseau(adresse, masque) = adresse_reseau alors
Renvoyer numero
Fin Si
Fin Pour
Renvoyer 0
Fin Fonction
Le parcours s'arrête dès qu'un VLAN correspond : c'est une recherche, pas un comptage. Le Renvoyer 0 est après la boucle : le placer dans un « Sinon » à l'intérieur arrêterait la recherche au premier VLAN qui ne correspond pas.
Question 4. Le jeu d'essai, avec le calcul qui justifie chaque résultat attendu :
| Adresse | Pourquoi ce test | Calcul | Attendu |
|---|---|---|---|
| 192.168.10.71 | Cas normal, masque /26 | 71 ET 192 = 64 | 10 |
| 192.168.10.180 | Masque /28 | 180 ET 240 = 176 | 20 |
| 192.168.21.37 | Troisième octet différent | 21.37 ET 255.0 = 21.0 | 21 |
| 192.168.10.140 | Masque /27 | 140 ET 224 = 128 | 30 |
| 192.168.10.64 | Limite : l'adresse du réseau elle-même | 64 ET 192 = 64 | 10 |
| 192.168.10.63 | Limite : dernière adresse du VLAN 40 | 63 ET 192 = 0 | 40 |
| 192.168.10.200 | Trou du plan d'adressage | 200 ET 240 = 192, aucun VLAN | 0 |
| 192.168.20.10 | Autre site (entrepôt de Mâcon) | aucun réseau du siège | 0 |
Questions 5, 6 et 7 : le programme complet.
# Composants fournis par le sujet
def octets(adresse):
"""Renvoie la liste des quatre entiers d'une adresse IPv4 écrite '192.168.10.71'."""
return [int(x) for x in adresse.split(".")]
VLANS = [
(10, "POSTES", "192.168.10.64", "255.255.255.192"),
(20, "SERVEURS", "192.168.10.176", "255.255.255.240"),
(21, "APPLIS", "192.168.21.0", "255.255.255.0"),
(30, "ENTREPOT", "192.168.10.128", "255.255.255.224"),
(40, "VISITEURS", "192.168.10.0", "255.255.255.192"),
(50, "TELEPHONIE", "192.168.10.160", "255.255.255.240"),
(60, "DMZ", "192.168.10.224", "255.255.255.240"),
(99, "ADMIN", "192.168.10.208", "255.255.255.240"),
]
def binaire8(n):
"""Écriture binaire de n (0 <= n <= 255) sur 8 bits, par divisions successives."""
bits = ""
for _ in range(8):
bits = str(n % 2) + bits
n = n // 2
return bits
def reseau(adresse, masque):
"""Adresse du réseau de adresse avec ce masque : ET bit à bit, octet par octet."""
a = octets(adresse)
m = octets(masque)
resultat = []
for i in range(4):
resultat.append(str(a[i] & m[i]))
return ".".join(resultat)
def vlan_de(adresse):
"""Numéro du VLAN du siège qui contient adresse, ou 0 si aucun."""
for numero, nom, adresse_reseau, masque in VLANS:
if reseau(adresse, masque) == adresse_reseau:
return numero
return 0
def hors_plan(adresses):
"""Liste des adresses qui n'appartiennent à aucun VLAN du siège."""
resultat = []
for adresse in adresses:
if vlan_de(adresse) == 0:
resultat.append(adresse)
return resultat
def prefixe(masque):
"""Longueur du préfixe d'un masque : nombre de bits à 1."""
total = 0
for octet in octets(masque):
total = total + binaire8(octet).count("1")
return total
# Jeu d'essai
assert binaire8(0) == "00000000"
assert binaire8(5) == "00000101"
assert binaire8(255) == "11111111"
assert reseau("192.168.10.71", "255.255.255.192") == "192.168.10.64"
essais = {
"192.168.10.71": 10, "192.168.10.180": 20, "192.168.21.37": 21,
"192.168.10.140": 30, "192.168.10.64": 10, "192.168.10.63": 40,
"192.168.10.200": 0, "192.168.20.10": 0,
}
for adresse, attendu in essais.items():
assert vlan_de(adresse) == attendu, adresse
assert hors_plan(["192.168.10.71", "192.168.10.200", "192.168.20.10"]) == ["192.168.10.200", "192.168.20.10"]
assert prefixe("255.255.255.192") == 26
assert prefixe("255.255.255.240") == 28
print("Tous les tests passent.")
Les assert gardent les tests dans le fichier : devant la commission, tu relances le programme et tout le jeu d'essai s'exécute en une seconde. Si un test échoue, Python affiche l'adresse en cause.
Les questions de l'entretien
| Question de la commission | Ce qu'on attend |
|---|---|
« Pourquoi ajoutez-vous le bit devant la chaîne dans binaire8 ? » | Le premier reste obtenu est le bit de poids faible : il doit finir à droite. |
« Que renvoie vlan_de("192.168.10.255") ? Pourquoi ? » | 0 : 255 ET 240 = 240, et aucun VLAN n'a le réseau 192.168.10.240. Le plan d'adressage s'arrête à .239. |
« Que se passe-t-il avec l'adresse "192.168.10" ? » | octets renvoie trois entiers et a[3] provoque une erreur d'indice. Correction : vérifier qu'il y a quatre octets entre 0 et 255 avant le calcul. |
| « Combien de calculs de réseau faites-vous au pire ? » | Un par VLAN, soit 8, quand l'adresse n'appartient à aucun : le parcours va jusqu'au bout. |
| « Comment renvoyer le nom du VLAN au lieu du numéro ? » | Renvoyer nom dans la boucle, et une chaîne comme "HORS PLAN" après la boucle ; changer les tests en conséquence. |
| « Pourquoi 192.168.10.64 est-il dans le VLAN 10, alors que ce n'est pas une adresse de machine ? » | Le calcul dit seulement qu'elle appartient au réseau ; c'est son adresse de réseau. Pour la refuser, il faudrait comparer aussi l'adresse au réseau et à la diffusion. |
Exercices
Exercice 1 sur 3 Faire la trace de binaire8 Réussi À revoir
Fais la trace de binaire8(13) : donne les valeurs de n et de bits après chacun des 8 tours de boucle.
Voir la réponseMasquer la réponse de l'exercice 1
| Tour | n % 2 | bits après le tour | n après le tour |
|---|---|---|---|
| 1 | 1 | 1 | 6 |
| 2 | 0 | 01 | 3 |
| 3 | 1 | 101 | 1 |
| 4 | 1 | 1101 | 0 |
| 5 | 0 | 01101 | 0 |
| 6 | 0 | 001101 | 0 |
| 7 | 0 | 0001101 | 0 |
| 8 | 0 | 00001101 | 0 |
Résultat : 00001101, et 8 + 4 + 1 = 13. Les tours 5 à 8 ajoutent les zéros de tête.
Tu avais trouvé ?
Exercice 2 sur 3 Corriger un algorithme fourni Réussi À revoir
Un collègue a écrit cette version de vlan_de. Trouve l'erreur, donne une adresse qui la révèle, puis corrige-la.
def vlan_de(adresse):
for numero, nom, adresse_reseau, masque in VLANS:
if reseau(adresse, masque) == adresse_reseau:
return numero
else:
return 0
Voir la réponseMasquer la réponse de l'exercice 2
Le return 0 est dans la boucle : dès le premier VLAN de la liste (le VLAN 10), la fonction renvoie un résultat, et les autres VLAN ne sont jamais examinés. L'adresse 192.168.10.180 le révèle : elle est dans le VLAN 20, mais la fonction renvoie 0. Correction : supprimer le else et placer return 0 après la boucle, au même niveau que le for.
Tu avais trouvé ?
Exercice 3 sur 3 Compter par VLAN Réussi À revoir
Écris une fonction compter(adresses, numero) qui renvoie le nombre d'adresses de la liste qui appartiennent au VLAN numero. Donne un jeu d'essai de trois cas.
Voir la réponseMasquer la réponse de l'exercice 3
def compter(adresses, numero):
"""Nombre d'adresses de la liste qui appartiennent au VLAN numero."""
total = 0
for adresse in adresses:
if vlan_de(adresse) == numero:
total = total + 1
return total
liste = ["192.168.10.71", "192.168.10.100", "192.168.10.180", "192.168.20.10"]
assert compter(liste, 10) == 2 # .71 et .100 sont dans 192.168.10.64/26
assert compter(liste, 99) == 0 # aucune adresse d'administration
assert compter([], 10) == 0 # liste vide
C'est le motif du comptage : un compteur initialisé à 0, incrémenté sous condition, renvoyé après la boucle. Le cas de la liste vide vérifie l'initialisation.
Tu avais trouvé ?