Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il...

39
Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” (DIU-EIL) Polycopié d’exercices (Bloc 1) avec éléments de correction

Transcript of Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il...

Page 1: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Diplôme inter-universitaire “Enseignerl’Informatique au Lycée” (DIU-EIL)

Polycopié d’exercices (Bloc 1)

avec éléments de correction

Page 2: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Table des matières

1 Prise en main 51.1 Échauffement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51.2 Premiers tours de piste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

2 Structures de données 1 : listes/tables 82.1 Premiers pas : listes simples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82.2 Recherches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92.3 Tris . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

3 Structures de données Python 2 : dictionnaires 183.1 Échauffement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183.2 Comparaison Liste/Dictionnaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193.3 Pour aller plus loin : implémenter les dictionnaires (tables de hachage) . . . . . . . . . . . . . . . . 20

4 Vérification fonctionnelle : spécifications, tests 224.1 Analyse de programme - correction et invariants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224.2 Tests unitaires - TP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244.3 Programmation défensive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

5 Représentation des données en machine 285.1 Binaire, hexadécimal, complément à deux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285.2 Virgule flottante . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305.3 Ascii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

6 Fichiers 346.1 Fichiers, fichiers textes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346.2 Calcul à partir de données contenues dans un fichier . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

6.2.1 Lecture d’un fichier ligne à ligne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356.3 Fichiers CSV . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

6.3.1 Calcul d’intégrale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366.3.2 Manipulations de chaînes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

6.4 Utilisation de la bibliothèque CSV . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 2/39

Page 3: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Résumé

Ce cahier Ce cahier d’exercices a été réalisé pour l’enseignement “Bloc1” du DIU “Enseigner l’Informatiqueau Lycée”, proposé par l’université Lyon1 en collaboration avec d’autres partenaires (Lyon2, ENSL, ENSSIB . . . )

Il peut être librement distribué (License CC-BY-SA 4.0).

Intervenants Les personnes suivantes ont été impliquées dans l’écriture de ces exercices et des supportsPython associés, et l’enseignement correspondant au sein du Bloc 1 :

— 2018/2019 : Pascal Busac, Laure Gonnord, Olivier Laurent, Serge Miguet, Matthieu Moy, Nicolas Pronost,Frédéric Suter.

— 2019/2020 : Nicolas Louvet.

https://diu-eil.univ-lyon1.fr/bloc1/index.html

Contenu Algorithmique, programmation, architecture du bloc 1

Solution. Les corrections fournies dans ce TD sont partielles, rédigées rapidement, et non garanties sanserreur. Une correction de code ne devrait pas venir sans explication, normalement.

1. Représentation de l’information

(a) Codage des nombres flottants.

Solution. Le codage en base b est censé être un prérequis. IL faut connaître les transforma-tions de et vers les bases courantes (2,8,10,16) et savoir écrire un algo python pour chaque.

Ne pas connaître le codage des flottants, mais savoir l’appliquer. Se reporter au cours associé.

(b) Fichiers et formats usuels, compression et archivage

Solution. Nous avons expérimenté avec différents formats de fichiers. Nous n’avons pas traitéla compression et l’archivage, vous verrez ceci dans une future partie Algo.

2. Langages et programmation

(a) Types structurés, p-uplets, tableaux et dictionnaires

Solution. Bien regarder les parties de cours sur les variables locales, la notion de variable mu-table ou pas. Bien être au point sur les fonctions (paramètres formels, effectifs, etc.). Ces pointsétaient explicitement “pré-requis”. La syntaxe des accès et des modifications des différentesstructures doit être connues.

(b) Traitement de données en tables (recherche, tris, fusion)

Solution. Il faut connaître (principe, algo rapide, implémentation fonctionnelle en Python)un tri simple (insertion, sélection). Connaître le principe de la fusion et du tri fusion. Le trirapide n’est pas exigible à ce stade.

(c) Modularité, bibliothèques

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 3/39

Page 4: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #0 – 2020

Solution. Voir les transparents associés sur la page web du cours.

(d) Diversité des langages de programmation

Solution. Nous n’avons pas vu cette partie. Il faut connaître une partie des caractéristiquesde Python (cf slides de cours).

(e) Spécification, prototypage et tests

Solution. Connaître le vocabulaire, savoir raisonner sur un programme simple (recherche, trisimple, fusion...) Pratiquer la partie test.

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 4/39

Page 5: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

TD 1Prise en main

1.1 Échauffement

EXERCICE #1 Ï Prise en mainOuvrez votre environnement Python (Spyder, Pyzo, . . . ), sauvez votre fichier courant dans un endroit pertinent,avec un nom pertinent.

EXERCICE #2 Ï Utilisation de Python comme calculatriceDans la partie “invite de commande” de votre environnement Python, faire des petits calculs :

>>> 2 + 24

En particulier ceux des transparents “introduction et prérequis”, par exemple :

— 1.0 + 1

— "Bonjour " + "a tous"

— "Bonjour" + 10

— 2 == 2

— 2 == 3

— (1 == 2) == (3 == 4)

EXERCICE #3 Ï Fichier Python et interprète ligne à ligne.Maintenant dans la partie “éditeur” (donc dans votre fichier source Python (ou fichier de script, mais je n’aimepas trop cette dénomination; ou fichier Python), réécrire les mêmes expressions de calcul qu’à l’exercice pré-cédent, et trouvez les menus de votre éditeur qui permettent d’évaluer ligne à ligne comme précédemment.Remarquez que dans ce mode l’évaluateur python imprime les valeurs que vous calculez, même si vous ne luidites pas explicitement..

EXERCICE #4 Ï Récupération d’un fichier source extérieurRécupérez le fichier demo1.py sur la page du DIU. Sauvez-le au bon endroit NE PAS cliquer sur le lien, maisclic droit “enregistrez-sous”, puis ouvrez-le dans votre environnement Python. Exécutez les premières lignescomme précédemment.

EXERCICE #5 Ï Interprétation du fichier completDans votre environnement python, exécutez le programme complet 1. Remarquez que seules les sorties écransont visibles.

EXERCICE #6 Ï Valeur de retour de fonction versus impressionToujours dans le même fichier, on a écrit deux versions “presque identiques” d’une fonction, qu’on vous laisseanalyser. Il est important de bien séparer le calcul des entrées/sorties. Ce sont des activités différentes.

1.2 Premiers tours de piste

Les exercices de cette section seront faits dans un nouveau fichier Python, avec un nom pertinent, dans unendroit pertinent. Il est important de bien vérifier que vos élèves savent faire cela, régulièrement.

EXERCICE #7 Ï IfÉcrivez un programme qui initialise une variable entière à une valeur donnée par l’utilisateur (utilisez la fonc-tion input) et imprime un message différent selon sa parité.

1. sous Spyder, par exemple, voici une démo https://matthieu-moy.fr/cours/liesse/spyder/editeur/

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 5/39

Page 6: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #1 – 2020

Solution.

inputvar = int(input("Choisissez un nombre : "))if inputvar % 2 == 0:

print("Pair")else:

print("Impair")

EXERCICE #8 Ï “Même exo”?Écrire une fonction :

def est_pair(x)"""retourne/renvoie Vrai si x:entier est pair"""

et réalisez les entrées/sorties dans le reste du programme pour qu’il ait le même comportement que le précé-dent.

Solution.

def est_pair(x)"""retourne/renvoie Vrai si x:entier est pair"""return x % 2 == 0

inputvar = int(input("Choisissez un nombre : "))if est_pair(inputvar):

print("Pair")else:

print("Impair")

À partir de maintenant, mettez une documentation minimale au début de vos fonctions, comme dans l’exer-cice précédent.

EXERCICE #9 Ï WhileSur le même modèle que précédemment (séparation calcul/entrées-sorties), érire un programme qui de-mande deux entiers à l’utilisateur, calcule et imprime leur pgcd.

Solution.

def pgcd(a, b):"""calcul du pgcd de a et b"""while b != 0:

a, b = b, a % breturn a

a = int(input("Choisissez le nombre a : "))b = int(input("Choisissez le nombre b : "))print("pgcd(a, b) = ", pgcd(a, b))

EXERCICE #10 Ï Factorielle récursiveMême question, avec une implémentation récursive de la factorielle.

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 6/39

Page 7: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #1 – 2020

Solution. On vous fournit l’implémentation de la fonction factorielle.

def fact(n):"""Calcule la factorielle de n"""return n * fact(n - 1) if n > 1 else 1

À partir de maintenant les programmes seront systématiquement testés, mais il est inutile de faire des entréessorties systématiquement, vous pouvez directement initialiser des variables dans votre programme python...

EXERCICE #11 Ï For/rangeEn utilisant les constructions for i in range(...), écrire un programme qui calcule la somme de tous lesi pairs de 2 à 42 inclus.

Solution. Attention en python3 le range est exclusif à droite !

the_integers = range(2, 43, 2)sum_of_integers = 0

for i in the_integers:sum_of_integers += i

print(sum_of_integers)

ou, moins malin :

s=0for i in range(1, 43):

if i % 2 == 0:s += i

print(s)

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 7/39

Page 8: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

TD 2Structures de données 1 : listes/tables

2.1 Premiers pas : listes simples

EXERCICE #1 Ï ListesÉcrire un programme qui déclare et initialise une liste (d’entiers), et calcule la somme de ses éléments. Remar-quer qu’il n’est pas simple de distinguer i , l ,1 et conclure sur le fait que l’utilisation de l comme identifiant deliste (ou whatever else) est à bannir.

Solution.

liste = [1, 2, 3, 4]somme = 0for i in liste:

somme += iprint(somme)

