Exercice 3 Asie – Bac NSI 2025 – Jour 2

🔥🔥🔥🔥🔥
Cet exercice porte sur la programmation Python (dictionnaire, récursivité, spécification), la programmation orientée objet, les bases de données relationnelles, les requêtes SQL et les arbres binaires.
Dans cette partie, on s'intéresse à la gestion de la base de données d'un hôpital.

mots clés: POO, BDD, SQL, arbres binaires

🔎 Voir les exercices similaires ↓

📘 Sujet PDF

Asie – Bac NSI 2025 – Jour 2 Énoncé de l'exercice 3

Cet exercice porte sur la programmation Python (dictionnaire, récursivité, spécification), la programmation orientée objet, les bases de données relationnelles, les requêtes SQL et les arbres binaires.

Cet exercice est composé de 3 parties indépendantes.

Partie A

Dans cette partie, on s’intéresse à la gestion de la base de données d’un hôpital. On pourra utiliser les mots-clés SQL suivants : AND, FROM, INSERT, INTO, JOIN, ON, SELECT, SET, UPDATE, VALUES, WHERE. On utilisera également la fonction d’agrégation COUNT qui renvoie le nombre d’enregistrements correspondant à une requête.

La table Patient possède les attributs suivants :

  • nom_patient de type TEXT (clé primaire) ;

  • prenom de type TEXT ;

  • numero_secu de type INT ;

  • age de type INT.

Patient
nom_patient prenom numero_secu age
Heartman Alice 207053523800187 17
Douglas Bob 100017500155572 24
Woods Caroll 258125930610747 65

La table Symptome possède les attributs suivants :

  • nom_patient de type TEXT (clé primaire et clé étrangère) ;

  • toux de type TEXT ;

  • fievre de type TEXT ;

  • nausee de type TEXT ;

  • anosmie de type TEXT.

Symptome
nom_patient toux fievre nausee anosmie
Heartman Oui Non Non Oui
Douglas Non Oui Oui Non
Woods Oui Oui Non Non

La table Maladie possède, entre autres, l’attribut nom_maladie de type TEXT, qui est la clé primaire. Les autres attributs de cette table ne sont pas représentés car ils ne sont pas utiles pour l’exercice.

Maladie
nom_maladie
Covid-19
Gastroentérite

La table Diagnostic possède les attributs suivants :

  • nom_patient de type TEXT (clé primaire et clé étrangère) ;

  • nom_maladie de type TEXT (clé étrangère).

Diagnostic
nom_patient nom_maladie
…….. …….. …….. …….. …….. ……..
  1. Écrire une requête SQL permettant d’obtenir les noms et prénoms des patients ayant strictement plus de 60 ans.

  2. Alice Heartman ne tousse plus. Écrire une requête SQL permettant de mettre à jour la base de données avec cette information.

  3. On souhaite effectuer des statistiques sur les symptômes des patients atteints de Covid-19. Écrire une requête SQL permettant de connaître le nombre de patients avec un diagnostic de Covid-19 qui toussent.

Un employé de l’hôpital saisit la requête suivante :

INSERT INTO Patients VALUES ('Douglas', 'Patrick', 168077230253829, 55)
  1. Expliquer pourquoi cette requête produit une erreur.

  2. Proposer une modification du schéma relationnel qui permettrait de résoudre ce problème.

Partie B

On s’intéresse maintenant à l’automatisation du diagnostic à partir des symptômes. Cette automatisation se fait à l’aide d’un arbre de décision binaire, tel que celui illustré sur la figure 1.

Figure 1. Exemple d’arbre de décision binaire
Figure 1. Exemple d’arbre de décision binaire

Chaque nœud interne de l’arbre est étiqueté par un symptôme, et chaque feuille est étiquetée par un diagnostic. Pour établir un diagnostic, on se place à la racine et on parcourt l’arbre de la manière suivante :

  • si on arrive à une feuille, le diagnostic est l’étiquette de cette feuille ;

  • sinon, on regarde si l’étiquette du nœud est un des symptômes du patient. Si oui, on continue le parcours dans le sous-arbre droit, sinon, on continue le parcours dans le sous-arbre gauche.

