Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • rvuillem/inf-tc1
  • hwei/inf-tc1
  • nmbengue/inf-tc1
  • fernanda/inf-tc1
  • mleger/inf-tc1
  • lmeng/inf-tc1
  • gferryla/inf-tc1
  • jconso/inf-tc1
  • smaghsou/inf-tc1
  • emarquet/inf-tc1
  • ecluzel/inf-tc1
  • aaudeoud/inf-tc1
  • tsegond/inf-tc1
  • aetienne/inf-tc1
  • djoly/inf-tc1
  • bcampeas/inf-tc1
  • dnovarez/inf-tc1
  • ruetm/inf-tc1
  • cchenu/inf-tc1
  • cguiotdu/inf-tc1
  • mclouard/inf-tc1
  • gwachowi/inf-tc1
  • qbaalaou/inf-tc1
  • sbrocas/inf-tc1
  • ppupion/inf-tc1
  • kinty/inf-tc1
  • hadomo/inf-tc1
  • tgicquel/inf-tc1
  • rhahn/inf-tc1
  • cguyau/inf-tc1
  • mpairaul/inf-tc1
  • rmuller/inf-tc1
  • rlecharp/inf-tc1
  • asebasty/inf-tc1
  • qmaler/inf-tc1
  • aoussaid/inf-tc1
  • kcherigu/inf-tc1
  • sgu/inf-tc1
  • malcalat/inf-tc1
  • afalourd/inf-tc1
  • phugues/inf-tc1
  • lsteunou/inf-tc1
  • llauschk/inf-tc1
  • langloia/inf-tc1
  • aboucard/inf-tc1
  • wmellali/inf-tc1
  • ifaraidi/inf-tc1
  • lir/inf-tc1
  • ynedjar/inf-tc1
  • schneidl/inf-tc1
  • zprandi/inf-tc1
  • acoradid/inf-tc1
  • amarcq/inf-tc1
  • dcombet/inf-tc1
  • gplaud/inf-tc1
  • mkernoaj/inf-tc1
  • gbichot/inf-tc1
  • tdutille/inf-tc1