EXERCICE #2 Ï Itérer sur des listesEn supposant que mylist soit une liste d’entiers, que font les instructions suivantes? Essayer d’abord de ré-pondre sans ordi.

[k ** 2 for k in mylist]

et

[k for k in mylist if k % 2 == 0]

Solution.Liste des carrés des éléments de la liste mylist, obtenue en 1 ligne de code.Sous-liste des éléments pairs de la liste mylist, obtenue en 1 ligne de code.

EXERCICE #3 Ï Initialisation de listesIl peut être utile de savoir initialiser des listes. En vous inspirant des fonctions précédentes, déclarer et initia-liser des listes :

— entiers pairs de 2 à 42 compris

— entiers pris au hasard entre 0 et 1000, en nombre n.

Solution.

evenlist = [k for k in range(1, 43) if k % 2 == 0]

ou

evenlist = list(range(2, 43, 2))

import random

def random_array(n):"""Génère un tableau de taille nd’entiers aléatoires entre 0 et 1000"""

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 8/39

Page 9: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #2 – 2020

return [random.randint(0, 1000) for i in range(n)]

Dans le programme de la formation, il y a les tuples “p-uplets”. Il n’y a pas grand chose à dire dessus (à partqu’une fois créé, un tuple n’est pas modifiable). Vous pouvez par exemple lire la documentation ici : https://docs.python.org/fr/3/tutorial/datastructures.html#tuples-and-sequences.

EXERCICE #4 Ï Tuples et listesÉcrire une fonction Python qui prend une liste d’entiers en paramètre et retourne un couple (2-uplet) de listes,la première étant la sous-liste des entiers pairs, et l’autre la sous-liste des entiers impairs.

Solution. Version “simple” :

def split_even_odd(mylist):"""sépare les éléments de mylist entre pairs et impairs"""

evenlist = []oddlist = []for k in mylist:

if k % 2 == 0:evenlist.append(k)

else:oddlist.append(k)

return (evenlist, oddlist)

ou, un peu plus avancée (mais parcourt 2 fois la liste) :

def split_even_odd(mylist):"""sépare les éléments de mylist entre pairs et impairs"""

return ([k for k in mylist if k % 2 == 0],[k for k in mylist if k % 2 == 1])

Dans la suite on va coder des algorithmes de base sur “les tableaux”. En Python (ce n’est pas le cas d’autreslangages de programmation), ces objets seront en fait les listes que nous venons de voir 1. Les règles du jeu sontque les “données en table” soient toutes du même type (entier chez nous), et que l’on accède à ces donnéesuniquement avec leur indice (mylist[42]). Les variables listes seront alors un poil abusivement nomméestab :-)

EXERCICE #5 Ï Listes, etc.Pour approfondir vous trouverez plein d’exercices intéressants dans ce polycopié http://www.prepamantes.fr/wp-content/uploads/2013/08/Bases_algo+python.pdf (pages 41 et suivantes).

2.2 Recherches

EXERCICE #6 Ï Recherche dans un tableauÉcrire une fonction de recherche d’un élément dans un tableau.

Solution. Solution partielle, il faut rajouter des choses dans la doc.

def recherche_tab(tab, e):"""ici types des params des fonctions"""for i, val in enumerate(tab):

1. Il y a bien d’autres utilisations des listes, par exemple allez voir à l’adresse https://docs.python.org/fr/3/tutorial/datastructures.html

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 9/39

Page 10: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #2 – 2020

if val == e:return i

return -1

EXERCICE #7 Ï Recherche dans un tableau triéÉcrire une fonction de recherche dichotomique dans un tableau trié. On fera une version récursive et uneversion itérative.

Solution. On pourrait mettre différents tests (notamment que tab est bien trié en entrée) mais on ne lefait pas ici pour la sobriété du code dans la mesure où c’est plutôt l’objet du TD 4.

# Version récursive de recherche dichodef recherche_dans_bornes(tab, e, idep, ifin):

"""recherche l’élément e dans tab entre les indices idep et ifintab est supposé triéretourne i qui est un indice de e dans tabou -1 si e n’est pas dans tab"""

if ifin < idep:return -1

ind_milieu = (ifin + idep) // 2if tab[ind_milieu] == e:

return ind_milieuif e < tab[ind_milieu]:

return recherche_dans_bornes(tab, e, idep, ind_milieu -1)return recherche_dans_bornes(tab, e, ind_milieu+1, ifin)

def recherche_dicho(tab, e):"""recherche l’élément e dans tab qui est supposé trié

retourne i qui est un indice de e dans tabou -1 si e n’est pas dans tab"""

return recherche_dans_bornes(tab, e, 0, len(tab)-1)

# Version impérativedef recherche_dicho2(tab, e):

"""recherche l’élément e dans tab qui est supposé triéretourne i qui est un indice de e dans tabou -1 si e n’est pas dans tab"""

idep, ifin = 0, len(tab)-1while ifin >= idep:

ind_milieu = (idep + ifin) // 2if tab[ind_milieu] == e:

return ind_milieuif e < tab[ind_milieu]:

ifin = ind_milieu - 1else:

idep = ind_milieu + 1return -1

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 10/39

Page 11: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Test si liste triée

Avant de commencer à écrire des algorithmes de tri, on s’intéresse à tester si une liste est triée (pasbesoin de la triée si elle l’est déjà). Programmer une fonction Python qui teste si une liste passée enparamètre est triée.

Tri par insertion

Le tri par insertion est l’algorithme utilisé par la plupart des joueurs lorsqu’ils trient leur « main » decartes à jouer. Le principe consiste à prendre le premier élément du sous-tableau non trié et àl’insérer à sa place dans la partie triée du tableau.

a. Dérouler le tri par insertion du tableau [5.1, 2.4, 4.9, 6.8, 1.1, 3.0].

b. Ecrire en Python la procédure de tri par insertion, par ordre croissant, d’un tableau de réels :

Procédure tri_par_insertion (tab : tableau de n réels)Précondition : tab[0], tab[1], … tab[n-1] initialisésPostcondition : tab[0] tab[1] … tab[n-1]

c. Un algorithme de tri est dit « stable » s’il préserve toujours l’ordre initial des ex-aequos. Dansnotre exemple, l’algorithme est stable si des valeurs identiques restent dans leur ordred’apparition avant le tri. L’algorithme de tri par insertion est-il stable ?

Tri par sélection

Le principe du tri par sélection est le suivant. Pour chaque élément i de 1 à n-1, on échange tab[i]avec l’élément minimum de tab[i..n]. Nous devons donc rechercher, pour chaque itération le miniumd’un sous-tableau de plus en plus petit. Les éléments à gauche de i sont à leur place définitive etdonc le tableau est complémentent trié lorsque i arrive sur l’avant dernier élément (le dernierélément étant forcément le plus grand

Ecrire en Python la procédure de tri par sélection, par ordre croissant, d’un tableau de réels :

Tri rapide (quick sort)

Cette méthode de tri consiste à placer un élément du tableau (appelé pivot) à sa place définitive, enpermutant tous les éléments de telle sorte que tous ceux qui sont inférieurs au pivot soient à sagauche et que tous ceux qui sont supérieurs au pivot soient à sa droite. Cette opération s'appelle lepartitionnement. Pour chacun des sous-tableaux, on définit un nouveau pivot et on répète l'opérationde partitionnement. Ce processus est répété récursivement, jusqu'à ce que l'ensemble des élémentssoit trié.

Informatique, Formation des enseignants DIU Exercices #2 – 2020

2.3 Tris

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 11/39

Page 12: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Concrètement, pour partitionner un sous-tableau :

on place le pivot arbitrairement à la fin (peut êtrefait aléatoirement), en l'échangeant avec le dernierélément du sous-tableau (étape 1 ci-contre)

on place tous les éléments inférieurs au pivot endébut du sous-tableau (étapes 2 et 3)

on place le pivot à la fin des éléments déplacés(étapes 4 et 5)

Écrire en Python la procédure de partitionnement et la procédure récurvise de tri rapide.

Tri par fusion interne

Explication Wikipedia-fr :

À partir de deux listes triées, on peut facilement construire une liste triée comportant leséléments issus de ces deux listes (leur *fusion*). Le principe de l'algorithme de tri fusion reposesur cette observation : le plus petit élément de la liste à construire est soit le plus petit élémentde la première liste, soit le plus petit élément de la deuxième liste. Ainsi, on peut construire laliste élément par élément en retirant tantôt le premier élément de la première liste, tantôt lepremier élément de la deuxième liste (en fait, le plus petit des deux, à supposer qu'aucune desdeux listes ne soit vide, sinon la réponse est immédiate).

Ce procédé est appelé fusion et est au cœur de l'algorithme de tri suivant :

•Si le tableau n'a qu'un élément, il est déjà trié.•Sinon, séparer le tableau en deux parties à peu près égales.•Trier récursivement les deux parties avec l'algorithme du tri fusion.•Fusionner les deux tableaux triés en un seul tableau trié.

Écrire en Python une version récursive de l’algorithme du tri par fusion d’un tableau d’entiers.

Informatique, Formation des enseignants DIU Exercices #2 – 2020

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 12/39

Page 13: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #2 – 2020

Solution. Différents programmes de tri :

# Test de tri

def est_trie(tab):"""teste si tab est trié"""for i in range(len(tab)-1):

if tab[i] > tab[i+1]:return False

return True

# Tri par insertion

def tri_par_insertion(tab):"""trie le "tableau" tab par l’algorithme tri insertion"""# On place successivement chaque élément à sa place# parmi les éléments d’indices plus petits déjà triés.for j in range(1, len(tab)):

