Corrigé Bac
Sujet 2023 - Jour 1 (20/03/2023) - Spécialité NSI - Corrigé

Sujet bac : annale 20 mars 2023

EXERCICE 1 (3 points)

$\bold{1.a.}$ Une clé primaire est un attribut dont la valeur prise pour chaque enregistrement dans la table doit être unique. Cette unicité permet de distinguer deux entrées dans la table.

$\bold{1.b.}$ Une clé étrangère permet de mettre en relation un enregistrement d’une table donnée vers un enregistrement d’une autre table.
La clé étrangère $\text{id\textunderscore client}$ dans la table $\text{Commandes}$ permet de relier chaque commande à un client dans la table $\text{Clients}$ via la clé primaire de celle-ci.
La clé étrangère $\text{id\textunderscore meuble}$ dans la table $\text{Commandes}$ permet de relier chaque commande à meuble dans la table $\text{Meubles}$ via la clé primaire de celle-ci.

$\bold{1.c.}$
$\text{Meubles (\underline{id} : INT, intitule : VARCHAR, prix : FLOAT, stock : INT, description : VARCHAR)}$

bannière astuce

Astuce

La clé primaire est indiquée par un soulignement, conformément à l’énoncé.

$\bold{2.}$ La requête correspond à la recherche des enregistrements, dans la table $\text{Meubles}$, dont l’attribut $\text{intitule}$ contient la valeur $\text{‘skap’}$ et dont on récupère la valeur des attributs $\text{id}$, $\text{stock}$ et $\text{description}$.

$62$ $2$ $\text{‘Armoire blanche 3 portes’}$
$63$ $3$ $\text{‘Armoire noire 3 portes’}$

$\bold{3.}$
$$\begin{aligned} &\text{SELECT nom, prenom}\\ &\text{FROM Clients}\\ &\text{WHERE ville = ‘Paris’;} \end{aligned}$$

La requête spécifie dans l’ordre des lignes :

  • les attributs retenus ;
  • la table concernée ;
  • la condition remplie par les enregistrements recherchés.

$\bold{4.}$
$$\begin{aligned} &\text{ UPDATE Meubles}\\ &\text{ SET stock = } 50\\ &\text{ WHERE id = } 98; \end{aligned}$$

bannière attention

Attention

Il ne faut pas utiliser la condition $\text{WHERE intitule = ‘hylla’}$ car l’attribut $\text{intitule}$ n’est pas une clé primaire et ne permet pas d’identifier à coup sûr l’enregistrement dont le champ $\text{id}$ a pour valeur $98$.

$\bold{5.}$
$$\begin{aligned} &\text{INSERT INTO Meubles}\\ &\text{VALUES (65, ‘matta’, 95.99, 25, ‘Tapis vert à pois rouges’)} \end{aligned}$$

bannière astuce

Astuce

La requête suivante est également possible : $$\begin{aligned} &\text{INSERT INTO Meubles}\\ &\text{(id, intitule, prix, stock, description)}\\ &\text{VALUES (65, ‘matta’, 95.99, 25, ‘Tapis vert à pois rouges’)} \end{aligned}$$

$\bold{6.}$
$$\begin{aligned} &\text{SELECT nom, prenom }\\ &\text{FROM Clients }\\ &\text{JOIN Commandes ON Clients.id = Commandes.idClient }\\ &\text{WHERE date = ‘30/04/2021’} \end{aligned}$$

bannière astuce

Astuce

La requête demandée par l’énoncé s’appuie sur des données situées dans plusieurs tables. Une jointure JOIN est donc nécessaire. Lorsqu’une jointure n’est pas précédée d’une clause de précision (INNER, LEFT, RIGHT ou FULL), c’est INNER qui est le défaut, cas que l’on observe dans la réponse ci-dessus. Il s’agit donc ici de ne retenir que les identifiants clients qui se situent à la fois dans la table $\text{Commandes}$ et dans la table $\text{Clients}$.

EXERCICE 2 (3 points)

$\bold{1.}$ En observant le schéma, on constate que R1, R2, R3, R4 et R5 ont chacun au moins 2 liaisons avec des routeurs voisins.
Le réseau est bâti de telle sorte que chaque routeur est rattaché à plus d’un routeur. Ainsi, si une liaison entre deux routeurs est coupée, la communication avec ces derniers est maintenue via la ou les liaisons que ces routeurs possèdent avec un autre routeur.