L’arbre de la figure 1 donne un diagnostic pour la Covid-19. Par exemple, un patient qui ne tousse pas et n’a pas d’anosmie, mais a de la fièvre et des nausées est diagnostiqué négatif si on suit cet arbre de décision.

  1. Donner le diagnostic pour un patient qui tousse et qui a de la fièvre, mais n’a pas de nausée ni d’anosmie, d’après l’arbre de la figure 1.

On décide d’implémenter les arbres binaires à l’aide de la classe Noeud ci-dessous :

class Noeud:
    def __init__(self, valeur, gauche = None, droit = None):
        """valeur correspond au symptome si le noeud est
        interne ou au diagnostic si le noeud est une feuille"""
        self.valeur = valeur
        self.gauche = gauche
        self.droit = droit

    def est_feuille(self):
        """renvoie vrai si le noeud est une feuille faux sinon"""
        return self.gauche == None and self.droit == None

    def symptome(self):
        assert not self.est_feuille()
        return self.valeur

    def diagnostic(self):
        assert self.est_feuille()
        return self.valeur
  1. Préciser la signification de l’assertion de la méthode symptome.

  2. Nommer un attribut et une méthode de la classe Noeud.

On représente les symptômes d’un patient en Python par un dictionnaire dont les clés sont les symptômes possibles, et les valeurs sont True si le patient présente ce symptôme et False sinon.

Par exemple, les symptômes du patient de la question 6 sont représentés par le dictionnaire suivant :

patient = {'toux': True, 'fievre': True, 'nausee': False, 'anosmie': False}
  1. Compléter la fonction applique suivante, définie récursivement, qui renvoie le diagnostic établi en utilisant un arbre de décision binaire implémenté à l’aide de la classe Noeud précédente.

def applique(arbre, patient):
    if arbre.est_feuille():
        ...
    else:
        if patient[arbre.symptome()]:
            ...
        else:
            ...
  1. Donner la taille de l’arbre représenté en figure 1. On considère que la taille d’un arbre constitué d’une unique feuille est 1.

On souhaite réduire la taille de cet arbre en utilisant l’observation suivante : un nœud dont les deux sous-arbres sont des feuilles correspondant au même diagnostic peut être remplacé par une feuille correspondant à ce diagnostic, comme illustré en figure 2.

Figure 2. Règle de réduction pour les arbres de décision binaire
Figure 2. Règle de réduction pour les arbres de décision binaire
  1. Appliquer cette règle à l’arbre de la figure 1 pour le réduire et dessiner le nouvel arbre.

  2. Compléter la méthode reduire qui permet d’appliquer cette règle récursivement pour réduire la taille d’un arbre de décision binaire.

def reduire(self):                                     # ligne 1
    """fonction récursive qui réduit la taille d'un arbre de
    décision sans changer les décisions prises"""
    if self.est_feuille():                             # ligne 4
        return
    self.gauche.reduire()                              # ligne 6
    self. ...                                          # ligne 7
    if self.gauche.est_feuille() and ... \
       and ... == ... :                                # ligne 9
        self.valeur = ...                              # ligne 10
        self.gauche = ...                              # ligne 11
        self.droite = ...                              # ligne 12

Partie C

Dans cette partie, on s’intéresse à l’intégrité et à la sécurité des données.

Sur les 15 chiffres du numéro de sécurité sociale, 2 servent à détecter les erreurs : étant donné le nombre n formé des 13 premiers chiffres, le nombre k formé des 2 derniers chiffres, appelé la clé, est choisi pour que n+k soit un multiple de 97.

Par exemple, 207053523800187 est bien formé car :

2070535238001 + 87 = 97 x 21345724104.

On rappelle que les opérateurs % et // permettent en Python d’obtenir respectivement le reste et le quotient dans une division euclidienne. Par exemple : 13 % 3 renvoie 1 et 13//3 renvoie 4 (car 13=3×4+1). On peut donc vérifier qu’un nombre entier 𝑛 est un multiple de 𝑝 en testant si le reste de la division de 𝑛 par 𝑝 vaut zéro.

  1. Recopier et compléter la fonction verifie suivante qui renvoie un booléen indiquant si un numéro de sécurité sociale représenté par un entier (type int) est bien formé.

def verifie(num_secu):
    n = num_secu // 100
    k = num_secu % 100
    return ...
  1. Compléter la fonction cle qui permet de renvoyer la clé k d’un numéro de sécurité sociale en prenant pour paramètre le nombre n formé des 13 premiers chiffres du numéro de sécurité sociale.

def cle(n):
     ...