# On commence par mémoriser l’élément en cours de placement.elt_a_placer = tab[j]# On parcourt tab de la droite vers la gauche# à partir de l’élément précédent.i = j - 1while i >= 0 and tab[i] > elt_a_placer:

# On décale tab[i] vers la droite# si il est plus grand que elt_a_placer.tab[i+1] = tab[i]i -= 1

tab[i+1] = elt_a_placer # Placement de l’élément à la sortie

# Tri par sélection

def tri_par_selection(tab):"""trie tab par l’algorithme de sélection"""for i in range(len(tab)-1): # de 0 à n-2 (n la longueur de tab)

indmin = ifor j in range(i+1, len(tab)): # de i+1 à n-1, recherche du min

if tab[j] < tab[indmin]:indmin = j

tab[indmin], tab[i] = tab[i], tab[indmin] # échange de valeurs

# Tri rapide (quick sort)# dans un premier temps on ne se soucie pas de faire les choses en place

def partitionner(tab, elt):"""partitionne tab entre les éléments < elt et ceux >= elt

rend une paire de listes"""gauche, droite = [], [] # initialisationfor val in tab:

if val < elt:gauche.append(val) # on range dans gauche les éléments < elt

else:

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 13/39

Page 14: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #2 – 2020

droite.append(val) # on range dans droite les éléments >= eltreturn gauche, droite

def tri_rapide_rec(tab):"""trie tab par l’algorithme de tri rapide (quick sort)"""if len(tab) <= 1: # liste vide ou singleton

return tab # dans ce cas tab est trié# choix de l’indice du pivot (au choix parmi les 3 lignes qui suivent)# ipivot = 0 # comme premier élément de tabipivot = len(tab)-1 # comme dernier élément de tab# ipivot = random.randint(0, len(tab)-1) # aléatoirementpivot = tab[ipivot] # le pivotgauche, droite = partitionner(tab[:ipivot] + tab[ipivot+1:], pivot)return tri_rapide_rec(gauche) + [pivot] + tri_rapide_rec(droite)

def tri_rapide1(tab):"""transforme tab en sa version triée en utilisant tri_rapide_rec"""tab_sort = tri_rapide_rec(tab)for i in range(len(tab)):

tab[i] = tab_sort[i]

## on fait maintenant les choses en place (économie de mémoire)

# plusieurs manières de partitionner sont possibles , en voici 2def partitionner_en_place(tab, deb, fin, ipivot):

"""partitionne les éléments de tab entre deb et finpar rapport à pivot = tab[ipivot]ipivot est supposé entre deb et finretourne l’indice ipart de tab[ipivot] après la partitionles éléments de tab entre deb et ipart sont <= pivotles éléments de tab entre ipart+1 et fin sont > pivot"""

tab[ipivot], tab[fin] = tab[fin], tab[ipivot] # on stocke pivot à la finj = deb # entre deb et j -1, une suite d’éléménts <= pivotfor i in range(deb, fin): # entre j et i-1, une suite d’éléments > pivot

if tab[i] <= tab[fin]: # si on a un élément <= pivot, on le place en jtab[i], tab[j] = tab[j], tab[i]j += 1

tab[fin], tab[j] = tab[j], tab[fin] # on replace le pivotreturn j

def partitionner_en_place2(tab, deb, fin, ipivot):"""partitionne les éléments de tab entre deb et fin

par rapport à pivot = tab[ipivot]ipivot est supposé entre deb et finretourne l’indice ipart de tab[ipivot] après la partitionles éléments de tab entre deb et ipart sont < pivotles éléments de tab entre ipart+1 et fin sont >= pivot"""

tab[ipivot], tab[fin] = tab[fin], tab[ipivot] # on stocke pivot à la fini, j = deb, fin-1 # initialisationwhile True:

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 14/39

Page 15: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #2 – 2020

while tab[i] < tab[fin]: # on cherche une valeur >= pivot# on s’arrête forcément si i = fin

i += 1while j >= i and tab[j] >= tab[fin]: # on cherche une valeur < pivot

# on s’arrête forcément si j = ij -= 1

if i < j: # on a trouvé deux valeurs à permutertab[i], tab[j] = tab[j], tab[i]

else: # on est arrivés au bout (i = fin ou i = j)tab[i], tab[i+1:fin+1] = tab[fin], tab[i:fin] # on replace le pivotreturn i

def tri_rapide_rec_en_place(tab, deb, fin):"""trie les éléments de tab entre deb et fin par tri rapide"""if deb < fin: # sinon c’est déjà trié

# choix de l’indice du pivot (au choix parmi les 3 lignes qui suivent)# ipivot = deb # comme premier élémentipivot = fin # comme dernier élément# ipivot = random.randint(deb, fin) # aléatoirementipivot_part = partitionner_en_place(tab, deb, fin, ipivot)# ipivot_part = partitionner_en_place2(tab, deb, fin, ipivot)tri_rapide_rec_en_place(tab, deb, ipivot_part -1)tri_rapide_rec_en_place(tab, ipivot_part+1, fin)

def tri_rapide2(tab):"""tri rapide de tab via tri_rapide_rec_en_place"""tri_rapide_rec_en_place(tab, 0, len(tab)-1)

# Tri par fusion# dans un premier temps on ne se soucie pas de faire les choses en place# on pourra choisir soit la fusion récursive soit la fusion itérative

def fusion_rec(gauche, droite):"""Fusion récursive :

construit la fusion triée des deux listes triées gauche et droite"""if len(gauche) == 0: # si la liste gauche est vide, la fusion est facile

return droiteif len(droite) == 0: # si la liste droite est vide, la fusion est facile

return gaucheif gauche[0] < droite[0]: # on place en tête le plus petit élément

return [gauche[0]] + fusion_rec(gauche[1:], droite)else:

return [droite[0]] + fusion_rec(gauche, droite[1:])

def fusion_it(gauche, droite):"""Fusion itérative :

construit la fusion triée des deux listes triées gauche et droite"""igauche, idroite = 0, 0result = []while igauche < len(gauche) and idroite < len(droite):

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 15/39

Page 16: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #2 – 2020

if gauche[igauche] < droite[idroite]:result.append(gauche[igauche])igauche += 1

else:result.append(droite[idroite])idroite += 1

# l’une des 2 listes est désormais vide, on ajoute ce qui resteresult += gauche[igauche:]result += droite[idroite:]return result

def tri_fusion_rec(tab):"""trie tab par l’algorithme de fusion

version récursive"""if len(tab) <= 1: # liste vide ou singleton

return tab # dans ce cas tab est triémilieu = len(tab) // 2 # on coupe en 2 au milieugauche = tri_fusion_rec(tab[:milieu]) # trie la partie gauche de tabdroite = tri_fusion_rec(tab[milieu:]) # trie la partie droite de tab

# return fusion_it(gauche, droite) # fusionne les deuxreturn fusion_rec(gauche, droite) # fusionne les deux

def tri_fusion1(tab):"""transforme tab en sa version triée en utilisant tri_fusion_rec"""tab_sort = tri_fusion_rec(tab)for i in range(len(tab)):

tab[i] = tab_sort[i]

# on fait maintenant les choses en place (économie de mémoire)# on pourra choisir soit la fusion récursive soit la fusion itérative

# une fonction récursive de fusion en placedef fusion_rec_en_place(tab, beg, mid, end):

"""fusionne les parties de tab situéesentre beg et mid-1 et entre mid et end"""

if beg < mid and mid <= end: # on teste qu’il y a encore des éléments# des 2 côtés sinon c’est fini

if tab[beg] <= tab[mid]: # on compare les 1ers éléments des 2 paquetsfusion_rec_en_place(tab, beg+1, mid, end)

else: # si le plus petit est à droite, on le met à gauche et on décaletab[beg], tab[beg+1:mid+1] = tab[mid], tab[beg:mid]fusion_rec_en_place(tab, beg+1, mid+1, end)

# une fonction itérative de fusion en placedef fusion_it_en_place(tab, beg, mid, end):

"""fusionne les parties de tab situéesentre beg et mid-1 et entre mid et end"""

i, j = beg, midwhile i < j and j <= end: # on teste qu’il y a encore des éléments

# des 2 côtés sinon c’est fini

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 16/39

Page 17: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #2 – 2020

if tab[i] > tab[j]: # si le plus petit est à droite,# on le met à gauche et on décale

tab[i], tab[i+1:j+1] = tab[j], tab[i:j]j += 1

i += 1 # l’élément d’indice i est désormais à sa place

def tri_fusion_rec_en_place(tab, beg, end):"""tri_fusion des élémentes de tab entre beg et end"""if beg < end:

mid = (beg + end) // 2tri_fusion_rec_en_place(tab, beg, mid) # trie la partie gauche de tabtri_fusion_rec_en_place(tab, mid+1, end) # trie la partie droite de tab

# fusion_rec_en_place(tab, beg, mid+1, end) # fusionne les deuxfusion_it_en_place(tab, beg, mid+1, end) # fusionne les deux

def tri_fusion2(tab):"""tri_fusion de tab"""tri_fusion_rec_en_place(tab, 0, len(tab)-1)

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 17/39

Page 18: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

TD 3Structures de données Python 2 : dictionnaires

EXERCICE #1 Ï Archive zipRécupérer sur la page web du bloc l’archive zip contenant tous les fichiers nécessaires à ce TD. Enregistrer aubon endroit, puis dés-archiver correctement.

Un dictionnaire est une collection non-ordonnée, éditable et indexée. L’indexation se fait par une clé quipeut être de n’importe quel type immuable comme des chaînes de caractères ou des nombres. Une liste nepeut donc pas être une clé. À une clé est associée une valeur. Nous pouvons donc voir un dictionnaire commeun ensemble non-ordonné de paires (clé,valeur). Les clés comme les valeurs d’un même dictionnaire peuventêtre de différents types.