$\bold{2.}$ Le chemin suivi est : SiteB $\to$ Routeur R2 $\to$ Routeur R3 $\to$ Routeur R4 $\to$ Routeur R5 $\to$ SiteC.

bannière astuce

Astuce

SiteB est rattaché au routeur R2. La table de routage dans le routeur R2 indique que la prochaine étape pour joindre SiteC est le routeur R3. Puis la table de routage dans le routeur R3 indique que la prochaine étape pour joindre SiteC est le routeur R4. Puis la table de routage dans le routeur R4 indique que la prochaine étape pour joindre SiteC est le routeur R5. Enfin, la table de routage dans le routeur R5 indique que SiteC est local, donc que les paquets peuvent lui être adressés directement.

$\bold{3.}$

Routeur R1 (RIP)
Destination Coût Nombre de sauts
Site A Local 0
Site B R2 1
Site C R2 2
Site D R3 2
bannière attention

Attention

Comme indiqué dans l’énoncé, le protocole RIP choisit toujours le chemin qui minimise le nombre de routeurs traversés. Par exemple, le routeur R1 choisit de passer par R2 pour transmettre les paquets destinés au site SiteB. Un autre chemin était possible : R3, puis R2. Mais dans ce cas, le nombre de sauts aurait été de 2, donc moins optimisé que celui du chemin via R2.

$\bold{4.}$ Le choix du protocole RIP va privilégier un chemin passant par la liaison Liaison2 pour les échanges entre les sites SiteA et SiteC, entre les sites SiteB et SiteC ainsi qu’entre les sites SiteB et SiteD. Or d’autres chemins sont possibles, évitant la liaison Liaison2, et donc plus rapides même si plus longs. Voilà pourquoi le choix du protocole RIP n’est pas judicieux car il ne tient pas compte du débit des liaisons.

bannière astuce

Astuce

Pour acheminer les paquets de SiteA à SiteC, le chemin présentant le nombre minimal de sauts est : SiteA $\to$ R1 $\to$ R2 $\to$ R5 $\to$ SiteC, soit 2 sauts. Mais ce chemin emprunte la liaison Liaison2.
Un autre chemin aurait été possible : SiteA $\to$ R1 $\to$ R3 $\to$ R4 $\to$ R5 $\to$ SiteC, soit 3 sauts. Ce chemin n’emprunte pas la liaison Liaison2.

$\bold{5.a.}$ Sachant que le coût est inversement proportionnel au débit, il faut repérer le coût le plus élevé dans le tableau pour identifier la liaison dont le débit est le plus faible. Il s’agit donc ici de la liaison Liaison2.

bannière astuce

Astuce

Il est possible de déterminer le débit de la liaison Liaison2 en s’appuyant sur la formule donnée dans l’énoncé. Ce débit vaut : $\frac{10^{10}}{10^6} = 10\ \text{kbit}/\text{s}$

$\bold{5.b.}$

Chemin de SiteA à SiteC Coût
SiteA $\to$ R1 $\to$ R2 $\to$ R5 $\to$ SiteC 1 100 000
SiteA $\to$ R1 $\to$ R2 $\to$ R3 $\to$ R4 $\to$ R5 $\to$ SiteC 100 020
SiteA $\to$ R1 $\to$ R3 $\to$ R2 $\to$ R5 $\to$ SiteC 1 050 005
SiteA $\to$ R1 $\to$ R3 $\to$ R4 $\to$ R5 $\to$ SiteC 50 015

Pour calculer le coût du premier chemin du tableau, on identifie successivement les liaisons empruntées et on additionne leur poids. Liaison1, Liaison2, soit 100 000 + 1 000 000 = 1 100 000. La même méthode est employée pour le reste du tableau.