▶✅ Correction (cliquer pour afficher) PDF

Asie – Bac NSI 2025 – Jour 2 Correction de l'exercice 3

PARTIE A — Base de données (SQL)

1) Patients de plus de 60 ans

SELECT nom_patient, prenom
FROM Patient
WHERE age > 60;

2) Mise à jour : Alice Heartman ne tousse plus

UPDATE Symptome
SET toux = 'Non'
WHERE nom_patient = 'Heartman';

3) Nombre de patients Covid-19 qui toussent

SELECT COUNT(*)
FROM Diagnostic
JOIN Symptome
ON Diagnostic.nom_patient = Symptome.nom_patient
WHERE nom_maladie = 'Covid-19'
AND toux = 'Oui';

4) Pourquoi la requête INSERT produit une erreur?

INSERT INTO Patients VALUES ('Douglas', 'Patrick', 168077230253829, 55)

Erreur car :

  • La table s’appelle Patient (et non Patients)

  • nom_patient est clé primaire

  • Douglas existe déjà

Il y a violation de la contrainte d’unicité.

5) Modification du schéma relationnel

Problème : plusieurs patients peuvent avoir le même nom.

Solution : ajouter un identifiant unique : id_patient INT PRIMARY KEY

Et faire de nom_patient un simple attribut.

Il faut alors remplacer nom_patient par id_patient dans les tables Symptome et Diagnostic, où il sert de clé étrangère (et de clé primaire).

Bonne pratique : ne jamais utiliser un nom comme clé primaire.

PARTIE B — Arbre de décision

6) Diagnostic du patient

Patient :

  • toux = True

  • fievre = True

  • nausee = False

  • anosmie = False

On suit l’arbre de la figure 1 : toux Oui → fievre Oui → nausee Non → anosmie Non : on arrive sur une feuille « + ».

Diagnostic : positif à la Covid-19.

7) Assertion de la méthode symptome

L’assertion vérifie que le nœud n’est pas une feuille.

Elle garantit qu’on appelle la méthode uniquement sur un nœud interne.

8) Un attribut et une méthode

Attribut : valeur (ou gauche, droit)

Méthode : est_feuille (ou symptome, diagnostic)

9) Fonction applique (récursive)

def applique(arbre, patient):
    if arbre.est_feuille():
        return arbre.diagnostic()
    else:
        if patient[arbre.symptome()]:
            return applique(arbre.droit, patient)   # symptôme : à droite
        else:
            return applique(arbre.gauche, patient)

10) Taille de l’arbre

L’arbre de la figure 1 est complet : 1 + 2 + 4 + 8 = 15 nœuds internes et 16 feuilles.

Taille = 15 + 16 = 31

11) Réduction de l’arbre

On applique la règle :

Si un nœud a deux feuilles identiques → on le remplace par une feuille.

Les nœuds anosmie dont les deux feuilles sont identiques deviennent des feuilles (6 nœuds sur 8). On réapplique la règle : le nœud nausee de la branche toux Oui, fievre Oui a alors deux feuilles « + » et devient lui aussi une feuille. Plus rien ne se simplifie ensuite.

Arbre de décision réduit

L’arbre réduit a 8 nœuds internes et 9 feuilles : sa taille passe de 31 à 17.

12) Méthode reduire

def reduire(self):
    """fonction récursive qui réduit la taille d'un arbre de
    décision sans changer les décisions prises"""
    if self.est_feuille():
        return
    self.gauche.reduire()
    self.droit.reduire()
    if self.gauche.est_feuille() and self.droit.est_feuille() \
       and self.gauche.valeur == self.droit.valeur:
        self.valeur = self.gauche.valeur
        self.gauche = None
        self.droit = None

PARTIE C — Intégrité des données

13) Fonction verifie

def verifie(num_secu):
    n = num_secu // 100
    k = num_secu % 100
    return (n + k) % 97 == 0

14) Fonction cle

On veut : n + k ≡ 0 mod 97

Donc :

Il suffit de compléter n jusqu’au multiple de 97 suivant : k = 97 − (n % 97).

def cle(n):
    reste = n % 97
    if reste == 0:
        return 0
    return 97 - reste

Une erreur, un oubli ? Écrivez-moi : frederic.peuriere@lfcl.pt

💻 Console Python (cliquer pour afficher)

🔎 Exercices sur des thèmes similaires