58 results
Select Git revision
Show changes
Showing
with 835 additions and 466 deletions
def selectionSort(alist):
for l in range(len(alist )-1,0,-1):
positionOfMax =0
for location in range (1, l+1):
if alist[location]>alist[ positionOfMax ]:
positionOfMax = location
temp = alist[l]
alist[l] = alist[positionOfMax]
alist[positionOfMax] = temp
alist = [54 ,26 ,93 ,17 ,77 ,31 ,44 ,55 ,20]
selectionSort(alist)
print(alist)
\ No newline at end of file
def algo(words):
t = []
for word in words:
t.append((len(word), word))
t.sort(key=lambda t: t[1][-1])
res = []
for l, w in t:
res.append(w)
res = filter(lambda t: 'a' in t, res)
return list(res)
if __name__=="__main__":
print(algo(["Pierre", "Jean", "Marie", "Eric", "Nathalie", "Yvonne"]))
\ No newline at end of file
# Un commentaire court commence par un # et se limite à la fin de la ligne
"""
On peut aussi créer un commentaire long = une zone de
commentaires sur plusieurs lignes placées
entre une paire de triple-guillements dont le second suit :
"""
# Remarques :
# Un ';' à la fin d'une ligne rend la ligne muette (pas d'affichage des résultats).
# Il permet également de placer plusieurs expressions sur la même ligne.
# Si vous placez un commentaire immédiatement après la signature d'une fonction}
# (ou une méthode, une classe, etc.) entre un couple de """,
# votre commentaire (appelé docstring) devient accessible avec help
\ No newline at end of file
from math import pi
s = "Python"
s.center(10) # centrer sur 10 positions
print(s)
# Donne -->' Python '
s.center(10,"*") # centrer sur 10 positions en complétant par des '*'
# Donne -->'**Python**'
print(s)
s = "Training"
s.ljust(12) # justifier à gauche sur 12 positions}
# Donne -->'Training '
print(s)
s.ljust(12,":")
# Donne -->'Training::::'
s = "Programming"
s.rjust(15)
# Donne -->' Programming'
s.rjust(15, "~")
# Donne -->'~~~~Programming'
account_number = "43447879"
account_number.zfill(12)
# Donne -->'000043447879'
# Même chose avec rjust :
account_number.rjust(12,"0")
# Donne -->'000043447879'
s = 'Hello, world.'
str(s)
# Donne -->'Hello, world.'
repr(s)
# Donne --> "'Hello, world.'"
str(1/7)
# Donne --> '0.14285714285714285'
r=2
print("La surface pour un rayon {rayon:3d} sera {surface:8.3f}".format(surface=r*r*pi, rayon=r))
# Donne --> 'La surface pour un rayon 2 sera 12.566'
x = 10 * 3.25
y = 200 * 200
s = 'The value of x is ' + repr(x) + ', and y is ' + repr(y) + '...'
print(s)
# Donne --> The value of x is 32.5, and y is 40000...
# Le repr() d'un string ajoute des quotes et backslashes:
hello = 'hello, world\n'
str(hello)
# Donne --> 'hello world\n'
repr(hello)
# Donne --> 'hello, world\\n' %* {\color{magenta} noter le double slash} *)
# L'argument d'appel de repr() peut être n'importe quel objet Python :
repr((x, y, ('spam', 'eggs')))
# Donne -->"(32.5, 40000, ('spam', 'eggs'))"
for x in range(1, 11):
print(repr(x).rjust(2), repr(x*x).rjust(3), repr(x*x*x).rjust(4))
# Donne -->
# 1 1 1
# 2 4 8
# 3 9 27
# 4 16 64
# 5 25 125
# 6 36 216
# 7 49 343
# 8 64 512
# 9 81 729
# 10 100 1000
for x in range(1, 6):
print(repr(x).rjust(2), end='#'*x+'\n') # on ajoute x fois \# + \textbackslash n à la fin de chaque ligne} *)
# Donne -->
# 1#
# 2##
# 3###
# 4####
# 5#####
#
\ No newline at end of file
# 8 Conversion de types
list1 = ['1', '2', '3']
str1 = ''.join(list1)
str1
# '123'
list1 = [1, 2, 3]
str1 = ''.join(str(e) for e in list1) # ou avec "" à la place de ''
str1
# '123'
a = "545.2222"
float(a)
# 545.2222 suivant le système, on peut avoir des '0' après les '2'
int(float(a))
# 545
def is_float(value):
try:
float(value)
return True
except:
return False
# On peut aussi utiliser la prédéfinie eval() qui évalue du code Python
eval("1.5")
# 1.5
# Une alternative plus sûre à eval()
import ast
ast.literal_eval("545.2222")
545.2222
ast.literal_eval("31")
31
# Des cas d'erreur
eval(toto) # toto non défini ou n'est pas un str/octes/code
ast.literal_eval(toto)
# Erreur dans les 2 cas
# Converstion en binaire
st = "hello Debase"
' '.join(format(ord(x), 'b') for x in st)
# '1101000 1100101 1101100 1101100 1101111 100000 1000100 1100101 1100010 1100001 1110011 1100101'
# Conversion de string en hexadécimal
s='Hello Debase of Ecl'
' '.join(format(ord(x), 'x') for x in s)
# '48 65 6c 6c 6f 20 44 65 62 61 73 65 20 6f 66 20 45 63 6c'
# Conversion entier en Unicode
chr(16) # Quelle est la forme hexa de 16 ?
#'\x10'
# Conversions décimal <==> base xx
int('12',8) # Quelle est la valeur décimale du nombre octal '12' (octal car base = 8)
# 10
int('12',16) # Quelle est la valeur décimale du nombre hexa '12' (hexa car base = 16)
# 18
int('12') # Quelle est la valeur décimale du nombre décimale '12' (décimal car base par défaut = 10)
# 12
int('1000',2) # Que donne le nombre binaire '1000' en décimal (binaire car base = 2)
# 8
# Pour convertir un entier en octal
oct(12)
# '0o14' #un 'O' au début (pour Octal)
oct(8)
# '0o10'
# Autres conversions
# octal
eval('0o010') == 10 # La valeur décimale de '0o010' est-elle 10
# False
eval('0o010')
# 8
oct(42) # La valeur octale de l'entier 42
# '0o52'
int('0o52', 0) # La valeur décimale de l'octale '0o52' (si base=0 alors base est dans le string)
# 42
int('1101', 2) # La valeur décimale du binaire '1101' (base explicite = 2)
#13
int('0b1101', 2) # Idem, base explicitée = 2, peut importe '0b'
#13
int('0b1101', 0) # La valeur décimale du binaire '0b1101' (base = 0 --> la base '0b' est dans le string)
#13
from struct import *
pack('hhl', 1, 2, 3)
# b'\x01\x00\x02\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00'
# b veut dire byte (2 octes). \x veut dire hexa
pack('b', 1)
# b'\x01'
pack('b', 16) # signed char de taille 1. On convertie 16 en signed char
# b'\x10'
In [39]: pack('B', 16) # unsigned char de taille 1
# b'\x10'
pack('h', 1)
# b'\x01\x00'
calcsize('h')
# 2
calcsize('b')
# 1
unpack('b', b'\x10')
# (16,)
type(unpack('b', b'\x10'))
# tuple
unpack('b', b'\x10')[0] # Première élé. Il y a virgule car taille tuple >= 2
# 16
pack('B',65) # donne b'A' = i.e. le caractère dont le code = 65
\ No newline at end of file
# 7 Types principaux en Python
if type(1) is not int : print('oups')
if type('1') is not int : print(1)
type(3.14)
# float
type(None)
# NoneType
f = lambda c : c if type(c) is str and c.isalpha() else '?'
type(f)
# function
# Utilisation de f (voir plus loin les "lambda expressions") :
f('a') # donne 'a' car 'a' est alphabétique
f('1') # donne '?' car '1' n'est pas alphabétique
f(1) # donne '?' car 1 n'est pas une chaine
import sys;
print(sys.int_info)
# sys.int_info(bits_per_digit=30, sizeof_digit=4)
print(sys.float_info)
# sys.float_info(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308,
# min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15,
# mant_dig=53, epsilon=2.220446049250313e-16, radix=2, rounds=1)
print(sys.getsizeof(float)) # La taille de la classe float
# 400
print(sys.getsizeof(float())) # La taille d'un float
# 24 # Ce que coute en octes un réel
# (valeur + infos supplémentaires)
# Vous devez valider ce code qui affiche le numéro de version
# Rien d'autre à faire !
import sys
if not sys.version_info.major == 3 and sys.version_info.minor >= 7:
print("Python 3.7 ou supérieur est nécessaire !")
else:
print("Vous utilisez {}.{}.".format(sys.version_info.major, sys.version_info.minor))
sys.exit(1)
\ No newline at end of file
code = zip([1000,900 ,500,400 ,100,90 ,50 ,40 ,10 ,9 ,5 ,4 ,1], ["M" ,"CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"])
# fonctions
def zipConversionRomain(num):
res = []
for d, r in code:
while num >= d:
res.append(r)
num -= d
return ''.join(res)
# programme principal -----------------------------------------------
for i in range(1, 15):
print(i, zipConversionRomain(i))
\ No newline at end of file
File deleted
%% Cell type:markdown id:c8809a88 tags:
NAME:
%% Cell type:markdown id:4079279c tags:
# INF TC1 - TD2 (2h) - Structures de données
%% Cell type:markdown id:74d75def tags:
---
%% Cell type:markdown id:42890ec6-251a-404c-a6f6-39c138db8650 tags:
### IMPORTANT A LIRE (SUR L'UTILISATION DE CE NOTEBOOK)
Le but de votre travail est de répondre aux questions des exercices en **remplissant certaines cellules de ce notebook avec votre solution**. Ces cellules, une foit remplies et lancées au fur et à mesure de vos avancées, permettront de valider des tests écrits dans d'autres cellules de ce notebook. **Il est donc important de bien suivre les instructions et répondre aux questions dans l'ordre**, et ne pas changer le nom des fonctions et/ou des cellules. En particulier :
1) Répondez aux questions dans les cellules en dessous des questions.
2) Votre code devra remplacer le texte suivant (que vous pouvez effacer) :
```python
# YOUR CODE HERE
raise NotImplementedError()
```
3) Exécutez enfin les cellules dans leur ordre d'apparition, de haut en bas et si votre code est correct. Ainsi les tests (sous forme d'`assert` seront validés et ne lanceront pas d'exception du type `AssertionError`. Vous pouvez lancer plusieurs fois la même cellule, cela ne pose pas de soucis.
4) Vous pouvez créer de nouvelles cellules comme bon vous semble.
**En cas de problème, une solution est de relancer les cellules depuis le début du notebook une par une.** Pensez à bien sauvegarder ce notebook et ne pas le remplacer par un notebook qui a le même nom.
%% Cell type:markdown id:b692d4dd-6dbc-40e9-9c19-0b59e31e5eab tags:
## Objectif du TD
Ce TD vous fera manipuler plusieurs structures de données standard en Python (listes `list`, dictionnaires `dict`) mais également des structures avancées (piles, files, tas) que vous allez créer au moyen de classes. Au final nous allons créer une méthode de tri efficace (tri par tas) et la comparer avec d'autres méthodes de tri de Python.
%% Cell type:markdown id:b6221ad1-379e-4e50-8c22-220994439b6d tags:
## Exercice 1 - Chargement et tri d'une liste
Le but de cet exercice est de charger une liste de dictionnaires et réaliser des méthodes de tri. Vous disposez pour cela d'un fichier appelé [`etudiants.txt`](etudiants.txt) où chaque ligne contient des informations sur des étudiants d'un cour. Pour commencer nous allons réaliser des tris simples et les rendre de plus en plus complexes.
%% Cell type:markdown id:985e2dd2-dc05-437c-b3f0-60696fe27e3f tags:
### Rappel : Tri de listes
Avant de commencer quelques rappels sur les structures de données de listes et leurs tris. Voici une liste en Python :
%% Cell type:code id:327780ed-4331-43ad-921b-9e42d762f2aa tags:
``` python
L1 = [3, 2 , 4]
```
%% Cell type:markdown id:01263b26-3983-4073-aaff-1a30d69ff914 tags:
Pour la trier vous pouvez utiliser ```.sort()``` [(doc)](https://docs.python.org/3/howto/sorting.html) qui modifie la liste actuelle :
%% Cell type:code id:79f084ad-942d-46c6-bfe7-2722eeeda426 tags:
``` python
L1 = [3, 2 , 4]
L1.sort()
L1
```
%% Cell type:markdown id:f04dbfe7-c000-4c2e-a2c4-e6187fe17ba7 tags:
Soit vous créez une nouvelle liste triée qui ne modifie pas la liste actuelle en utilisant ```sorted``` [(doc)](https://docs.python.org/3/howto/sorting.html) :
%% Cell type:code id:c9b79862-a7b6-4b74-af5c-3d36f85f7b67 tags:
``` python
L2 = [3, 2 , 4]
L2 = sorted(L2)
L2
```
%% Cell type:markdown id:f06e9236-898c-460e-bb23-3a4fed30ad1a tags:
..Et les deux tris sont identiques :
%% Cell type:code id:45b395c0-192f-47db-833d-4087d8244dea tags:
``` python
L1 == L2
```
%% Cell type:markdown id:4affcb3d-d8ae-4c5e-a7f5-fbc59b1fff76 tags:
Enfin les fonctions de tri peuvent prendre un [paramètre nommé](https://docs.python.org/3/glossary.html#term-parameter) `key` afin d'indiquer sur quel attribut de la liste réaliser le tri. Ci-dessous le tri sera appliqué sur le premier élément d'une liste de listes à trier :
%% Cell type:code id:76f37b8b-69f5-4df0-91ae-b221a372e519 tags:
``` python
L = [[3, "C"], [1, "A"], [2, "B"]]
L.sort(key=lambda x: x[0])
L
```
%% Cell type:markdown id:c815465f tags:
### Chargement d'un fichier en dictionnaire
Le code ci-dessous permet de charger ce fichier dans la variable `students_list`.
%% Cell type:code id:fe36de75-c9c4-49b7-ad79-de78c4f5b3ca tags:
``` python
students_list = []
with open("etudiants.txt") as f:
keys = None
for line in f:
l = [w.strip() for w in line.split(';')]
if keys is None:
keys = l
else:
students_list.append({k:v for k, v in zip(keys, l)})
```
%% Cell type:markdown id:cfb09dcd-d8eb-474d-9f01-bff6de7b114a tags:
Un échantillon du jeu de données vous est donné comme suit, il s'agit une liste de dictionnaires [(doc)](https://docs.python.org/3/tutorial/datastructures.html#dictionaries) :
%% Cell type:code id:a0ab86a7-ed2a-4265-be05-fabd7a7b7fe5 tags:
``` python
students_list[0:2]
```
%% Cell type:markdown id:d54fe400 tags:
**Question 1.1 -** Calculez la moyenne des dans la liste `students_list`. Vous nommerez votre fonction `average_grade` et lui donnerez en paramètre la variable `L` qui contient la liste d'étudiant. Conseil : pensez à convertir les variables au bon type de données (par ex. en utilisant `int()`ou `float()`).
%% Cell type:code id:084ca248-e638-4416-9fed-32dde916fb5b tags:
``` python
def average_grade(L: list)-> int:
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:markdown id:66486e51-46fa-4475-a990-9764f1206f21 tags:
La moyenne attendue de votre fonction est :
%% Cell type:code id:e6086d5b-1a84-4cee-8bd3-b3acf46d68d3 tags:
``` python
average_grade(students_list)
```
%% Cell type:markdown id:65b4a7d1-d0d6-4ec4-a609-b7eb42157cea tags:
Le test ci-dessous doit donc être validé (autrement dit aucune `Exception` ne doit être lancée) :
%% Cell type:code id:836938d8-a4c7-44e2-b17b-2159acd11aad tags:
``` python
assert average_grade(students_list) == 16.6
```
%% Cell type:markdown id:2f986196-2afa-4baf-96a3-3d22280e6c22 tags:
**Question 1.2 -** Trouvez la note maximale de manière _récursive_ et comparez avec la fonction `max` (qui peut prendre un argument `key` afin de trier par note) donnée ci-dessous. Attention encore au type des données.
%% Cell type:code id:45624183-f5e7-43ae-9e41-ab8b456d9360 tags:
``` python
def find_maximum_recursive(L: list)-> int:
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:code id:ef350eab tags:
``` python
find_maximum_recursive(students_list)
```
%% Cell type:code id:59684c44-83db-47c3-a192-781041fc3b59 tags:
``` python
assert find_maximum_recursive(students_list) == int(max(students_list, key=lambda x: int(x["note"]))["note"])
```
%% Cell type:markdown id:a9bca555-e31a-4294-bdac-d9e2ff5fa950 tags:
**Question 1.3 -** Ecrivez une fonction de recherche d'une pair d'étudiants qui ont la même note, et renvoyez leurs noms sous forme de `Tuple`. Conseil :
- parcourez la liste et mémoriser les notes que vous parcourrez;
- si une note a déjà été visitée alors renvoyer l'indice du dictionnaire;
- enfin renvoyez les noms des étudiants.
%% Cell type:code id:1dd770ee-1c63-4fcc-b564-158803c665e9 tags:
``` python
def find_same_grade(L: list)-> tuple:
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:code id:dbfbaf85-01b6-4bbc-ae1e-b9e7cc47489e tags:
``` python
find_same_grade(students_list)
```
%% Cell type:code id:5ef24de8-ed61-40e1-ad9a-26f118223c17 tags:
``` python
assert find_same_grade(students_list) == ('Dupond', 'Dupont')
```
%% Cell type:markdown id:0f948f2e tags:
**Question 1.4 (BONUS si vous avez du temps) -** Triez la liste d'étudiants par ordre croissant en implémentant un _tri par sélection_ fourni dans le pseudo-code ci-dessous (issu de [cette page](https://fr.wikipedia.org/wiki/Tri_par_s%C3%A9lection)). L'argument `key` permettra d'indiquer sur quel attribut réaliser le tri (par exemple la note). Voir l'usage de cet attribut dans la cellule de test suivante.
```
procédure tri_selection(tableau t)
n ← longueur(t)
pour i de 0 à n - 2
min ← i
pour j de i + 1 à n - 1
si t[j] < t[min], alors min ← j
fin pour
si min ≠ i, alors échanger t[i] et t[min]
fin pour
fin procédure
```
%% Cell type:code id:03e651d7-1143-4a9f-b453-3469d5b75e52 tags:
``` python
def sort_selection(L: list, key=lambda x: x) -> list:
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:markdown id:d95d2146-847a-4c21-9a9a-af277d236aea tags:
Comparer votre tri avec la méthode `sorted` de Python.
%% Cell type:code id:e27a7071-e10b-4801-8d16-aa611f0866f6 tags:
``` python
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:markdown id:dae866db tags:
## Exercice 2 : Piles et files
Désormais nous allons implémenter de nouvelles structures de manipulation de listes : les Piles et les Files. Et à terme réaliser un tri de plus en plus efficace (avec un Tas). Nous allons commencer avec la Pile dont nous vous fournissons la structure de données, nommée `Stack` et disponible ci-desous:
%% Cell type:code id:c4f1b0a9 tags:
``` python
class Stack:
def __init__(self):
self.items = []
def push(self, item):
self.items.append(item)
def pop(self):
if not self.is_empty():
return self.items.pop()
def peek(self):
if not self.is_empty():
return self.items[-1]
def is_empty(self):
return len(self.items) == 0
```
%% Cell type:markdown id:5ee3c79e-be53-4d98-a2fb-3b0e9adadeb8 tags:
La Pile ci-dessus a son équivalent avec la méthode `LifoQueue` du module `queue` de Python défini ci-dessous [(doc)](https://docs.python.org/3/library/queue.html). Nous voyons bien que le dépilement renvoie les données dans l'ordre inverse de leur empilement.
%% Cell type:code id:77dee078-c30f-40a0-bd29-f64c978b3e0b tags:
``` python
import queue
pile = queue.LifoQueue()
for i in range (5):
pile.put(i)
while not pile.empty():
print(pile.get(), end=" ")
```
%% Cell type:markdown id:bfaae7f4 tags:
**Question 2.1 -** Utilisez la Pile `Stack` afin d'empiler les données de la liste `students_list`. Maintenant dépilez cette Pile et comparer les résultats avec la méthode `LifoQueue` (avec le `while` fourni dans le code ci-dessous) :
%% Cell type:code id:3ad4b923-5f23-4921-b02e-f8b9fd22dd55 tags:
``` python
pile = queue.LifoQueue()
s = Stack()
# YOUR CODE HERE
raise NotImplementedError()
while not s.is_empty() and not pile.empty():
assert s.pop() == pile.get()
```
%% Cell type:markdown id:78b1b0fb-41fb-4e2e-8c2b-3a040fbcc5e0 tags:
**Question 2.2 -** Transformer la structure de Pile `Stack` en une **File** (que vous nommerez `File`) et vérifiez que vous obtenez les mêmes résultats en récupérant les données qu'avec le module `Queue()` de Python.
%% Cell type:code id:7ac004cd-f59e-4aa8-a31d-961e24acba69 tags:
``` python
class File():
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:code id:9b588c0e-d8b8-4a57-b54f-6aef316bb5c5 tags:
``` python
file = queue.Queue()
f = File()
# YOUR CODE HERE
raise NotImplementedError()
while not f.is_empty() and not file.empty():
assert f.pop() == file.get()
```
%% Cell type:markdown id:5a8722ae-500d-4956-9b8c-18e664e5b09f tags:
Nous voyons bien que le dé-filement renvoie les données dans l'ordre de leur empillement afin de respecter le principe de File.
%% Cell type:markdown id:e1f0a957-2c18-4edd-b37b-d766ac1e8557 tags:
**Question 2.3** - Mettez à jour votre File afin de ne pas générer d'[exception](https://docs.python.org/3/tutorial/errors.html) `IndexError`. On peut par exemple renvoyer une valeur de type `None` si aucune valeur n'est disponible. Ci-dessous un exemple de capture d'exception en Python sur lequel vous pouvez vous baser :
%% Cell type:code id:49a596f0-fc7c-4158-bab1-e715e1cf6a57 tags:
``` python
file = File()
try:
assert file.pop() == None # si on renvoie None pour une file vide, pas d'Exception !
except IndexError:
print("On ne doit pas générer d'exception IndexError !")
```
%% Cell type:markdown id:9ebbd490-abcd-45e4-8296-c311e34ddf2d tags:
**Question 2.4** - Enfin, transformez la File (classe `Queue`) pour en faire une file de Priorité nommée `FilePriorite`. Pour rappel, une File de Priorité renvoie les éléments selon un critère particulier (par exemple la note minimale des valeurs contenues dans la file).
Conseils :
- garderzla liste des valeurs internes constamment triée lors de l'ajout de nouvelles valeurs;
- pour cela inclure la nouvelle valeur avec la méthode `ajoute()` à la bonne place (en conservant l'ordre de la liste interne) avec `.insert(index, valeur)`
Nous vous fournissons aussi le module `PriorityQueue` qui est une file de priorité existante [(doc)](https://docs.python.org/3/library/queue.html) afin de comparer le comportement de votre code.
%% Cell type:code id:fa163d01-ed34-447e-8b55-6198140c349b tags:
``` python
from queue import PriorityQueue
import random
filep = PriorityQueue()
list_random = [random.randint(1, 10) for _ in range(5)] # Liste aléatoire
for i in list_random: filep.put(i)
while not filep.empty():
print(filep.get(), end=" ")
```
%% Cell type:markdown id:738fe9f0-7885-40b6-a8cf-eb0c7cd8f3aa tags:
Remplir le code ci-dessous basé sur la File afin d'en faire une File de Priorité.
%% Cell type:code id:3b0a1122-5d8f-4f5f-8ef4-460f9896f4b6 tags:
``` python
class FilePriorite():
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:code id:4e608d6b-458b-4836-8ab2-4371d96ae54b tags:
``` python
filep = PriorityQueue()
f = FilePriorite()
note_list = [student["note"] for student in students_list]
# YOUR CODE HERE
raise NotImplementedError()
while not f.is_empty() and not filep.empty():
assert f.pop() == filep.get()
```
%% Cell type:markdown id:014b7c3e-cfaf-4e80-9aa8-aff4e2ca821d tags:
La complexité de la structure de données de file de priorité est $O(n)$ en ajout et de $O(1)$ en lecture.
%% Cell type:markdown id:77038e6d-0b73-434c-910d-c7da733b643a tags:
## Exercice 3 : Arbre binaire complet sous forme de liste
%% Cell type:markdown id:5f3fc128-2a2e-42bd-924a-d691c09150d6 tags:
Nous allons maintenant implémenter un **arbre binaire complet**. Cet arbre sera utile pour l'exercice suivant et la création d'une nouvelle structure de données : le Tas. Cet arbre binaire sera implémenté en utilisant un tableau (car il s'agit d'un arbre _complet_ où tous les niveaux sont remplis, sauf éventuellement le dernier). L'arbre binaire possède des noeuds ayant un index $i$, avec un fils gauche et un fils droit. Le tableau et l'arbre sont reliés de la façon suivante :
- La racine a la position $i = 0$ (cette valeur sera renvoyée par la fonction `get_racine`)
- Le parent a la position $\lfloor (i - 1)/ 2 \rfloor$ (fonction `get_parent`)
- Le fils gauche a la position $2 \times i + 1$ (fonction `get_fils_gauche`)
- Le fils droit a la position $2 \times i + 2$ (fonction `get_fils_droit`)
```
1
/ \
2 5
/ \ /
3 4 6
La liste correspondante :
[1, 2, 5, 3, 4, 6]
```
%% Cell type:markdown id:ea502a0e-faa7-4bb2-9627-35cd128521a4 tags:
**Exercice 3.1** - Implémentez un arbre binaire sous forme de classe appellée `BinaryTree` (vous pouvez vous inspirer de la classe de File de Priorité). En particulier les méthodes `get_parent`, `get_fils_gauche`, `get_fils_droit` renvoient un `Tuple` (valeur, indice). Vous rajouterez une méthode `taille`qui renvoie la taille de l'arbre binaire (longueur de la liste interne).
%% Cell type:code id:d6648668-c0e3-47d5-bd83-a49785939877 tags:
``` python
class BinaryTree():
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:markdown id:d0dd4680-92db-4dad-8647-951269330870 tags:
**Exercice 3.2** - Assurez vous que tous les tests ci-dessous sont validés.
%% Cell type:code id:ac65be98-9649-4753-8ead-c0deb89f5f0c tags:
``` python
# test arbre vide
tree_empty = BinaryTree()
assert tree_empty.taille() == 0
assert tree_empty.get_racine() == None
assert tree_empty.get_parent()[0] == None
assert tree_empty.get_fils_gauche(0)[0] == None
assert tree_empty.get_fils_droit(0)[0] == None
```
%% Cell type:code id:f548b21a-b2f5-4de5-9261-38d23035e25d tags:
``` python
L = [1, 2, 5, 3, 4, 6]
tree_values = BinaryTree(L)
assert tree_values.taille() == len(L) # 6
assert tree_values.get_racine() == L[0] # 3
assert tree_values.get_fils_gauche(0)[0] == L[2*0+1] # 2
assert tree_values.get_fils_droit(0)[0] == L[2*0+2] # 5
assert tree_values.get_parent(1)[0] == L[0] # 5
```
%% Cell type:markdown id:25213313-5058-415a-a3bc-7948c3d98588 tags:
Cette structure de donnée sera utile pour la question suivante afin de créer un tas.
%% Cell type:markdown id:5f35e9de-025f-4c89-a004-a24af997474a tags:
**Exercice 3.3** - Ecrivez une fonction de parcours de l'arbre qui renvoie `True` si un noeud est inférieur à ses enfants, sinon `False`. Conseil :
1. Proposez une approche récursive
2. Le cas d'arrêt est un noeud vide
3. L'appel récursif est déclanché en fonction de la valeur du noeud en cours et celle de ses enfants
4. Au final renvoyer `True` si aucune condition ne renvoie `False`
%% Cell type:code id:93924cc3-9d92-40c7-b7d7-96a775e121b1 tags:
``` python
def check_min_tree(T, i=0):
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:code id:da01b2ab-4633-443f-97ea-b1022bc714ef tags:
``` python
check_min_tree(tree_values)
```
%% Cell type:code id:a28bf560-5fed-40cd-b8bf-0389e11fd8bd tags:
``` python
assert check_min_tree(BinaryTree([1])) == True
assert check_min_tree(BinaryTree([1, 2])) == True
assert check_min_tree(BinaryTree([1, 2, 3])) == True
assert check_min_tree(BinaryTree([1, 2, 3, 4])) == True
assert check_min_tree(BinaryTree([5, 6, 4])) == False
```
%% Cell type:markdown id:d9f0166d-d12f-42a1-989a-b7014117e73d tags:
## Exercice 4 (Bonus) : Création d'un tas et tri par tas
Nous allons désormais créer une nouvelle structure de donnée : le `Tas`. Celle-ci permettra à termes de réduire la complexité de manipulation d'une file de priorité, en répartissant le coût de la recherche du plus petit élément (qui sera renvoyé) entre l'ajout et la suppression. Pour rappel la file créée précédemment avant une complexité de $O(n)$ en ajout et de $O(1)$ en lecture.
Nous nous baserons pour cela sur l'arbre binaire de la question précédente, qui est dit dans une configuration [min-heap](https://en.wikipedia.org/wiki/Min-max_heaphttps://en.wikipedia.org/wiki/Min-max_heap), où les données sont renvoyées par ordre croissant. Cette structure de données sera plus efficace en $O(log(n)$ pour l'ajout d'une nouvelle valeur (mais aussi pour le retrait).
%% Cell type:markdown id:6061d866-51fb-48bc-9f1a-46b1b57a0ec0 tags:
**Question 4.1 -** Implémentez une structure de `Tas`comme suit :
1. Créez une structure de données de `Tas` similaire au `BinaryTree`
2. Créez une méthode `inserer`, que l'on utilisera à la place d'`ajoute`, dont le principe est le suivant :
- Chaque nouveau noeud est rajouté comme dernier élément du tableau (à la fin donc)
- Comparez ce noeud à son parent et si il est plus grand que ce parent inversez-le
- Répétez tant que la condition ci-dessus est vraie et que la racine n'est pas atteinte
3. Créez une méthode `enlever` dont le principe est le suivant :
- Enlever l'élément racine de l'arbre (premier élément du tableau)
- Déplacer le dernier noeud de l'arbre (dernier élément du tableau) à la place de la racine de l'arbre
- Vérifier que la racine conserve la propriété de Tas (qu'elle est inférieur à ses enfants); si ce n'est pas le cas alors implémenter une méthode `descendre` définie par la suite.
4. Créez une méthode `descendre` qui :
- Prend le plus petit des enfants
- Echange sa place avec lui si il est plus petit
- Répéte cela tant qu'il existe des enfants
Attention : pensez à tester si il existe un fils droit et un fils gauche lors des opération de descente lors de l'insertion.
%% Cell type:code id:301e69f3-4035-4b10-9c85-f4427d92e03b tags:
``` python
class Tas():
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:markdown id:0b467f58-c800-4ae3-b066-8717732a1095 tags:
Votre tas doit valider les tests suivants :
%% Cell type:code id:3c41d4a7-5971-497b-b484-4a42a2480b06 tags:
``` python
# test tas vide
tas_vide = Tas()
assert tas_vide.taille() == 0
assert tas_vide.get_racine() == None
assert tas_vide.get_fils_droit()[0] == None
assert tas_vide.get_fils_droit()[0] == None
# test tas simple
tas_simple = Tas()
tas_simple.inserer(1)
tas_simple.inserer(2)
assert tas_simple.taille() == 2
# test tas un peu plus complexe
tas = Tas()
liste = [1, 4, 10000, 2, 29, .2, 13, .5, 14, .1, 100]
liste_triee = sorted(liste)
for l in liste:
tas.inserer(l)
assert tas.taille() == len(liste)
assert tas.get_racine() == liste_triee[0]
assert tas.get_fils_gauche(0) == (liste_triee[1], 1)
assert tas.get_fils_droit(0) == (liste_triee[2], 2)
while not tas.est_vide():
assert tas.enlever(0) == liste_triee.pop(0)
assert tas.taille() == len(liste_triee)
```
%% Cell type:markdown id:ec678229-485e-4f3b-8c24-56febe7bd69e tags:
**Question 4.2 -** Implémentez un tri par tas en utilisant la structure de données de `Tas` que vous avez réalisé précédemment.
%% Cell type:code id:1d483588-4153-4614-b969-854846b08f4e tags:
``` python
def triTas(l: list = []) -> list:
t = Tas()
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:markdown id:e7ab0b07-f13c-4b95-b5fa-c38aea9b6ead tags:
Comparez à la méthode de tri `sorted`.
%% Cell type:code id:4e9fd04a-910a-4d32-b0dc-0a1502599901 tags:
``` python
liste = [54,26,93,17,77,31,44,55,20]
l2 = triTas(liste.copy())
assert(l2 == sorted(liste))
assert([] == triTas([]))
assert([1] == triTas([1]))
assert([1, 1] == triTas([1, 1]))
```
%% Cell type:markdown id:49bae650-a23a-41f7-8896-8ac502cd71e8 tags:
Pour information, le module `heapq` contient l'implémentation d'un tas en Python et s'utilise comme les Piles, Files, etc.
%% Cell type:code id:5bcc3ebf-749e-4a10-8b90-37cfd2488171 tags:
``` python
import heapq
tas = []
for i in range(5): heapq.heappush(tas, i)
while not len(tas) == 0:
print(heapq.heappop(tas), end=" ")
# 0 1 2 3 4
```
%% Cell type:markdown id:7f774fa4-c586-4d5c-9cf3-5f9bb899f725 tags:
**Question 4.2 -** Comparez la performance (en temps) des méthodes de tri que vous avez implémenté dans les questions précentes.
%% Cell type:code id:56e72b68-1d5c-4cea-8e9a-6d9f5f9ae34d tags:
``` python
import time
import random
import matplotlib.pyplot as plt
nvalues = [100, 500, 1500, 2000, 2500, 3000]
timesSorted = []
timesSort = []
timesSelection = []
timesHeap = []
for i in nvalues:
random.seed()
p = 12**2
liste = []
for x in range(i): liste.append(random.randint(0, p))
# tri sorted
c = liste.copy()
a=time.perf_counter()
triSorted = sorted(c)
b=time.perf_counter()
timesSorted.append(b-a)
# tri .sort()
c = liste.copy()
a=time.perf_counter()
triSort = c
triSort.sort()
b=time.perf_counter()
timesSort.append(b-a)
# YOUR CODE HERE
raise NotImplementedError()
plt.plot(nvalues, timesSorted, "g-", label="Tri Sorted")
plt.plot(nvalues, timesSort, "b-", label="Tri .sort()")
plt.plot(nvalues, timesSelection, "r-", label="Tri Selection")
plt.plot(nvalues, timesHeap, "r-", label="Tri Heap")
plt.xlabel("Taille du jeu de données")
plt.ylabel("Temps")
plt.legend(loc="upper left")
plt.title("Comparaison des performances des algorithmes de tri")
plt.show()
```
%% Cell type:markdown id:04456b1e-92fd-4433-b230-8ea4374595a0 tags:
Pour en savoir plus comment Python réalise le tri, lire la documentation du `TimSort` (doc)[https://en.wikipedia.org/wiki/Timsort] qui est l'algorithme de tri utilisé.
%% Cell type:markdown id:3e925273-2161-4c10-8e79-dabcc9bb38cb tags:
## Pour aller plus loin
- Mettez à jour votre file afin de renvoyer [une exception](https://docs.python.org/3/tutorial/errors.html) si on demande une valeur qui n'est pas dans la structure de données (pile, file, etc.)
%% Cell type:code id:50f77357-df56-486b-a3c0-7d2d950c766e tags:
``` python
def popx(self):
if not self.is_empty():
return self.items.pop(0)
else:
raise IndexError("Le tas est vide")
Stack.popx = popx
s = Stack()
try:
s.popx()
except IndexError as e:
print(e)
```
%% Cell type:markdown id:3bf64f58-fbcd-44e8-b827-378e85968285 tags:
- Utilisez un [grand jeu de donnée](https://generatedata.com/) d'étudiants pour les premières questions. Réaliser une analyse de complexité avec ce jeu de données.
%% Cell type:code id:ca5f3173-89da-4103-ae04-b60f8b4c8065 tags:
``` python
```
data = []
with open("etudiants.txt") as f:
keys = None
for line in f:
l = [w.strip() for w in line.split(';')]
if keys is None:
keys = l
else:
data.append(l)
print(data)
\ No newline at end of file
#%%
import time
import random
import matplotlib.pyplot as plt
import numpy as np
#%matplotlib inline
nvalues = [100, 500, 1000, 1500, 2000, 2500, 3000]
timesEtudiants1 = []
for i in nvalues:
random.seed()
p = 12**2 # Ordre de grandeur des valeurs
liste = []
for x in range(i): liste.append(random.randint(0, p))
a=time.perf_counter()
e1 = []
for n in liste:
e1.append(n)
b=time.perf_counter()
timesEtudiants1.append(b-a)
plt.plot(nvalues,timesEtudiants1, "r-", label="Etudiants 1")
plt.title("Comparaison des performances")
# %%
from File import *
if __name__=="__main__":
data = []
with open("etudiants.txt") as f:
keys = None
for line in f:
l = [w.strip() for w in line.split(';')]
if keys is None:
keys = l
else:
data.append({k:v for k, v in zip(keys, l)})
file = File()
for d in data:
file.ajoute(d)
e = file.renvoie(lambda x : x['filiere'] == "PC")
print(e['nom'] + " " + e['prenom'])
\ No newline at end of file
import heapq
tas = []
for i in range(5): heapq.heappush(tas, i)
while not len(tas) == 0:
print(heapq.heappop(tas), end=" ")
# 0 1 2 3 4
\ No newline at end of file
import queue
pile = queue.LifoQueue()
for i in range(5): pile.put(i)
while not pile.empty():
print(pile.get(), end=" ")
# 4 3 2 1 0
\ No newline at end of file
from Pile import *
if __name__=="__main__":
data = []
with open("etudiants.txt") as f:
keys = None
for line in f:
l = [w.strip() for w in line.split(';')]
if keys is None:
keys = l
else:
data.append({k:v for k, v in zip(keys, l)})
p = Pile()
for d in data:
p.ajoute(d)
e = p.supprime()
assert(e['nom'] == "Arthaud" and e['prenom'] == "Nathalie")
\ No newline at end of file
from Tas import *
if __name__=="__main__":
data = []
with open("etudiants.txt") as f:
keys = None
for line in f:
l = [w.strip() for w in line.split(';')]
if keys is None:
keys = l
else:
data.append({k:v for k, v in zip(keys, l)})
tas = Tas()
for d in data:
tas.ajoute(int(d['moyenne']))
r = tas.get_racine()
fg, fg_i = tas.get_fils_gauche(0)
ffg, ffg_i = tas.get_fils_droit(0)
assert(r == 19 and fg == 14 and ffg == 16)
\ No newline at end of file
nom;prenom;filiere;moyenne;absences
Dickerson;Chaney;PSI;6;4
King;Shay;PSI;2;2
Chan;Aileen;MP;8;3
Schwartz;Destiny;PSI;16;5
Parrish;Prescott;MP;1;4
Calhoun;Brenda;PSI;10;4
Watts;Shellie;PSI;6;4
Baird;Octavius;PC;4;2
Graves;Vanna;MP;10;0
Decker;Nerea;PSI;9;4
Townsend;Naomi;PC;13;3
Decker;Nichole;PSI;10;3
Mcgee;Blythe;PSI;7;0
Franco;Cyrus;PSI;12;1
Mcdowell;Zelda;MP;6;1
Cherry;Stone;PSI;10;5
Mendoza;Kirsten;PC;18;0
Mathis;Xaviera;MP;12;1
Booker;Gretchen;MP;2;1
Hansen;Slade;PSI;1;1
Mason;Forrest;MP;13;3
Wolfe;Fatima;PC;15;5
Richards;Justine;MP;20;0
Kelley;Abra;PC;2;4
Lang;Ulysses;PSI;2;5
Barker;Austin;MP;15;5
Cannon;Kalia;MP;3;4
Higgins;Charity;PSI;18;5
Parker;Fritz;PC;14;2
Chambers;Yvette;PSI;7;1
Vinson;Denise;PSI;3;5
Mcmillan;Chava;PSI;7;3
Gallegos;Lee;PC;16;0
Ferguson;Solomon;PSI;11;4
Camacho;Zena;MP;4;4
Sexton;Fallon;PSI;16;2
Campbell;Preston;PC;0;0
Greer;Lance;PC;15;5
Oliver;Aileen;PC;10;2
Nielsen;Timon;PC;1;2
Perkins;Roth;PSI;1;2
Beard;Blair;PSI;13;1
Burgess;Keely;PSI;4;4
Wells;Honorato;PSI;17;0
Richardson;Cherokee;PC;20;1
Burgess;Blair;PC;16;4
Rice;Florence;PC;7;4
Villarreal;Delilah;MP;9;5
Cherry;Maite;MP;0;2
Berry;Jermaine;MP;17;4
Shepherd;Alfreda;PSI;20;5
Workman;April;PC;3;1
Carter;Herman;PC;11;1
Carpenter;Teagan;MP;0;1
Fowler;Leo;PSI;19;4
Mcgee;Kristen;PSI;9;4
Mcpherson;Channing;PC;0;0
Diaz;Nathaniel;PC;4;5
Klein;Maisie;PSI;16;3
Graham;Gary;MP;12;4
Jensen;Raja;PC;18;1
Wilkinson;Sawyer;PSI;10;0
Wagner;Lamar;MP;16;2
Abbott;Sybil;MP;17;1
Glenn;Arsenio;PSI;4;3
Moreno;Axel;PSI;7;4
Barrett;Dylan;PC;14;4
Keith;Rae;PC;9;1
Shepard;Rebecca;PC;8;5
Meyers;Illiana;MP;3;3
Bruce;Tatyana;MP;2;0
Mcguire;Olivia;PC;17;4
Merritt;Tatiana;PSI;19;3
Berg;Dale;MP;12;1
Matthews;Tallulah;MP;5;3
Steele;Cain;MP;8;2
Ellison;Britanni;PC;4;1
Richards;Audra;MP;15;0
Hood;Rylee;PSI;1;4
Townsend;Paul;PC;14;4
Cervantes;Thaddeus;MP;10;5
Dudley;Amela;PC;2;0
Lucas;Matthew;MP;4;1
Parrish;Nell;PC;13;3
Patterson;Bertha;PSI;18;0
Knapp;Lawrence;MP;3;5
Stanton;Keith;MP;5;2
Hayes;Mannix;PSI;3;2
Pearson;Ross;PC;10;4
Kaufman;Uta;MP;10;4
Bauer;Naida;PC;20;5
Carrillo;Quamar;PC;15;3
Orr;Lisandra;PSI;6;2
Randolph;Darryl;PSI;16;4
Boyer;Prescott;PC;20;2
Serrano;Ashely;PSI;10;2
Carney;Oren;PC;7;4
Riley;Arden;PC;1;5
Phillips;Joshua;PSI;20;3
Soto;Colt;PC;16;3
\ No newline at end of file
nom;prenom;filiere;moyenne;absences nom;prenom;filiere;note;absences
Dupond;Pierre;MP;19;0 Dupond;Pierre;MP;19;7
Dupont;Jeanne;MP;19;5
Clavier;Christian;PSI;14;1 Clavier;Christian;PSI;14;1
Gilles;Eric;PC;16;3 Gilles;Eric;PC;16;3
Arthaud;Nathalie;MP;15;0 Arthaud;Nathalie;MP;15;0
\ No newline at end of file
File deleted