C9.EB4 : Gestion des processus

Cet exercice porte sur l’algorithmique, les structures de données, et la gestion de processus.

On cherche à créer une application de type liste de tâches à faire pour aider Alice à planifier sa journée. Pour cela Alice saisit les informations concernant chacune des tâches qu’elle doit effectuer : elle indique un nom pour la tâche, ainsi que la durée qu’elle estime nécessaire afin de la réaliser. On représente une tâche saisie par Alice à l’aide d’un objet de type Tache, muni de quatre attributs :

Avancer de n minutes (n entier positif) dans une tâche consiste à diminuer de n la durée restante de cette tâche. Une tâche est terminée si la durée restante est négative ou nulle.

Lors de la phase de planification de ses tâches (aucune d’entre elles n’est commencée), Alice liste les tâches suivantes qui doivent être effectuées :

Numéro Nom Durée Durée restante
1 Répondre aux e-mails 45 45
2 Ranger ma chambre 60 60
3 Réviser la NSI 90 90
4 S’entraîner aux échecs 30 30
5 Apprendre le vocabulaire de chinois 30 30
6 Lire Fondation 60 60
7 Écrire ma lettre au Père Noël 20 20

On dispose de la classe Tache ci-dessous pour représenter les tâches :

class Tache:
    def __init__(self, numero, nom, duree):
        self.numero = numero
        self.nom = nom
        self.duree_initiale = duree
        self.duree_restante = duree
    
    def __repr__(self):
        return ''

1. Donner le code Python qui permet d’instancier deux variables tache1 et tache2 représentant les tâches :

  • – tâche numéro 1 : Répondre aux e-mails. Durée estimée : 45 minutes.
  • – tâche numéro 2 : Ranger ma chambre. Durée estimée : 60 minutes.

On supposera dans la suite que les variables tache1, tache2, …, tache7 représentent les tâches établies par Alice lors de la phase de planification.

La méthode __repr__ renvoie une représentation de l’instance sous forme d’une chaîne de caractères. La fonction print utilise cette méthode. Ainsi on a :

>>> print(tache1)
<t1>

2. Recopier et compléter le code de la méthode avancer de la classe Tache qui permet d’avancer la tâche self de n minutes.

def avancer(self, n):
    ...

3. Recopier et compléter le code de la méthode est_terminee de la classe Tache qui renvoie True si la tâche est terminée, ou False sinon.

def est_terminee(self):
    ...

Afin d’aider Alice à planifier sa journée, on lui propose d’associer à chacune des tâches une priorité. La priorité d’une tâche est représentée par un entier de la manière suivante : 1 est la priorité minimale et, plus le nombre est grand, plus la tâche associée est prioritaire.

Pour stocker toutes les tâches à effectuer, on utilise une file, dans laquelle les éléments sont des tuples (tache, priorite). Les éléments stockés dans la file doivent respecter les deux conditions ci-après.

Par exemple, si la file de tâches f est la file :

[début] (<t3>, 4) (<t1>, 3) (<t2>, 3) (<t4>, 1) (<t5>, 1) [fin]

Cela signifie que :

4. Représenter l’état de la file f lorsqu’on lui ajoute successivement la tâche numéro 6 avec la priorité 2, puis la tâche numéro 7 avec la priorité 4 en respectant les conditions 1 et 2 décrites ci-dessus.

On suppose déjà définies les méthodes suivantes pour la classe File :

5. En repartant de la file f suivante :

[début] (<t3>, 4) (<t1>, 3) (<t2>, 3) (<t4>, 1) (<t5>, 1) [fin]

donner la valeur de f.defiler()[0], et représenter le contenu de la file f après l’exécution de cette instruction.

6. En repartant de la file f suivante :

[début] (<t3>, 4) (<t1>, 3) (<t2>, 3) (<t4>, 1) (<t5>, 1) [fin]

donner la valeur de f.examiner()[1], et représenter le contenu de la file f après l’exécution de cette instruction.

On souhaite écrire une fonction ajouter_file_prio qui prend en paramètres :

et qui ajoute le tuple (t, p) à la bonne position dans la file f.

On utilise une file auxiliaire f_aux que l’on remplit en défilant les éléments en début de file f tant que la priorité du premier élément de la file est supérieure ou égale à p. Puis on enfile l’élément (t, p) dans la file auxiliaire. On défile ensuite tous les éléments restants de f dans f_aux et enfin on enfile dans f tous les éléments de f_aux.

7. Recopier et compléter le code de la fonction ajouter_file_prio.

def ajouter_file_prio(f, t, p):
    f_aux = File()
    while ...:
        ...
    ...enfiler(...)
    while not ...:
        ...
    while not ...:
        ...

8. Donner le coût d’exécution temporel dans le pire des cas de la fonction ajouter_file_prio, en fonction du nombre m d’éléments de la file f.

Une fois qu’Alice a entré les tâches qu’elle doit effectuer, leur durée estimée, ainsi que la priorité à laquelle elle doit les effectuer, l’application lui propose un planning en utilisant la technique dite Pomodoro :

On rappelle les tâches à effectuer ci-dessous, classées par ordre de priorité. On considérera que les tâches sont ajoutées à la file de priorité dans l’ordre du tableau ci-dessous :

Numéro Nom Durée Priorité
3 Réviser la NSI 90 4
7 Écrire ma lettre au Père Noël 20 4
1 Répondre aux e-mails 45 3
2 Ranger ma chambre 60 3
6 Lire Fondation 60 2
4 S’entraîner aux échecs 30 1
5 Apprendre le vocabulaire de chinois 30 1

9. Indiquer pour chaque bloc de 25 minutes la tâche qui avance, en suivant le modèle proposé, jusqu’à la fin de toutes les tâches. On fera particulièrement attention au cas où la tâche n’est pas terminée : celle-ci est rajoutée à la file des tâches à effectuer (dont elle avait été supprimée) avec la même priorité qu’initialement, en respectant les conditions 1 et 2 de l’énoncé.

10. Écrire le code d’une fonction planning qui prend en paramètre une file de priorité f dont les éléments sont des tuples (tache, prio), et qui renvoie une liste de tâches, dans l’ordre dans lequel elles vont être effectuées par tranche de 25 minutes avec la méthode Pomodoro.

Par exemple, si tache1, tache2 et tache3 sont les tâches numéro 1, numéro 2 et numéro 3, alors le programme suivant :

file = File()
for t, p in [(tache1, 3), (tache2, 3), (tache3, 4)]:
    ajouter_file_prio(file, t, p)
print(planning(file))

produit l’affichage :

[<t3>, <t3>, <t3>, <t3>, <t1>, <t2>, <t1>, <t2>, <t2>]