Pour créer un dictionnaire, les accolades sont utilisées. {} est donc un dictionnaire vide. Pour ajouter despaires (clé,valeur), nous les espaçons par des virgules avec des deux points entre la clé et la valeur.

Par exemple :

dictionnaire = {cle1 : valeur1 , cle2 : valeur2 , ... clen : valeurn}.

Les opérations principales sur un dictionnaire sont l’ajout d’une paire (clé,valeur) et l’accès à une valeurpar sa clé. La suppression d’une paire d’un dictionnaire est évidement aussi possible. Dans un dictionnaire, iln’y a pas deux clés identiques (l’essai de l’ajout d’une clé déjà existante va changer la valeur associée à la cléet non ajouter une deuxième occurrence de la clé). Par contre deux clés différentes peuvent être associées à lamême valeur.

Les opérations classiques sur les containers comme len, min/max, enumerate, in etc. sont disponibles surles dictionnaires et sont effectuées sur les clés. En plus de ces opérations classiques, des opérations spécifiquesaux dictionnaires suivantes sont disponibles telles que :

FIGURE 3.1 – Opérations simples sur les dictionnaires

3.1 Échauffement

EXERCICE #2 Ï Fonctions de base dictionnaires

1. Donner les instructions permettant de créer un dictionnaire associant des prénoms et des âges.

2. Donner les instructions permettant d’itérer sur le dictionnaire et d’afficher les paires sous le format ’pre-nom a age ans.’

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 18/39

Page 19: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #3 – 2020

Solution.

dictionnaire = {’Léa’:15, ’Élie’:16, ’Lucas’:18, ’Médina’:16,’Théo’:17, ’Hugo’:18, ’Stacy’:16}

for prenom, age in dictionnaire.items():print(prenom + ’ a ’ + str(age) + ’ ans.’)

ou

for prenom in dictionnaire:print(prenom, ’a’, dictionnaire[prenom], ’ans.’)

On peut s’apercevoir qu’un dictionnaire n’est pas très différent d’une liste de tuples (d.items() ressemblebeaucoup à d lui-même). Alors pourquoi utiliser des dictionnaires? La réponse est dans la performance desopérations. Accéder et modifier une paire est beaucoup plus rapide dans un dictionnaire que dans une listecar dans une liste on doit la parcourir pour trouver l’élément alors que dans un dictionnaire on y accède direc-tement.

Ceci se fait grâce à une table de hachage. Une fonction de hachage de cette table sert à mettre en corres-pondance une clé et l’indice de sa valeur dans la liste stockant les valeurs. En réalité la fonction donne unevaleur de hachage qui donne l’indice. La fonction de hachage dépend du type de la clé, mais dans tous lescas, elle donne un identificateur (valeur de hachage) idéalement unique pour la clé. Ensuite l’identificateurest converti en indice dans la liste des valeurs du dictionnaire.

Mais alors pourquoi ne pas toujours utiliser des dictionnaires au lieu des listes si c’est plus rapide? C’estparce que la table de hachage prend de la place en mémoire. On choisit donc entre dictionnaire et liste enfonction du compromis souhaité entre performance et espace mémoire.

EXERCICE #3 Ï Conversion Liste DictionnaireÉcrire une fonction dictToList qui convertit un dictionnaire en une liste de tuples (sans utiliser la fonctionitems()) et une fonction listToDict qui convertit une liste de tuples en dictionnaire.

Solution. Cette correction devrait être développée.

def dict_to_list(d):"""calcule une liste de paires (cle, valeur)

à partir d’un dictionnaire"""result_list = []for cle in d:

result_list.append((cle, d[cle]))return result_list

def list_to_dict(mylist):"""calcule un dictionnaire

à partir d’une liste de paires (cle, valeur)"""d = {}for paire in mylist:

d[paire[0]] = paire[1]return d

3.2 Comparaison Liste/Dictionnaire

EXERCICE #4 Ï Charger une liste à partir d’un fichierDans l’archive, on fournit diu-dico-english.py ainsi que le dictionnaire dico.en2fr. Ouvrir le fichier Py-thon et expérimenter. Il n’est pas nécessaire de comprendre plus que cela comment est réalisé le chargement àpartir du fichier. Un TD y sera consacré..

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 19/39

Page 20: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #3 – 2020

EXERCICE #5 Ï Charger un dictionnaire à partir d’un fichierRemplir les trous de l’exemple précédent avec des fonctions utilisant un dictionnaire 1. Comparez les tempsd’exécution.

Solution.

def update_dict(mot, trad, mydict):"""met à jour le dictionnaire mydict avec la paire (mot, trad)"""mydict[mot] = trad

def load_dict(nom_fichier , dico):"""charge les mots de nom_fichier dans le dictionnaire dico"""with open(nom_fichier) as fichier:

for ligne in fichier:mot, trad = ligne.strip().split("\t")update_dict(mot, trad, dico)

def search_tuple_dict(dico, elem):"""recherche la valeur associée à elem dans dico"""return dico[elem]

EXERCICE #6 Ï Utilisation de dictionnaires en classeImaginer des scénarios d’usage pour des élèves, quel dictionnaire pour quel usage ? Construire un tel exer-cice.

Solution. On peut faire un annuaire gens → information (numéro de tel, etc). On peut aussi faire unevariante où une information n’est pas écrasée mais mise à jour en cas d’ajout d’une deuxième informationavec le même id, et à ce moment là on peut faire des stats sur un texte (nombre d’occurrences de “the”dans un texte anglais, le texte intégral d’Hamlet est disponible en texte par exemple).

3.3 Pour aller plus loin : implémenter les dictionnaires (tables de hachage)

Cette partie nécessitera l’usage de la librairie matplotlib qu’il faudra donc peut-être installer. On va danscette section implémenter des tables de hachage, en utilisant une librairie fournie de listes triées. C’est unevariante de cette structure de données qui est fournie par Python sous le nom de dictionnaire.

Une table de hachage est un compromis entre les listes chaînées efficaces sur les ajouts et les tableaux(ou listes contiguës) efficaces sur les accès. Soit un ensemble fini D de données (ici les mots du dictionnaire)que l’on va stocker dans un tableau ht. Pour ranger un élement x de D, on calcule son image par une fonc-tion de hachage hash, qui donne son indice (appelé “indice de hachage”) dans ht, x sera donc rangé dansht[hash(x)]. Il reste à trouver une fonction hash adéquate :

— l’idéal est de trouver une fonction bijective entre D et l’intervalle d’indices du tableau, ainsi chaque casedu tableau contient 1 élément de D . Mais il est difficile de trouver une telle fonction bijective, ne serait-ce que parce que D est rarement connu a priori.

— l’utilisation d’une fonction injective (ie qui associe à chaque x de D une case différente de D) mène àun tableau de taille sup{hash(x), x ∈D}, c’est-à-dire à un tableau à trous, ce qui peut générer une perteimportante de place.

— le principe consiste alors à prendre une fonction surjective, obtenue généralement par modulo sur unetaille limitée de tableau, soit TABLE_SIZE ¿ car d(D). On tombe alors sur un problème de “collisions”parce que plusieurs données peuvent avoir le même indice de hachage. On choisit donc une structuremixte formée d’un tableau statique de listes chaînées contenant les éléments de même indice de ha-chage (appelées “listes de collisions”). Si possible ces listes sont ordonnées pour optimiser les accès.

1. Nous avons généré ce fichier “élève” à partir de notre source de correction en utilisant le script generate_skeletons.pydisponibleà l’adresse https://gitlab.com/moy/generate-skeletons. C’est extrêmement pratique, essayez !

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 20/39

Page 21: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #3 – 2020

L’ajout d’un élément x revient alors à calculer hash(x) de coût quasi constant et insérer x dans la listeht[hash(x)], en o(n) n étant la taille de la liste correspondante. Toute la difficulté est de trouver unbon compromis entre la taille du tableau et la taille des listes. Remarquez que prendre TABLE_SIZE=1revient à faire une simple liste.

EXERCICE #7 Ï Coder une table de hachageLes fichiers nécessaires diu-dico-hash.py, libdiulistechainee.py dico.english sont dans l’archive.Ouvrir le fichier Python diu-dico-hash, l’objectif est de remplir les TODO.

EXERCICE #8 Ï Librairie de listes chaînéesOuvrir la librairie, pour voir.

Exemple fourni : dictionnaire anglais Le dictionnaire anglais fourni, avec la fonction de hachage qui cal-cule la somme des codes ASCII des caractères du mot modulo TABLE_SIZE donne la hachtable suivante siTABLE_SIZE=50 :

hash("robot")=20

0

20

49

abridged

able

absence

access ...

yetnullabasement

... robot

... zest

nullaccomplish

...

ht

FIGURE 3.2 – Table ht du dictionnaire anglais

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 21/39

Page 22: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

TD 4Vérification fonctionnelle : spécifications, tests

4.1 Analyse de programme - correction et invariants

Se rapporter aux transparents du cours sur la page web du DIU. Cette partie sera refaite dans d’autres blocs,il s’agit d’une première mise en situation. Ces exercices seront principalement faits sur papier.

EXERCICE #1 Ï Recherche d’un élément dans un tableauProuver la correction de la recherche d’un élément dans un tableau, sans rupture prématurée du flot ; puisavec.

Solution. Voici un brouillon pour la rupture prématurée du flot. Le code concerné est :

def val_in_tab(val, t):for i in range(len(t)):

if t[i] == val:return i

return -1