$\bold{5.c.}$ Pour déterminer le routeur suivant pour acheminer des paquets vers le site SiteB depuis le routeur R1, il faut identifier tous les chemins possibles de R1 vers le site SiteB et retenir celui qui présente le coût le moins élevé.
Ainsi, de R1 au site SiteB, on identifie xx chemins :

  • R1 $\to$ R2 $\to$ SiteB : Liaison 1, soit coût de 100 000
  • R1 $\to$ R3 $\to$ R2 $\to$ SiteB : Liaison 4, Liaison 3, soit 50 000 + 5 = 50 005
  • R1 $\to$ R3 $\to$ R4 $\to$ R5 $\to$ R2 $\to$ SiteB : Liaison 4, Liaison 5, Liaison 2 soit 50 000 + 5 + 10 + 1 000 000 = 1 050 015 On retient donc le chemin R1 $\to$ R3 $\to$ R2 $\to$ SiteB.
    La même méthode est employée pour le reste du tableau.

Routeur R1 (OSPF)
Destination Suivant Coût total du chemin
Site A Local 0
Site B R3 50 005
Site C R3 50 015
Site D R3 50 005

EXERCICE 3 (6 points)

Partie 1

$\bold{1.}$
$\text{nom}$ : attribut de la classe $\text{Region}$
$\text{tab\textunderscore voisines}$ : attribut de la classe $\text{Region}$
$\text{tab\textunderscore couleurs\textunderscore disponibles}$ : attribut de la classe $\text{Region}$
$\text{couleur\textunderscore attribuee}$ : attribut de la classe $\text{Region}$

bannière rappel

Rappel

La classe est un modèle qui permet d’instancier des objets. Ce modèle est constitué d’attributs (données représentant l’objet) et de méthodes (opérations applicables à l’objet). Ici, la classe est $\text{Region}$, un objet serait $\text{Region(‘Ile de France’)}$, un attribut est $\text{‘nom’}$ et l’énoncé définit la méthode $\text{\textunderscore \textunderscore init\textunderscore \textunderscore}$ pour la classe $\text{Region}$.

$\bold{2.}$ Le paramètre $\text{nom\textunderscore region}$ de la méthode $\text{\textunderscore \textunderscore init\textunderscore \textunderscore}$ de la classe $\text{Region}$ est de type $\text{‘str’}$ selon le commentaire donné dans le code fourni par l’énoncé à la ligne 6. Il s’agit donc d’une chaîne de caractères.

$\bold{3.}$ $\text{ge = Region(‘Grand Est ‘)}$
On instancie la classe $\text{Region}$ en lui passant la chaîne de caractères $\text{‘Grand Est’}$. La méthode $\text{\textunderscore \textunderscore init\textunderscore \textunderscore}$ est alors déclenchée avec le paramètre $\text{‘Grand Est’}$.

$\bold{4.}$ Le nom de la méthode évoquée dans la question et le commentaire qui figure dans son code sont suffisamment explicites pour comprendre qu’elle renvoie le premier élément de l’attribut tableau $\text{tab\textunderscore couleurs\textunderscore disponibles}$ de la classe $\text{Region}$.

$$\begin{aligned} &\text{def renvoie\textunderscore premiere\textunderscore couleur\textunderscore disponible(self):} \\ &\qquad\text{return self.tab\textunderscore couleurs\textunderscore disponibles[0]} \end{aligned}$$

$\bold{5.}$ Le nombre de régions voisines correspond au nombre d’éléments qui se trouvent dans l’attribut tableau $\text{tab\textunderscore voisines}$ de la classe $\text{Region}$. C’est l’instruction $\text{len}$ qui donne cette valeur.

$$\begin{aligned} &\text{def renvoie\textunderscore nb\textunderscore voisines(self):} \\ &\qquad\text{return len(self.tab\textunderscore voisines)} \end{aligned}$$

$\bold{6.}$
$$\begin{aligned} &\text{def est\textunderscore coloriee(self):} \\ &\qquad\text{if self.couleur\textunderscore attribuee == None:}\\ &\qquad \qquad \text{return False}\\ &\qquad\text{else:} \\ &\qquad \qquad \text{return True} \end{aligned}$$

bannière astuce

Astuce

Une alternative au code précédent est la suivante : $$\begin{aligned} &\text{def est\textunderscore coloriee(self):} \\ &\qquad\text{return self.couleur\textunderscore attribuee != None} \end{aligned}$$

