Slides - BAPP

publicité
21/12/2016
Guidance spéciale
Préparation à l'examen
[email protected]
[email protected]
Code Python (1/10)
Que fait cette fonction ?
def foo1(a,b) :
res = False
if len(a) == len(b)
dic_a = {}
dic_b = {}
for i in a :
dic_a[i] = dic_a.get(i,0)+1
for i in b :
dic_b[i] = dic_b.get(i,0)+1
res = True
for j in dic_a :
res = res and (dic_a[j] == dic_b.get(j,0))
for j in dic_b :
res = res and (dic_b[j] == dic_a.get(j,0))
return res
2
Code Python (2/10)
Et celle-ci ?
def foo2 (a,b):
res = False
if len(a) == len(b):
res = True
for i in a:
if i in b:
a.remove(i)
b.remove(i)
else:
res = False
return res
3
Code Python (3/10)
●
Ces 2 fonctions font en réalité la même chose :
elles vérifient toutes les deux que les 2 séquences
données en paramètres contiennent exactement les
mêmes éléments (pas forcément dans le même
ordre).
●
Il y a cependant une grosse différence entre les 2
fonctions :
4
Code Python (4/10)
●
Ces 2 fonctions font en réalité la même chose :
elles vérifient toutes les deux que les 2 séquences
données en paramètres contiennent exactement les
mêmes éléments (pas forcément dans le même ordre).
●
Il y a cependant une grosse différence entre les 2
fonctions :
La deuxième modifie les séquences données en
paramètres, elle en retire les éléments.
5
Code Python (5/10)
Examen juin 2016
Complexité (1ère fonction)
●
Notons len(a) = len(b) = n
●
Les parties du code les plus influentes sur la complexité sont les boucles for :

Les 2 premières boucles parcourent n éléments. ( O(n) )

On considère le pire cas : les 2 dernières boucles parcourront donc aussi n
éléments ( O(n) )

●
Dans les 4 boucles, on appelle la méthode get (moyenne O(1), max O(n) )
Elles sont donc équivalentes du point de vue de la complexité, on n'en
considérera qu'une puisqu'elles sont en séquence.
●
Au final on obtient une complexité moyenne O(n.1) = O(n) et une complexité
maximale O(n.n) = O(n²)
6
Code Python (6/10)
Examen juin 2016
Complexité (2ème fonction)
●
Notons len(a) = len(b) = n
●
La partie du code la plus influente sur la complexité est la boucle for :

La boucle parcourt n éléments ( O(n) ).

