\documentclass[11pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[french]{babel}
\usepackage[T1]{fontenc}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{graphicx}
\usepackage{enumitem}
\usepackage{minted}
\newcommand{\mip}[1]{\mintinline{python}{#1}}
\newcommand{\mis}[1]{\mintinline{sql}{#1}}
\usepackage{hyperref}
\usepackage{pstricks,pst-plot,pst-3dplot,pst-grad,pst-tree,pst-math,pst-eucl}
\usepackage{pst-plot,pst-tree,pst-eucl,pst-math,pstricks-add}
\usepackage[margin=1cm,bottom=1.5cm]{geometry}
\begin{document}
\fbox{\textsc{25NSIJ2JA1}}


\bigskip

\textbf{Exercice 1} (6 points)

\medskip

\textit{Cet exercice porte sur la programmation orientée objet et l’algorithmique.}

\medskip

\textbf{Partie A}

\medskip

\begin{enumerate}
\item On complète le constructeur.

\begin{minted}[linenos,firstnumber=3]{python}
        self.jour = jour
        self.mois = mois
        self.annee = annee
\end{minted}

\item La date qui correspond à \mip{d = Date(1, 5, 2000)} est le 1er mai 2000.

\item On instancie la date demandée par \mip{d = Date(19, 6, 2024)}.



\item On complète la méthode \mip{get_annee}.



\begin{minted}[linenos,firstnumber=15]{python}
    def get_annee(self):
        return self.annee
\end{minted}

\item On complète la méthode \mip{set_mois}.



\begin{minted}[linenos,firstnumber=21]{python}
    def set_mois(self, mois):
        self.mois = mois
\end{minted}

\item On insère les lignes suivantes dans le constructeur.


\begin{minted}[linenos,firstnumber=7]{python}
    if self.est_bissextile():
        self.nb_jours_par_mois[1] = 29
    
\end{minted}

\end{enumerate}

\medskip

\textbf{Partie B}


\begin{enumerate}[resume]

\item On écrit le code de la méthode \mip{est_bissextile}.



\begin{minted}{python}
    def est_bissextile(self):
        a = self.annee
        return a%4 ==0 and a%100!=0 or a%400 == 0
\end{minted}

\item L'affichage sera 79 (résultat du calcul $20+31+28$).



\item On complète la méthode \mip{nb_jours_restants}.

\begin{minted}[]{python}
    def nb_jours_restants(self):
        j = 365
        if self.est_bissextile():
            j = 366
        return j - self.nb_jours_passes()
\end{minted}

\end{enumerate}


\medskip

\textbf{Partie C}


\begin{enumerate}[resume]

\item On présente les affichages obtenus en console.



\begin{minted}{python}
>>> d1.nb_jours_depuis(d2)
0
>>> d1.nb_jours_depuis(d3)
-1
>>> d1.nb_jours_depuis(d4)
-1
>>> d1.nb_jours_depuis(d5)
731
\end{minted}

\newpage

\item On complète la méthode \mip{timestamp}.

\begin{minted}[linenos]{python}
    def timestamp(self):
        d = Date(1, 1, 1970) # epoch
        return self.nb_jours_depuis(d) * 24 * 3600
\end{minted}

\end{enumerate}



\bigskip

\textbf{Exercice 2} (6 points)


\medskip

\textit{Cet exercice porte sur la programmation Python, la gestion des processus.}



\begin{enumerate}
\item Ce programme est un ordonnanceur.

\item Les états possibles d'un processus sont élu, prêt, bloqué.

\item Proposition 2, comme indiqué explicitement par l'énoncé.

\item On complète le constructeur.


\begin{minted}[linenos]{python}
class Processus:
    __init__(self, PID, priorite, temps_CPU):
        self.priorite = priorite
        self.PID = PID
        self.temps_utilisation = 0
        self.temps_CPU = temps_CPU
\end{minted}

\item On complète la simulation, en supposant que les files sont implémentées par des \mip{list} avec enfilement par \mip{f.insert(0)} et défilement par \mip{f.pop()}.

\begin{tabular}{lll}
Cycle 1:& \mip{CPU=P1}& \mip{liste_files=[[P3, P2], [], []]}\\
Cycle 2:& \mip{CPU=P2}& \mip{liste_files=[[P3],[P1],[]]}\\
Cycle 3:& \mip{CPU=P3}& \mip{liste_files=[[], [P2, P1],[]]}\\
Cycle 4:& \mip{CPU=P3}& \mip{liste_files=[[], [P2, P1], []]}\\
Cycle 5:& \mip{CPU=P1}& \mip{liste_files=[[], [P2], [P3]]}\\
\end{tabular}





\item Chaque nouveau processus court arrive avec la priorité maximale zéro, tandis que le processus long a une priorité qui s'éloigne de zéro à chaque fois qu'il s'exécute ; en particulier au bout de quatre cycles le processus long ne sera plus jamais prioritaire sur les processus courts, qui sont sans cesse renouvelés, donc le processus long ne sera plus jamais élu.   

\item Au bout de \mip{Max_Temps} cycles en attente, la priorité du processus long augmente, donc en temps fini ce processus sera élu, et puisqu'il a besoin d'un temps CPU fini il termine.

\item On écrit la fonction \mip{meilleur_priorite}.



\begin{minted}[linenos]{python}
def meilleur_priorite(liste_files):
    m=0
    while m < len(liste_files) and liste_files[m] == []:
        m = m + 1
    if m < len(liste_files):
        return m
    return None
\end{minted}

\item On écrit la fonction \mip{prioritaire}.


\begin{minted}[linenos]{python}
def prioritaire(liste_files):
    m = meilleur_priorite(liste_files)
    if m is not None:
        return liste_files[m].pop()
    return None
\end{minted}

\item On écrit la fonction \mip{gerer}. Bien que l'énoncé soit peu explicite sur ce point, on suppose que le paramètre \mip{p} peut être \mip{None}, faute de quoi il se peut qu'aucun processus ne soit élu malgré la présence de processus prêts. On interprétera l'énoncé par \og la fonction \mip{gerer} met à jour les structures et renvoie le nouveau processus élu \fg{}. 



\begin{minted}[linenos]{python}
def gerer(p, liste_files):
    if p is None:
        return prioritaire(liste_files)
    else:
        if p.temps_utilisation == p.temps_CPU:
            return None
        else:
            p.temps_utilisation += 1
            q=prioritaire(liste_files)
            if q is not None and q.priorite <= p.priorite:
                p.priorite +=1
                if p.priorite < len(liste_files):
                    liste_files[p.priorite].insert(0,p)
                else:
                    liste_files.append([p])
                return q 
            if q is None:
                p.priorite +=1
                return p
\end{minted}

\end{enumerate}



\bigskip

\textbf{Exercice 3} (8 points)

\medskip

\textit{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.}

\medskip

\textbf{Partie A}

\begin{enumerate}
\item La requête \mis{SELECT nom_patient, prenom FROM Patient WHERE age > 60;} convient.

\item La requête \mis{UPDATE Symptome SET toux='Non' WHERE nom_patient='Heartman';} convient.

\item La requête \mis{SELECT COUNT(*) FROM Diagnostic JOIN Symptome} 

\mis{ON Diagnostic.nom_patient=Symptome.nom_patient WHERE nom_maladie="Covid-19" AND toux='Oui';} convient.

\item La requête provoque une erreur car la clé primaire \mis{Douglas} est déjà utilisée.

\item On pourrait utiliser très classiquement un attribut supplémentaire entier \mis{id_patient} dans la relation \mis{Patient} qui servirait de clé primaire.


\end{enumerate}

\bigskip

\textbf{Partie B}


\begin{enumerate}[resume]
\item Le diagnostic est positif pour le patient considéré.

\item  L'assertion de la ligne 14 permet de vérifier que \mip{self} n'est pas une feuille et donc que \mip{self.valeur} est effectivement un symptôme.



\item La classe \mip{Noeud} possède les attributs \mip{valeur}, \mip{gauche} et \mip{droit} et les méthodes \mip{est_feuille}, \mip{symptome} et \mip{diagnostic}.

\item On complète la fonction.

\begin{minted}[linenos]{python}
def applique(arbre, patient):
    if arbre.est_feuille():
        return arbre.valeur
    else:
        if patient[arbre.symptome()]:
            return applique(arbre.droit, patient)
        else:
            return applique(arbre.gauche, patient)
\end{minted}

\item La taille de l'arbre est 31.

\newpage

\item On réduit l'arbre (récursivement).

\begin{center}
\psset{unit=8mm}
\psset{radius=2.5mm}
\begin{pspicture}(17,10)
\rput(8.5,9){\rnode{toux}{\psframebox{toux}}}
\rput(4.5,7){\rnode{fievre0}{\psframebox{fievre}}}
\rput(12.5,7){\rnode{fievre1}{\psframebox{fievre}}}
\ncline{toux}{fievre0}
\ncline{toux}{fievre1}
\rput(6,8.3){Non}\rput(11,8.3){Oui}

\rput(2.5,5){\rnode{nausee00}{\psframebox{nausee}}}
\rput(6.5,5){\rnode{nausee01}{\psframebox{nausee}}}
\ncline{fievre0}{nausee00}
\ncline{fievre0}{nausee01}
\rput(3,6.2){Non}\rput(6,6.2){Oui}

\rput(10.5,5){\rnode{nausee10}{\psframebox{nausee}}}
\rput(14.5,5){\Circlenode{nausee11}{$+$}}
\ncline{fievre1}{nausee10}
\ncline{fievre1}{nausee11}
\rput(11,6.2){Non}\rput(14,6.2){Oui}

\rput(1.5,3){\rnode{anosmie000}{\psframebox{anosmie}}}
\rput(3.5,3){\Circlenode{anosmie001}{$-$}}
\ncline{anosmie000}{nausee00}\rput(1.5,4.2){Non}
\ncline{anosmie001}{nausee00}\rput(3.5,4.2){Oui}

\rput(5.5,3){\Circlenode{anosmie010}{$+$}}
\rput(7.5,3){\Circlenode{anosmie011}{$-$}}
\ncline{anosmie010}{nausee01}\rput(5.5,4.2){Non}
\ncline{anosmie011}{nausee01}\rput(7.5,4.2){Oui}

\rput(9.5,3){\Circlenode{anosmie100}{$+$}}
\rput(11.5,3){\rnode{anosmie101}{\psframebox{anosmie}}}
\ncline{anosmie100}{nausee10}\rput(9.5,4.2){Non}
\ncline{anosmie101}{nausee10}\rput(11.5,4.2){Oui}

\rput(1,1){\Circlenode{f0000}{$-$}}\rput(0.9,2){N}\ncline{f0000}{anosmie000}
\rput(2,1){\Circlenode{f0001}{$+$}}\rput(2.1,2){O}\ncline{f0001}{anosmie000}

\rput(11,1){\Circlenode{f1010}{$-$}}
\rput(10.9,2){N}\ncline{f1010}{anosmie101}
\rput(12,1){\Circlenode{f1011}{$+$}}
\rput(12.1,2){O}\ncline{f1011}{anosmie101}

\end{pspicture}
\end{center}
\item On complète la méthode.

\begin{minted}[linenos]{python}
    def réduire(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.droite = None
\end{minted}

\end{enumerate}


\bigskip

\textbf{Partie C}


\begin{enumerate}[resume]
\item On complète la fonction.

\begin{minted}[linenos]{python}
def verifie(num_secu):
    n = num_secu // 100
    k = num_secu % 100
    return (n + k) % 97 == 0
\end{minted}

\item On complète la fonction.

\begin{minted}[linenos]{python}
def cle(n):
    return 97 - n % 97
\end{minted}




\end{enumerate}




\end{document}