On peut prendre comme invariant : “à la fin de la boucle numéro i (ligne après le return i ), on a0 ≤ i < n (où n est la longueur de t ) et, pour tout k ≤ i , t [k] 6= val”

— c’est clairement vrai pour la première boucle

— c’est inductif : si on arrive à la fin d’une boucle supplémentaire, c’est que l’on n’a toujours pas trouvéla valeur qu’on recherche.

— cela implique la postcondition : en effet, 1) si le flot est arrivé à la ligne "return -1" c’est que la boucle“for” a terminé correctement donc en particulier l’invariant est vrai pour i = n−1, et donc pour toutk ≤ n −1, t [k] 6= val , i.e. la valeur cherchée n’est pas dans le tableau. 2) si le flot n’est pas arrivé àreturn -1, c’est qu’il existe une valeur de i pour laquelle t [i ] = val , et à ce moment là on a retournéi , ce qui est ce qu’on veut.

EXERCICE #2 Ï Recherche dans un tableau triéRéécrire la précondition de cet algorithme, et ce qu’on veut prouver. Trouver le bon invariant et le prouver.

Solution. Précondition : tableau de longeur N , ∀0 ≤ i < N −2,tab[i ] ≤ tab[i +1].En version impérative :

def recherche_dicho2(tab, e):idep, ifin = 0, len(tab)-1while ifin >= idep:

ind_milieu = (idep + ifin) // 2if tab[ind_milieu] == e:

return ind_milieuif e < tab[ind_milieu]:

ifin = ind_milieu - 1else:

idep = ind_milieu + 1return -1

Le tableau n’est jamais modifié donc la précondition reste toujours valide.Invariant : soit e n’est pas dans tab, soit e est entre idep et ifin

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 22/39

Page 23: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #4 – 2020

— Par initialisation, l’invariant est vrai avant de rentrer dans la boucle.

— En fin de boucle :

— soit on a trouvé e et on est sorti,

— soit e < tab[ifin+1] (première branche du if), donc d’après la précondition, si e est danstab c’est entre idep (qui n’a pas changé) et ifin : l’invariant est vérifié

— soit e > tab[idep−1] (deuxième branche du if), donc d’après la précondition, si e est danstab c’est entre idep et ifin (qui n’a pas changé) : l’invariant est vérifié

On vise la correction faible donc on suppose que le programme termine. Soit on est sorti par returnind_milieu et on a bien une position de e dans tab. Soit on est sorti par le return -1 et, d’après l’inva-riant, e n’est pas dans tab puisque idep> ifin.

EXERCICE #3 Ï Fonction de McCarthyOn va étudier le programme suivant :

def mc(n):if n > 100:

return n - 10else:

return mc(mc(n + 11))

On cherche notamment à déterminer la fonction calculée par ce programme.

1. Reproduire le code et expérimenter en l’exécutant sur différentes valeurs de n ∈N.

2. Modifier le code pour faire apparaître les différents appels récursifs du programme lors de l’exécution.

Les questions suivantes se font principalement sur papier.

3. Déterminer la valeur de la fonction calculée par mc pour n > 100.

4. Montrer que si 90 ≤ n ≤ 100, mc(n) = mc(n +1). En déduire mc(n) pour 90 ≤ n ≤ 100.

5. Montrer que l’intervalle [90,111] est un invariant de la fonction, i.e. :

90 ≤ n ≤ 111 =⇒ 90 ≤ mc(n) ≤ 111

6. Montrer que, pour tout n < 90, mc(n) ∈ [90,111].

7. Déterminer la valeur de la fonction pour n < 90.

8. En conclure quelle est la fonction calculée par le programme mc pour n ∈N.

Solution. 1.

for i in range(80, 111): print("Valeur en", i, "=", mc(i))

2.

def mc_call(n):"""calcule la fonction de McCarthy en nindique les différents appels récursifs"""

print("Calcul de mc({})".format(n))

if n > 100:return n - 10

else:return mc_call(mc_call(n + 11))

3. Si n > 100, n 7→ n −10

4. Si 90 ≤ n ≤ 100, mc(n) = mc(mc(n +11)) = mc(n +11−10) = mc(n +1).

mc(90) = mc(91) = ·· · = mc(100) = mc(101) = 91.

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 23/39

Page 24: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #4 – 2020

5. D’après les questions précédentes : [101,111] 7→ [91,101] ⊆ [90,111], et [90,100] 7→ {91}.

6. Par récurrence sur 100−n :

— si n+11 ∈ [90,111], d’après la question précédente, mc(n) = mc(mc(n+11)) ∈ mc(mc([90,111])) =[90,111]

— si n+11 < 90, par hypothèse de récurrence, mc(n) = mc(mc(n+11)) ∈ mc([90,111]) = [90,111]

7. Si n < 90, on montre par récurrence sur 100−n que mc(n) = mc(...mc(mc(k))...) avec k ∈ [90,100]donc mc(n) = 91.

8. Si n ≤ 100, mc(n) = 91 et si n > 100, mc(n) = n −10. Autrement dit, mc(n) = max(91,n −10).

4.2 Tests unitaires - TP

EXERCICE #4 Ï DémoRécupérer l’archive sur la page web du cours. Nous proposons ici plusieurs manières de tester des algorithmesde tri (ici tri_insertion), en “testant” si la sortie de l’algorithme de tri est bien triée 1) :

— Dans un premier temps, uniquement avec Python : demo_test0.py, demo_test1.py.

— Puis pytest, librairie de test, lancée par Python : demo_test2, demo_test3.py 2.

Expérimentez ! Un peu d’explications : pytest lance chacune des fonctions préfixées par test_.

@pytest.mark.parametrize(’execution_number’, range(5))def test_one_random(execution_number , random_array):

tri_insertion(random_array)assert est_bien_trie(random_array)

Le assert est ce qui va déterminer si le test est ok ou non. Remarquez comment la fonction random_array estappelée pour générer un tableau aléatoire, et comment on peut réaliser un nombre paramétré de tests.

EXERCICE #5 Ï Testez vos trisMaintenant testez vos implémentations des tris du TD précédent, avec une des infrastructures fournies. Trouvez-vous des bugs ?

Solution. Un programme qui teste une liste de fonctions de tri issues d’un autre fichier :

#! /usr/bin/env python3# -*- coding: utf-8 -*-

"""Algorithmes de tris - Tests avec Pytestpython3 test_tris.py

"""

import random

import pytest

import tris

__author__ = "Olivier Laurent et Laure Gonnord"__copyright__ = "ENS de Lyon & Univ Lyon1, 2019"

1. Il faudrait aussi vérifier que les éléments du tableau d’entrée sont tous là, ceci est laissé en exercice au lecteur.2. On peut aussi lancer le logiciel pytest à la ligne de commande, mais c’est un peu sportif suivant l’IDE Python que vous utilisez, donc

on oublie pour l’instant

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 24/39

Page 25: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #4 – 2020

# liste des fonctions de tri à tester# ces fonctions doivent trier leur argument en place,# elles ne retournent rienTRIS_TESTES = [tris.tri_par_insertion , tris.tri_par_selection ,

tris.tri_rapide1 , tris.tri_rapide2 ,tris.tri_fusion1 , tris.tri_fusion2]

def is_sorted(tab):"""teste si tab est trie"""for i in range(len(tab) - 1):

if tab[i] > tab[i + 1]:return False

return True

def is_sorted_of(tab, tabref):"""teste si tab est la version triée de tabref"""test = is_sorted(tab)for i in set(tab):

test = test and tab.count(i) == tabref.count(i)return test

def random_tab(size, vmin, vmax):"""tableau aléatoire de longueur size

contenant des valeurs entre vmin et vmax"""return [random.randint(vmin, vmax) for _ in range(size)]

LG_TESTS = 100 # volume des tests aléatoires effectuésLISTE_TESTS = (# tests avec éléments identiques

[random_tab(100, 1, 100) for _ in range(LG_TESTS)]# tests sans éléments identiques (en général)

+ [random_tab(5, 1, 100) for _ in range(LG_TESTS)]# liste triée et liste à l’envers

+ [list(range(300)), [300 - i for i in range(300)]])

@pytest.mark.parametrize(’sort_fun’, TRIS_TESTES)@pytest.mark.parametrize(’tab_value’, LISTE_TESTS)def test_sorted(sort_fun, tab_value):

"""test si sort_fun(tab_value) a trié tab_value"""tab_sort = tab_value.copy()sort_fun(tab_sort)assert is_sorted_of(tab_sort, tab_value)

# lancement de pytestif __name__ == ’__main__’:

pytest.main()

EXERCICE #6 Ï Tests unitaires pour des exercices d’élèves

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 25/39

Page 26: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #4 – 2020

Récupérer une liste des premiers éléments de la suite factorielle par exemple sur le site ici :https://oeis.org/search?q=factorial&sort=&language=&go=Search

Faire un fichier de tests qui pourra tester du code élève fournissant la factorielle. Réfléchir sur les contraintesà donner pour que “tout se passe bien”.

Solution. La fonction factorielle (correcte) et son test :

def factoriel(n):if n == 0 or n == 1:

return 1return n * factoriel(n - 1)

resultat = [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880,3628800, 39916800]

@pytest.mark.parametrize(’n’, range(len(resultat)))def test_factoriel(n):

assert factoriel(n) == resultat[n]

Pour aller plus loin :

https://code-maven.com/slides/python-programming/testing-with-pytest.

4.3 Programmation défensive

EXERCICE #7 Ï MoyenneÉcrire une fonction qui calcule la moyenne de deux entiers positifs, de la manière la plus défensive possible.Utiliser pytest pour comparer aux fonctions de librairie min et max.