On appelle la méthode remove dans la boucle 2 fois mais en séquence, on
peut donc n'en considérer qu'une (moyenne O(n), max O(n) ) .
●
Au final on obtient une complexité moyenne égale à la complexité maximale
O(n.n) = O(n²)
7
Code Python (7/10)
Examen janvier 2015
Que fait cette fonction ?
Faites un diagramme d'état pour chaque print en
considérant que la fonction est appelée comme
suit : foo4('''', ''ab'')
def foo4 (res, remain):
print(res)
for i in range(len(remain)):
foo4(res+remain[i],
remain[:i]+remain[i+1:])
8
Code Python (8/10)
Examen janvier 2015
9
Code Python (9/10)
Examen janvier 2015
10
Code Python (10/10)
Examen juin 2016
Complexité
●
Notons len(remain) = n (le remain initial)
●
Dans sa boucle for, la fonction appelle récursivement n instances
d'elle-même, qui appellent chacune n-1 instances d'elles-mêmes, etc (
O(n!) ).
●
A chaque instance, le print est en O(n).
●
Au final, la factorielle domine la complexité de la fonction, qui est donc
en O(n!)
11
Opérations sur les fichiers (1/4)
Examen juin 2016
On demande de créer la fonction import_dict(fname, key_idx) qui, à partir
d'un fichier formaté en colonnes séparées par des « | » comme cidessous, crée un dictionnaire ayant pour clés les éléments de la colonne
d'indice key_idx. A chaque clé sera associée une liste de listes contenant
les éléments des autres colonnes correspondant à cette clé.
Fichier exemple.txt :
>>> print(import_dico(exemple.txt, 1))
Antoine|ULB|Polytech|BA1
Aurélie|UCL|Philo|BA1
Wassim|ULB|Philo|MA1
Dounia|ULG|Polytech|BA2
{'ULB': [['Antoine', 'ULB', 'Polytech',
'BA1'],['Wassim', 'ULB', 'Philo',
'MA1']],
'UCL': [['Aurélie', 'UCL', 'Philo',
'BA1']],
'ULG': [['Dounia', 'ULG', 'Polytech',
'BA2']]}
12
Opérations sur les fichiers (2/4)
Examen juin 2016
1. def import_dict(fname, key_idx):
2.
res = {}
3.
f = open(fname)
4.
lines = f.readlines()
5.
f.close()
6.
for l in lines:
7.
data = l.strip().split('|')
8.
key = data[key_idx]
9.
if not key in res:
10.
res[key] = []
11.
res[key].append(data)
12. return res
Peut-on faire mieux ?
13
Opérations sur les fichiers (3/4)
Examen juin 2016
En réalité, les lignes 9 à 11 reprennent un schémas très courant
avec les dictionnaires qui consiste à créer un couple clé/valeur
avec une valeur initialisée par défaut si la clé n'existe pas ou
simplement modifier la valeur si la clé existe. Ces lignes
deviennent donc la nouvelle ligne 9.
1. def import_dict(fname, key_idx):
2.
res = {}
3.
f = open(fname)
4.
lines = f.readlines()
5.
f.close()
6.
for line in lines:
7.
data = line.strip().split('|')
8.
key = data[key_idx]
9.
res.setdefault(key, []).append(data)
10.
return res
14
Tris (1/4)
Examen septembre 2016
On considère une liste d'étudiants représentés par un tuple
de 4 éléments : leur nom (string), leur note sur 20 en math
(int), leur note sur 20 en physique (int) et leur note sur 20 en
anglais (int).
On demande de trier cette liste (du meilleur étudiant au moins
bon) avec un tri par selection en prenant en compte les
priorités suivantes : d'abord la note en math, puis si il y a
égalité la moyenne des notes et enfin la note en physique.
15
Tris (2/4)
Examen septembre 2016
def moyenne(etud):
return (etud[1] + etud[2] + etud[3]) / 3
def grade(etud):
return 441 * etud[1] + 21 * moyenne(etud) + etud[2]
def vient_avant(e1, e2):
return grade(e1) > grade(e2)
def echange(ls, i, j):
ls[i], ls[j] = ls[j], ls[i]
def tri_etudiants(ls):
for i in range(len(ls) - 1):
posMin = i
for j in range(i + 1, len(ls)):
if vient_avant(ls[j], ls[posMin]):
posMin = j
echange(ls, i, posMin)
16
Tris (3/4)
Examen septembre 2016
Remarquez que la fonction grade n'est pas vraiment une
bonne solution. Les constantes utilisées sont complètement
arbitraires et le moindre changement peut entraîner des
erreurs (notes sur 40 plutôt que sur 20, etc).
Ici, une série de if/else imbriqués sera certes (beaucoup) plus
longue mais plus rigoureuse et surtout résistante aux
changements.
17
Tris (4/4)
Examen janvier 2015
On demande de trier une liste de mots dans l'ordre croissant
de la longueur des mots en utilisant le tri par insertion.
18
Tris (4/4)
Examen janvier 2015
On demande de trier une liste de mots dans l'ordre croissant
de la longueur des mots en utilisant le tri par insertion.
def len_sort(words):
for i in range(1, len(words)):
val = words[i]
j = i
while j > 0 and len(words[j - 1]) > len(val):
words[j] = words[j - 1]
j -= 1
words[j] = val
19
Récursivité (1/2)
Examen septembre 2016
On considère une liste ls dont chaque élément est soit un
entier soit une sous-liste (qui peut elle-même contenir des
entiers et/ou des sous-listes).
On demande d'écrire la fonction récursive noEmptySublists(ls)
qui fait une deepcopy de ls en ignorant les sous-listes vides.
20
Récursivité (2/2)
Examen septembre 2016
def noEmptySubLists(ls):
res = []
for x in ls:
if type(x) == list:
y = noEmptySubLists(x)
if y != []:
res.append(y)
else:
res.append(x)
return res
21
Téléchargement