Baccalauréat — Amérique du Nord J2 — 2024 — NSI
Bac NSI — Amérique du Nord 2024 (Jour 2)
Sujet
Présentation de l'épreuve
Sujet officiel du baccalauréat général, épreuve de spécialité Numérique et Sciences Informatiques, session 2024, Amérique du Nord, jour 2 (code sujet 24-NSIJ2AN1). Durée 3h30, calculatrice interdite. Le sujet comporte 3 exercices indépendants, tous à traiter.
Exercice 1 — Le tri de Stooge (6 points)
Pour trier les éléments d'indice i à j (i < j) d'un tableau tab par le tri de Stooge : si les éléments d'indice i et j sont mal placés, on les échange ; puis, s'il y a au moins trois éléments entre les indices i et j, on trie les deux premiers tiers du tableau par cette même méthode, puis les deux derniers tiers, puis à nouveau les deux premiers tiers. Le découpage utilise k = (j - i + 1) // 3 et les indices intermédiaires i+k et j-k.
Code partiel :
def triStooge(tab, i, j):
if tab[i] > tab[j]:
echange(tab, i, j)
if (j - i) > 1:
k = (j - i + 1)//3
triStooge(...) # ligne 6
triStooge(...) # ligne 7
triStooge(...) # ligne 8- Écrire
echange(tab, i, j), qui échange sur place les valeurs detabaux indicesietj(ne renvoie rien). - Compléter les lignes 6, 7 et 8.
- L'algorithme est-il itératif ou récursif ? Justifier.
Soit l'appel triStooge(A, 0, 5) avec A = [5, 6, 4, 2, 3, 1].
- Déterminer la valeur de
klors de ce premier appel, en justifiant. - Dénombrer le nombre d'appels récursifs effectués lors de ce tri (sans compter l'appel initial), sachant que l'arbre des appels a 3 niveaux de profondeur après l'appel initial, chaque nœud ayant 3 enfants dès que
(j-i) > 1. - Le premier appel se divise en 3 appels :
triStooge(A,0,3),triStooge(A,2,5), et un troisième appel de mêmes paramètres que le premier (triStooge(A,0,3), puisque le troisième sous-appel retrie les deux premiers tiers). Le second de ces trois appels,triStooge(A,2,5), se divise à son tour selon le même principe avec k=(5-2+1)//3=1 : déterminer ses trois sous-appels. - Reprendre
A = [5, 4, 6, 2]et l'appeltriStooge(A, 0, 3). Ce dernier commence par comparertab[0]ettab[3](5 et 2 : mal placés, échange), puis se divise en 3 appels imbriqués (k=1) :triStooge(A,0,2),triStooge(A,1,3),triStooge(A,0,2). Compléter le tableau de trace suivant (valeur deAavant/après chaque étape) :
| Étape | Valeur de A avant | Valeur de A après |
|---|---|---|
| triStooge(A,0,3) — échange initial tab[0]/tab[3] | [5, 4, 6, 2] | ?? |
| triStooge(A,0,2) | ?? | ?? |
| triStooge(A,1,3) | ?? | ?? |
| triStooge(A,0,2) | ?? | [2, 4, 5, 6] |
- Le coût en temps, dans le pire des cas, du tri de Stooge est de l'ordre de n^e avec e environ égal à 8/3. Donner un algorithme de tri au coût strictement meilleur.
Exercice 2 — SQL et bases de données (6 points)
Un pharmacien crée son système de gestion des médicaments. Table client(id_client: INT, nom_client: VARCHAR(30), prenom_client: VARCHAR(30), num_secu_sociale: VARCHAR(15)) :
| id_client | nom_client | prenom_client | num_secu_sociale |
|---|---|---|---|
| 1 | Martin | Sophie | 202103812326129 |
| 2 | Dufour | Marc | 105073817009595 |
- Écrire le résultat de
SELECT nom_client, prenom_client FROM client ORDER BY nom_client;.
Table medicament(id_medic: INT, nom_medic: VARCHAR(30), categorie: VARCHAR(20), conditionnement: INT, quantite: INT, prix: FLOAT) :
| id_medic | nom_medic | categorie | conditionnement | quantite | prix |
|---|---|---|---|---|---|
| 1 | Paracétamol 1 gramme CP | antalgique | 8 | 50 | 3,50 |
| 2 | Acide acétylsalicylique | antalgique | 8 | 20 | 2,30 |
| 3 | Gel hydroalcoolique 100 ml | désinfectant | 1 | 300 | 2,30 |
| 4 | Acide ascorbique | vitamine | 10 | 450 | 5,50 |
- Écrire une requête affichant les noms des médicaments de prix strictement inférieur à 3 €.
Madame Sophie Martin présente une ordonnance (Dr Louis Farti, Grenoble, 13 décembre 2023) : Paracétamol 1 gramme CP (boîte de 8), 1 comprimé par prise, au maximum 3 comprimés par jour, pendant 2 jours ; Acide ascorbique 500 mg effervescent (boîte de 10), 1 comprimé par jour pendant 4 semaines. Ces prescriptions sont saisies dans ordonnance(id_ordo, id_client, date_ordo, id_medic, nb_boites) :
| id_ordo | id_client | date_ordo | id_medic | nb_boites |
|---|---|---|---|---|
| 6 | 2 | 2023-11-29 | 2 | 2 |
| 7 | 1 | 2023-12-13 | 1 | ... |
| 8 | 1 | 2023-12-13 | 4 | ... |
- Écrire la requête ajoutant la troisième cliente Nathalie Durand (carte Vitale n° 2 69 05 49 588 157 80), avec
id_client = 3. - Donner les attributs devant être déclarés clés étrangères de
ordonnance, et préciser leur utilité. - Indiquer, pour les lignes 7 et 8, le nombre de boîtes prescrites (justifier à partir du texte de l'ordonnance et du conditionnement de chaque médicament).
- Écrire la requête mettant à jour la quantité en stock d'Acide ascorbique suite à cette délivrance.
- Calculer le coût total des médicaments fournis à Mme Martin (sans écrire de requête, en justifiant le calcul à partir du prix par boîte).
- Écrire la requête affichant le nom du médicament pour l'ordonnance d'
id_ordo6.
Exercice 3 — Programmation objet, réseaux et sécurisation (8 points)
Un réseau local relie les machines d'Alice (192.168.1.1) et de Bob (192.168.1.2) ; l'adresse de diffusion est 192.168.1.255 (réservée), le masque 255.255.255.0.
Partie A.
- Donner une adresse IP possible pour la machine de Charlie afin qu'elle communique avec Alice et Bob, en justifiant toutes les conditions à respecter.
Le réseau sert à des transactions en monnaie nsicoin entre trois utilisateurs :
class Transaction:
def __init__(self, expediteur, destinataire, montant):
self.expediteur = expediteur
self.destinataire = destinataire
self.montant = montant- Dans un intervalle de dix minutes, Alice envoie dix nsicoin à Charlie, puis Bob envoie cinq nsicoin à Alice. Écrire la liste Python de ces transactions.
Pour tracer toutes les transactions, on utilise une blockchain :
class Bloc:
def __init__(self, liste_transactions, bloc_precedent):
self.liste_transactions = liste_transactions
self.bloc_precedent = bloc_precedent # de type Bloc
class Blockchain:
def __init__(self):
self.tete = self.creer_bloc_0()
def creer_bloc_0(self):
"""Cree le premier bloc, qui distribue 100 nsicoin a chaque
utilisateur (expediteur pseudo-utilisateur Genesis)."""
liste_transactions = [
Transaction("Genesis", "Alice", 100),
Transaction("Genesis", "Bob", 100),
Transaction("Genesis", "Charlie", 100)
]
return Bloc(liste_transactions, None)Les trois premiers blocs d'une blockchain (tête = bloc2) sont : bloc0 (les 3 transactions Genesis ci-dessus) ; bloc1 (Alice->Charlie 50 ; Charlie->Bob 30) ; bloc2 (Bob->Charlie 20 ; Bob->Charlie 20 ; Charlie->Alice 30).
- Pourquoi la valeur de l'attribut
bloc_precedentdu bloc0 est-elleNone? - Donner la valeur de l'attribut
bloc_precedentdu bloc1 pour qu'il soit lié au bloc0. - À l'aide des classes
BlocetBlockchain, écrire le code créant un objetma_blockchainreprésentant cette situation. - Donner le solde en nsicoin de Bob à l'issue du bloc2.
- Écrire la méthode
ajouter_bloc(self, liste_transactions)deBlockchain, qui crée un nouveau bloc (à partir des transactions passées et du bloc courant en tête) et l'ajoute à la chaîne. - Lorsqu'un utilisateur ajoute un bloc, il l'envoie à tous les autres membres. Donner le nom et la valeur de l'adresse IP à utiliser pour cet envoi.
- On veut doter
Blocd'une méthode récursivecalculer_solde(self, utilisateur)renvoyant le solde d'un utilisateur à l'issue de ce bloc (cas de base : bloc sans précédent, solde 0 ; cas général : appel récursif sur le bloc précédent, puis ajustement selon les transactions de ce bloc où l'utilisateur est expéditeur ou destinataire). L'écrire. - Écrire l'appel permettant de calculer le solde actuel d'Alice à partir de
ma_blockchain.
Partie B — Sécurisation. On enrichit Bloc de trois attributs : hash_bloc_precedent (le hash du bloc précédent, ou "0" s'il n'y en a pas), nonce (entier, 0 par défaut), hash (calculé par calculer_hash, non détaillé ici). Propriétés du hash : il dépend de tout le contenu du bloc et uniquement de lui ; il se calcule rapidement ; la moindre modification du bloc change complètement le hash ; il est impossible de retrouver le bloc à partir de son hash ; deux blocs de même hash sont identiques. « Miner » un bloc consiste à trouver une valeur de nonce telle que le hash commence par "00".
- Expliquer en quoi consiste la recherche exhaustive de cette valeur de
nonce. - Donner, en justifiant, la valeur de
hash_bloc_precedentdu bloc0. - Le hash étant codé sur 256 bits, donner le calcul du nombre de hash possibles.
- Compléter le code de
minage_bloc:
def minage_bloc(self):
"""modifie le nonce d'un bloc pour que son hash commence par '00'
en enumerant tous les entiers naturels en partant de 0."""
self.nonce = 0
self.hash = self.calculer_hash()
while ... :
self.nonce = ...
self.hash = ...Corrigé
Créez un compte gratuit : votre première correction est offerte.