ajout de tous les cours et TP préparés cet été
This commit is contained in:
102
Pile_File/README.md
Normal file
102
Pile_File/README.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# Structure de données : Pile et File
|
||||
|
||||
> Structures essentielles pour résoudre des problèmes où l'ordre de traitement des données est crucial, comme la gestion des processus ou la navigation dans des graphes, les piles et files permettent de stocker et manipuler des données selon des règles spécifiques. La pile suit un principe **LIFO** (Last In, First Out), tandis que la file suit un principe **FIFO** (First In, First Out).
|
||||
|
||||
## Le programme
|
||||
|
||||
<img src="Images/bo_1.png" alt="BO_Pile & File" style="zoom:67%;" />
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<img src="Images/bo_2.png" alt="BO_Pile&File_2" style="zoom:67%;" />
|
||||
|
||||
|
||||
|
||||
|
||||
## 1. Rappel :
|
||||
|
||||
<u>**Structure de données**</u> : Collection d'information dans laquelle il est possible de stocker, traiter, organiser, extraire des données.
|
||||
|
||||
Les structures de données connues à ce jour sont : Les tableaux, les dictionnaires, les chaînes de caractères, les n-uplets. Chacune de ces structures possèdent des caractéristiques propres qui créent des avantages et des inconvénients selon la situation.
|
||||
|
||||
De plus, ces types sont natifs à Python, et aux autres langages selon les cas. Nous n'avons donc ici aucune idée de comment le type *dict* ou *tuple* est créé par exemple.
|
||||
|
||||
Les structures de données Pile et File ne sont pas natives à Python et nous aurons donc besoin de les implémenter.
|
||||
|
||||
## 2. Interface et implémentation :
|
||||
|
||||
Ces deux termes sont particuliers et très importants pour ce chapitre. Alors un petit rappel n'est pas de trop.
|
||||
|
||||
<u>**Interface :**</u> L'interface d'un type est définie par les méthodes qui lui sont associées.
|
||||
|
||||
**<u>Implémentation :</u>** L'implémentation d'un type est la manière dont on va le coder.
|
||||
|
||||
Il faut bien faire la distinction entre les deux termes.
|
||||
|
||||
## 3. Pile
|
||||
|
||||
### 3. 1. Définition
|
||||
|
||||
Une pile est une structure de données dans laquelle les derniers éléments entrant dans la structure seront les premiers à en sortir, nous appelons ce principe **LIFO (Last In First Out)**. Afin d'imager cette structure nous pouvons penser à une pile d'assiettes par exemple.
|
||||
|
||||

|
||||
|
||||
Ici seul le premier élément est accessible.
|
||||
|
||||
### 3. 2. Interface
|
||||
|
||||
Méthodes associées à la pile :
|
||||
|
||||
- Empile : Méthode permettant d'empiler un élément.
|
||||
- L'élément sera positionné au haut de la pile
|
||||
- Depile : Méthode permettant d'enlever un élément.
|
||||
- L'élément enlevé sera celui en haut de la pile.
|
||||
|
||||
- Est_vide : Permet de savoir si la pile est vide ou non
|
||||
|
||||
On peut ajouter d'autres méthodes :
|
||||
|
||||
- Taille : Permet de savoir le nombre d'éléments de la pile
|
||||
- Top : Permet de connaître l'élément au-dessus de la pile.
|
||||
|
||||
## 4. File
|
||||
|
||||
### 4. 1. Définition
|
||||
|
||||
Une file est une structure de données dans laquelle les premiers éléments entrant dans la structure seront les premiers à en sortir, nous appelons ce principe **FIFO (First In First Out)**. Afin d'imager cette structure nous pouvons penser à une file de voitures sur une route par exemple.
|
||||
|
||||

