Benjamin Fernandes Léo Cavaillé Gautier Minster Louis Guthmann
Plan du rattrapage Introduction et conseils Commandes et notions de base Les listes Les piles Les files Le tri Les dictionnaires Les fichiers Les arbres Graphes de contrôle et logique de Hoare
Objectif : valider le CF Epreuve d’une heure et demi à complexité croissante Rappelez vous bien que vous avez droit aux documents Retrouvez sur : people.via.ecp.fr/~lothar/algo/people.via.ecp.fr/~lothar/algo/ Cours Slides Mais aussi sur ClarolineClaroline Cours Exemples et bouts de codes Annales Documentation
Préparation et organisation Pas de secret : faire des exos L’épreuve est courte Faire proprement les premières questions Réfléchir au plus simple Indentation Commentaire au besoin Tester sur cas simples Gratter les points Ne pas perdre son temps sur le PC Se relire contre les étourderies
Algorithmique vs Programmation Différence entre algorithme (concept) et programmation (langage) Notre langage : le Python Simple et haut niveau Répandu et utilisé (Google, Yahoo!, Cern, NASA, Youtube, … ) Ca peut toujours resservir… Préférer le Python au Pseudo code.
Coder simplement : IDLE Indentation automatique Coloration syntaxique Vérification du code Erreurs détaillées Exécution Partir d’un fichier code.py Ctrl + S pour sauvegarder F5 pour exécuter
Notions de base On va voir : Les nombres Expression logique L’instruction if Fonctions Boucles Dans Python : On ne déclare pas les variables L’indentation définit les blocs Sauter une ligne change d’instruction
Les nombres A = 10 B = A# B vaut 10 C = A + B + 4# C vaut 24 D = 5*C# D vaut /3# **2# 16 Print(A)# affiche 10 Print(D – 20)# affiche 100
Les commandes de base Sur les entiers: +,-,* donnent addition, soustraction, multiplication / donne une division mais qui arrive dans les réels // donne une division entière % signifie modulo ** signifie puissance Sur les décimaux: Même chose sauf que // donne la partie entière
Les fonctions def nom_fonction (param1, param2, …): bloc instruction {return solution} Nombre de paramètre quelconque Si on utilise un return, la fonction s’utilise comme une variable Voir les exemples
Les expressions logiques Expression qui retourne un booléen (True/False) Egalité(1+1) == 11# False Différence42 != 15# True Inégalité5 < 5# False 5 <= 5# True Etand# False Ouor# True Négationnot(True)# False En cas de doute, ajouter des parenthèses
L’instruction if Si… Alors… {Sinon Si… Alors…} Sinon… if cond1: inst1# Exécuté si cond1 inst2# est vrai elif conf2: inst3# Exécuté si cond1 est faux inst4# et cond2 est vrai else: inst5# Exécuté dans les autres cas #Sortie du if Indentation très importante
Les boucles (1/2) : la boucle for Pour i allant de x à y-1 faire for i in range (x,y): instructions (avec la valeur de i) Si on veut i de 0 à n inclus: for i in range (n+1): instructions Exemple: def remplissage (L) L=[] for i in range (0,5) L=[-i]+L+[i] Le résultat est: [-4,-3,-2,-1,0,0,1,2,3,4]
Les boucles (2/2) : la boucle while Tant que… Faire… while condition: instructions Attention aux boucles infinies : la condition doit devenir fausse Exemples
Les listes Définition : variable contenant un nombre fini d’éléments numérotés Syntaxe : [a, b, c] (puis affecter à une variable) Accès à un élément : liste[i] Attention ! Numérotation à partir de 0 ! len(liste) : nombre d’éléments La taille d’une liste est fixée au moment de la création mais … ABCD 2013
Concaténation de deux listes Syntaxe: liste3 = liste1 + liste2 Utile pour rajouter un élément en fin de liste : liste = liste + [élément] En début de liste: Liste = [élément] + liste ABCD 2013 EFGHI ABCD 2013 EFGHI =
Extraction d’une tranche Syntaxe : liste[i:j] pour récupérer les éléments de i à j-1 Exemple : pour enlever un élément : liste = liste[0:len(liste)-1] ABCD 2013 EF 45 CD 23 E 4 liste liste[2:5]
Test de sous-liste (CF 2009) Est-ce que liste2 est une sous-liste de liste1 ? Eléments contigus Dans le même ordre ABCD 2013 EF 45 liste1 G 6 CDE 201 liste2 ADG 201 DC 01 ouinon
Test de sous-liste (CF 2009) Idée : regarder toutes les sous-listes de liste1 qui ont la bonne longueur Exemple : la sous-liste cherchée est de longueur 4 ABCD 2013 EF 45 G 6 ABCD 2013 Complexité :O(n) BCDE 2013 CDEF 2013 DEFG 2013 à comparer avec la sous-liste cherchée
Récursivité Fonction qui s'appelle elle-même, et pour laquelle une certaine quantité décroît (strictement). Pour une valeur minimale, la fonction renvoie une valeur, c'est le cas de base. Exemple 1: def fact(n): if (n==1): 1 else: n * fact(n-1) Quantité décroissante : n Cas de base : n=1 Exemple 2: def pgcd(a,b): if (b>a): return pgcd(b,a) else: if (a%b == 0): return b else: return pgcd(b,a%b) Quantité décroissante : a%b Cas de base : a%b=0
Les files ● Liste FIFO (First In First Out, i.e. file d’attente)
Algorithmes de tri Entrée : liste de nombres Sortie : les mêmes en ordre croissant Pourquoi plusieurs algorithmes de tri ? Complexités Variantes itératives ou récursives + ou – adaptés aux listes déjà triées, ou triées à l’envers
Algorithmes classiques Tri bulle Tri par insertion Tri rapide
Tri bulle Idée : examiner des couples (« bulles »). Solution itérative : On parcourt la liste du début à la fin (ça fait n-1 bulles) On échange les bulles qui sont à l’envers Condition d’arrêt : si en un passage on n’a rien changé.
Tri bulle Exemple : Puis on recommence, jusqu’à ce que la liste soit triée. Complexité O(n²)
Tri par insertion Idée : on fait reculer chaque élément jusqu’à ce qu’il trouve sa place. Exemple : Solution itérative (avec un compteur du nombre d’éléments déjà triés) Complexité O(n²)
Tri rapide Algorithme récursif = s’appelle lui-même sur de plus petites listes Idées : On sait trier une liste de 2 éléments On coupe la liste de départ en deux morceaux (autour d’un pivot) auxquels on applique le tri rapide … jusqu’à ce que les morceaux fassent 2 éléments Ensuite on combine Complexité O(nlog(n))
Tri rapide < >4 21 <3> <7> Il ne reste plus qu’à regrouper!
C’est quoi un dictionnaire ? Définition : comme une liste sauf que les éléments ne sont pas forcément repérés par des numéros Exemple : dico 60 "France" 46 "Espagne" 10 "Belgique" dico = {"France": 60, "Espagne": 46, "Belgique": 10}
Caractéristiques Eléments pas ordonnés Un seul élément par clé Appel d’un élément : dico[clé] (si la clé est une chaîne de caractères on n’oublie pas les guillemets …) dico.keys() renvoie un tableau des clés dico.values() renvoie un tableau des éléments
Les fichiers De l'utilité des fichiers La manipulation des fichiers est très importante car elle permet de gérer un grand nombre de données, soit pour les utiliser en entrée (ex : une page web pour l'afficher) soit pour enregistrer le résultat d'un programme Il est donc primordial d'écrire et de lire des fichiers
Qu'est-ce qu'un fichier ? Modules (Rappel : import module) pour les répertoires et les fichiers, ce sont des file en python os os.path os.stat fileinput gzip zipfile
Ouverture-lecture- fermeture Première approche Le fichier est dans le répertoire courant et se nomme test.txt #On ouvre le fichier test.txt f=open(''test.txt'') #on lit les 4 premiers caractères avec read qui renvoie une chaîne de caractère f.read(4) #on lit les 4 caractères suivant et on les met dans x x=f.read(4) print x #on ferme le fichier qui n'est donc plus accessible f.close()
Manipulation de fichier L'ouverture se fait à l'aide de open([nom[,mode]]) mais mode est optionnel nom = nom sur le disque Modes 'r' en lecture (par défaut) 'r+' en lecture et écriture 'a' en ajout (écriture en fin du fichier) 'w' en écriture (écrase) 'w+' en lecture et écriture (écrase) La fermeture se fait avec close()
Lecture d'un fichier On suppose que l'on a ouvert un fichier f (f = open(nom)) Lecture f.read() : lit le fichier f et le renvoie sous forme de string f.read(n) : lit n caractères de f à partir de la position courante f.readline() : lit une ligne du fichier f et renvoie un string f.readlines() : lit plusieurs lignes et renvoie une liste de string Écriture f.write(texte) : ecrit la texte (de type string) dans f f.writelines(seq) : ecrit la séquence de chaine dans f Autre f.tell() : retourne la position courante f.seek(npos) : change la position courante en npos
Définitions Racine Nœud Feuille Hauteur Arrête Les arbres
Définitions (suite) Chemin Clés Degré = nombre de fils
Arbres binaires Définition : arbre dont chaque nœud est de degré au plus deux. Se construit récursivement : chaque arbre est constitué d’une clé, d’un sous-arbre gauche (« fils gauche ») et d’un sous-arbre droit (« fils droit »).
{‘rac’ = 6, ‘g’ = {‘rac’ = 1, ‘g’ = {}, ‘d’ = {} }, ‘d’ = {} } Arbres binaires : implémentation On les implémente avec un dictionnaire ayant trois champs : ‘rac’, ‘g’ et ‘d’. Ex: {‘rac’ = 1, ‘g’ = {}, ‘d’ = {} } {‘rac’ = 8, ‘g’ = {‘rac’ = 2, ‘g’ = {}, ‘d’ = {} }, ‘d’ = {‘rac’ = 6, ‘g’ = {‘rac’ = 1, ‘g’ = {}, ‘d’ = {} }, ‘d’ = {} } } {‘rac’ = 2, ‘g’ = {}, ‘d’ = {} }
Quelques fonctions Il est clairement plus simple de faire des fonctions récursives pour traiter un arbre. Ex : nombre de nœuds = 1 + nombre de nœuds du fils gauche + nombre de nœuds du fils droit. En python: def nombre_noeud(arbre): if arbre == {}: return 0; else: return 1 + nombre_noeud (arbre[’g’]) + nombre_noeud (arbre[‘d’]);
Arbre binaire de recherche Principe : un arbre ordonné ! Tout ce qui est dans le fils gauche <= racine < tout ce qui est dans le fils droit. Lors d’une recherche, on ne parcours qu’un seul chemin => complexité en O(h) où h est la hauteur. Si l’arbre est équilibré, on a h = log(n) donc une recherche en O(log(n)).
Ex : recherche dans un arbre binaire def recherche(elem, arbre): if arbre == {}: return false; elif arbre[‘rac’] == elem: return true; elif arbre[‘rac’] < elem: return recherche(elem, arbre[‘d’]); else: return recherche(elem, arbre[‘g’]);
Pour les courageux : le parcours en largeur Manipule à la fois les arbres et les piles !
Principe du parcours en largeur Problème : on ne peut pas le faire récursivement, car il faut traiter les deux sous-arbres simultanément ! Astuce : à chaque nœud, on affiche la racine et on mémorise sous-arbres pour les traiter plus tard. Il faut traiter d’abord les premiers sous-arbres enregistrés : on utilise une file.
def largeurFile2(a): file = [a] liste = [] while len(file)>0: #je prends le premier élément, je l'affiche liste.append(racine(file[0])) #j'ajoute ses fils s'il y en a, à la fin de la file if not est_vide(gauche(file[0])): file.append(gauche(file[0])) if not est_vide(droit(file[0])): file.append(droit(file[0])) #je défile file = file[1:] return liste
Graphes de contrôle La formalisation logique permet de retracer l’ensemble des chemins possibles d’un algorithme et d’expliciter tous ces chemins. * est l’opérateur représentant un while
Le symbole + signifie « ou alors » : A+B signifie que A ou alors B est évaluée. Ainsi : if C: A else: B S’exprime sous forme d’expression régulière : A+B. L’expression A* signifie : l’expression A est évaluée 0, 1 ou plusieurs fois. Ainsi : while C do: A B S’exprime sous forme d’expression régulière: (AB)*
Exemple For i in range(n):#a x=i#b if x=3:#c x=5#d z=i+2#e Donne en logique des graphes: (abc(d+ε)e)) n où ε représente le fait de ne rien faire (instruction vide).
Logique de Hoare
Exercice
Première Partie Affectation: {A ≥ 0 ^ B > 0} q=0 {A ≥ 0 ^ B > 0 ^ q==0} ? {A ≥ 0 ^ B > 0} => {A ≥ 0 ^ B > 0 ^ 0==0} {A ≥ 0 ^ B > 0 ^ 0==0} q=0 {A ≥ 0 ^ B > 0 ^ q==0} Deuxième partie Affectation: {A ≥ 0 ^ B > 0 ^ q==0} r=A {A ≥ 0 ^ B > 0 ^ q==0 ^ r==A}? {A ≥ 0 ^ B > 0 ^ q==0} => {A ≥ 0 ^ B > 0 ^ q==0 ^ A==A} {A ≥ 0 ^ B > 0 ^q==0 ^A==A} r=A {A ≥ 0 ^B > 0 ^q==0 ^ r==A}
La 3 ème assertion sera prouvée au tableau.
C’est fini ! Récupérer sur votre PC tous les documents Faites quelques exos Retrouvez tout sur : people.via.ecp.fr/~lothar/algo/people.via.ecp.fr/~lothar/algo/ Bonnes révisions !