Solution de Adresse IPv4 - Sujet 22 - EP NSI 2025
Énoncé du problème
Exercice 1
EXERCICE 1 (10 points)
Écrire une fonction recherche qui prend en paramètres elt un nombre entier et tab un tableau de nombres entiers (type list), et qui renvoie l’indice de la dernière occurrence de elt dans tab si elt est dans tab et None sinon.
Exemples :
>>> recherche(1, [2, 3, 4]) # renvoie None
>>> recherche(1, [10, 12, 1, 56])
2
>>> recherche(1, [1, 0, 42, 7])
0
>>> recherche(1, [1, 50, 1])
2
>>> recherche(1, [8, 1, 10, 1, 7, 1, 8])
5
Exercice 2
EXERCICE 2 (10 points)
On définit une classe gérant une adresse IPv4.
On rappelle qu’une adresse IPv4 est une adresse de longueur 4 octets, notée en décimale à point, en séparant chacun des octets par un point. On considère un réseau privé avec une plage d’adresses IP de 192.168.0.0 à 192.168.0.255.
On considère que les adresses IP saisies sont valides.
Les adresses IP 192.168.0.0 et 192.168.0.255 sont des adresses réservées.
Le code ci-dessous implémente la classe AdresseIP.
class AdresseIP:
def __init__(self, adresse):
self.adresse =...
def liste_octets(self):
"""renvoie une liste de nombres entiers,
la liste des octets de l'adresse IP"""
# Note : split découpe la chaine de caractères
# en fonction du séparateur
return [int(i) for i in self.adresse.split(".")]
def est_reservee(self):
"""renvoie True si l'adresse IP est une adresse
réservée, False sinon"""
reservees = [ ... ]
return ...
def adresse_suivante(self):
"""renvoie un objet de AdresseIP avec l'adresse
IP qui suit l'adresse self si elle existe et None sinon"""
octets = ...
if ... == 254:
return None
octet_nouveau = ... + ...
return AdresseIP('192.168.0.' + ...)
Compléter le code ci-dessus et instancier trois objets : adresse1, adresse2, adresse3 avec respectivement les arguments suivants :
'192.168.0.1','192.168.0.2','192.168.0.0'
Vérifier que :
>>> adresse1.liste_octets()
[192, 168, 0, 1]
>>> adresse1.est_reservee()
False
>>> adresse3.est_reservee()
True
>>> adresse2.adresse_suivante().adresse # acces valide à adresse
# ici car on sait que l'adresse suivante existe
'192.168.0.3'
Les contraintes ci-dessous sont ajoutées par la plateforme et ne font pas partie du sujet.
Exercice 1
Contraintes :
eltest un nombre entier (int)tabest un tableau (list) de nombres entiers, éventuellement vide0 <= len(tab) <= 10^4-10^9 <= elt <= 10^9et-10^9 <= tab[i] <= 10^9tabn’est pas nécessairement trié et peut contenir plusieurs fois la même valeur- la fonction renvoie l’indice de la dernière occurrence de
elt, etNonesieltn’apparaît pas danstab(en particulier sitabest vide)
Exercice 2
Contraintes :
adresseest une chaîne de caractères (str) de la forme'192.168.0.x'avec0 <= x <= 255, écrite sans zéro initial- toutes les adresses fournies sont valides : aucune vérification de validité n’est demandée
liste_octetsrenvoie une liste de 4 nombres entiers compris entre0et255- les adresses réservées sont exactement
192.168.0.0et192.168.0.255 adresse_suivanterenvoieNonelorsque le dernier octet vaut254, et sinon un objetAdresseIPdont l’attributadresseest l’adresse suivante- le comportement de
adresse_suivantesur192.168.0.255n’est pas spécifié par le sujet et n’est pas évalué
Solution
Exercice 1 - indice de la dernière occurrence
L’idée. On cherche la dernière fois que elt apparaît dans tab. Le plus simple est de parcourir le tableau du début à la fin en retenant dans une variable l’indice de chaque occurrence rencontrée. Chaque nouvelle occurrence écrase la précédente : quand la boucle est terminée, la variable contient donc l’indice de la dernière. Si on n’a jamais rien trouvé, elle vaut encore None, ce qui est exactement la réponse attendue.
Un petit exemple. Pour recherche(1, [8, 1, 10, 1, 7, 1, 8]), la variable prend successivement la valeur 1, puis 3, puis 5. À la fin de la boucle elle vaut 5 : c’est la réponse.
def recherche(elt, tab):
indice = None
# On parcourt tout le tableau : chaque occurrence trouvée remplace la
# précédente, donc à la fin indice retient bien la dernière
for i in range(len(tab)):
if tab[i] == elt:
indice = i
return indice
indice est initialisé à None : c’est la valeur qu’on renverra si aucune case ne contient elt, et cela règle du même coup le cas du tableau vide, où la boucle ne s’exécute pas du tout. On boucle sur range(len(tab)) et non sur les valeurs, parce que c’est l’indice i qui nous intéresse, pas le contenu. Surtout, on ne s’arrête pas à la première occurrence : il faut aller jusqu’au bout du tableau pour être sûr d’avoir vu la dernière.
Variante : on peut aussi parcourir le tableau à l’envers et renvoyer le premier indice trouvé, mais il faut alors penser à renvoyer None après la boucle.
Exercice 2 - la classe AdresseIP
L’idée. Il y a quatre trous à compléter, et chacun est court.
__init__doit simplement ranger la chaîne reçue dans l’attributself.adresse, puisque toutes les autres méthodes s’en servent.est_reservee: les deux seules adresses réservées sont192.168.0.0et192.168.0.255. On les place dans la listereservees, puis on demande avecinsiself.adresses’y trouve.adresse_suivante: dans ce réseau, seul le dernier octet change. On récupère les octets avecliste_octets()et on regarde le dernier,octets[3]. S’il vaut254, l’adresse suivante serait192.168.0.255, qui est réservée : on renvoieNone. Sinon on ajoute1à ce dernier octet et on construit une nouvelleAdresseIP.
Un petit exemple. Pour 192.168.0.2, liste_octets() donne [192, 168, 0, 2], le dernier octet vaut 2, il n’est pas égal à 254, donc le nouvel octet vaut 3 et on renvoie une AdresseIP d’adresse '192.168.0.3'.
class AdresseIP:
def __init__(self, adresse):
self.adresse = adresse
def liste_octets(self):
"""renvoie une liste de nombres entiers,
la liste des octets de l'adresse IP"""
# Note : split découpe la chaine de caractères
# en fonction du séparateur
return [int(i) for i in self.adresse.split(".")]
def est_reservee(self):
"""renvoie True si l'adresse IP est une adresse
réservée, False sinon"""
reservees = ['192.168.0.0', '192.168.0.255']
return self.adresse in reservees
def adresse_suivante(self):
"""renvoie un objet de AdresseIP avec l'adresse
IP qui suit l'adresse self si elle existe et None sinon"""
octets = self.liste_octets()
# Seul le dernier octet change : s'il vaut 254, l'adresse suivante
# serait 192.168.0.255, qui est réservée
if octets[3] == 254:
return None
octet_nouveau = octets[3] + 1
return AdresseIP('192.168.0.' + str(octet_nouveau))
Quelques points de vigilance. Dans est_reservee, la comparaison porte sur la chaîne self.adresse : les éléments de reservees sont donc bien des chaînes entre guillemets, pas des nombres. Dans adresse_suivante, octets est une liste de quatre entiers et octets[3] en est le dernier, celui des unités. Enfin octet_nouveau est un entier alors qu’on veut construire une chaîne : la conversion par str(octet_nouveau) est indispensable, sans elle Python refuse d’additionner une chaîne et un entier.
Pour vérifier, on crée les trois objets demandés par le sujet :
adresse1 = AdresseIP('192.168.0.1')
adresse2 = AdresseIP('192.168.0.2')
adresse3 = AdresseIP('192.168.0.0')
et on retrouve les résultats attendus : adresse1.liste_octets() vaut [192, 168, 0, 1], adresse1.est_reservee() vaut False, adresse3.est_reservee() vaut True, et adresse2.adresse_suivante().adresse vaut '192.168.0.3'.