|
||||
|
||||
Ici seul le premier élément peut sortir de la structure.
|
||||
|
||||
### 4. 2. Interface
|
||||
|
||||
Méthodes associées à la file :
|
||||
|
||||
- Enfile : Méthode permettant d'enfiler un élément.
|
||||
- L'élément sera positionné en queue de la file
|
||||
- Defile : Méthode permettant d'enlever un élément.
|
||||
- L'élément enlevé sera celui en tête de la file.
|
||||
|
||||
- Est_vide : Permet de savoir si la file est vide ou non
|
||||
|
||||
On peut ajouter d'autres méthodes :
|
||||
|
||||
- Taille : Permet de savoir le nombre d'éléments de la file
|
||||
- Top : Permet de connaître l'élément en tête de la file.
|
||||
|
||||
## 5. Conclusion
|
||||
|
||||
Les deux structures ont une interface très semblable. Seul le principe FIFO / LIFO peut les différencier.
|
||||
|
||||
La suite du chapitre se concentrera sur l'utilisation de ces structures et leurs implémentations.
|
||||
|
||||
---------
|
||||
|
||||
Auteurs : Florian Mathieu, Enzo Frémeaux, Thimothée Decooster
|
||||
|
||||
Licence CC BY NC
|
||||
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International</a>.
|
||||
181
Pile_File/TD/Corrige_TD_Pile_File.md
Normal file
181
Pile_File/TD/Corrige_TD_Pile_File.md
Normal file
@@ -0,0 +1,181 @@
|
||||
# Corrigé du TD Pile et File
|
||||
|
||||
---
|
||||
|
||||
## 1. Application de cours
|
||||
|
||||
### 1. 1. Pile
|
||||
|
||||
**État initial de la pile :**
|
||||
```
|
||||
5 ← sommet
|
||||
4
|
||||
3
|
||||
2
|
||||
1 ← fond
|
||||
```
|
||||
|
||||
**Question 1** : État après `Depile(), Depile(), Empile(7), Empile(8), Depile()`
|
||||
|
||||
Exécution pas à pas :
|
||||
|
||||
| Opération | État de la pile | Élément retourné |
|
||||
|-----------|-----------------|------------------|
|
||||
| Initial | [1, 2, 3, 4, 5] | - |
|
||||
| Depile() | [1, 2, 3, 4] | 5 |
|
||||
| Depile() | [1, 2, 3] | 4 |
|
||||
| Empile(7) | [1, 2, 3, 7] | - |
|
||||
| Empile(8) | [1, 2, 3, 7, 8] | - |
|
||||
| Depile() | [1, 2, 3, 7] | 8 |
|
||||
|
||||
**État final :**
|
||||
```
|
||||
7 ← sommet
|
||||
3
|
||||
2
|
||||
1 ← fond
|
||||
```
|
||||
|
||||
**`top()` renvoie : 7**
|
||||
|
||||
---
|
||||
|
||||
**Question 2** : Pour que `Est_vide()` soit vrai, il faut dépiler tous les éléments.
|
||||
|
||||
```
|
||||
Depile() → renvoie 5
|
||||
Depile() → renvoie 4
|
||||
Depile() → renvoie 3
|
||||
Depile() → renvoie 2
|
||||
Depile() → renvoie 1
|
||||
Est_vide() → True
|
||||
```
|
||||
|
||||
**Réponse : 5 appels à Depile()**
|
||||
|
||||
---
|
||||
|
||||
**Question 3** : Créer une pile contenant 19982018 (1 en bas de pile)
|
||||
|
||||
La pile doit ressembler à :
|
||||
```
|
||||
8 ← sommet
|
||||
1
|
||||
0
|
||||
2
|
||||
8
|
||||
9
|
||||
9
|
||||
1 ← fond
|
||||
```
|
||||
|
||||
**Séquence de méthodes :**
|
||||
```
|
||||
Empile(1)
|
||||
Empile(9)
|
||||
Empile(9)
|
||||
Empile(8)
|
||||
Empile(2)
|
||||
Empile(0)
|
||||
Empile(1)
|
||||
Empile(8)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 1. 2. File
|
||||
|
||||
**État initial de la file :**
|
||||
```
|
||||
Entrée → 5 | 4 | 3 | 2 | 1 → Sortie
|
||||
↑ ↑
|
||||
queue tête
|
||||
```
|
||||
|
||||
**Question 1** : État après `Defile(), Defile(), Enfile(7), Enfile(8), Defile()`
|
||||
|
||||
Exécution pas à pas :
|
||||
|
||||
| Opération | État de la file | Élément retourné |
|
||||
|-----------|-----------------|------------------|
|
||||
| Initial | [5, 4, 3, 2, 1] | - |
|
||||
| Defile() | [5, 4, 3, 2] | 1 |
|
||||
| Defile() | [5, 4, 3] | 2 |
|
||||
| Enfile(7) | [7, 5, 4, 3] | - |
|
||||
| Enfile(8) | [8, 7, 5, 4, 3] | - |
|
||||
| Defile() | [8, 7, 5, 4] | 3 |
|
||||
|
||||
**État final :**
|
||||
```
|
||||
Entrée → 8 | 7 | 5 | 4 → Sortie
|
||||
```
|
||||
|
||||
**`top()` renvoie : 4** (élément en tête, prêt à sortir)
|
||||
|
||||
---
|
||||
|
||||
**Question 2** : Pour que `Est_vide()` soit vrai, il faut défiler tous les éléments.
|
||||
|
||||
```
|
||||
Defile() → renvoie 1
|
||||
Defile() → renvoie 2
|
||||
Defile() → renvoie 3
|
||||
Defile() → renvoie 4
|
||||
Defile() → renvoie 5
|
||||
Est_vide() → True
|
||||
```
|
||||
|
||||
**Réponse : 5 appels à Defile()**
|
||||
|
||||
---
|
||||
|
||||
**Question 3** : Créer une file contenant 19982018 (1 en tête de file)
|
||||
|
||||
La file doit ressembler à :
|
||||
```
|
||||
Entrée → 8 | 1 | 0 | 2 | 8 | 9 | 9 | 1 → Sortie
|
||||
↑
|
||||
tête
|
||||
```
|
||||
|
||||
Pour que 1 soit en tête (premier à sortir), il faut l'enfiler en premier :
|
||||
|
||||
**Séquence de méthodes :**
|
||||
```
|
||||
Enfile(1)
|
||||
Enfile(9)
|
||||
Enfile(9)
|
||||
Enfile(8)
|
||||
Enfile(2)
|
||||
Enfile(0)
|
||||
Enfile(1)
|
||||
Enfile(8)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tableau récapitulatif
|
||||
|
||||
| Structure | Principe | Ajout | Retrait | Accès |
|
||||
|-----------|----------|-------|---------|-------|
|
||||
| **Pile** | LIFO (Last In First Out) | Empile (sommet) | Depile (sommet) | Top (sommet) |
|
||||
| **File** | FIFO (First In First Out) | Enfile (queue) | Defile (tête) | Top (tête) |
|
||||
|
||||
---
|
||||
|
||||
## Analogies pour mémoriser
|
||||
|
||||
| Structure | Analogie | Explication |
|
||||
|-----------|----------|-------------|
|
||||
| **Pile** | Pile d'assiettes | On pose et on prend toujours par le dessus |
|
||||
| **File** | File d'attente | Le premier arrivé est le premier servi |
|
||||
| **Pile** | Historique du navigateur | Le bouton "retour" revient à la page précédente (la dernière visitée) |
|
||||
| **File** | Imprimante | Les documents sont imprimés dans l'ordre d'envoi |
|
||||
|
||||
---
|
||||
|
||||
Auteurs : Florian Mathieu, Enzo Frémeaux, Thimothée Decooster
|
||||
|
||||
Licence CC BY NC
|
||||
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International</a>.
|
||||
@@ -15,8 +15,8 @@ Le but du TD est de manipuler des piles et des files sans avoir d'implémentatio
|
||||
1. Quel sera l'état de la pile après l'utilisation des méthodes suivantes :
|
||||
- Depile(), Depile(), Empile(7), Empile(8),Depile()
|
||||
- Que renvoie la méthode top() ?
|
||||
2. Reprenons la pile de l'image, que faut t'il faire comme méthode pour que Est_vide() soit vrai ?
|
||||
3. En partant de 0 écrire les méthodes permettant de créer une pile contenant les numéros dans cette ordre 19982018. (1 est en bas de pile)
|
||||
2. Reprenons la pile de l'image, que faut-il faire comme méthode pour que Est_vide() soit vrai ?
|
||||
3. En partant de 0, écrire les méthodes permettant de créer une pile contenant les numéros dans cet ordre : 19982018. (1 est en bas de pile)
|
||||
|
||||
### 1. 2. File
|
||||
|
||||
@@ -27,5 +27,13 @@ Le but du TD est de manipuler des piles et des files sans avoir d'implémentatio
|
||||
1. Quel sera l'état de la file après l'utilisation des méthodes suivantes :
|
||||
- Defile(), Defile(), Enfile(7), Enfile(8),Defile()
|
||||
- Que renvoie la méthode top() ?
|
||||
2. Reprenons la file de l'image, que faut t'il faire comme méthode pour que Est_vide() soit vrai ?
|
||||
3. En partant de 0 écrire les méthodes permettant de créer une file contenant les numéros dans cette ordre 19982018. (1 est en haut de pile)
|
||||
2. Reprenons la file de l'image, que faut-il faire comme méthode pour que Est_vide() soit vrai ?
|
||||
3. En partant de 0, écrire les méthodes permettant de créer une file contenant les numéros dans cet ordre : 19982018. (1 est en tête de file)
|
||||
|
||||
---
|
||||
|
||||
Auteurs : Florian Mathieu, Enzo Frémeaux, Thimothée Decooster
|
||||
|
||||
Licence CC BY NC
|
||||
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International</a>.
|
||||
494
Pile_File/TP/Corrige_TP_Navigateur.py
Normal file
494
Pile_File/TP/Corrige_TP_Navigateur.py
Normal file
@@ -0,0 +1,494 @@
|
||||
"""
|
||||
Corrigé du TP Navigateur — Piles et Files en action
|
||||
"""
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# PARTIE 1 : Implémentation des structures
|
||||
# =============================================================================
|
||||
|
||||
class Pile:
|
||||
"""Structure de données LIFO (Last In First Out)."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialise une pile vide."""
|
||||
self.elements = []
|
||||
|
||||
def empile(self, element):
|
||||
"""Ajoute un élément au sommet de la pile."""
|
||||
self.elements.append(element)
|
||||
|
||||
def depile(self):
|
||||
"""
|
||||
Retire et renvoie l'élément au sommet.
|
||||
Renvoie None si la pile est vide.
|
||||
"""
|
||||
if self.est_vide():
|
||||
return None
|
||||
return self.elements.pop()
|
||||
|
||||
def est_vide(self):
|
||||
"""Renvoie True si la pile est vide."""
|
||||
return len(self.elements) == 0
|
||||
|
||||
def sommet(self):
|
||||
"""
|
||||
Renvoie l'élément au sommet sans le retirer.
|
||||
Renvoie None si la pile est vide.
|
||||
"""
|
||||
if self.est_vide():
|
||||
return None
|
||||
return self.elements[-1]
|
||||
|
||||
def taille(self):
|
||||
"""Renvoie le nombre d'éléments dans la pile."""
|
||||
return len(self.elements)
|
||||
|
||||
def __repr__(self):
|
||||
"""Affichage de la pile."""
|
||||
if self.est_vide():
|
||||
return "Pile vide"
|
||||
result = "Sommet\n"
|
||||
for i in range(len(self.elements) - 1, -1, -1):
|
||||
result += f" | {self.elements[i]} |\n"
|
||||
result += "Fond"
|
||||
return result
|
||||
|
||||
|
||||
class File:
|
||||
"""Structure de données FIFO (First In First Out)."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialise une file vide."""
|
||||
self.elements = []
|
||||
|
||||
def enfile(self, element):
|
||||
"""Ajoute un élément en queue de file."""
|
||||
self.elements.append(element)
|
||||
|
||||
def defile(self):
|
||||
"""
|
||||
Retire et renvoie l'élément en tête de file.
|
||||
Renvoie None si la file est vide.
|
||||
"""
|
||||
if self.est_vide():
|
||||
return None
|
||||
return self.elements.pop(0)
|
||||
|
||||
def est_vide(self):
|
||||
"""Renvoie True si la file est vide."""
|
||||
return len(self.elements) == 0
|
||||
|
||||
def tete(self):
|
||||
"""
|
||||
Renvoie l'élément en tête sans le retirer.
|
||||
Renvoie None si la file est vide.
|
||||
"""
|
||||
if self.est_vide():
|
||||
return None
|
||||
return self.elements[0]
|
||||
|
||||
def taille(self):
|
||||
"""Renvoie le nombre d'éléments dans la file."""
|
||||
return len(self.elements)
|
||||
|
||||
def __repr__(self):
|
||||
"""Affichage de la file."""
|
||||
if self.est_vide():
|
||||
return "File vide"
|
||||
result = "Tête → "
|
||||
result += " → ".join(str(e) for e in self.elements)
|
||||
result += " → Queue"
|
||||
return result
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# PARTIE 2 : Simulateur de navigateur web
|
||||
# =============================================================================
|
||||
|
||||
class Navigateur:
|
||||
"""Simulateur de navigateur web avec historique."""
|
||||
|
||||
def __init__(self, page_accueil="https://www.google.com"):
|
||||
"""
|
||||
Initialise le navigateur avec une page d'accueil.
|
||||
|
||||
:param page_accueil: (str) URL de la page d'accueil
|
||||
"""
|
||||
self.historique = Pile()
|
||||
self.suivant = Pile()
|
||||
self.historique.empile(page_accueil)
|
||||
|
||||
def page_actuelle(self):
|
||||
"""
|
||||
Renvoie l'URL de la page actuellement affichée.
|
||||
|
||||
:return: (str) URL de la page actuelle ou None
|
||||
"""
|
||||
return self.historique.sommet()
|
||||
|
||||
def visiter(self, url):
|
||||
"""
|
||||
Visite une nouvelle page.
|
||||
- Empile l'URL dans l'historique
|
||||
- Vide la pile 'suivant' (on ne peut plus avancer)
|
||||
|
||||
:param url: (str) URL de la page à visiter
|
||||
"""
|
||||
self.historique.empile(url)
|
||||
# Vider la pile suivant
|
||||
while not self.suivant.est_vide():
|
||||
self.suivant.depile()
|
||||
|
||||
def retour(self):
|
||||
"""
|
||||
Revient à la page précédente (bouton ←).
|
||||
- Dépile l'historique
|
||||
- Empile la page actuelle dans 'suivant'
|
||||
|
||||
:return: (str) URL de la nouvelle page actuelle ou None si impossible
|
||||
"""
|
||||
if not self.peut_reculer():
|
||||
return None
|
||||
|
||||
page_actuelle = self.historique.depile()
|
||||
self.suivant.empile(page_actuelle)
|
||||
return self.page_actuelle()
|
||||
|
||||
def avancer(self):
|
||||
"""
|
||||
Avance à la page suivante (bouton →).
|
||||
- Dépile 'suivant'
|
||||
- Empile dans l'historique
|
||||
|
||||
:return: (str) URL de la nouvelle page actuelle ou None si impossible
|
||||
"""
|
||||
if not self.peut_avancer():
|
||||
return None
|
||||
|
||||
page_suivante = self.suivant.depile()
|
||||
self.historique.empile(page_suivante)
|
||||
return self.page_actuelle()
|
||||
|
||||
def peut_reculer(self):
|
||||
"""Renvoie True si le bouton Retour est actif."""
|
||||
return self.historique.taille() > 1
|
||||
|
||||
def peut_avancer(self):
|
||||
"""Renvoie True si le bouton Suivant est actif."""
|
||||
return not self.suivant.est_vide()
|
||||
|
||||
def afficher_etat(self):
|
||||
"""Affiche l'état actuel du navigateur."""
|
||||
retour = "←" if self.peut_reculer() else "✗"
|
||||
avancer = "→" if self.peut_avancer() else "✗"
|
||||
print(f"[{retour}] [{avancer}] | {self.page_actuelle()}")
|
||||
|
||||
def afficher_historique(self):
|
||||
"""
|
||||
Affiche l'historique complet de navigation.
|
||||
La page actuelle est marquée d'une flèche.
|
||||
"""
|
||||
print("Historique de navigation :")
|
||||
# Copier la pile pour l'afficher sans la modifier
|
||||
temp = Pile()
|
||||
pages = []
|
||||
|
||||
while not self.historique.est_vide():
|
||||
page = self.historique.depile()
|
||||
pages.append(page)
|
||||
temp.empile(page)
|
||||
|
||||
# Restaurer la pile
|
||||
while not temp.est_vide():
|
||||
self.historique.empile(temp.depile())
|
||||
|
||||
# Afficher (inverser pour avoir l'ordre chronologique)
|
||||
pages.reverse()
|
||||
for i, page in enumerate(pages, 1):
|
||||
if i == len(pages):
|
||||
print(f"→ {i}. {page} (page actuelle)")
|
||||
else:
|
||||
print(f" {i}. {page}")
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# PARTIE 3 : File d'attente Netflix
|
||||
# =============================================================================
|
||||
|
||||
class ListeVisionnage:
|
||||
"""Gestionnaire de file d'attente de visionnage."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialise une liste de visionnage vide."""
|
||||
self.file_attente = File()
|
||||
self.historique = Pile()
|
||||
|
||||
def ajouter(self, titre):
|
||||
"""
|
||||
Ajoute un film/série à la file d'attente.
|
||||
|
||||
:param titre: (str) Titre du contenu à ajouter
|
||||
"""
|
||||
self.file_attente.enfile(titre)
|
||||
|
||||
def regarder_suivant(self):
|
||||
"""
|
||||
Regarde le prochain élément de la file.
|
||||
- Défile le contenu
|
||||
- L'ajoute à l'historique
|
||||
|
||||
:return: (str) Titre du contenu regardé ou None
|
||||
"""
|
||||
if self.file_attente.est_vide():
|
||||
return None
|
||||
|
||||
contenu = self.file_attente.defile()
|
||||
self.historique.empile(contenu)
|
||||
return contenu
|
||||
|
||||
def prochain(self):
|
||||
"""
|
||||
Renvoie le prochain contenu sans le retirer.
|
||||
|
||||
:return: (str) Titre du prochain contenu ou None
|
||||
"""
|
||||
return self.file_attente.tete()
|
||||
|
||||
def revoir_dernier(self):
|
||||
"""
|
||||
Remet le dernier contenu regardé dans la file (en tête).
|
||||
Utile pour revoir un épisode.
|
||||
|
||||
:return: (str) Titre du contenu remis en file ou None
|
||||
"""
|
||||
if self.historique.est_vide():
|
||||
return None
|
||||
|
||||
contenu = self.historique.depile()
|
||||
# Créer une nouvelle file avec ce contenu en tête
|
||||
nouvelle_file = File()
|
||||
nouvelle_file.enfile(contenu)
|
||||
|
||||
# Transvaser l'ancienne file
|
||||
while not self.file_attente.est_vide():
|
||||
nouvelle_file.enfile(self.file_attente.defile())
|
||||
|
||||
self.file_attente = nouvelle_file
|
||||
return contenu
|
||||
|
||||
def ajouter_prioritaire(self, titre):
|
||||
"""
|
||||
Ajoute un contenu en tête de file (sera regardé en premier).
|
||||
|
||||
:param titre: (str) Titre du contenu prioritaire
|
||||
"""
|
||||
nouvelle_file = File()
|
||||
nouvelle_file.enfile(titre)
|
||||
|
||||
while not self.file_attente.est_vide():
|
||||
nouvelle_file.enfile(self.file_attente.defile())
|
||||
|
||||
self.file_attente = nouvelle_file
|
||||
|
||||
def afficher(self):
|
||||
"""Affiche l'état de la liste de visionnage."""
|
||||
print("=== Ma Liste Netflix ===")
|
||||
print(f"À regarder : {self.file_attente.taille()} élément(s)")
|
||||
print(f"Déjà vus : {self.historique.taille()} élément(s)")
|
||||
if not self.file_attente.est_vide():
|
||||
print(f"Prochain : {self.prochain()}")
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# PARTIE 4 : Système Undo/Redo
|
||||
# =============================================================================
|
||||
|
||||
class EditeurTexte:
|
||||
"""Éditeur de texte avec Undo/Redo."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialise l'éditeur."""
|
||||
self.texte = ""
|
||||
self.historique_undo = Pile()
|
||||
self.historique_redo = Pile()
|
||||
|
||||
def ecrire(self, texte_ajoute):
|
||||
"""
|
||||
Ajoute du texte.
|
||||
Sauvegarde l'état actuel dans l'historique.
|
||||
|
||||
:param texte_ajoute: (str) Texte à ajouter
|
||||
"""
|
||||
self.historique_undo.empile(self.texte)
|
||||
self.texte += texte_ajoute
|
||||
# Vider l'historique redo car nouvelle action
|
||||
while not self.historique_redo.est_vide():
|
||||
self.historique_redo.depile()
|
||||
|
||||
def effacer(self, n=1):
|
||||
"""
|
||||
Efface les n derniers caractères.
|
||||
|
||||
:param n: (int) Nombre de caractères à effacer
|
||||
"""
|
||||
if n > len(self.texte):
|
||||
n = len(self.texte)
|
||||
|
||||
self.historique_undo.empile(self.texte)
|
||||
self.texte = self.texte[:-n] if n > 0 else self.texte
|
||||
# Vider l'historique redo
|
||||
while not self.historique_redo.est_vide():
|
||||
self.historique_redo.depile()
|
||||
|
||||
def undo(self):
|
||||
"""
|
||||
Annule la dernière action (Ctrl+Z).
|
||||
|
||||
:return: (bool) True si l'annulation a réussi
|
||||
"""
|
||||
if self.historique_undo.est_vide():
|
||||
return False
|
||||
|
||||
self.historique_redo.empile(self.texte)
|
||||
self.texte = self.historique_undo.depile()
|
||||
return True
|
||||
|
||||
def redo(self):
|
||||
"""
|
||||
Refait la dernière action annulée (Ctrl+Y).
|
||||
|
||||
:return: (bool) True si le redo a réussi
|
||||
"""
|
||||
if self.historique_redo.est_vide():
|
||||
return False
|
||||
|
||||
self.historique_undo.empile(self.texte)
|
||||
self.texte = self.historique_redo.depile()
|
||||
return True
|
||||
|
||||
def afficher(self):
|
||||
"""Affiche le texte actuel."""
|
||||
undo_dispo = "Ctrl+Z" if not self.historique_undo.est_vide() else "-----"
|
||||
redo_dispo = "Ctrl+Y" if not self.historique_redo.est_vide() else "-----"
|
||||
print(f"[{undo_dispo}] [{redo_dispo}]")
|
||||
print(f'Texte : "{self.texte}"')
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# BONUS : File avec deux piles (complexité amortie O(1))
|
||||
# =============================================================================
|
||||
|
||||
class FileDeuxPiles:
|
||||
"""
|
||||
Implémentation efficace d'une file avec deux piles.
|
||||
Complexité amortie O(1) pour toutes les opérations.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialise une file vide."""
|
||||
self.pile_entree = Pile() # Pour les enfilements
|
||||
self.pile_sortie = Pile() # Pour les défilements
|
||||
|
||||
def enfile(self, element):
|
||||
"""Ajoute un élément en queue de file. O(1)"""
|
||||
self.pile_entree.empile(element)
|
||||
|
||||
def _transferer(self):
|
||||
"""Transfère pile_entree vers pile_sortie si nécessaire."""
|
||||
if self.pile_sortie.est_vide():
|
||||
while not self.pile_entree.est_vide():
|
||||
self.pile_sortie.empile(self.pile_entree.depile())
|
||||
|
||||
def defile(self):
|
||||
"""Retire et renvoie l'élément en tête. O(1) amorti."""
|
||||
self._transferer()
|
||||
return self.pile_sortie.depile()
|
||||
|
||||
def tete(self):
|
||||
"""Renvoie l'élément en tête sans le retirer. O(1) amorti."""
|
||||
self._transferer()
|
||||
return self.pile_sortie.sommet()
|
||||
|
||||
def est_vide(self):
|
||||
"""Renvoie True si la file est vide. O(1)"""
|
||||
return self.pile_entree.est_vide() and self.pile_sortie.est_vide()
|
||||
|
||||
def taille(self):
|
||||
"""Renvoie le nombre d'éléments. O(1)"""
|
||||
return self.pile_entree.taille() + self.pile_sortie.taille()
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# TESTS
|
||||
# =============================================================================
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("=" * 60)
|
||||
print("TEST DU NAVIGATEUR")
|
||||
print("=" * 60)
|
||||
|
||||
nav = Navigateur()
|
||||
nav.afficher_etat()
|
||||
|
||||
nav.visiter("https://www.wikipedia.org")
|
||||
nav.visiter("https://www.youtube.com")
|
||||
nav.visiter("https://www.github.com")
|
||||
nav.afficher_etat()
|
||||
|
||||
print("\nRetour...")
|
||||
nav.retour()
|
||||
nav.afficher_etat()
|
||||
|
||||
print("\nRetour...")
|
||||
nav.retour()
|
||||
nav.afficher_etat()
|
||||
|
||||
print("\nAvancer...")
|
||||
nav.avancer()
|
||||
nav.afficher_etat()
|
||||
|
||||
print("\nVisite nouvelle page...")
|
||||
nav.visiter("https://www.python.org")
|
||||
nav.afficher_etat()
|
||||
|
||||
print("\n")
|
||||
nav.afficher_historique()
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("TEST DE NETFLIX")
|
||||
print("=" * 60)
|
||||
|
||||
netflix = ListeVisionnage()
|
||||
netflix.ajouter("Stranger Things S5")
|
||||
netflix.ajouter("Wednesday S2")
|
||||
netflix.ajouter("Squid Game S3")
|
||||
netflix.afficher()
|
||||
|
||||
print(f"\nRegardé : {netflix.regarder_suivant()}")
|
||||
print(f"Regardé : {netflix.regarder_suivant()}")
|
||||
netflix.afficher()
|
||||
|
||||
print(f"\nRevoir dernier : {netflix.revoir_dernier()}")
|
||||
netflix.afficher()
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("TEST DE L'EDITEUR")
|
||||
print("=" * 60)
|
||||
|
||||
editeur = EditeurTexte()
|
||||
editeur.ecrire("Bonjour")
|
||||
editeur.ecrire(" le monde")
|
||||
editeur.afficher()
|
||||
|
||||
print("\nUndo...")
|
||||
editeur.undo()
|
||||
editeur.afficher()
|
||||
|
||||
print("\nRedo...")
|
||||
editeur.redo()
|
||||
editeur.afficher()
|
||||
|
||||
print("\nEffacer 6 caractères...")
|
||||
editeur.effacer(6)
|
||||
editeur.afficher()
|
||||
@@ -53,8 +53,8 @@ class File1 :
|
||||
Fonction qui ajoute un élément, si la taille le permet.
|
||||
return (bool): Renvoie True si l'ajout de l'élément a eu lieu, False sinon
|
||||
"""
|
||||
if file.taille() < 5 :
|
||||
file.enfile(fichier)
|
||||
if self.taille() < 7 :
|
||||
self.enfile(element)
|
||||
return True
|
||||
else :
|
||||
return False
|
||||
@@ -63,8 +63,8 @@ class File1 :
|
||||
"""
|
||||
Fonction qui vide une file et affiche ces éléments
|
||||
"""
|
||||
while file.est_vide() == False :
|
||||
e = file.defile()
|
||||
while self.est_vide() == False :
|
||||
e = self.defile()
|
||||
print(e)
|
||||
|
||||
# PARTIE 3 :
|
||||
|
||||
@@ -27,7 +27,7 @@ Supposons que notre file à une taille fixe, disons 7 éléments maximum.
|
||||
|
||||
## 3. Deuxième implémentation
|
||||
|
||||
Ici nous allons implémenter la file de manière récursive. Elle possèdera deux attributs, le premier sera un élément de la pile nommé tête, le second sera une autre File. Cette seconde file possèdera elle aura un élément et une autre file en attribut. Ainsi de suite.
|
||||
Ici nous allons implémenter la file de manière récursive. Elle possèdera deux attributs, le premier sera un élément de la file nommé tête, le second sera une autre File. Cette seconde file possèdera elle aura un élément et une autre file en attribut. Ainsi de suite.
|
||||
|
||||
1. Programmez cette classe nommée File2 avec les méthodes suivantes
|
||||
* **enfile( )**
|
||||
@@ -44,11 +44,11 @@ Chacun tire la carte du dessus de son paquet et la pose sur la table. Celui qui
|
||||
|
||||
Lorsqu'il y a "bataille" les joueurs tirent la carte suivante et la posent, face cachée, sur la carte précédente. Puis ils tirent une deuxième carte qu'ils posent cette fois-ci face découverte et c'est cette dernière qui départagera les joueurs.
|
||||
|
||||
Lorsqu'il y a bataille et qu'un des deux joueur à moins de 3 cartes alors il a perdu
|
||||
Lorsqu'il y a bataille et qu'un des deux joueurs a moins de 3 cartes alors il a perdu.
|
||||
|
||||
Le gagnant est celui qui remporte toutes les cartes.
|
||||
|
||||
Le jeu de la bataille peut être facilement coder avec des Files.
|
||||
Le jeu de la bataille peut être facilement codé avec des Files.
|
||||
|
||||
Un fichier carte.py contient la classe carte et les fonctions suivantes :
|
||||
|
||||
@@ -69,4 +69,12 @@ Un fichier carte.py contient la classe carte et les fonctions suivantes :
|
||||
|
||||
## Pour aller plus loin :
|
||||
|
||||
Ecrire une nouvelle implémentation d'une file, cette fois-ci il faut manipuler la file avec deux piles.
|
||||
Écrire une nouvelle implémentation d'une file, cette fois-ci il faut manipuler la file avec deux piles.
|
||||
|
||||
---
|
||||
|
||||
Auteurs : Florian Mathieu, Enzo Frémeaux, Thimothée Decooster
|
||||
|
||||
Licence CC BY NC
|
||||
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International</a>.
|
||||
530
Pile_File/TP/TP_Navigateur.md
Normal file
530
Pile_File/TP/TP_Navigateur.md
Normal file
@@ -0,0 +1,530 @@
|
||||
# TP : Simulateur de Navigateur Web — Piles et Files en action
|
||||
|
||||
> **Thème** : Structures de données linéaires (Pile, File)
|
||||
|
||||
---
|
||||
|
||||
## Contexte
|
||||
|
||||
Chaque jour, vous utilisez un navigateur web (Chrome, Firefox, Safari...). Avez-vous déjà remarqué comment fonctionnent les boutons **← Retour** et **→ Suivant** ? Et comment Netflix gère votre file d'attente "**À regarder ensuite**" ?
|
||||
|
||||
Dans ce TP, vous allez recréer ces mécanismes en utilisant les structures **Pile** et **File**.
|
||||
|
||||
---
|
||||
|
||||
## Partie 1 : Implémentation des structures
|
||||
|
||||
### Exercice 1 : La classe Pile
|
||||
|
||||
Implémentez une classe `Pile` avec les méthodes suivantes :
|
||||
|
||||
```python
|
||||
class Pile:
|
||||
"""Structure de données LIFO (Last In First Out)."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialise une pile vide."""
|
||||
pass
|
||||
|
||||
def empile(self, element):
|
||||
"""Ajoute un élément au sommet de la pile."""
|
||||
pass
|
||||
|
||||
def depile(self):
|
||||
"""
|
||||
Retire et renvoie l'élément au sommet.
|
||||
Renvoie None si la pile est vide.
|
||||
"""
|
||||
pass
|
||||
|
||||
def est_vide(self):
|
||||
"""Renvoie True si la pile est vide."""
|
||||
pass
|
||||
|
||||
def sommet(self):
|
||||
"""
|
||||
Renvoie l'élément au sommet sans le retirer.
|
||||
Renvoie None si la pile est vide.
|
||||
"""
|
||||
pass
|
||||
|
||||
def taille(self):
|
||||
"""Renvoie le nombre d'éléments dans la pile."""
|
||||
pass
|
||||
|
||||
def __repr__(self):
|
||||
"""Affichage de la pile."""
|
||||
pass
|
||||
```
|
||||
|
||||
**Tests à effectuer :**
|
||||
```python
|
||||
>>> p = Pile()
|
||||
>>> p.est_vide()
|
||||
True
|
||||
>>> p.empile("A")
|
||||
>>> p.empile("B")
|
||||
>>> p.empile("C")
|
||||
>>> p.sommet()
|
||||
'C'
|
||||
>>> p.depile()
|
||||
'C'
|
||||
>>> p.taille()
|
||||
2
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Exercice 2 : La classe File
|
||||
|
||||
Implémentez une classe `File` avec les méthodes suivantes :
|
||||
|
||||
```python
|
||||
class File:
|
||||
"""Structure de données FIFO (First In First Out)."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialise une file vide."""
|
||||
pass
|
||||
|
||||
def enfile(self, element):
|
||||
"""Ajoute un élément en queue de file."""
|
||||
pass
|
||||
|
||||
def defile(self):
|
||||
"""
|
||||
Retire et renvoie l'élément en tête de file.
|
||||
Renvoie None si la file est vide.
|
||||
"""
|
||||
pass
|
||||
|
||||
def est_vide(self):
|
||||
"""Renvoie True si la file est vide."""
|
||||
pass
|
||||
|
||||
def tete(self):
|
||||
"""
|
||||
Renvoie l'élément en tête sans le retirer.
|
||||
Renvoie None si la file est vide.
|
||||
"""
|
||||
pass
|
||||
|
||||
def taille(self):
|
||||
"""Renvoie le nombre d'éléments dans la file."""
|
||||
pass
|
||||
|
||||
def __repr__(self):
|
||||
"""Affichage de la file."""
|
||||
pass
|
||||
```
|
||||
|
||||
**Tests à effectuer :**
|
||||
```python
|
||||
>>> f = File()
|
||||
>>> f.est_vide()
|
||||
True
|
||||
>>> f.enfile("Premier")
|
||||
>>> f.enfile("Deuxième")
|
||||
>>> f.enfile("Troisième")
|
||||
>>> f.tete()
|
||||
'Premier'
|
||||
>>> f.defile()
|
||||
'Premier'
|
||||
>>> f.taille()
|
||||
2
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Partie 2 : Simulateur de navigateur web
|
||||
|
||||
### Principe de fonctionnement
|
||||
|
||||
Un navigateur utilise **deux piles** pour gérer l'historique :
|
||||
|
||||
- **Pile `historique`** : contient les pages visitées (la page actuelle est au sommet)
|
||||
- **Pile `suivant`** : contient les pages "en avant" (après avoir cliqué sur Retour)
|
||||
|
||||
| Action | Effet |
|
||||
|--------|-------|
|
||||
| Visiter une page | Empile dans `historique`, vide `suivant` |
|
||||
| Clic sur ← Retour | Dépile `historique` → empile dans `suivant` |
|
||||
| Clic sur → Suivant | Dépile `suivant` → empile dans `historique` |
|
||||
|
||||
---
|
||||
|
||||
### Exercice 3 : La classe Navigateur
|
||||
|
||||
```python
|
||||
class Navigateur:
|
||||
"""Simulateur de navigateur web avec historique."""
|
||||
|
||||
def __init__(self, page_accueil="https://www.google.com"):
|
||||
"""
|
||||
Initialise le navigateur avec une page d'accueil.
|
||||
|
||||
:param page_accueil: (str) URL de la page d'accueil
|
||||
"""
|
||||
self.historique = Pile()
|
||||
self.suivant = Pile()
|
||||
# À compléter : empiler la page d'accueil
|
||||
|
||||
def page_actuelle(self):
|
||||
"""
|
||||
Renvoie l'URL de la page actuellement affichée.
|
||||
|
||||
:return: (str) URL de la page actuelle ou None
|
||||
"""
|
||||
# À compléter
|
||||
pass
|
||||
|
||||
def visiter(self, url):
|
||||
"""
|
||||
Visite une nouvelle page.
|
||||
- Empile l'URL dans l'historique
|
||||
- Vide la pile 'suivant' (on ne peut plus avancer)
|
||||
|
||||
:param url: (str) URL de la page à visiter
|
||||
"""
|
||||
# À compléter
|
||||
pass
|
||||
|
||||
def retour(self):
|
||||
"""
|
||||
Revient à la page précédente (bouton ←).
|
||||
- Dépile l'historique
|
||||
- Empile la page actuelle dans 'suivant'
|
||||
|
||||
:return: (str) URL de la nouvelle page actuelle ou None si impossible
|
||||
"""
|
||||
# À compléter
|
||||
pass
|
||||
|
||||
def avancer(self):
|
||||
"""
|
||||
Avance à la page suivante (bouton →).
|
||||
- Dépile 'suivant'
|
||||
- Empile dans l'historique
|
||||
|
||||
:return: (str) URL de la nouvelle page actuelle ou None si impossible
|
||||
"""
|
||||
# À compléter
|
||||
pass
|
||||
|
||||
def peut_reculer(self):
|
||||
"""Renvoie True si le bouton Retour est actif."""
|
||||
# À compléter
|
||||
pass
|
||||
|
||||
def peut_avancer(self):
|
||||
"""Renvoie True si le bouton Suivant est actif."""
|
||||
# À compléter
|
||||
pass
|
||||
|
||||
def afficher_etat(self):
|
||||
"""Affiche l'état actuel du navigateur."""
|
||||
retour = "←" if self.peut_reculer() else "✗"
|
||||
avancer = "→" if self.peut_avancer() else "✗"
|
||||
print(f"[{retour}] [{avancer}] | {self.page_actuelle()}")
|
||||
```
|
||||
|
||||
**Tests à effectuer :**
|
||||
```python
|
||||
>>> nav = Navigateur()
|
||||
>>> nav.afficher_etat()
|
||||
[✗] [✗] | https://www.google.com
|
||||
|
||||
>>> nav.visiter("https://www.wikipedia.org")
|
||||
>>> nav.visiter("https://www.youtube.com")
|
||||
>>> nav.visiter("https://www.github.com")
|
||||
>>> nav.afficher_etat()
|
||||
[←] [✗] | https://www.github.com
|
||||
|
||||
>>> nav.retour()
|
||||
'https://www.youtube.com'
|
||||
>>> nav.afficher_etat()
|
||||
[←] [→] | https://www.youtube.com
|
||||
|
||||
>>> nav.retour()
|
||||
'https://www.wikipedia.org'
|
||||
>>> nav.avancer()
|
||||
'https://www.youtube.com'
|
||||
|
||||
>>> nav.visiter("https://www.python.org")
|
||||
>>> nav.afficher_etat()
|
||||
[←] [✗] | https://www.python.org
|
||||
>>> nav.peut_avancer()
|
||||
False # La pile 'suivant' a été vidée
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Exercice 4 : Historique complet
|
||||
|
||||
Ajoutez une méthode pour afficher tout l'historique de navigation :
|
||||
|
||||
```python
|
||||
def afficher_historique(self):
|
||||
"""
|
||||
Affiche l'historique complet de navigation.
|
||||
La page actuelle est marquée d'une flèche.
|
||||
"""
|
||||
# À compléter
|
||||
pass
|
||||
```
|
||||
|
||||
**Exemple de sortie :**
|
||||
```
|
||||
Historique de navigation :
|
||||
1. https://www.google.com
|
||||
2. https://www.wikipedia.org
|
||||
3. https://www.youtube.com
|
||||
→ 4. https://www.github.com (page actuelle)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Partie 3 : File d'attente Netflix
|
||||
|
||||
### Contexte
|
||||
|
||||
Sur Netflix, vous pouvez ajouter des films à votre liste "**À regarder**". Les films sont regardés dans l'ordre d'ajout (FIFO), mais vous pouvez aussi mettre un film en priorité.
|
||||
|
||||
---
|
||||
|
||||
### Exercice 5 : La classe ListeVisionnage
|
||||
|
||||
```python
|
||||
class ListeVisionnage:
|
||||
"""Gestionnaire de file d'attente de visionnage."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialise une liste de visionnage vide."""
|
||||
self.file_attente = File()
|
||||
self.historique = Pile() # Films déjà regardés
|
||||
|
||||
def ajouter(self, titre):
|
||||
"""
|
||||
Ajoute un film/série à la file d'attente.
|
||||
|
||||
:param titre: (str) Titre du contenu à ajouter
|
||||
"""
|
||||
# À compléter
|
||||
pass
|
||||
|
||||
def regarder_suivant(self):
|
||||
"""
|
||||
Regarde le prochain élément de la file.
|
||||
- Défile le contenu
|
||||
- L'ajoute à l'historique
|
||||
|
||||
:return: (str) Titre du contenu regardé ou None
|
||||
"""
|
||||
# À compléter
|
||||
pass
|
||||
|
||||
def prochain(self):
|
||||
"""
|
||||
Renvoie le prochain contenu sans le retirer.
|
||||
|
||||
:return: (str) Titre du prochain contenu ou None
|
||||
"""
|
||||
# À compléter
|
||||
pass
|
||||
|
||||
def revoir_dernier(self):
|
||||
"""
|
||||
Remet le dernier contenu regardé dans la file (en tête).
|
||||
Utile pour revoir un épisode.
|
||||
|
||||
:return: (str) Titre du contenu remis en file ou None
|
||||
"""
|
||||
# À compléter (utiliser une file temporaire ou une autre approche)
|
||||
pass
|
||||
|
||||
def afficher(self):
|
||||
"""Affiche l'état de la liste de visionnage."""
|
||||
print("=== Ma Liste Netflix ===")
|
||||
print(f"À regarder : {self.file_attente.taille()} élément(s)")
|
||||
print(f"Déjà vus : {self.historique.taille()} élément(s)")
|
||||
if not self.file_attente.est_vide():
|
||||
print(f"Prochain : {self.prochain()}")
|
||||
```
|
||||
|
||||
**Tests à effectuer :**
|
||||
```python
|
||||
>>> netflix = ListeVisionnage()
|
||||
>>> netflix.ajouter("Stranger Things S5")
|
||||
>>> netflix.ajouter("Wednesday S2")
|
||||
>>> netflix.ajouter("Squid Game S3")
|
||||
>>> netflix.afficher()
|
||||
=== Ma Liste Netflix ===
|
||||
À regarder : 3 élément(s)
|
||||
Déjà vus : 0 élément(s)
|
||||
Prochain : Stranger Things S5
|
||||
|
||||
>>> netflix.regarder_suivant()
|
||||
'Stranger Things S5'
|
||||
>>> netflix.regarder_suivant()
|
||||
'Wednesday S2'
|
||||
>>> netflix.afficher()
|
||||
=== Ma Liste Netflix ===
|
||||
À regarder : 1 élément(s)
|
||||
Déjà vus : 2 élément(s)
|
||||
Prochain : Squid Game S3
|
||||
|
||||
>>> netflix.revoir_dernier()
|
||||
'Wednesday S2'
|
||||
>>> netflix.prochain()
|
||||
'Wednesday S2'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Exercice 6 : File avec priorité
|
||||
|
||||
Netflix permet aussi de mettre un contenu "en haut de la liste". Ajoutez cette fonctionnalité :
|
||||
|
||||
```python
|
||||
def ajouter_prioritaire(self, titre):
|
||||
"""
|
||||
Ajoute un contenu en tête de file (sera regardé en premier).
|
||||
Nécessite de reconstruire la file.
|
||||
|
||||
:param titre: (str) Titre du contenu prioritaire
|
||||
"""
|
||||
# Indice : créer une nouvelle file, enfiler le titre prioritaire,
|
||||
# puis transvaser l'ancienne file
|
||||
pass
|
||||
```
|
||||
|
||||
**Test :**
|
||||
```python
|
||||
>>> netflix.ajouter("Film 1")
|
||||
>>> netflix.ajouter("Film 2")
|
||||
>>> netflix.ajouter_prioritaire("Film URGENT")
|
||||
>>> netflix.prochain()
|
||||
'Film URGENT'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Partie 4 : Système Undo/Redo
|
||||
|
||||
### Exercice 7 : Éditeur de texte simplifié
|
||||
|
||||
Créez un éditeur qui permet d'annuler (Ctrl+Z) et de refaire (Ctrl+Y) des actions.
|
||||
|
||||
```python
|
||||
class EditeurTexte:
|
||||
"""Éditeur de texte avec Undo/Redo."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialise l'éditeur."""
|
||||
self.texte = ""
|
||||
self.historique_undo = Pile() # États précédents
|
||||
self.historique_redo = Pile() # États annulés
|
||||
|
||||
def ecrire(self, texte_ajoute):
|
||||
"""
|
||||
Ajoute du texte.
|
||||
Sauvegarde l'état actuel dans l'historique.
|
||||
|
||||
:param texte_ajoute: (str) Texte à ajouter
|
||||
"""
|
||||
# À compléter
|
||||
pass
|
||||
|
||||
def effacer(self, n=1):
|
||||
"""
|
||||
Efface les n derniers caractères.
|
||||
|
||||
:param n: (int) Nombre de caractères à effacer
|
||||
"""
|
||||
# À compléter
|
||||
pass
|
||||
|
||||
def undo(self):
|
||||
"""
|
||||
Annule la dernière action (Ctrl+Z).
|
||||
|
||||
:return: (bool) True si l'annulation a réussi
|
||||
"""
|
||||
# À compléter
|
||||
pass
|
||||
|
||||
def redo(self):
|
||||
"""
|
||||
Refait la dernière action annulée (Ctrl+Y).
|
||||
|
||||
:return: (bool) True si le redo a réussi
|
||||
"""
|
||||
# À compléter
|
||||
pass
|
||||
|
||||
def afficher(self):
|
||||
"""Affiche le texte actuel."""
|
||||
undo_dispo = "Ctrl+Z" if not self.historique_undo.est_vide() else "-----"
|
||||
redo_dispo = "Ctrl+Y" if not self.historique_redo.est_vide() else "-----"
|
||||
print(f"[{undo_dispo}] [{redo_dispo}]")
|
||||
print(f"Texte : \"{self.texte}\"")
|
||||
```
|
||||
|
||||
**Tests :**
|
||||
```python
|
||||
>>> editeur = EditeurTexte()
|
||||
>>> editeur.ecrire("Bonjour")
|
||||
>>> editeur.ecrire(" le monde")
|
||||
>>> editeur.afficher()
|
||||
[Ctrl+Z] [-----]
|
||||
Texte : "Bonjour le monde"
|
||||
|
||||
>>> editeur.undo()
|
||||
True
|
||||
>>> editeur.afficher()
|
||||
[Ctrl+Z] [Ctrl+Y]
|
||||
Texte : "Bonjour"
|
||||
|
||||
>>> editeur.redo()
|
||||
True
|
||||
>>> editeur.afficher()
|
||||
[Ctrl+Z] [-----]
|
||||
Texte : "Bonjour le monde"
|
||||
|
||||
>>> editeur.effacer(6)
|
||||
>>> editeur.afficher()
|
||||
[Ctrl+Z] [-----]
|
||||
Texte : "Bonjour le"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Bonus : Comparaison des complexités
|
||||
|
||||
| Opération | Pile (liste Python) | File (liste Python) | File (deux piles) |
|
||||
|-----------|---------------------|---------------------|-------------------|
|
||||
| Empile/Enfile | O(1) | O(n)* | O(1) amorti |
|
||||
| Dépile/Défile | O(1) | O(1) | O(1) amorti |
|
||||
| Sommet/Tête | O(1) | O(1) | O(1) |
|
||||
| Est_vide | O(1) | O(1) | O(1) |
|
||||
|
||||
*L'insertion en début de liste Python est en O(n).
|
||||
|
||||
**Exercice bonus** : Implémentez une file efficace en utilisant deux piles.
|
||||
|
||||
---
|
||||
|
||||
## Résumé des notions
|
||||
|
||||
| Structure | Principe | Analogie | Cas d'usage |
|
||||
|-----------|----------|----------|-------------|
|
||||
| **Pile** | LIFO | Pile d'assiettes | Historique, Undo, Appels de fonctions |
|
||||
| **File** | FIFO | File d'attente | Impression, Streaming, BFS |
|
||||
|
||||
---
|
||||
|
||||
Auteurs : Florian Mathieu
|
||||
|
||||
Licence CC BY NC
|
||||
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International</a>.
|
||||
@@ -44,7 +44,7 @@ Afin d'implémenter la pile il nous faut utiliser une structure de données perm
|
||||
|
||||
|
||||
|
||||
## 2. 2. Calculatrice polonaise inverse
|
||||
### 2. 2. Calculatrice polonaise inverse
|
||||
|
||||
La calculatrice polonaise inverse permet de faire des calculs simple mais pose l'opérateur après les deux opérandes.
|
||||
|
||||
@@ -75,7 +75,7 @@ La calculatrice polonaise inverse permet de faire des calculs simple mais pose l
|
||||
|
||||
Le but ici est de trier une pile. Pour cela nous utiliserons une autre pile temporaire permettant de stocker les éléments.
|
||||
|
||||
1. Ecrire une fonction tri_pile( ) prennant en paramètre une pile et renvoyant la pile triée.
|
||||
1. Écrire une fonction tri_pile( ) prenant en paramètre une pile et renvoyant la pile triée.
|
||||
|
||||
> L'idée ici est d'utiliser seulement deux piles. Afin de comprendre le fonctionnement il faut faire quelques essais à la main.
|
||||
|
||||
@@ -98,3 +98,10 @@ Le but ici est de trier une pile. Pour cela nous utiliserons une autre pile temp
|
||||
9
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Auteurs : Florian Mathieu, Enzo Frémeaux, Thimothée Decooster
|
||||
|
||||
Licence CC BY NC
|
||||
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International</a>.
|
||||
|
||||
@@ -8,8 +8,8 @@ class Pile :
|
||||
|
||||
def empile(self,x) :
|
||||
"""
|
||||
Méthode qui enpile un élément
|
||||
param x : () Elément x à enpiler
|
||||
Méthode qui empile un élément
|
||||
param x : () Elément x à empiler
|
||||
"""
|
||||
self.pile.append(x)
|
||||
|
||||
@@ -52,8 +52,8 @@ class Pile :
|
||||
while pile_tmp.taille() != 0 and pile_tmp.top() < val_tmp:
|
||||
self.empile(pile_tmp.depile())
|
||||
pile_tmp.empile(val_tmp)
|
||||
p.pile = pile_tmp.pile
|
||||
return p
|
||||
self.pile = pile_tmp.pile
|
||||
return self
|
||||
|
||||
|
||||
p = Pile()
|
||||
|
||||
Reference in New Issue
Block a user