$\bold{7.}$
$$\begin{aligned} &\text{def retire\textunderscore couleur(self, couleur):} \\ &\qquad\text{if couleur in self.tab\textunderscore couleurs\textunderscore disponibles:}\\ &\qquad \qquad \text{ self.tab\textunderscore couleurs\textunderscore disponibles.remove(couleur)} \end{aligned}$$

bannière attention

Attention

Il est nécessaire de vérifier que la couleur est présente dans le tableau avant de la supprimer, car, dans le cas contraire, l’instruction $\text{remove}$ génère une erreur.

$\bold{8.}$
$$\begin{aligned} &\text{def est\textunderscore voisine(self, region):} \\ &\qquad\text{for region\textunderscore voisine in self.tab\textunderscore voisines:}\\ &\qquad \qquad \text{if region == region\textunderscore voisine:}\\ &\qquad \qquad \qquad\text{return True}\\ &\qquad \text{return False} \end{aligned}$$

bannière astuce

Astuce

Si l’usage d’une boucle n’avait pas été imposé, le code aurait été largement réduit : $$\begin{aligned} &\text{def est\textunderscore voisine(self, region):} \\ &\qquad\text{return region in self.tab\textunderscore voisines } \end{aligned}$$

Partie 2

$\bold{9.}$
$$\begin{aligned} &\text{def renvoie\textunderscore tab\textunderscore regions\textunderscore non\textunderscore coloriees(self):} \\ &\qquad\text{tab=[\,]}\\ &\qquad\text{for region in self.tab\textunderscore regions:}\\ &\qquad \qquad \text{if not region.est\textunderscore coloriee():}\\ &\qquad \qquad \qquad\text{tab.append(region)}\\ &\qquad \text{return tab} \end{aligned}$$

bannière astuce

Astuce

Penser à créer le tableau avant de le remplir. Penser également à mettre les parenthèses ouvrante et fermante lors de la l’appel de la méthode $\text{est\textunderscore coloriee}$, même si celle-ci n’admet pas de paramètres.

$\bold{10.a.}$ Pour que la méthode $\text{renvoie\textunderscore max}$ renvoie $\text{None}$, il faut que la boucle $\text{for}$ ne démarre jamais, ainsi, $\text{region\textunderscore max}$ reste initialisé à $\text{None}$. Il faut donc que la méthode $\text{renvoie\textunderscore tab\textunderscore regions\textunderscore non\textunderscore coloriees}$ soit vide. Deux cas sont possibles :

  • Si l’attribut tableau $\text{tab\textunderscore regions}$ de la classe $\text{Pays}$ est vide, autrement dit, si aucune région n’est définie pour le pays ;
  • Si la méthode $\text{renvoie\textunderscore tab\textunderscore regions\textunderscore non\textunderscore coloriees}$ renvoie un tableau vide, autrement dit, si toutes les régions sont coloriées.

$\bold{10.b.}$ Lorsqu’elle ne renvoie pas $\text{None}$, la méthode $\text{renvoie\textunderscore max}$ renvoie la région :

  • qui n’est pas coloriée et ;
  • qui a le plus de voisines.

On peut noter que si deux régions sont ex aequo, c’est la première des deux dans la liste des régions qui est retenue.

$\bold{11.}$
$$\begin{aligned} &\text{def colorie(self):} \\ &\qquad\text{region\textunderscore max = self.renvoie\textunderscore max()}\\ &\qquad\text{while region\textunderscore max != None:}\\ &\qquad\qquad\text{couleur = region\textunderscore max.renvoie\textunderscore premiere\textunderscore couleur\textunderscore disponible()}\\ &\qquad\qquad\text{region\textunderscore max.couleur\textunderscore attribuee = couleur}\\ &\qquad\qquad\text{for region\textunderscore voisine in region\textunderscore max.tab\textunderscore voisines:}\\ &\qquad \qquad\qquad \text{ region.retire\textunderscore couleur(couleur):}\\ &\qquad \qquad \text{region\textunderscore max = self.renvoie\textunderscore max()} \end{aligned}$$

Noter que la méthode $\text{self.renvoie\textunderscore max()}$ est effectivement appelée deux fois, pour des objectifs différents. La première fois pour initialiser la variable $\text{region\textunderscore max}$ avant l’entrée dans la boucle, la seconde dans la boucle, pour la faire progresser.