Solution. La fonction moyenne teste que ses arguments sont valides puis des tests sont effectués parpytest : sur des mauvais arguments pour valider l’aspect défensif, et sur des arguments valides pour testerle résultat.

def moyenne(a, b):"""Calcule la moyenne de a et b (entiers strictement positifs)"""assert type(a) == int and type(b) == int, "les arguments doivent être des entiers"assert a > 0 and b > 0, "les arguments doivent être strictement positifs"

# on pourrait faire ici des tests sur le résultat# result = (a + b) / 2# assert result >= min(a, b)# assert result <= max(a, b)# mais on va plutôt tester plus bas via pytest

return (a + b) / 2

# tests d’échecs sur des appels avec mauvais arguments

# liste de mauvaises paires d’argumentsfailure_list_moy = [(’a’, 3), (3, ’b’), (0, 4), (-2, 3), (3, -1)]

# test avec des mauvais arguments# @pytest.mark.xfail prévient pytest que ces tests doivent é[email protected](’value_fail’, failure_list_moy)@pytest.mark.xfail

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 26/39

Page 27: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #4 – 2020

def test_failing_args(value_fail):moyenne(value_fail[0], value_fail[1])

# tests sur des bons arguments

# un générateur de tests aléatoires avec valeurs entre 1 et 100def gen_tuple_int():

return (random.randint(1,100), random.randint(1,100))

# test de comparaison avec min et [email protected](’tuple_int’, [gen_tuple_int() for _ in range(1000)])def test_moyenne_min_max(tuple_int):

assert moyenne(tuple_int[0], tuple_int[1]) >= min(tuple_int[0], tuple_int[1])assert moyenne(tuple_int[0], tuple_int[1]) <= max(tuple_int[0], tuple_int[1])

Cet exercice a été délicatement copié du site https://swcarpentry.github.io/python-novice-inflammation/08-defensive/index.html. Je vous conseille de faire l’ensemble de ces exercices, ils sont tous très pertinents.

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 27/39

Page 28: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

TD 5Représentation des données en machine

Quelques trucs utiles

En Python, chr(i) renvoie la chaîne représentant un caractère dont le code de caractère Unicode est pré-cisément i ; réciproquement, ord(c) renvoie le code Unicode du caractère représenté par la chaîne donnée.Notez aussi que le constructeur int() permet déjà d’obtenir un entier à partir d’une chaîne de caractère :

>>> int(’314’)314>>> int(’1010’, 2)10>>> int(’1a’, 16)26

Pour convertir un entier en une chaîne de caractères, vous pouvez aussi utiliser les fonctions bin() ethex(), ainsi bien-entendu que la méthode format() de la classe str :

>>> bin(456)’0b111001000’>>> hex(458)’0x1ca’>>> "{:x}".format(458)’1ca’

5.1 Binaire, hexadécimal, complément à deux

On commence par des exercices classiques de décomposition en base, vous pouvez sauter si vous êtes à l’aise.2020 : ajout de quelques indications et exercices, par N. Louvet

EXERCICE #1 Ï Fonctions standard PythonPython fournit les fonctions standards bin(n) et hex(n) qui réalisent les conversions décimal vers binaire, ethexadécimal vers binaire. Vous pouvez expérimenter avec le fichier demo_repnombres.py (archive sur la pagedu DIU).

EXERCICE #2 Ï Conversions en base b

On vous fournit un fichier change_repr.py. Remplissez les deux fonctions à trous :

— lire_repr(rep, b) interprète la chaîne de caractères r ep en base b et retourne le nombre décimalassocié. On utilisera la fonction auxiliaire nombre.

— repr_nombre(n, b) réalise la conversion inverse. On utilisera la fonction auxiliaire chiffre.

Tester, etc.

Solution. Voici le code solution :

#! /usr/bin/env python3"""

python3 demo_test2.py"""__author__ = "Laure Gonnord"__copyright__ = "Univ Lyon1, 2019"

## fortement inspiré de http://sdz.tdct.org/sdz/du-decimal-au-binaire.html

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 28/39

Page 29: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #5 – 2020

CHIFFRES = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"NOMBRES = {c: n for (n, c) in enumerate(CHIFFRES)}

# Fonctions utilitairesdef chiffre(n):

return CHIFFRES[n]

def nombre(ch):"""ch= caractère qui désigne le nombreretourne le nombre associé"""return NOMBRES[ch]

chiffre(12) # ’C’nombre(’C’) # 12

# base b vers décimaldef lire_repr(rep, b):

nb_chiff = len(rep)somme = 0# TODO# BEGIN CUTb_puiss_i = 1for i in range(nb_chiff):

c_i = rep[nb_chiff - i - 1] #on lit de droite à gauchesomme = somme + nombre(c_i) * b_puiss_ib_puiss_i = b_puiss_i * b

# END CUTreturn somme

print(lire_repr(’2A’,16))

# représentation du nombre n en base b, retourne une chaîne# à chaque fois on ajoute à la fin de la chaîne.def repr_nombre(n, b):

# UNCOMMENT pass# BEGIN CUTrep = ""q = nwhile q != 0: # quotient, reste de la division eucl. par b

r = q % brep = chiffre(r) + repq = q // b

if rep == "":return chiffre(0)

else:return rep

# END CUT

print(repr_nombre(10, 2)) # 1010print(repr_nombre(42, 16)) # 2A

EXERCICE #3 Ï Calcul avec l’algorithme de Horner

Le principe de la conversion par la méthode de Horner de l’entier naturel n = (x3x2x1x0)β est le suivant.

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 29/39

Page 30: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #5 – 2020

On a :n = x3·β3 +x2·β2 +x1·β1 +x0,= (x3·β2 +x2·β1 +x1)·β+x0,= ((x3·β+x2)·β+x1)·β+x0.

Si on exécute l’algorithme suivant,

r3 = x3

r2 = r3 ×β+x2

r1 = r2 ×β+x1

r0 = r1 ×β+x0

alors par construction on a l’égalité r0 = x3·β3+x2·β2+x1·β1+x0. Si on effectue tous les calculs dans une based’arrivée γ, on obtient l’écriture de n en base γ. En outre, on comprend bien que la méthode de Horner n’estpas limitée à des nombres de 4 chiffres en base β, et qu’elle peut se généraliser facilement.

1. Testez l’algorithme de Horner pour convertir l’entier n = (11010101)2 en décimal.

2. Plus fastidieux à faire à la main : testez l’algorithme de Horner pour convertir l’entier n = (567)10 enbinaire. Combien de multiplications avez vous posées ? Combien en auriez-vous posées si vous aviezutilisé la définition de la notation positionnelle pour faire cette conversion?

3. Ecrivez une fonction en Python pour convertir une chaîne de caractères représentant un entier positifen décimal, en un entier non-signé en machine, en utilisant l’algorithme de Horner. Si k est le nombrede chiffres dans la chaîne d’entrée, combien de multiplications sont utilisées? Que penser de cette mé-thode ?

EXERCICE #4 Ï Et encore

1. Donnez en Python une fonction qui permet d’obtenir, sous la forme d’une chaîne de caractères, le co-dage en complément à 2 d’un entier sur k bits.

2. Donnez en Python une fonction qui permet de convertir en un entier une chaîne de longueur k forméede caractères ’0’ ou ’1’, en l’interprétant comme le codage en complément à deux d’un entier sur kbits.

5.2 Virgule flottante

EXERCICE #5 Ï Représentation en machine, norme IEEE-754 : TDLa norme IEEE-754 définit la manière dont sont représentés les flottants sur les ordinateurs actuels. On consi-dère le code suivant :

c = s code de l’exposant : ce code de la mantisse : cm

1 bit k bits p −1 bits

Pour un flottant normal, la valeur codée est f (c) = (−1)s(c) ×m(c)×2e(c), avec

— s(c) = s le signe du flottant.

— m(c) = (1,cm)2, ce qui signifie que le 1 de tête est codé implicitement.

— e(c) dépend de (ce )2, mais doit être interprété avec moultes précautions. . .

Comme ce est un code sur k bits, notons que 0 ≤ (ce )2 ≤ 2k −1.

— (ce )2 = 0 et (cm)2 = 0 indique que le nombre représenté est 0. Il y a deux codages de 0 : −0 ou +0 selon s.

— (ce )2 = 2k −1 indique une valeur exceptionnelle (+Inf, -Inf, NaN) : 1/0 =+Inf, 0/0 = NaN, a+ Inf = Inf, . . .

— 1 ≤ (ce )2 ≤ 2k −2 indique que le nombre représenté est normal. Alors,

m(c) = (1,cm)2 et e(c) = (ce )2 − (2k−1 −1)︸ ︷︷ ︸biais

.

Les types float et double du C correspondent à deux formats prévus par la norme IEEE-754, appelés simpleprécision et la double précision :

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 30/39

Page 31: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #5 – 2020

format mantisse exposant tailleprécision p −1 k biais emin emax

simple p = 24 23 8 127 −126 127 32 bitsdouble p = 53 52 11 1023 −1022 1023 64 bits

— Donnez les valeurs extrêmes λ et σ pour la simple et la double précision.

Solution. Valeurs extrêmes λ et σ pour la simple et la double précision :

format plus petit flt normalisé positif plus grand flottant normalisésimple 2−126 ≈ 1,2×10−38 (1−2−24)×2128 ≈ 3,4×1038

double 2−1022 ≈ 2,2×10−308 (1−2−53)×21024 ≈ 1,8×10308

— Donnez le codage de (1,5)10 en simple précision, sous la forme d’un code en hexadécimal.

Solution. Détaillons bien le principe. . . On a (1,5)10 = (1,1)2 ×20, et cette écriture est normalisée.Ainsi, m(c) = (1,1)2, et puisque la partie fractionnaire de la mantisse est codée sur 23 bits en simpleprécision,

cm = 10 · · ·0︸ ︷︷ ︸22 fois

.

De plus, en simple précision e(c) = (ce )2−127, donc (ce )2 = 0+127 = (127)10 = (0111 1111)2. Comme(1,5)10 est positif, le bit de signe est à 0 ((−1)0 = 1). Le codage de (1,5)10 en simple précision estdonc :

0 01111111 1000 0000 0000 0000 0000 000 = 0011 1111 1100 0000 0000 0000 0000 0000 = 3FC 00000.

Ce qui est confirmé par la calculette ici :https://www.h-schmidt.net/FloatConverter/IEEE754.html

EXERCICE #6 Ï Arrondi correct�� ��À savoir ! Pour représenter un réel r par un nombre flottant, il faut en général arrondir r . La norme IEEE-754propose 4 modes d’arrondi, mais on n’utilise que l’arrondi au plus proche (RN) dans ce TD : RN(r ) est le flottantle plus proche de r , et si r est équidistant de deux flottants consécutifs alors RN(r ) est celui dont la mantissese termine par un 0. La norme impose l’arrondi correct pour les opérations +, -, ×, / et

p· : le résultat calculédoit être le résultat exact arrondi selon le mode d’arrondi courant.

— Donnez la représentation positionnelle en base 2 de (0,1)10.

Solution. On effectue des multiplications par deux, pour extraire un à un les bits dans l’écriture de(0,1)10 en base 2.

1/10×2 = 0+2/102/10×2 = 0+4/10

4/10×2 = 0+8/108/10×2 = 1+6/10

6/10×2 = 1+2/100, 0 0 0 1 1

On en déduit que (0,1)10 = (0,00011)2.

— Est-il possible de représenter exactement (0,1)10 par un flottant binaire?

Solution. Non, car l’écriture en notation positionnelle de (0,1)10 est infinie en base 2 : il faudraarrondir pour représenter ce nombre par un flottant binaire, quelle que soit la précision utilisée.

— Représentez (0,1)10 par un flottant sur 8 bits de précision. S’il y a lieu, effectuez un arrondi au plusproche.

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 31/39

Page 32: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #5 – 2020

Solution. On a vu (0,1)10 = (0,00011)2. On commence par écrire :

(0,1)10 = (0,00011001100︸ ︷︷ ︸8 bits

110011)2 = (1,1001100︸ ︷︷ ︸8 bits

110011)2 ×2−4.

Donc (0,1)10 est dans l’intervalle suivant, délimité par deux flottants consécutifs :

[(1,1001100︸ ︷︷ ︸8 bits

)2 ×2−4; (1,1001101︸ ︷︷ ︸8 bits

)2 ×2−4].

Le milieu de cet intervalle est (1,1001100︸ ︷︷ ︸8 bits

1)2 ×2−4. On effectue un arrondi au plus proche : comme

(0,1)10 est supérieur au point milieu, on choisit l’approximation (0,1)10 ≈ (1,1001101︸ ︷︷ ︸8 bits

)2 ×2−4.

EXERCICE #7 Ï À lire à la maisonLe texte de la documentationhttps://docs.python.org/fr/3.6/tutorial/floatingpoint.html est trèsintéressant. Faire les petites manipulations.

5.3 Ascii

EXERCICE #8 Ï Ascii “à la main”exercice du à N. Louvet

1. On considère les informations ci-dessous, obtenues en tapant des commandes dans un shell Linux :

nlouvet@ninjutsu:~/$ cat toto.txtToto a fait du vélo tout l’été !!!nlouvet@ninjutsu:~/$ file toto.txttoto.txt: UTF-8 Unicode textnlouvet@ninjutsu:~/docsvn/diu-lyon/nicolas/td-num$ hexdump -C toto.txt00000000 54 6f 74 6f 20 61 20 66 61 69 74 20 64 75 20 76 |Toto a fait du v|00000010 c3 a9 6c 6f 20 74 6f 75 74 20 6c 27 c3 a9 74 c3 |..lo tout l’..t.|00000020 a9 20 21 21 21 0a |. !!!.|00000026nlouvet@ninjutsu:~/$

En vous basant sur votre culture générale, votre bon sens, et sans consulter de table des codes ASCII :

— Quel est le code ASCII de ’a’?

— Quel est le code ASCII de ’A’?

— Quel est le code UTF-8 de ’é’?

— Quel est le codage de votre prénom en code ASCII?

2. Le fichier song.txt contient le (1er) refrain d’une chanson célèbre d’un auteur-compositeur-interprète,musicien, peintre et poète américain (toujours en vie en 2019) : retrouvez le titre de cette chanson!

nlouvet@ninjutsu:~/$ file song.txtsong.txt: ASCII textnlouvet@ninjutsu:~/$ hexdump -v -e ’8/1 "%02X " "\n"’ song.txt48 6F 77 20 64 6F 65 7320 69 74 20 66 65 65 6C2C 20 68 6F 77 20 64 6F65 73 20 69 74 20 66 6565 6C 3F 0A 54 6F 20 6265 20 6F 6E 20 79 6F 7572 20 6F 77 6E 2C 20 7769 74 68 20 6E 6F 20 6469 72 65 63 74 69 6F 6E20 68 6F 6D 65 0A 41 2063 6F 6D 70 6C 65 74 6520 75 6E 6B 6E 6F 77 6E2C 20 6C 69 6B 65 20 61

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 32/39

Page 33: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #5 – 2020

20 72 6F 6C 6C 69 6E 6720 73 74 6F 6E 65 0Anlouvet@ninjutsu:~/$

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 33/39

Page 34: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

TD 6Fichiers

Adapté de Matthieu Moy, Benjamin Wack, . . . , stage Liesse Grenoble

6.1 Fichiers, fichiers textes

Pour organiser des données sur un disque dur, on utilise généralement des fichiers et des répertoires (par-fois appelés « dossiers »).

— Les fichiers (« file » en anglais) contiennent l’information à proprement parler.

— Les répertoires (« directory » en anglais) contiennent des fichiers ou d’autres répertoires.

Un fichier est une suite d’octets (1 octet = 8 bits = 1 nombre de 0 à 255). Par exemple, pour un fichiercontenant un programme python, et plus généralement pour tous les fichiers textes, chaque octet correspondà un caractère du programme. Chaque octet est un nombre, et il existe une correspondance entre ces nombreset les caractères : le code ASCII 1. Par exemple, le code ASCII dit que le nombre 97 est associé au caractère a, lenombre 98 au caractère b, etc.

Pour d’autres formats de fichier plus évolués (texte mis en forme par LibreOffice ou Word, image JPEG ouPNG...), la suite de caractères n’a pas forcément de sens pour un être humain, mais les logiciels appropriéssavent les lire.

EXERCICE #1 Ï Prise en mainTéléchargez et extrayez l’archive ZIP disponible sur le site du cours. Ouvrez le fichier display_file.py quis’y trouve. Ce fichier contient une fonction display_file(name) qui permet d’afficher les 10 premiers caractèresd’un fichier.

Vous n’avez pas besoin de comprendre les détails, mais vous pouvez comprendre le principe en sachantque :

— open() ouvre le fichier. La valeur renvoyée est appelée un “descripteur de fichier”, on peut la voir commeun curseur qui avance dans le fichier au fur et à mesure qu’on lit.

— f .read(1) lit un caractère à la position courante dans le fichier. Elle renvoie une chaîne vide si f est déjà àla fin du fichier.

— ord(c) renvoie le code ASCII du caractère c.

— f .close() ferme le descripteur de fichier f. Si on oublie de le faire, Python va continuer à utiliser desressources de l’ordinateur inutilement.

Exécutez display_file.py. Vous devriez voir :

— Pour les fichiers binaires (traitement-de-texte.odt, et l’image cpp.png), une suite de caractères plusou moins incompréhensible (certains ne s’affichent pas correctement, c’est normal). Pour l’image PNG,on voit apparaître les caractères PNG au début du fichier, ce n’est pas une coïncidence. Attention, mêmesi traitement-de-texte.odt ressemble à un fichier texte, c’est un fichier au format OpenDocumentbien plus compliqué qu’un fichier texte (on aurait eu un résultat similaire avec un fichier produit par MSWord). Pour obtenir un fichier texte avec MS Word ou LibreOffice, on peut faire : « Enregistrer Sous » puischoisir « Texte » comme format d’enregistrement.

— Pour les fichiers textes (programme Python, fichier CSV), les caractères correspondent à ce qu’on voitquand on ouvre le fichier.

1. les choses se compliquent si on veut représenter correctement les caractères accentués pour lesquels ASCII ne suffit pas malheu-reusement

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 34/39

Page 35: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #6 – 2020

6.2 Calcul à partir de données contenues dans un fichier

Nous allons maintenant faire un calcul simple sur des données lues depuis un fichier. On suppose qu’uninstrument de mesure a fourni des données dans un fichier texte, avec une valeur par ligne, comme ceci :

112.343310

6.2.1 Lecture d’un fichier ligne à ligne

Le but de cette section est de calculer la moyenne de ces valeurs. On commence avec le programme sui-vant :

f = open(’donnees.txt’, ’r’)ligne = f.readline()while ligne != ’’:

print("ligne =", ligne)ligne = f.readline()

Explications :

— Pour lire dans un fichier, il faut d’abord l’ouvrir. C’est ce que fait la fonction open, qui ouvre le fichierdonnes.txt en lecture (’r’, pour « read »).

— La fonction open renvoie un objet f que l’on peut utiliser avec f.readline() qui veut dire « lire la lignesuivante dans le fichier ». Une fois la fin du fichier atteint, f.readline() renvoie la chaîne vide.

La variable ligne va donc contenir successivement les chaînes "1", "12.3", "43", "3" et "10" 2. On vamaintenant extraire les nombres contenus dans cette ligne, et en faire la moyenne.

EXERCICE #2 Ï Ordre des instructions dans la boucleEssayez d’inverser les lignes print(ligne) et ligne = f .readline() et exécutez le programme. Cette inversion pro-voque deux problèmes : la première ligne n’est plus affichée, et une ligne blanche est affichée en fin de pro-gramme. Expliquez ces problèmes. Attention, il y a une ligne

Solution. ligne = f .readline() dans l’initialisation avant de rentrer dans la boucle. Donc, si on fait print("ligne=", ligne)après ligne = f .readline() dans la boucle, on aura bien exécuté deux fois ligne = f .readline() avant le pre-mier print, donc la première ligne est lue mais pas affichée. À la dernière exécution, on affiche nécessai-rement une ligne vide puisque le dernier print serait exécuté entre le dernier readline et le test de sortiede boucle.

En pratique, il est donc important d’exécuter ligne = f .readline() en dernier : c’est cette instruction quimarque le passage à l’itération suivante, donc c’est la dernière chose qu’on fait avant de revenir en tête deboucle et de tester ligne != ’’ à nouveau.

EXERCICE #3 Ï Calcul de moyenneEn ajoutant quelques lignes au programme ci-dessus, calculez la moyenne des nombres lus. Attention, la fonc-tionf.readline() renvoie une chaîne de caractère. Pour la convertir en nombre, on peut utiliserfloat(...).

Solution. Notre code :

f = open(’donnees.txt’, ’r’)# Première valeurligne = f.readline()nombre = 0

2. plus précisément, la variable ligne contient elle-même une fin de ligne, ce qui fait que print(ligne) affiche deux retours à laligne

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 35/39

Page 36: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #6 – 2020

somme = 0while ligne != ’’:

v = float(ligne)somme = somme + vnombre = nombre + 1# Lecture de la valeur suivanteligne = f.readline()

f.close()print("La moyenne des lignes est :", somme / nombre)

On peut bien sûr généraliser la méthode à des fichiers d’entrée plus compliqués, par exemple avoir plu-sieurs valeurs par ligne (typiquement séparées par des virgules).

6.3 Fichiers CSV

Nous allons maintenant travailler sur des fichiers permettant d’écrire plusieurs valeurs par ligne. Uneconvention classique est le CSV : comma-separated values.Un exemple de fichier CSV est donné dans donnees-2-colonnes.csv.

0,101,124,15

EXERCICE #4 Ï Ouvrir un fichier “pas py” dans l’éditeurOuvrez le fichier donnees-2-colonnes.csv dans Spyder (menu File → Open, puis choisir « All files » commetype de fichier).

Nous allons calculer des intégrales par la méthode des trapèzes, à partir de données disponibles dans unun fichier CSV 3 : la première colonne donne l’instant de la mesure t , et la seconde la vitesse v au moment dela mesure. L’objectif est de calculer la position du mobile après la dernière mesure.

EXERCICE #5 Ï Découpage d’une ligneUtiliser ligne.split(’,’) pour transformer ligne en une liste de chaînes (par exemple la liste ["0", "10"] pour la première ligne).

Extraire le premier élément et le convertir en flottant avec float(...) et mettre le résultat dans une va-riable t. De même, extraire le deuxième élément dans une variable v.

Vérifiez votre programme en ajoutant une ligne print(t, v).

6.3.1 Calcul d’intégrale

EXERCICE #6 Ï Méthode des trapèzesModifiez votre programme pour calculer la position du mobile en intégrant sa vitesse selon la méthode des

trapèzes.Indice : Pour calculer l’intégrale, ajoutez une variable position initialisée à 0 en début de fichier, puis

dans le corps de la boucle, ajoutez une ligne du type position = position + .... Pour faire une intégraleavec la méthode des trapèzes, il suffit d’ajouter (t − tpr ec )

v+vpr ec

2 , où tpr ec (resp. vpr ec ) est la valeur qu’avait t(resp. v) au précédent tour de boucle, ou 0 au premier tour (à vous de les définir en Python).

Solution. Notre code, qui pourrait être plus commenté :

f = open(’../donnees -2-colonnes.csv’, ’r’)ligne = f.readline()position = 0t = 0v = 0

3. Dans la vraie vie, on utiliserait un module Python comme csv mais ici nous allons faire les choses “à la main”

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 36/39

Page 37: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #6 – 2020

while ligne != ’’:t_prec = tv_prec = vvaleurs = ligne.split(’,’)t = float(valeurs[0])v = float(valeurs[1])# Méthode des trapèzesposition = position + (t - t_prec) * (v + v_prec) / 2ligne = f.readline()

f.close()print("La position à la fin de la mesure est :", position)

EXERCICE #7 Ï Écriture des résultats intermédiairesAjoutez un affichage intermédiaire (avec print) de chaque valeur, pour produire un affichage comme :

0.0,0.01.0,11.04.0,51.5

En fait, cette sortie est aussi au format CSV, on peut la sauvegarder dans un fichier. Pour écrire dans unfichier, il faut :

— Ouvrir le fichier avec, par exemple : out_file = open(’resultat.csv’, ’w’)

— Écrire dans le fichier avec : out_file.write (...)

— Fermer le fichier avec : out_file.close(). Tant que le fichier n’est pas fermé, les écritures faites via out_file.write (...)peuvent ne pas être appliquées (Python les garde en mémoire mais n’envoie pas les données sur disqueimmédiatement).

EXERCICE #8 Ï Écriture dans un fichierModifiez votre programme pour qu’il produise son résultat dans un fichierresultat.csv. Ouvrezresultat.csvpour vérifier que le résultat a bien été calculé.

Solution.

entree = open(’donnees -2-colonnes.csv’, ’r’)sortie = open(’resultat.csv’, ’w’)ligne = entree.readline()position = 0t = 0v = 0while ligne != ’’:

t_prec = tv_prec = vvaleurs = ligne.split(’,’)t = float(valeurs[0])v = float(valeurs[1])# Méthode des trapèzesposition = position + (t - t_prec) * (v + v_prec) / 2sortie.write(str(t) + "," + str(position) + "\n")ligne = entree.readline()

entree.close()sortie.close()print("La position à la fin de la mesure est :", position)

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 37/39

Page 38: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #6 – 2020

Si le temps le permet, essayez de modifier les valeurs du fichier d’entrée, relancez votre programme etvérifiez que resultat.csv est bien mis à jour (sous Spyder : menu File → Revert pour recharger un fichierouvert).

6.3.2 Manipulations de chaînes

Pour découper les lignes du fichier CSV, nous avons utilisé ligne. split (’,’) . En réalité, vous avez tous leséléments pour coder cette fonction vous-mêmes, et c’est un exercice de manipulation de chaînes et de listesintéressant :

EXERCICE #9 Ï Découpage de chaîneÉcrire une fonction decoupe(chaine) qui prend en paramètre une chaîne et qui renvoie une liste contenant

les éléments de la chaîne séparés par des virgules. Par exemple :

>>> decoupe("1,2,14")[’1’, ’2’, ’14’]>>> decoupe("1,2,14,666,")[’1’, ’2’, ’14’, ’666’, ’’]

Indice : le code peut ressembler à ceci :

def decoupe(chaine):indice_virgule = -1resultat = []for i in range(len(chaine)):

# ...return resultat

indice_virgule est l’indice de la dernière virgule rencontrée. On ajoute les éléments au résultat avec resultat.append().Pour rappel, on peut accéder à la sous-chaîne de i à j − 1 avec chaine[i : j ].

Vous pouvez tester votre code en remplaçant ligne. split (’,’) par un appel à decoupe dans votre pro-gramme (exercices 6.3 et 6.3.1).

Solution.

def decoupe(chaine):indice_virgule = -1resultat = []for i in range(len(chaine)):

if chaine[i] == ’,’:resultat.append(chaine[indice_virgule + 1: i])indice_virgule = i

resultat.append(chaine[indice_virgule + 1:])return resultat

6.4 Utilisation de la bibliothèque CSV

EXERCICE #10 Ï ExempleLa bibliothèquecsv est vraiment très simple à utiliser, on vous fournit un exemple dans l’archive (ex_csvlib.py).

EXERCICE #11 Ï À vousVous trouverez sur le web une infinité de ressources sous ce format, regardez par exemple :

— Génération de données bidon, ou aléatoires : http://www.generatedata.com/#generator— https://data.grandlyon.com/

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 38/39

Page 39: Diplôme inter-universitaire “Enseigner l’Informatique au Lycée” … · 2020-06-28 · Il peut être librement distribué (License CC-BY-SA 4.0). Intervenants Les personnes

Informatique, Formation des enseignants DIU Exercices #6 – 2020

— http://donnees.ville.montreal.qc.ca/une bible, par exemplehttp://donnees.ville.montreal.qc.ca/dataset/monuments

— https://www.data.gouv.fr/fr/datasets/population/ le format dbase est lisible par OO, norma-lement, ensuite “save as” pour sauver un CSV.

Imaginez un exercice à faire avec vos élèves avec du traitement de telles données.

Solution. LG : J’ai un jour généré des badges avec nom prénom affiliation. Je vous laisse trouver d’autrescas d’utilisation.

DIU-EIL Lyon1 - bloc1 https://diu-eil.univ-lyon1.fr/bloc1/index.html 39/39