Vous êtes sur la page 1sur 391

Avant-propos

Cet ouvrage, comme tous ceux de la collection Compétences


attendues, s'adresse aux élèves qui souhaitent travailler en
autonomie.

Il est découpé en chapitres qui suivent le programme


d'informatique de première. Chaque chapitre est structuré en quatre
grandes parties :
● le cours développé, précis avec des encadrés qui soulignent le
vocabulaire à connaître par cœur et les concepts à maîtriser ;
● les exercices classés par compétences attendues du
programme avec devant chaque énoncé la démarche
scientifique exigée ;
● des exercices de type EC ;
● les corrigés détaillés de tous les exercices avec les remarques
et conseils précieux, tirés de l'expérience de l'auteur,
professeur de lycée.

Au début du livre une introduction présente les grandes


compétences associées à l'enseignement en Numérique et Sciences
Informatiques (NSI). Un index permettra aux lecteurs de travailler
différemment en choisissant la compétence liée à la démarche
scientifique qu'il veut maîtriser.

Cet ouvrage a été conçu dans l'esprit des nouveaux programmes


avec la volonté de répondre aux grands enjeux de notre époque
imposés par les nouvelles technologies. Les grands thèmes retrouvés
lors des épreuves communes de NSI première au baccalauréat
structurent cet ouvrage, à savoir :
● Thème A : types de base
● Thème B : types construits
● Thème C : traitement de données en table
● Thème D : interactions entre l'homme et la machine
● Thème E : architectures matérielles et systèmes d'exploitation
● Thème F : langages et programmation
● Thème G : algorithmique

Ceux-ci ne sont pas nécessairement abordés dans cet ordre dans


un souci de progressivité dans la difficulté.

Nous espérons que cet ouvrage vous donnera entière


satisfaction.
Sommaire

Introduction
Les compétences en NSI

Thème A
Types de base
Chapitre 1
Premiers pas en Python
Chapitre 2
Représentation des nombres
Chapitre 3
Représentation d'un texte en machine

Thème B
Types construits
Chapitre 4
Les types de données construits

Thème F
Langage et programmation (1)
Chapitre 5
Les fonctions
Chapitre 6
Séquences conditionnelles et boucles

Thème G
Algorithmique
Chapitre 7
Recherche d'une valeur dans une liste
Chapitre 8
Les méthodes de tri de listes
Chapitre 9
Algorithme des k plus proches voisins
Chapitre 10
Algorithmes gloutons

Thème C
Traitement de donnéesen tables
Chapitre 11
Traitement de données en tables

Thème E
Architectures matérielles et systèmes d'exploitation
Chapitre 12
Architectures matérielles et systèmes d'exploitation

Thème D
Interactions entre l'homme et la machine sur le Web
Chapitre 13
Interactions entre l'homme et la machine sur le Web
Chapitre 14
Questionnaire à choix multiples type EC

Table des matières détaillée


Introduction
Les compétences en NSI

L'enseignement de spécialité de numérique et sciences


informatiques en première voie générale a pour objectif de poser les
fondements de l'informatique afin de se préparer à une poursuite
d'études dans l'enseignement supérieur.
Cet enseignement permet de développer les compétences
suivantes :
● analyser et modéliser un problème en termes de flux et de
traitement d'informations ;
● décomposer un problème en sous-problèmes, reconnaître des
situations déjà̀ analysées et réutiliser des solutions ;
● concevoir des solutions algorithmiques ;
● traduire un algorithme dans un langage de programmation, en
spécifier les interfaces et les interactions, comprendre et
réutiliser des codes sources existants, développer des
processus de mise au point et de validation de programmes ;
● mobiliser les concepts et les technologies utiles pour assurer
les fonctions d'acquisition, de mémorisation, de traitement et
de diffusion des informations ;
● développer des capacités d'abstraction et de généralisation.

1 Les compétences
A Analyser et modéliser un problème en termes de flux et de
traitement d'informations

Il s'agit d'appréhender les informations utiles à la résolution d'un


problème ainsi que leur origine et le moyen de les traiter. Puis de
mettre en œuvre les moyens afin de produire une solution au
problème.
Exemple : J'ai planté mon petit sapin de Noël, quelle taille
fera-t-il dans 10 ans ?

Conseils du professeur
Ne pas hésiter à prendre un papier brouillon et à y mettre quelques idées avant de
résoudre un problème sur ordinateur. Ceci vous fera gagner du temps par la suite.

B Décomposer un problème en sous-problèmes,


reconnaître des situations déjà analysées et réutiliser des
solutions
Un problème à résoudre peut être assez vaste au premier abord
et donc un peu déroutant. Une astuce consiste à décomposer le
problème en plusieurs sous-problèmes que l'on peut résoudre plus
facilement. On retombera souvent sur des problèmes déjà résolus par
le passé ou tout au moins sur des situations de départ similaires à
certaines vues par le passé.
Exemple :

Dans cet exemple, le problème a été simplifié afin de ne faire


figurer que trois sous-problèmes : rechercher des informations,
écrire un algorithme, le traduire en langage Python.

C Concevoir des solutions algorithmiques


Un algorithme est une méthode précise constituée d'une suite
d'instructions logiques (d'étapes) et permettant de résoudre un
problème. Il s'agit finalement d'une liste d'étapes à suivre pour
parvenir à une solution. C'est un peu comme une recette de cuisine
ou un protocole opératoire en laboratoire.
Remarque
Il existe bien souvent plusieurs algorithmes qui mènent à la même solution.
Exemple : D'après l'article « Étude de la croissance en
hauteur chez quelques résineux, effet de la température », G.
Aussenac (https://hal.archives-ouvertes.fr/hal-
00882112/document), on sait qu'un sapin d'espèce Picea (le plus
commun des sapins de Noël), pousse d'environ de c = 0,25 m
par an. Ceci donne lieu à l'algorithme suivant :
Initialiser a, l'âge actuel du sapin
Initialiser h, la hauteur actuelle du sapin
Initialiser c, la vitesse de croissance annuelle du sapin
Pour a allant de 1 à 10, faire :
Ajouter c à h
Afficher h

Remarque
Pour un Picea initialement de 1 m de haut, la solution est 3,5 m et sera développée
dans le chapitre sur les boucles for.

D Traduire un algorithme dans un langage de programmation,


en spécifier les interfaces et les interactions, comprendre
et réutiliser des codes sources existants, développer
des processus de mise au point et de validation de
programmes
Une fois l'algorithme écrit, il doit être traduit en une suite
d'instructions comprises par une machine, (comme un ordinateur,
ou une calculatrice). La machine sera alors à même d'effectuer les
calculs nécessaires qui mènent à la solution du problème étudié.
Cette étape de traduction s'intitule la programmation de
l'algorithme.
Une fois le programme écrit, il est essentiel de vérifier sa validité,
c'est-à-dire que le programme est correct et qu'il produit bien le
résultat attendu.

Conseils du professeur
Nous avons dit qu'il existe bien souvent plusieurs algorithmes qui mènent à la même
solution. Il en va de même pour leur programmation : il existe bien souvent plusieurs
façons de programmer un même algorithme. Aussi, lorsque vous écrirez des
programmes, il faudra bien garder en tête qu'il n'existe pas toujours de solution
unique à un même problème.

E Mobiliser les concepts et les technologies utiles


pour assurer les fonctions d'acquisition, de mémorisation,
de traitement et de diffusion des informations
Dans le monde actuel, la récolte, le stockage et la diffusion de
l'information est devenue une activité primordiale. Aussi, les
entreprises utilisent elles-mêmes des systèmes
d'information (appelés SI) qui sont justement des ensembles de
ressources qui permet de collecter, stocker, traiter et distribuer de
l'information, en général grâce à des ordinateurs.
Le programme de NSI ne requiert pas la connaissance d'un
système d'information en particulier mais plutôt la connaissance de
quelques technologies permettant l'acquisition, la mémorisation, le
traitement et la diffusion de données. Il faut savoir y faire appel à bon
escient.

F Développer des capacités d'abstraction et de généralisation


L'écriture d'algorithmes et de programmes informatiques vous
permettra de développer une forte capacité d'abstraction qui sera
répercutée sur votre capacité à résoudre un problème aussi bien en
mathématiques, qu'en physique, chimie, SVT, etc. Vous devrez en
effet bien souvent partir d'un problème très spécifique (comme la
recherche de la taille d'un sapin développée au début de ce chapitre)
et développer une résolution plus abstraite en modélisant les variables
par des lettres, les phénomènes par une formule mathématique
(comme ici la vitesse de croissance).

Conseils du professeur
Cette démarche d'abstraction vous sera bien utile en cours de physique-chimie où
vous devrez bien souvent tâcher de parvenir à une expression littérale plutôt que
d'effectuer votre raisonnement sur des valeurs numériques.
G Compétences transversales
Au cours de ce livre, diverses activités sont proposées, celles-ci
vous permettront de :
● faire preuve d'autonomie, d'initiative et de créativité́ ;
● présenter un problème ou sa solution, développer une
argumentation dans le cadre d'un débat ;
● coopérer au sein d'une équipe dans le cadre d'un projet ;
● rechercher de l'information, partager des ressources ;
● faire un usage responsable et critique de l'informatique.

2 Récapitulatif des exercices illustrant les


compétences

Compétences Exercices concernés

► Analyser ● Chap. 2 : 2.4, 2.5, 2.6


● Chap. 4 : 4.3, 4.4
● Chap. 5 : 5.1, 5.2
● Chap. 6 : 6.3, 6.11
● Chap. 7 : 7.1
● Chap. 8 : 8.1, 8.3
● Chap. 10 : 10.1, 10.2
● Chap. 12 : 12.1, 12.2, 12.7
● Chap. 13 : 13.2

► Décomposer ● Chap. 1 : 1.2


● Chap. 2 : 2.1, 2.2, 2.3
● Chap. 3 : 3.1, 3.2
● Chap. 4 : 4.1, 4.2
● Chap. 5 : 5.5, 5.6
● Chap. 6 : 6.11
● Chap. 11 : 11.3
● Chap. 12 : 12.5, 12.6

► Concevoir ● Chap. 1 : 1.1,1.3


● Chap. 6 : 6.1, 6.2, 6.10
● Chap. 8 : 8.1
● Chap. 9 : 9.1, 9.2
► Traduire ● Chap. 1 : 1.1,1.3
● Chap. 2 : 2.1, 2.2, 2.3, 2.5
● Chap. 3 : 3.2
● Chap. 5 : 5.3, 5.4, 5.5, 5.6, 5.7
● Chap. 6 : 6.2, 6.3, 6.4, 6.5, 6.6, 6.7, 6.10
● Chap. 7 : 7.1, 7.2
● Chap. 8 : 8.3
● Chap. 9 : 9.3, 9.4
● Chap. 10 : 10.1, 10.2
● Chap. 11 : 11.1, 11.2, 11.1,
● Chap. 13 : 13.1, 13.3

► Mobiliser ● Chap. 2 : 2.5


● Chap. 3 : 3.3
● Chap. 4 : 4.5
● Chap. 9 : 9.1, 9.2
● Chap. 12 : 12.1, 12.2, 12.3, 12.4
● Chap. 13 : 13.3, 13.4

► Développer ● Chap. 1 : 1.4, 1.5, 1.6


● Chap. 3 : 3.1
● Chap. 4 : 4.2
● Chap. 5 : 5.8
● Chap. 6 : 6.8, 6.9
● Chap. 7 : 7.2
● Chap. 9 : 9.3, 9.4
● Chap. 12 : 12.3, 12.7
Thème A
Types de base
Chapitre 1
Premiers pas en Python
Cours

Le programme de Numérique et Sciences Informatiques de première


voie générale stipule qu'un langage de programmation est
« nécessaire pour l'écriture des programmes : un langage simple
d'usage, interprété, concis, libre et gratuit, multiplateforme, largement
répandu, riche de bibliothèques adaptées et bénéficiant d'une vaste
communauté d'auteurs dans le monde éducatif. Au moment de la
conception de ce programme, le langage choisi est Python version 3
(ou supérieure). »
Ce même programme indique qu'il n'est pas question de devenir
un/une expert/e en Python. Quelques bases doivent néanmoins être
maîtrisées et seront exposées dans cet ouvrage. L'environnement de
développement en Python choisi dans ce livre est le logiciel gratuit
Pyzo.

1 Un peu d'histoire de Python


Python est un langage de programmation dit
interprété. Il a été développé en 1989 par Guido Von
Rossum, à l'Université d'Amsterdam. Guido Von
Rossum était un fan de la série Monthy Python's
Flying Circus d'où l'origine du nom de son langage de
programmation.
Vocabulaire à connaître
Un langage interprété (contrairement à un langage compilé) est retranscrit en langage
machine au fur et à mesure de son exécution via un interprète.

Python est devenu un langage de programmation généraliste très


utilisé autant dans l'industrie que dans le milieu académique et
scolaire. Certaines calculatrices proposent même ce langage
actuellement. De plus, il est très facile à apprendre, d'où ce choix pour
un enseignement au lycée. Python est un langage open source (libre
de droit et gratuit) développé et utilisé par une large communauté
d'utilisateurs. En 2020, la communauté de développeurs en Python
excédait celle développant sous Java pour environ huit millions
d'utilisateurs dans le monde !

2 L'environnement Pyzo

Les différentes fenêtres de Pyzo

Pyzo va permettre de saisir des programmes (ou scripts) plus ou


moins courts en langage Python et d'en visualiser les résultats. Tout
d'abord, il faut lancer le logiciel Pyzo : pour cela il suffit de double-
cliquer sur l'icône Pyzo (si Pyzo a bien été installé sur votre
ordinateur). Les fenêtres les plus utiles pour la suite sont :
● le shell (pour la saisie de scripts très courts et la visualisation de
résultats) ;
● l'éditeur (pour l'écriture de programmes plus ou moins longs que l'on
peut sauvegarder) ;
● le gestionnaire de fichiers (pour visualiser les fichiers de travail).
Premiers calculs dans le shell
Le shell de Pyzo 4 invite à saisir des instructions avec >>> (ou In[1]:
dans l'ancienne version du logiciel, à savoir Pyzo 3). On peut alors y
taper :
>>> 1+1

Puis taper sur la touche Enter du clavier. Dans ce cas, le shell renvoie
un nombre entier (aussi appelé integer, nous reviendrons là-dessus
plus loin dans ce chapitre) :
2

On peut aussi choisir d'effectuer un calcul, par exemple 23/3 :


>>> 23/3

Une fois la touche Entrée enfoncée, le shell renvoie un nombre réel


(appelé nombre flottant en Python) :
7.666666666666667

Les parenthèses s'emploient comme vous le feriez sur une


calculatrice. La commande 2*3+2 donne 8, là où la commande 2*
(3+2) donne 10.
Il faut savoir que le calcul d'une puissance est prioritaire sur les autres
opérations :
>>> 1+3**2

Le shell renvoie un nombre entier (aussi appelé integer) qui


correspond au résultat du calcul :
10

Premiers programmes dans l'éditeur


On peut commencer par taper dans l'éditeur :
1. a = 1
2. b = 2
3. print("Le calcul de a+b donne", a+b)

Remarque
Les numéros 1. à 3. sont ici générés automatiquement par l'éditeur Pyzo dans la colonne de
gauche (il ne faut pas les saisir à la main vous-même) et correspondent au numéro de
chaque ligne.

Vocabulaire à connaître
Dans ce programme, on effectue une affectation des variables a et b (cela signifie que l'on
stocke l'entier 1 dans la variable a, et 2 dans la variable b). On demande ensuite un
affichage du résultat grâce à la fonction print(). Le mot print est un mot réservé à Pyzo,
il s'affiche en bleu.
La phrase de commentaire "Le calcul de a+b donne" est appelée une chaîne de
caractères, elle s'affiche en bleu clair.

Une fois ces lignes tapées dans l'éditeur, on enregistre le programme


(aussi appelé script) créé sous le nom Calcul.py (par exemple) avant
de l'exécuter :
Remarque
À noter que .py est l'extension qui correspond à un fichier Pyzo.

Une fois le fichier enregistré, on peut exécuter le programme. Il existe


deux méthodes assez pratiques pour exécuter du code sous Pyzo. On
peut exécuter tout un fichier .py (raccourci clavier : Ctrl+E) ou bien
une partie d'un fichier : ce qui correspond à exécuter le l'onglet
courant ou exécuter la sélection.

Une fois le fichier Calcul.py enregistré, on peut vérifier qu'il figure bien
dans le répertoire …/Info par exemple :
Une bonne pratique en programmation est de commenter ses
programmes. Le programme Calcul.py agrémenté de commentaires
donne par exemple :
1. ###Mon premier programme
2. #Affectations
3. a = 1
4. b = 2
5.
6. #Calcul et affichage du résultat
7. print("Le calcul de a+b donne", a+b)

Remarque
Un commentaire est donc ajouté grâce à un ou plusieurs #. Aussi, tout ce qui suit un # sur
une même ligne, n'est pas exécuté par Pyzo et s'affiche en vert dans l'éditeur.

3 Quelques types de base : les integers et les


flottants
Les nombres en python peuvent être de différents types. Pour tester
le type d'un nombre ou d'une variable, il suffit d'utiliser la commande
type( ).

Les integers
On se place dans le shell (pour plus de simplicité) et on tape par
exemple :
>>> type(3)

Le shell renvoie 'int' pour integer (nombre entier en anglais) :


<class 'int'>

Remarque
On obtient le même résultat avec :
>>> type(-3)

Donc les entiers naturels et entiers relatifs sont des integers en


Python.
Les flottants
On peut aussi tester le type d'un nombre réel ou le type du résultat
d'un calcul qui donne lieu à un nombre réel :
>>> type(3.0)
>>> type(20/3)

Ces deux instructions renvoient chacune dans le shell le type flottant


(float) qui correspond à un nombre réel :
<class 'float'>

4 La bibliothèque math et ses fonctions


La bibliothèque math contient des nombres préenregistrés comme le
nombre mais aussi des fonctions comme les fonctions
trigonométriques (celles-ci seront définies et développées en classe
de Terminale).
En mathématique En Python

exp(x) exp(x)

ln(x) ln(x)

sin(x) sin(x)

cos(x) cos(x)

π pi

√x sqrt(x)

Cette bibliothèque peut être utilisée dans le shell mais l'utilisation de


l'éditeur est plus simple dans le cadre de l'écriture d'un programme.
Pour cela, on peut d'abord importer les fonctions (et nombres)
souhaités de la bibliothèque math. On tape par exemple dans
l'éditeur :
1. ###Fonctions mathématiques de la bibliothèque math
2. from math import cos, pi #on importe la fonction cosinus et le
nombre pi exclusivement
3. print("cos(pi/2) =",cos(pi/2))

On exécute ce programme avec Ctrl+E (par exemple) et ceci donne


dans le shell :
cos(pi/2) = 6.123233995736766e-17

Remarque
Le résultat du calcul donne en réalité 0 sur votre calculatrice. Ceci nous permet de
faire remarquer que la manipulation de nombres flottants entraîne une erreur numérique (ici
l'ordre de grandeur de l'erreur est ). Il faudra en tenir compte par la suite. Par
exemple, si on compare le résultat du calcul de à 0 avec :

4. cos(pi/2) == 0 # == est un test de comparaison

On obtient dans le shell :


False

Pyzo indique que le résultat de cette comparaison semble faux et que , ce qui n'a
pas de sens d'un point de vue mathématique.

5 Les variables en Python

Affectation d'une ou plusieurs variables

Dans le programme Calcul.py, on a créé deux variables a et b et donc


déclaré a et b. Pour cela, à chacune de ces variables, on a affecté une
valeur.
1. a = 1
2. b = 2

Remarque
L'affectation d'une variable peut être effectuée dans le shell ou dans l'éditeur.

Vocabulaire à connaître
On parle de déclaration de variable lorsque celle-ci apparaît pour la première fois dans un
programme et qu'une valeur lui est affectée.

Pour déclarer deux variables a et b en une seule ligne, on peut taper :


>>> a,b = 1,2

La valeur 1 est affectée à la variable a et la valeur 2 est affectée à la


variable b. Ou bien si les variables doivent être égales, on peut taper :
>>> a,b = 2

La valeur 2 est alors affectée à chacune des deux variables a et b.


Conseil
Attention à ne pas confondre l'affectation = avec ==.

1. #Une affectation de variable :


2. a = 1
3. #Une comparaison de valeur :
4. a == 1

On peut aussi déclarer une variable en lui affectant un nombre écrit en


notation scientifique. Par exemple si :
>>> c = 1.2E-3

Ou encore :
>>> c = 1.2e-3

Remarque
La virgule se note . en Python.

Mots réservés et caractères à éviter


Attention à ne pas utiliser un mot réservé pour le nom d'une variable :
1. lambda = 1 #lambda apparaît en bleu contrairement à a et b
précédemment
2. print(lambda)

Si on exécute ce programme, la tentative d'affectation de lambda (lambda


est un mot réservé) renvoie un message d'erreur dans le shell :
SyntaxError: invalid syntax

Quelques mots réservés en Python :


and, as, assert, break, class, continue, def, del, elif, else, except,
exec, finally, for, from, global, if, import, in, is, lambda, not, or,
pass, print, raise, return, try, while, with, yield

Conseil
Pour le nom d'une variable on peut utiliser des lettres, des _ mais pas des -, des (),
des *, ni des '. On peut aussi utiliser des nombres dès lors qu'ils suivent une lettre ou
un _.

1. a' = 1 #interdit
2. a_prim = 1 #OK
3. a-1 = 1 #interdit
4. a_-1 = 1 #interdit
5. a_moins1 = 1 #OK

Modification du contenu d'une variable


Pour multiplier par 2 le contenu de la variable a, on peut taper :
>>> a = 2*a #a multiplié par 2

>>> a *= 2 #a multiplié par 2

Remarque
La syntaxe *= est propre à Python. L'équivalent existe pour une somme, une division, une
soustraction etc. Exemples :
>>> a += 2 #on ajoute 2 à a

>>> a /= 2 #on divise a par 2

>>> a -= 2 #on soustraie 2 à a

Permutation de deux variables


Python permet la permutation du contenu affecté à deux variables de
manière très aisée.
1. a = 1 #a vaut 1
2. print("a vaut :",a)
3. b = 2 #b vaut 2
4. print("b vaut :",b)
5. a,b = b,a #permutation
6. print("a vaut :",a,", b vaut :",b)
Après exécution, l'affichage dans le shell permet de vérifier la
permutation effectuée :
a vaut : 1
b vaut : 2
a vaut : 2 , b vaut : 1

6 Un autre type de base : les booléens

Valeurs booléennes : True et False

Un booléen est une variable qui peut prendre deux états : soit l'état
vrai (True) qui correspond à 1, soit l'état faux (False) qui correspond à
0. L'intérêt des booléens en informatique est qu'ils permettent de
tester si une expression logique est vraie ou fausse.
Pour s'exercer sur quelques tests, on affecte tout d'abord les valeurs
ci-dessous à trois variables a, b, c dans le shell :
>>> a,b,c = 4,2,1

On se doute alors que : le test a<b sera faux, le test b>c sera vrai. Dans
un script Python, lorsque l'on essaie de déterminer si une expression
logique est vraie ou fausse, le shell renvoie un booléen : le booléen
True si l'expression est vraie et le booléen False si l'expression est
fausse. Il suffit de taper les lignes suivantes dans le shell pour le
vérifier :
>>> a<b

>>> b>c

On peut continuer à s'entraîner en tapant les instructions de la


première colonne du tableau ci-dessous et vérifier le résultat
qu'indique le shell :
Instruction Python Signification Résultat

a==b a est égal à b False

a>b a est strictement supérieur à b True


a<b a est strictement inferieur à b False

a>=b a est supérieur ou égal à b True

a<=b a est inférieur ou égal à b False

a!=b a est différent de b True

a<b and b>c a est inférieur à b ET b est supérieur à c False

a<b or b>c a est inférieur à b OU b est supérieur à c True

a<b ^ b>c a est inférieur à b « ou exclusif » b est supérieur à c False

not(True) Le contraire de True False

not(False) Le contraire de False True

Vocabulaire à connaître
Chaque test (en colonne de gauche) correspond à une expression booléenne.
Les mots and, or et not sont appelés des opérateurs booléens.

Table de l'expression booléenne : a and b


Dans le shell, si l'on tape l'expression True and True, c'est tout à fait
équivalent à taper 1 and 1 : le résultat obtenu est True. On obtiendra un
résultat identique en tapant l'expression booléenne :
>>> 2>1 and 3 != 0 #True and True

Ainsi le shell affichera True.


On peut établir la table de l'expression booléenne a and b en effectuant
plusieurs tests successifs comme :
>>> 0 and 0
0
>>> 0 and 1
0
>>> 1 and 0
0
>>> 1 and 1
1

Ceci se résume dans la table :


Table d'une expression : a and b (ET)

a b a and b

0 0 0

0 1 0

1 0 0

1 1 1

Table de l'expression booléenne : a or b


Si l'on tape l'expression booléenne :
>>> 2>1 or 3 != 0 #True or True

Le shell affichera aussi True.


Comme on l'a fait pour la table du and, si on effectue divers tests avec
l'opérateur or (tels que 0 or 0, 0 or 1 etc.), on peut établir la table de
l'expression a or b :
Table d'une expression : a or b (OU)

a b a or b

0 0 0

0 1 1

1 0 1

1 1 1

Table de l'expression booléenne : a xor b


À noter qu'il existe aussi un opérateur booléen appelé « ou exclusif »
appelé xor et noté ^ en Python :
>>> 1 ^ 0 #True

Le résultat d'un test a ^ b ne sera vrai que si seulement un des deux


(a,b) n'est vrai.
Table d'une expression : a ^ b (xor càd OU exclusif)

a b a xor b

0 0 0

0 1 1
1 0 1

1 1 0
Exercices

Compétence attendue

➡ Définir une variable et la manipuler en Python.


➡ Afficher le résultat d'un programme écrit en Python.

Exercice 1.1
► Concevoir, traduire

➡ Écrire un programme dans l'éditeur :


● qui affecte un nombre à une variable x
● qui ajoute 7 au triple du nombre donné
● qui multiplie le résultat par le nombre donné
● qui soustrait au résultat le nombre donné
● qui affiche le résultat obtenu et le type du résultat obtenu.
On tachera de créer un minimum de variables. Appliquer le
programme à un nombre entier puis à un nombre réel.

Exercice 1.2
► Concevoir, traduire, décomposer

Vous avez vu dans le cours de seconde comment évaluer l'intensité


de la pesanteur g selon l'altitude à laquelle on se situe h. Pour cela on
rappelle que :
Avec :
● RTerre = 6 371 km
● G = 6,67 × 10−11 USI
● mTerre = 6,0 × 1024 kg
➡ Écrire un script Python dans l'éditeur qui permet d'évaluer la
constante g à une altitude de 1 m. L'exécuter et afficher le résultat
de manière conviviale (c'est-à-dire avec un peu de texte puis le
résultat suivi de son unité SI).
Indiquer le type du résultat obtenu.

Compétence attendue

➡ Utiliser une bibliothèque.

Exercice 1.3
► Concevoir, traduire

Soit un angle dont la mesure en degrés est connue avec une


précision de 1°.
➡ Écrire un script (donc un court programme dans l'éditeur) qui
réalise les opérations suivantes :
● Affecter une valeur de mesure d'angle en degrés à la variable
deg.
● Convertir cet angle en radians et stocker cette grandeur dans
une variable rad.
● Calculer le sinus et le cosinus de rad et afficher le résultat de ces
deux calculs de manière conviviale (c'est-à-dire avec un peu de
texte puis les résultats).
Compétence attendue

➡ Manipuler des booléens.

Exercice 1.4
► Développer

L'image suivante peut être codée en binaire grâce à des 0 et des 1.

➡ Compléter son codage à l'aide des booléens 0 et 1 :


1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1

1 1 0 0 1 0 0 1 1
1 1 1 0 0 0 1 1 1

1 1 1 1 1 1 1 1 1

Compétence attendue

➡ Savoir interpréter une expression booléenne.

Exercice 1.5
► Développer

➡ Dessiner la forme définie à l'aide des expressions booléennes ci-


dessous (un 1 donne une case noire, un 0 une case blanche) :
1 1 1 1 1 1 1 1 1

1 or 1 or 1 or 0 and 1 or
1 and 1 0 and 0 1 or 1 1 or 1
1 1 1 0 1

1 and 1 or 0 and 1 or 0 and 1 or 1 and 1 or


0 0 1 0 0
1 0 0 0

1 and 1 or 0 and 1 or 0 and 1 or 1 and 1 or


0 0 0 0 0
1 0 0 0

1 and 1 or 0 and 1 or 0 and 1 or 1 and 1 or


0 0 0 0 0
1 0 0 0

0 xor 0 xor
1 1 0 0 0 1 1
1 1

1 1 1 0 0 0 1 1 1

1 xor
1 1 1 1 1 1 1 1
1

1 1 1 1 1 1 1 1 1

Compétence attendue

➡ Savoir effectuer une addition binaire.


Exercice 1.6
► Développer

On définit la table d'addition :


+ 0 1

0 0 1

1 1 10

Pour le calcul de 1 + 1 qui donne 10 : on pose 0, on retient 1.


➡ À l'aide de cette table, effectuer les opérations binaires :
● 11 + 100 puis
● 10101 + 11 et
● 101 + 111.
Exercices de type EC - QCM

Pour chaque question, le candidat gagne 3 points s'il choisit la bonne


réponse, perd 1 point s'il choisit une réponse fausse. S'il ne répond
pas ou choisit plusieurs réponses, il ne gagne ni ne perd aucun point.

Exercice EC 1.1
1 min ● 3 points
Choisir parmi les quatre expressions suivantes celle(s) qui donneront
True :

Réponses :
a) True and (True and True)
b) True and (True and False)
c) True and (False and True)
d) True or (True and False)

Exercice EC 1.2
1 min ● 3 points
On impose :
1. a = 1
2. b = 4

Choisir parmi les quatre expressions suivantes celle(s) qui donneront


True :

Réponses :
a) a>2 and b>a
b) a>2 and b<a
c) a<2 and b>a
d) a<2 or b<a
Corrigé des exercices

Exercice 1.1

Pour un nombre entier (integer) x = 5 :


1. ###Ex1.1
2. x = 5
3. y = 7 + 3*x
4. y = y*x
5. y = y-x
6. print("le résultat est :",y)
7. print("Le type du résultat est :",type(y))

Le shell affiche après exécution :


Le résultat est : 105
Le type du résultat est : <class 'int'>

Pour un nombre réel (flottant) x = 5.1 :


1. x = 5.1
2. y = 7 + 3*x
3. y = y*x
4. y = y-x
5. print("Le résultat est :",y)
6. print("Le type du résultat est :",type(y))

Le shell affiche après exécution :


Le résultat est : 108.62999999999998
Le type du résultat est : <class 'float'>

Exercice 1.2

On déclare les variables et on exécute le programme.


1. ###Ex 1.2
2. R_Terre = 6371E3 #en m
3. G = 6.67E-11 #USI
4. m_Terre = 6.0E24 #kg
5. h = 1 #m
6.
7. g = G*m_Terre/(R_Terre+h)**2
8. print("La valeur de g est :",g, "m/s^2")
9. print("Le type du résultat est :",type(g))

Erreurs à éviter
Ne pas oublier les . pour la virgule d'un flottant.

Le shell affiche un résultat de type flottant proche de 9,81 m.s–2 après


exécution :
La valeur de g est : 9.859655431992135 m/s^2
Le type du résultat est : <class 'float'>

Exercice 1.3

Dans l'éditeur, il faut importer les fonctions cos et sin ainsi que le
nombre π de la bibliothèque math. On se rappelle la conversion
d'unité radian à degré avec :
1 radian = degré

1. ###Ex 1.3
2. from math import pi, cos, sin
3. deg = 90 # deg est un entier
4. rad = deg*pi/180 #rad sera un réel
5. # python utilise automatiquement le type approprié pour rad qui
est un réel (float)
6. print("La conversion de cet angle en radians donne :", rad)
7. print("cos(",rad,") = ",cos(rad))
8. print("sin(",rad,") = ",sin(rad))

Le shell affiche après exécution :


La conversion de cet angle en radians donne : 1.5707963267948966
cos( 1.5707963267948966 ) = 6.123233995736766e-17
sin( 1.5707963267948966 ) = 1.0
Exercice 1.4

1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1

1 1 0 0 1 0 0 1 1

1 1 0 0 1 0 0 1 1

1 1 1 1 1 1 1 1 1

1 0 0 1 1 1 0 0 1

1 1 0 1 1 1 0 1 1

1 1 1 0 0 0 1 1 1

1 1 1 1 1 1 1 1 1

Exercice 1.5

Exercice 1.5
On obtient :
● 111 puis
● 11000
● 1100

Erreurs à éviter
Ne pas oublier la retenue pour les deux dernières additions.
Corrigé des exercices de type EC -
QCM

Exercice EC 1.1

a) True and (True and True)


b) True and (True and False)
c) True and (False and True)
d) True or (True and False)

Exercice EC 1.2

a) a>2 and b>a


b) a>2 and b<a
c) a<2 and b>a
d) a<2 or b<a
Chapitre 2
Représentation des nombres
Cours

1 Écriture d'un entier positif


dans une base b ≥ 2

Les bases

Il existe plusieurs bases pour écrire les nombres. Seules la base 2, la


base 10 et la base 16 seront présentées dans ce chapitre.
Pour exprimer un nombre n dans une base b, il suffit de l'écrire
comme suit :
Soit b un entier supérieur ou égal à 2, pour tout entier n , il
existe p et des entiers compris entre 0 et tels
que :

Base 10 :
La notation des nombres en base 10 est celle que l'on utilise tous les
jours en calcul. C'est en effet la plus simple à manipuler :
signifie «135 en base 10 » et se traduit par :

Base 2 :
La notation des nombres en base 2 est très importante car elle permet
de comprendre comment sont codés les nombres dans un ordinateur.
signifie « 1011 en base 2 » et se traduit par :

Base 16 :
La notation des nombres en base 16 est également utilisée en
informatique notamment pour représenter des niveaux de canaux de
couleur.
signifie « 111 en base 16 » et se traduit par :

Passage d'un nombre de la base 10 à la base 2 (écriture binaire)

► Méthode
On divise par 2 le nombre donné, on note le quotient et le reste qui
est 0 ou 1. Puis on divise par 2 le quotient, on note le reste (0 ou 1),
etc. On s'arrête une fois que le quotient devient 0.
Exemple : écriture en base 2 du nombre 135.
➟ On divise 135 par 2, on obtient 67, il reste 1.
➟ On divise 67 par 2, on obtient 33, il reste 1.
➟…
➟ On divise 1 par 2, on obtient 0, il reste 1. On s'arrête car le
quotient est devenu 0.
► Méthode
On déroule ensuite les restes (entourés d'une bulle dans la figure
précédente) de droite à gauche. Les restes sont : 1, puis 0, puis 0,
puis 0, 0, 1, 1, 1.
Résultat : (135)10 en base 2 se note (10000111)2. (135)10 peut
alors se retrouver avec le calcul suivant :

2 Représentation binaire d'un entier relatif

Un peu d'histoire des nombres

Que ce soient des images, des vidéos, des fichiers de traitement de


texte, des nombres, toute donnée stockée sur un ordinateur ou
transmise vers un ordinateur ne l'est que par l'intermédiaire de circuits
électroniques (transistors) ne pouvant se trouver que sous deux
états : sous tension (on note cela l'état 1) ou hors tension (on note
cela l'état 0).
En 1970, le premier microprocesseur (Intel 4004) commercialisé
comptait environ 2000 transistors, en 2018, le microprocesseur Intel
Core i7 (destiné au grand public) en compte 2,3 milliards !
Cette unité de stockage est appelée bit, qui peut prendre les valeurs
conventionnelles 0 ou 1. Ainsi, toute action informatique est une suite
d'opérations sur des paquets de 0 et de 1, regroupés par huit : les
octets. Les processeurs récents sont des processeurs 32 bits ou 64
bits qui disposent de 32 ou 64 bits pour stocker un nombre.
Pour cela les entiers relatifs positifs seront codés en appliquant la
décomposition en binaire vue dans la partie précédente. Les entiers
relatifs négatifs ou entiers signés seront codés grâce à la méthode du
complément à deux développée plus loin dans le chapitre.

Notion de bit de signe


On représente les entiers relatifs sur n bits. On appelle bit de signe, le
premier bit de la représentation binaire d'un entier relatif. La valeur 0
est réservée aux entiers relatifs positifs, la valeur 1 aux entiers relatifs
négatifs. Les entiers relatifs seront donc représentés de la sorte par le
processeur :
0 : Entier relatif positif

1 : Entier relatif négatif

Pour rappel, en Python, le type des entiers relatifs positifs ou négatifs


est integer (int) ce qui signifie entier en français.

Écriture d'un entier positif en binaire sur n bits

► Méthode
On utilise l'écriture en binaire vue en début de ce chapitre. Si le
nombre de bits obtenu est inférieur à n, on rajoute des 0 pour
parvenir à n bits. S'il n'y a pas assez de bits disponibles, on dit que
la capacité d'écriture est insuffisante (on parle d'overflow).
Exemple : écriture en binaire du nombre (135)10 sur n bits.
On a trouvé son écriture en binaire : (10000111)2.
Lorsque c'est possible, on ajoute des 0 pour aller jusqu'à n bits :
Entier Sur 4 bits Sur 8 bits Sur 16 bits Sur 32 bits

135 overflow 10000111 0000000010000111 00000000000000000000000010000111

Donc il est impossible de coder (135)10 sur 4 bits : il y a un


problème d'overflow. Il faut un minimum de 8 bits pour coder
(135)10.

Somme et produit de deux nombres binaires


Voici la table d'addition binaire déjà vue dans le chapitre précédent :
+ 0 1
0 0 1
1 1 10

Aussi pour sommer deux nombres codés en binaire, il suffit


d'additionner les 1 ou les 0 un à un, en démarrant par la droite.
Exemple : (135)10 + (100)10 ce qui donne en binaire :
(10000111)2 + (1100100)2, soit :
1 0 0 0 0 1 1 1

+ 1 1 0 0 1 0 0

= 1 1 1 0 1 0 1 1

Ce qui une fois repassé en base 10 donne (235)10 : c'est logique !


Donc l'écriture du résultat de l'addition nécessite 8 bits (soit un
octet, au même titre que l'écriture en binaire du nombre (135)10 ).
Conseils
Attention à l'overflow ! L'addition (135)10 + (135)10 donne (270)10, soit en binaire
(100001110)2. Si on ne dispose que de 8 bits (un octet), cela ne suffit pas. Il y a donc
dépassement de capacité (donc overflow).

Voici la table de multiplication binaire :


× 0 1
0 0 0
1 0 1

Pour multiplier deux nombres codés en binaire, il suffit de procéder


comme en base dix et de décaler d'un rang quand on change de bit
du multiplicateur.
Exemple : (6)10 × (3)10 ce qui donne en binaire
(110)2 × (11)2
0 0 1 1 0

× 0 0 0 1 1

Soit 1 × (110)2 puis on décale d'un rang et on effectue encore


1 × (110)2 :
0 0 1 1 0

+ 0 1 1 0

= 1 0 0 1 0

Ce qui repassé en base 10 donne (18)10 : on ne s'est donc pas


trompé.
L'écriture du résultat de la multiplication nécessite 5 bits donc un
octet.

Erreur à éviter
Ne pas oublier la retenue lorsque l'on effectue la somme en binaire de 1 + 1.

Écriture d'un entier négatif en binaire sur n bits


(méthode du complément à deux)

► Méthode
➟ On inverse les bits de l'écriture binaire de sa valeur absolue, on
fait ce qu'on appelle le complément à un ;
➟ On ajoute 1 (donc (00000001)2 sur 8 bits) au résultat.
Exemple : Représentation binaire de (–8)10 sur 8 bits.
➟ On écrit en binaire (+8)10 : cela donne (0000 1000)2. On inverse
les 1 et les 0 : (1111 0111)2 ;
➟ On ajoute 1 au résultat en tenant compte des retenues (c'est-à-
dire que 1 + 1 donne 10) :
(11110111)2 + (00000001)2 = (11111000)2.

3 Représentation en base hexadécimale

Codage en base 16

On a développé le codage des entiers en binaire (donc en base 2). La


base 16 est aussi communément utilisée, notamment pour le codage
des entiers longs.
Pour cela en plus de l'utilisation des chiffres 0,1, …, 9, on ajoute les
lettres A, B, C, D, E, F.
Ce qui donne un tableau d'équivalence entre les bases décimale,
binaire et hexadécimale :
Base décimale 0 1 2 3 4 5 6 7

Base hexadécimale 0 1 2 3 4 5 6 7

Base binaire 0000 0001 0010 0011 0100 0101 0110 0111

Base décimale 8 9 10 11 12 13 14 15

Base hexadécimale 8 9 A B C D E F

Base binaire 1000 1001 1010 1011 1100 1101 1110 1111

Exemples : On souhaite représenter le nombre 26 en base 16


cela donne :
Le nombre (en base 16) vaut en base 10 :

Conversion d'un octet en base hexadécimale


Pour convertir un octet (écrit en binaire) en base hexadécimale, il
suffit de partager cet octet en deux groupes de 4 bits. Puis chaque
groupe correspond à un chiffre ou une lettre en hexadécimal.
Exemple :

On se rend compte que l'écriture en base hexadécimale est bien


plus compacte qu'en binaire.

4 Représentation approximative des nombres réels

Écriture à virgule flottante

On peut par analogie avec les nombres décimaux (comme 3,3125),


écrire un nombre à virgule en notation binaire en utilisant les
puissances négatives de 2 :

Il devient vite compliqué d'utiliser cette méthode pour les très petits ou
très grands nombres comme le nombre d'Avogadro par exemple : Na
= 6,022.1023 mol–1.
On utilise pour cela la notation scientifique d'un nombre décimal x qui
consiste à préciser son signe s (+ ou –), à déterminer un nombre
décimal m (appelé mantisse de x) et un entier relatif n (appelé
exposant de x), soit :
x = s m.10n
Exemple :

Vocabulaire à connaître
Cette écriture est appelée virgule flottante. En effet, la virgule peut flotter de gauche à
droite : on peut la placer là où on le souhaite.

Nombres à virgule flottante : les flottants


Il reste à adapter cette méthode à la base 2, ce qui est défini dans la
norme IEEE-754. Tout nombre réel peut-être représenté sous la
forme :

Où s correspond au signe de x, m (la mantisse) est un réel de


l'intervalle , n un entier relatif tel que avec N le
niveau de précision de la machine (32 ou 64 bits sur les machines
modernes).
Cette norme définit les points suivants :
Encodage Signe s n Mantisse m Valeur x

32 bits 1 bit 8 bits 23 bits (−1)sm2(n−127)

64 bits 1 bit 11 bits 52 bits (−1)sm2(n−1023)


Donc sur 32 bits :

Le premier bit de la mantisse d'un nombre normalisé est forcément 1,


il n'est pas nécessaire de le représenter.
Concept logique
Par convention, on considère qu'un nombre vaut zéro si tous les bits de son exposant et de
sa mantisse sont nuls.

Concept logique
Les valeurs extrêmes (0 et 2N − 1) de l'exposant sont réservées pour zéro et les infinis (en
Python NaN = Not a Number).

Exemple : on souhaite savoir à quoi correspond le nombre ci-


dessous codé en 32 bits.

● Le premier 1 représente s = 1, le signe sera (−1)1 donc −


● 0100 0110 : c'est le n de l'exposant, n = 26 + 22 + 21 = 70 d'où E
= n − 127 = 70 − 127 = −57
● 1001 0000 0000 0000 0000 000 : est la mantisse m et vaut :

m
● Le nombre codé vaut en base 10 :
x = −1,5625.2−57 ≈ 1,0842.10−17
C'est une représentation approximative.

Erreurs à éviter
Ne pas oublier le bit implicite.

Exemple :
● Le premier 0 représente s = 0, le signe sera (−1)0 donc +
● 01111100 : n = 26 + 25 + 24 + 23 + 22 = 124 ; E = 124 − 127 = −3
● 0100 0000 0000 0000 0000 000 :

● Le nombre codé vaut en base 10 :

C'est une représentation exacte.

Dépassement de capacité
Les nombres à virgule flottante sont définis sur un nombre fini de bits,
il y a donc forcément un nombre maximal représentable dans ce
format.
Notamment, en 64 bits, on ne peut pas utiliser un exposant supérieur
à 1023 (211 − 1) sinon on obtient à nouveau un dépassement de
capacité (overflow).

Arrondis et conséquence
On note également que rares sont les nombres décimaux
représentables exactement en virgule flottante.
Vocabulaire à connaître
La représentation des nombres réels, donc des flottants, est dite souvent approximative.

La principale conséquence de ces arrondis est que la notion d'égalité


en virgule flottante n'a bien souvent pas de sens. Si on souhaite
comparer deux flottants a et b, on ne pourra pas utiliser la syntaxe
Python :
>>> a == b

Exemple :
>>> 0.1 + 0.2 - 0.3 == 0.0

Le shell renvoie False, ce qui n'a pas de sens ! Il faut plutôt effectuer
un test du type │a − b│< ε où ε est une valeur proche de zéro à
définir :
1. x = 0.1 + 0.2 - 0.3
2. y = 0.0
3. eps = 1E-5 #définition de la précision à 0.00001 près
4. print(abs(x - y)< eps) #test adapté aux flottants

Le shell renvoie True, ce qui est plus logique à présent.


Exercices

Compétence attendue

➡ Passer de la représentation d'une base dans une autre.

Exercice 2.1
► Traduire, décomposer

Écrire en binaire l'entier (300)10, détailler les étapes de calcul.


Convertir aussi en base 2 les nombres : (42)10, (137)10.
Dans chaque cas, on indiquera le nombre de bits nécessaires au
codage.
➡ Convertir ces trois entiers en base hexadécimale.

Exercice 2.2
► Traduire, décomposer

Écrire un script Python permettant de convertir en base 10 les


nombres suivants écrits en base 2 :
(10011101)2, (11010001)2, (10111111)2.

Compétence attendue

➡ Utiliser le complément à 2.
Exercice 2.3
► Traduire, décomposer

Coder, sur 8 bits, en complément à deux les entiers relatifs : (−121) 10


et (−100)10.

Compétence attendue

➡ Évaluer le nombre de bits nécessaires à l'écriture en base 2 d'un entier, de la


somme ou du produit de deux nombres entiers.

Exercice 2.4
► Analyser

Donner le résultat des opérations binaires suivantes ainsi que le


nombre de bits nécessaires au codage du résultat en binaire :
a) (1101)2 + (111)2

b) (1101)2 × (111)2
c) (1111)2 + (10)2

Compétence attendue

➡ Décoder quelques nombres réels écrits en norme IEEE-754.

Exercice 2.5
► Analyser, mobiliser

On a découvert un parchemin sur lequel sont inscrites trois suites de 0


et de 1 (chaque suite contient 32 valeurs). On sait que ce sont des
nombres… Mais, tachez de décoder ce qu'ils peuvent bien vouloir
représenter :
a) 0 0111101 11001100 11001100 11001101
b) 0 0111110 10101010 10101010 10101011
c) 0 0111110 10000000 00000000 00000000

Compétence attendue

➡ Savoir comparer des nombres flottants.

Exercice 2.6
► Analyser, traduire

Écrire un script python qui permet de comparer à zéro de


manière correcte : c'est-à-dire que le test doit renvoyer True.
Exercices de type EC - QCM

Pour chaque question, le candidat gagne 3 points s'il choisit la bonne


réponse, perd 1 point s'il choisit une réponse fausse. S'il ne répond
pas ou choisit plusieurs réponses, il ne gagne ni ne perd aucun point.

Exercice EC 2.1
5 min ● 18 points
Convertir en base décimale les nombres binaires suivants :
a) (1110)2

□ 3 □ 14 □ 7 □ 9
b) (00101100)2

□ 22 □ 33 □ 44 □ 7
Convertir en binaire les nombres décimaux suivants :
c) (135)10

□ (10000111)2 □ (11100001)2 □ (111000010)2


d) (300)10
□ (001101001)2 □ (110010110)2 □ (100101100)2
Convertir en binaire sur 8 bits, les nombres décimaux suivants :
e) (−57)10

□ (11000111)2 □ (11100011)2 □ (00111000)2


f) (−1)10
□ (11111111)2 □ (10000000)2 □ (01111111)2
Exercice EC 2.2
2 min ● 3 points
Ce vieux coffre-fort s'ouvre à l'aide du code secret à
trois chiffres (en base 10) suivant, à vous de trouver
le code !

(011)2 (010)2 + (01)2 (10)2 × (01)2

Réponses :
a) 12
b) 15
c) 332
d) 116

Exercice EC 2.3
1 min ● 3 points
Quelle méthode utiliser pour effectuer le codage binaire d'un
entier négatif ?
Réponses :
a) Le codage hexadécimal
b) Le codage flottant
c) La méthode du complément à deux
d) La méthode IEE-754

Exercice EC 2.4
1 min ● 3 points
On s'intéresse à l'égalité d'un calcul par rapport à zéro. On tape
d'abord :
1. from math import sin, pi
2. a = sin(2*pi)
3. eps=1E-5

Quelle(s) expression(s) affichent True ?


Réponses :
a) print(abs(a-0)==0)
b) print(abs(a-0) != 0)
c) print(abs(a-0)<eps)
d) print(abs(a-0)>eps)

Exercice EC 2.5
1 min ● 3 points
Un entier n est codé grâce à la méthode du complément à deux et
donne :
(0000 0010)2. Quelle est la représentation binaire de -n ?
Réponses :
a) (0000 0110)2

b) (0000 1110)2
c) (1111 1101)2
d) (1111 1110)2

Exercice EC 2.6
1 min ● 3 points
Comment s'écrit en base 16 (en hexadécimal) le nombre dont
l'écriture binaire est (0101 0101)2 ?
Réponses :
a) 55
b) 155
c) 77
d) 88
Exercice EC 2.7
1 min ● 3 points
Comment s'écrit en base 2 (en binaire) le nombre dont l'écriture en
base hexadécimale est (D21)2 ?
Réponses :
a) (1111 0100 1001)2

b) (1101 0010 0001)2


c) (1101 0110 0001)2
d) (1101 1010 0001)2
Corrigé des exercices

Exercice 2.1

► Pour (300)10, on obtient la décomposition :


On divise 300 par 2, on obtient 150, il reste 0.
On divise 150 par 2, on obtient 75, il reste 0.

On divise 1 par 2, on obtient 0, il reste 1. On s'arrête car le quotient
est devenu 0.

On déroule ensuite les restes de droite à gauche. À savoir : 1 puis 0


puis 0, 1, 0, 1, 1, 0, 0 :
(300)10 = (100101100)2
On vérifie notre résultat :
1 × 28 + 0 × 27 + 0 × 26 + 1 × 25 + 0 × 24 + 1 × 23 + 1 × 22
+ 0 × 21 + 0 × 20 = (300)10
Il faut donc au minimum 9 bits pour écrire (300)10 en base 2.
En base hexadécimale cela donne : (12C)16.
► Pour (42)10, on obtient la décomposition :
42 = (101010)2

Il faut donc au minimum 6 bits pour écrire (42)10 en base 2.


En base hexadécimale cela donne : (2A)16.
► Pour (137)10, on obtient la décomposition :
137 = (10001001)2

Il faut donc au minimum 8 bits pour écrire (137)10 en base 2.


En base hexadécimale cela donne : (89)16.

Exercice 2.2

On utilise la formule : n = (a0a1…ai…ap)b = aPbp + … + aibi + … + a0b0.

On choisit de se servir de Pyzo comme calculatrice et de taper dans


l'éditeur les commandes suivantes et de les exécuter :
1. # 1001 1101 = 2**7+2**4+2**3+2**2+2**0
2. print ("Le nombre en base 10 est :",2**7+2**4+2**3+2**2+2**0)

Le shell affiche alors :


Le nombre en base 10 est : 157
1. # 1101 0001 = 2**7+2**6+2**4+2**0
2. print ("Le nombre en base 10 est :",2**7+2**6+2**4+2**0)

Le shell affiche alors :


Le nombre en base 10 est : 209
1. # 1011 1111 = 2**7+2**5+2**4+2**3+2**2+2**1+2**0
2. print ("En base 10 :",2**7+2**5+2**4+2**3+2**2+2**1+2**0)

Le shell affiche alors :


En base 10 : 191

Exercice 2.3

Représentation binaire de (−222)10


● On écrit en binaire l'entier positif (222)10 :
(222)10 = (11011110)2
On inverse les 1 et les 0 : (00100001)2
● On ajoute 1 : (00100001)2 + (00000001)2 = (00100010)2
Aussi (−222)10 = (00100010)2

Représentation binaire de (−100)10 :


● On écrit en binaire (+100)10 : cela donne (01100100)2.
On inverse les 1 et les 0 : (10011011)2
● On ajoute 1 au résultat :
(10011011)2 + (00000001)2 = (10011100)2.
Aussi (−100)10 =(10011100)2

Exercice 2.4

a) (1101)2 + (111)2 = (10100)2 = (20)10


Il faut 5 bits minimum pour coder le résultat.
b) (1101)2 × (111)2 = (10110011)2 = (91)10

Il faut 8 bits minimum pour coder le résultat.


c) (1111)2 + (10)2 = (10001)2 = (17)10
Il faut 5 bits minimum pour coder le résultat.

Exercice 2.5

a)

● Le s = 0, le signe sera (−1)0 donc +


● 0111 1011 : n = 26 + 25 + 24 + 23 + 21 + 20 = 123 d'où
E = 123 − 127 = −4
● 1001100 11001100 11001101 : est la mantisse m et vaut :

● Le nombre codé vaut donc en base 10 :


x = +1.599609375.2−4 = 0.0999755859375 ≈ 0,1
Conseils
Il faut remarquer que le codage est approximatif.

b)

● Le signe sera +
● 01111101 : n = 26 + 25 + 24 + 23 + 22 + 20 = 125
E = 125 − 127 = −2
● 0101010 10101010 10101011 : est la mantisse m et vaut :

m= = 1,33301…

● Le nombre codé vaut donc en base 10 :

Conseils
Il faut remarquer que le codage est approximatif.
c)

● Le signe sera +
● 01111101 : n = 26 + 25 + 24 + 23 + 22 + 20 = 125
E = 125 − 127 = −2
● 0000000 00000000 00000000 :

● Le nombre codé vaut donc en base 10 :


x = +1.2−2 = 0.25
Conseils
Le codage est cette fois exact !

Exercice 2.6
1. from math import sin, pi
2. a = sin(2*pi)
3. eps=1E-5
4.
5. print(abs(a-0)==0) #mauvais test
6. print(abs(a-0)<eps) #test correct
Corrigé des exercices de type EC -
QCM

Exercice EC 1.1

a) 14
b) 44
c) (10000111)2

d) (100101100)2
e) (11000111)2
f) (11111111)2

Exercice EC 2.2

Le code secret est en réponse C :

Exercice EC 2.3

a) Le codage hexadécimal
b) Le codage flottant
c) La méthode du complément à deux
d) La méthode IEE-754
Exercice EC 2.4

a) print(abs(a-0)==0)

b) print(abs(a-0) != 0)
c) print(abs(a-0)<eps)
d) print(abs(a-0)>eps)

En effet comparer un flottant à zéro n'est pas correct.

Exercice EC 2.5

a) (0000 0110)2
b) (0000 1110)2
c) (1100 1101)2
d) (1111 1110)2
Il suffit d'inverser les 1 et les 0 puis d'ajouter 1 (attention (1)2 + (1)2 =
(10)2).

Exercice EC 2.6

a) 55
b) 155
c) 77
d) 88

Exercice EC 2.7

a) (1111 0100 1001)2


b) (1101 0010 0001)2
c) (1101 0110 0001)2
d) (1101 1010 0001)2
Chapitre 3
Représentation d'un texte
en machine
Cours

1 Le code ASCII

Un peu d'histoire

Les ordinateurs ne sachant pas manipuler autre chose que des 0 et


des 1, il y a eu nécessité de traduire le texte en binaire afin de pouvoir
envoyer des emails, créer des pages web etc.
Ceci a été possible grâce à tout d'abord l'American Standard Code for
Information Interchange (Code américain normalisé pour l'échange
d'information) ou ASCII : une norme informatique de codage de
caractères (donc du texte) apparue dans les années 1960.

La table ASCII
La norme ASCII définit 128 codes (numérotés de 0 à 127 et codés en
binaire) et utilise 7 bits. Ceci comprend 95 caractères imprimables :
les chiffres de 0 à 9, les lettres minuscules et capitales de A à Z, et
des symboles mathématiques et de ponctuation. Chaque caractère
d'un texte en ASCII est souvent stocké dans un octet dont le 8-
ième bit est 0.
● Les codes 0 à 31 et le 127 sont des caractères de contrôle. Ils
permettent de faire des actions telles que :
– o retour à la ligne ;
– o bip sonore.
● Les codes 65 à 90 représentent les majuscules.
● Les codes 97 à 122 représentent les minuscules (il suffit de modifier
le 6-ième bit pour passer de majuscule à minuscule).
Exemple : on veut trouver l'écriture binaire en norme ASCII du mot
« Info ».
En lisant par correspondance dans la table on parvient à I → 73 ce
qui donne en binaire : 01001001
Puis n → 110 soit 01101110
Puis f → 102 soit 01100110
Puis o → 111 soit 01101111
Au final le mot « Info » s'écrit sur 4 octets :
01001001 01101110 01100110 01101111
Exemple : on veut trouver l'écriture binaire grâce à la norme ASCII
du mot « défi ».
Cette fois, c'est impossible car la lettre « é » ne figure pas dans la
table ASCII.

Limitations
ASCII est suffisant pour représenter les textes en anglais, mais il ne
permet pas de représenter les accents ou les lettres spécifiques de
l'espagnol, du français etc. comme « é, è, ç » etc. D'où la nécessité de
trouver une norme plus internationale.

2 La norme ISO-8859-1

Nécessité

Une première tentative d'amélioration fut la norme ISO-8859-1. Elle


s'écrit sur 8 bits : il s'agit d'une extension de l'ASCII. Elle permet
l'affichage des caractères accentués de plusieurs langues et de
symboles courants.
Exemple : on cherche l'écriture ISO-8859-1 du mot « défi ».
En lisant par correspondance dans la nouvelle table on parvient à
« é » → 130 ce qui donne en binaire : 10000010. On note que les
8 bits sont utilisés.
L'écriture complète donne :
01100100 10000010 01100110 01101001
Limitations
Cette norme permet l'écriture en binaire de mots français mais ce
n'est pas le cas pour le chinois, l'arabe. D'où la nécessité d'un code
encore plus large.

3 La norme Unicode

Nécessité d'une norme internationale

Il est vite devenu essentiel de proposer une version unifiée des


différents encodages de caractères. Ceci a été permis en complétant
l'ASCII et en permettant l'encodage de caractères autres que ceux de
l'alphabet latin. Unicode définit à cet effet des dizaines de milliers de
codes. Les 128 premiers restent compatibles avec ASCII.
L'Unicode est tout simplement une énorme table de correspondance
appelée Caractère-Code (Charset). L'UTF-8 est l'encodage
correspondant (Encoding) qui est le plus utilisé. Les navigateurs
Internet utilisent le codage UTF-8 et les concepteurs de sites utilisent
à présent presque tous cette même norme ; c'est pourquoi il y a de
moins en moins de problèmes de compatibilité.

Convertisseur de texte en Unicode


On utilisera par exemple le site :
https://nickciske.com/tools/binary.php.
Exemple : on cherche cette fois l'écriture du mot « défi » grâce à
l'UTF-8
L'écriture complète donne :
01100100 11000011 10101001 01100110 01101001
Remarque
On a vu que dans la norme ISO 8859-1 le « é » est codé 1110 1001. Mais en UTF-8 on le
code sur deux octets : 11000011 10101001.
Les erreurs d'encodage : incompatibilité de normes
Un problème d'encodage se manifeste par le fait qu'une partie ou la
totalité des caractères spéciaux (« é, è, à » etc.) d'un document ne
sont pas affichés correctement. On peut par exemple voir des é ou
des ? à la place des « é ».
Vocabulaire à connaître
Ces erreurs d'affichage donnent lieu à du texte appelé couramment Mojibake qui
signifie « apparaître de manière déguisée en japonais ».

Conseil
Les incompatibilités de normes sont donc à l'origine des problèmes que l'on rencontre
parfois avec les caractères accentués. Lorsque l'on écrit un email, il est plus sûr de
n'utiliser que des caractères non accentués (un « e » remplace un « é » par exemple).
En effet, un destinataire qui n'utilise pas la même norme que vous verra sinon des
caractères é ou ? à la place des « é » …
Exercices

Compétence attendue

➡ Convertir un texte dans différents formats d'encodage. Traduire l'encodage d'un


texte.

Exercice 3.1
► Décomposer, développer

À l'aide de la table de correspondance ci-dessous, chercher la


première lettre de votre prénom. Écrire sa correspondance en binaire
(une case blanche est un 1, une noire, un 0).

Reproduire ce code personnalisé sur la bande ci-dessous afin de


construire votre bracelet « geek » !
Exercice 3.2
► Décomposer, traduire

Quels mots se cachent sous les codes UTF-8 suivants ? :


a) 0110100001100101011011000110110001101111
b) 01101001011011100110011001101111011100100110110
1011000010111010001101001011100010111010101100101
c) 01100010011010010110111001100001011010010111
001001100101

Compétence attendue

➡ Convertir un fichier texte dans différents formats d'encodage.

Exercice 3.3
► Mobiliser

L'objectif de cet exercice est d'étudier la conversion de format d'un


fichier texte et l'impact sur la taille et sur le contenu du fichier.
● Pour cela, créer un fichier Microsoft Word (ou autre éditeur de texte
gratuit), dans lequel vous tapez les mots : «Le petit» (sans espace
avant le L ou après le t). Enregistrer le fichier sous le nom Le
petit.docx et noter la taille du fichier obtenu. Pour avoir accès à la
taille, il suffit d'effectuer un clic simple sur le fichier dans le
gestionnaire de fichiers :
● Puis dans Word, aller dans Fichier → Enregistrer sous (indiquer le
nom Le petit-utf8), sélectionner format du fichier Texte brut (.txt),
cliquer sur enregistrer. Choisir autre codage et sélectionner Unicode
(UTF-8) comme ci-dessous :

Noter la taille du fichier Le petit-utf8.txt obtenu. Comparer la taille du


fichier.docx à celle du fichier .txt. Comment expliquer cette
différence ?
● S'il est fermé, ouvrir le fichier Le petit.docx (en double-cliquant
dessus) et y copier-coller du texte contenant des caractères
spéciaux (voir exemple ci-dessous avec le texte du petit chaperon
rouge). Convertir le format du fichier en .txt et choisir le codage
UTF-8 comme précédemment et renommer le fichier en Le petit
chaperon rouge-utf8.txt. Le contenu donne par exemple :
● Reproduire les étapes précédentes mais cette fois choisir le codage
en ASCII et renommer le fichier en Le petit chaperon rouge-
ASCII.txt. Que donne le contenu ? Que s'est-il produit ?
Exercices de type EC - QCM

Pour chaque question, le candidat gagne 3 points s'il choisit la bonne


réponse, perd 1 point s'il choisit une réponse fausse. S'il ne répond
pas ou choisit plusieurs réponses, il ne gagne ni ne perd aucun point.

Exercice EC 3.1
1 min ● 3 points
Le code ASCII permet de représenter en binaire les caractères
alphanumériques. Sur combien de bits sont-ils codés ?
Réponses :
a) 7
b) 4
c) 9
d) 2

Exercice EC 3.2
1 min ● 3 points
Le code ASCII de la lettre A est 0x41, celui de la lettre B est 0x42, celui
de la lettre C est 0x43, etc. Quel est le code ASCII, en hexadécimal, de
la lettre F ?
Réponses :
a) 1x45
b) 0x48
c) 2x45
d) 0x46

Exercice EC 3.3
1 min ● 3 points
Parmi les choix suivants, lequel n'est pas celui d'un d'encodage de
caractères ?
Réponses :
a) Unicode
b) UTF-8
c) ASCII
d) Comic SANS MS

Exercice EC 3.4
1 min ● 3 points
Parmi les caractères ci-dessous, lequel ne fait pas partie du code
ASCII ?
Réponses :
a) ù
b) space
c) )
d) @

Exercice EC 3.5
1 min ● 3 points
Donner un inconvénient correct de la norme ASCII :
Réponses :
a) L'encodage est trop long
b) Elle n'est pas adaptée à toutes les langues
c) Elle ne permet pas d'écrire en majuscules
d) Elle ne permet pas d'écrire de ponctuation
Corrigé des exercices

Exercice 3.1

La lettre E donne 01000101.

Exercice 3.2

a) hello
b) informatique
c) binaire

Exercice 3.3

● La taille du fichier Le petit.docx est de 13 ko soit 13 000 octets.


● La taille du fichier Le petit-utf8.txt est de 8 octets ! Ce fichier contient
du texte brut, contrairement à Word qui ajoute une mise en forme,
des polices plus élaborées, se souvient de la position du curseur,
compresse le fichier, etc.
● Le contenu du fichier Le petit-chaperon-rouge-ASCII.txt donne :
Les « é », les « è », les « û », les « à », etc. ont été mal convertis :
on obtient des ? à la place. Le texte a été détérioré.
Corrigé des exercices de type EC -
QCM

Exercice EC 3.1

a) 7
b) 4
c) 9
d) 2

Exercice EC 3.2

a) 1x45
b) 0x48
c) 2x45

d) 0x46

Exercice EC 3.3

a) Unicode
b) UTF-8
c) ASCII
d) Comic SANS MS

Exercice EC 3.4
a) ù
b) space
c) )
d) @

Exercice EC 3.5

a) L'encodage est trop long


b) Elle n'est pas adaptée à toutes les langues
c) Elle ne permet pas d'écrire en majuscules
d) Elle ne permet pas d'écrire de ponctuation
Thème B
Types construits
Chapitre 4
Les types
de données construits
Cours

1 Les p-uplets

Créer un p-uplet

Un p-uplet (ou tuple en anglais) est tout simplement une suite de


valeurs séparées par des virgules. On peut créer un tuple a si on tape
dans le shell :
>>> a = (10,20,30)
>>> a # on cherche à connaître le contenu de la variable a
(10,20,30)

Aussi la variable a contient trois valeurs. On cherche ensuite le type


de la variable a :
>>> type(a)
<class 'tuple'>

Ceci confirme que a est bien de type tuple.


Remarque
On peut aussi créer un tuple en omettant les ( ) :
>>> a = 10,20,30
Les ( ) ne sont pas obligatoires mais rendent la lecture plus claire.

Notion d'indexation
On tape cette fois dans le shell :
>>> a[0]
10
On peut donc accéder au contenu de la variable a en utilisant des
indices (aussi appelés index). Ces indices notés i démarrent à 0. Donc
l'indice associé à l'entier 10 est i = 0, celui associé à 20 est i = 1 etc. :
a=

Erreurs à éviter
On peut parfois par inadvertance utiliser une « , » à la place d'un « . » lors de la saisie d'un
flottant. Dans ce cas Python identifiera la saisie à un type tuple et non à un flottant.
Exemple : soit la variable b = –1,2 dont on souhaite prendre la valeur absolue, on tape
dans l'éditeur :
1. b = -1,2 #Erreur, il fallait saisir b = -1.2
2. print(abs(b))
Le shell renvoie un message d'erreur car on ne peut pas prendre la valeur absolue d'un
tuple :
Traceback (most recent call last):
File "<tmp 1>", line 2, in <module> print(abs(b))
TypeError: bad operand type for abs(): 'tuple'

2 Les listes

Créer une liste

Une liste en Python permet de stocker des données. On parle alors de


structure de données ou bien d'objet conteneur (un objet qui en
contient d'autres). Il s'agit d'une façon de ranger et d'ordonner des
objets (nombres, caractères ASCII, listes, etc.). L'utilisation des listes
en Python est très répandue car celles-ci sont modifiables (mutables),
ce qui permet une certaine flexibilité́. Pour créer une liste en Python il
suffit de séparer les données par des « , » (comme pour les tuples) et
de placer des crochets aux extrémités :
1. liste1 = [1,2,3] #liste d'entiers
2. liste2 = [11.2,5.0,8.0,21.0] #liste de flottants
3. liste3 = [[1,2],[1],[2,1,3]] #liste de listes d'entiers
liste1 et liste2 sont des listes. liste3 est une liste de listes.
Remarque
Dans le programme de première NSI, on se restreint aux listes dont les éléments sont du
même type. Mais Python permet de créer et utiliser des listes contenant des éléments de
types différents comme liste = [1.2,2,'a'].

Lire et modifier les éléments d'une liste grâce à leurs index


Tout comme pour les tuples, chaque élément d'une liste porte un
indice. Les indices positifs démarrent à 0 en Python, les indices
négatifs démarrent à −1 en partant de la fin. Les indices (ou index)
notés souvent i (ou j) sont indiqués ci-dessous :

liste1 = liste1[2] vaut 3

liste1 = liste1[-1] vaut 3

liste3 = liste3[-1] vaut [2,1,3], liste3[0][1] vaut 2

Vocabulaire à connaître
On dit que les listes sont des types de données modifiables, ou mutables.

Aussi, on peut modifier un élément d'une liste en lui affectant une


nouvelle valeur :
1. liste2[1] = 12.1
2. print(liste2)

Conseils
Ne pas oublier que les indices positifs ou index démarrent à 0.

La modification de l'élément d'index 1 est visible dans le shell :


[11.2,12.1,8.0,21.0]

Construire une liste par compréhension


Il est possible de créer une liste d'entiers ou de flottants de manière
plus efficace avec une liste en (ou « par ») compréhension :
L = [i for i in range(n)]

On utilise range(n) qui renvoie une liste démarrant à 0 et qui finit à n-1.
Donc attention n est exclu ! Ainsi la variable i prend tour à tour les
valeurs 0, 1, … , n-1.
Remarque
La syntaxe complète est range(debut,fin,pas) : cela crée une liste allant de debut à
fin-1 avec l'incrémentation pas. Si la valeur debut n'est pas mentionnée, elle vaut 0 par
défaut. Si le pas n'est pas fourni, il vaut 1 par défaut.

Exemple :
1. n = 5
2. L = [i for i in range(n)] #i va de 0 à 5 exclu par pas de 1
3. print(L)

On obtient [0, 1, 2, 3, 4] car i prend les valeurs de 0 à 4.


Exemple :
1. L = [i**2 for i in range(n)] # i va de 0 à 5 exclu par pas de 1
2. print(L)

On obtient [0, 1, 4, 9, 16] car i2 prend les valeurs de 02 à 04.


Exemple :
1. L = [i/2 for i in range(n)]
2. print(L)

On obtient [0.0, 0.5, 1.0, 1.5, 2.0].

Exemple :
1. L = [i for i in range(1,10,2)]
2. print(L)

On obtient [1, 3, 5, 7, 9] car i prend les valeurs de 1 à 9 par pas


de 2.
Remarque
On verra en exercice 4.2 qu'il est aussi possible de construire une liste en compréhension
avec la syntaxe : L = [i for i in liste].
liste étant une liste déjà constituée : i parcourt alors un à un les éléments de liste.
Opérations sur les listes
Deux opérations sont possibles sur les listes : la concaténation et la
duplication. La concaténation de deux listes consiste à mettre bout à
bout ces deux listes. L'opération de concaténation se note +. Soit
dans le shell :
>>> [2, 4, 6, 8] + [1, 3, 5, 7]
[2, 4, 6, 8, 1, 3, 5, 7]

L'opérateur de duplication (et non multiplication) se note * et


s'utilise comme suit :
>>> [1, 2, 3] * 3
[1, 2, 3, 1, 2, 3, 1, 2, 3]

Ajout d'un élément en fin de liste


On peut utiliser pour cela une méthode associée aux listes : la
méthode append( ).
Exemple :
1. liste = [] #liste vide
2. liste1.append(4) #on y met un 4
3. print(liste1)
4. liste1.append(5) #puis on y met un 5
5. print(liste1)
6. liste1 = liste + [6] #puis on y met un 6
7. print(liste1)

Soit dans le shell : [4] puis [4,5], [4,5,6]. On peut donc partir d'une liste
vide que l'on construit au fur et à mesure avec append( ) ou effectuer
une concaténation simple avec un +.

Recherche d'un élément dans une liste avec in


La commande suivante renvoie le booléen True si le contenu de la
variable x est dans la liste, False sinon :
>>> x in liste

Exemple :
>>> x = 5
>>> x in liste1 #on cherche 5 dans la liste1
True
Remarque
La recherche d'un élément avec in implique que le programme va parcourir un à un les
éléments de la liste.
Sachant qu'une opération sur un ordinateur prend en moyenne environ 10−9 s, si la liste
contient 106 éléments, le programme mettra 10−3 s. Si la liste contient 1012 éléments, le
programme mettra 103 s etc. Donc le temps de recherche est proportionnel à la longueur de
la liste. On dit que le coût en temps est linéaire.

Quelques commandes à retenir


Type Commande Affichage ou résultat

Créer une liste vide L = [] []


Créer une liste de n zéros L = [0]*n [0,..,0]
Créer une liste en compréhension : obtenir L=[i for i in
[0,1,.,n-1]
un ensemble d'entiers range(n)]
Créer une liste en compréhension : obtenir L=[i*0.1 for i in
[0.0,..,(n-1)*0.1]
un ensemble de réels range(n)]
Appel de l'élément i de la liste liste[i] élément d'indice i de la liste
élément d'indices (i,j)
Appel de l'élément (i,j) d'une liste de listes liste[i][j]
de la liste

Appel du 1er élément d'une liste liste[0] 1er élément de la liste


Appel du dernier élément
liste[-1] dernier élément de la liste
d'une liste
Affecter la valeur n à l'élément i de la liste liste[i] = n liste[i] vaut n : [..,n,..]
Afficher le nombre d'éléments
len(liste) longueur de la liste
de la liste

une seule liste contenant liste1


Concaténation de deux listes
liste1 + liste2 et liste2 mises
avec l'opérateur +
bout à bout
Duplication d'une liste une seule liste contenant n fois
liste*n
avec l'opérateur ∗ liste
Ajout de n en fin de liste
liste.append(n) liste vaut [.,.,.,n]
par la méthode append
Ajout de n en fin de liste liste + [n] liste vaut [.,.,.,n]
Suppression d'un élément liste[i] del liste[i] Supprime liste[i]
3 Les dictionnaires

Créer un dictionnaire

Tout comme les listes, les dictionnaires sont des objets structurés
pouvant contenir d'autres objets. Les dictionnaires sont délimités par
des { }, là où les listes l'étaient par des [ ].
Dans un dictionnaire les informations ne sont pas stockées dans un
ordre précis. Aussi, pour accéder aux objets contenus dans le
dictionnaire, on utilise plutôt des clés que des indices.
On peut, comme on l'a fait pour les listes, créer un dictionnaire vide
(avec { }) et le remplir au fur et à mesure. On crée par exemple ci-
dessous un répertoire de numéros de téléphone en tapant dans le
shell :
>>> repertoire = {}
>>> repertoire["nom"] = "Alex"
>>> repertoire["numero de tel"] = "06 67 65 13 21"
>>> repertoire
{'nom': 'Alex', 'numero de tel': '06 67 65 13 21'}

Dans cet exemple les clés sont 'nom' et 'numero de tel'.

Le dictionnaire contient deux éléments : 'nom': 'Alex' et 'numero de tel':


'06 67 65 13 21'.
Le nombre d'éléments est renvoyé en tapant len(repertoire).
On peut vérifier d'autre part que répertoire est bien de type
dictionnaire c'est-à-dire dict :
>>> type(repertoire)
<class 'dict'>

Remarque
On aurait pu aussi créer le dictionnaire en une seule fois plutôt que de le remplir au fur et à
mesure :
>>> repertoire = {'nom': 'Alex', 'numero de tel': '06 67 65 13 21'}

Vocabulaire à connaître
Les clés et leurs valeurs sont ici des chaînes de caractères. Ils sont déclarés entre
guillemets ou entre apostrophes : 'nom' ou "nom".
Les guillemets sont plus pratiques lorsque la chaîne contient des apostrophes : 'numero
d'aide' n'est pas une chaîne valide. "numero d'aide" et "numero de tel" sont des
chaînes correctes.

Remarque
On peut aussi avoir des clés et valeurs sous forme d'entier (assez classique) ou sous un
autre type de donnée.

Accéder aux valeurs d'un dictionnaire


Pour accéder à la valeur correspondant à une clé, il suffit de placer
cette clé entre [ ] :
>>> repertoire["numero de tel"]
'06 67 65 13 21'

On peut aussi modifier une valeur correspondant à une clé :


>>> repertoire["numero de tel"] = "07 67 65 13 21"
>>> repertoire
{'nom': 'Alex', 'numero de tel': '07 67 65 13 21'}

La modification est visible.

Parcourir les clés ou les valeurs d'un dictionnaire


La méthode keys() permet d'accéder aux différentes clés d'un
dictionnaire :
>>> repertoire.keys()
dict_keys(['nom', 'numero de tel'])

La méthode values() donne, elle, accès aux valeurs :


>>> repertoire.values()
dict_values(['Alex', '07 67 65 13 21'])

De même, la méthode items() donne accès à tout le contenu du


dictionnaire :
>>> repertoire.items()
dict_items([('nom', 'Alex'), ('numero de tel', '07 67 65 13 21')])
Ainsi, on peut par exemple vérifier avec le mot clé in si une valeur (ou
une clé) est contenue dans le dictionnaire. Pour cela tous les
éléments du dictionnaire seront parcourus un à un. On obtient le
booléen True si la valeur recherchée (ou la clé recherchée) est
présente, False sinon.
>>> '07 67 65 13 21' in repertoire.values() #parcours des valeurs
True

Ou encore :
>>> 'adresse' in repertoire.keys() #parcours des clés
False

Remarque
Tout comme pour les listes, la recherche d'un élément avec in implique que le programme
doive parcourir un à un les éléments du dictionnaire (dans ce cas repertoire ne contient que
deux éléments ce qui est peu : on peut le vérifier avec len(repertoire)). Mais dans la pratique
on peut manipuler des dictionnaires très longs, auquel cas la durée de parcours peut vite
augmenter.
À nouveau le temps de recherche est proportionnel à la longueur du dictionnaire : le coût en
temps est linéaire.
Exercices

Compétence attendue

➡ Construire une liste par compréhension.

Exercice 4.1
► Décomposer

Créer une liste en compréhension contenant les cubes des 4 premiers


entiers naturels : [0,1,8,27]. De même créer une liste contenant les 4
premiers multiples de 0.2 : [0.0,0.2,0.4,0;6].
➡ Vérifier via le shell si 8 est bien dans la première liste puis si 0.6 est
dans la seconde.

Compétence attendue

➡ Construire une liste par compréhension.


➡ Itérer sur les éléments d'une liste.

Exercice 4.2
► Décomposer, développer

Créer les listes suivantes à l'aide de listes en compréhension :


X = [0.1,0.2,0.3,...,1.9, 2]
Y = [(0.1)3,(0.2)3,(0.3)3,...,(1.9)3,23]
Z=

Remarque
Pour constituer Y et Z, vous pouvez vous servir de la liste X.

Compétence attendue

➡ Lire et modifier les éléments d'une liste grâce à leur index.

Exercice 4.3
► Analyser

Trouver ce que font les instructions suivantes, indiquer ce que


contient la liste a à chaque étape :
1. #Script 1
2. a = [2,1,0.5]
3. a[1] = 2
4. del a[2]
5. a.append(3)

1. #Script 2
2. a = [2,1,0.5]
3. a = [3] + a
4. a[1] = 2
5. del a[2]

Exercice 4.4
► Analyser

Voici deux scripts :


1. a = 2 1. V = []
2. V = [a] 2. a = 2
3. b = a**2 3. V.append(a)
4. V.append(b) 4. a = a**2
5. c = b**3 5. V.append(a)
6. X = V + [c] 6. a = a**3
7. print(X) 7. V.append(a)
8. print(V)
1) Quel est l'avantage du script 2 par rapport au script 1 ?
2) Le script 2 fonctionne-t-il si on supprime sa première ligne ? À quoi
sert cette première ligne ?
3) Sur le même modèle que le script 2, créer la liste [1,3,6,10,15].

Compétence attendue

➡ Construire une entrée de dictionnaire.


➡ Parcourir les éléments d'un dictionnaire.
➡ Utiliser des méthodes.

Exercice 4.5
► Modéliser

On va tâcher de représenter le parc de vélos en libre accès (les velibs


à Paris, les velovs à Lyon, etc.) à l'aide de dictionnaires.
Les clés et leurs valeurs possibles seront :
● "id" : qui correspond à l'identifiant du vélo (un entier).
● "typ" : qui peut être "électrique" ou "classique".
● "station" : qui correspond à la station (une chaîne de caractères) où
est stationné le vélo ou à celle où il a dernièrement stationné.
● "statut" : qui correspond au statut du vélo. Il peut être "en déplacement",
"en panne", ou "dispo".
1) D'après cette représentation, créer un vélo électrique d'identifiant
121000, stationné à place d'Italie mais en panne.
2) Ce vélo est ensuite réparé et quitte sa station : modifier son
dictionnaire en conséquence.
3) Vérifier à l'aide d'une ligne de code si la valeur "dispo" figure dans le
dictionnaire créé.
Exercices de type EC - QCM

Pour chaque question, le candidat gagne 3 points s'il choisit la bonne


réponse, perd 1 point s'il choisit une réponse fausse. S'il ne répond
pas ou choisit plusieurs réponses, il ne gagne ni ne perd aucun point.

Exercice EC 4.1
1 min ● 3 points
On tape les lignes suivantes :
1. L = [2, 6, 8, 4]
2. L[1] = L[1] + 4
3. print(L[1])

Que s'affiche-t-il dans le shell ?


Réponses :
a) 7
b) 10
c) 9
d) 6

Exercice EC 4.2
1 min ● 3 points
On tape les lignes suivantes :
1. L = [2, 6, 8, 4]
2. L[1] = L[1] + 4
3. print(L)
Que s'affiche-t-il dans le shell ?
Réponses :
a) [2, 6, 8, 4]
b) [4, 6, 8, 4]
c) [2, 10, 8, 4]
d) [6, 6, 8, 4]

Exercice EC 4.3
1 min ● 3 points
On a construit une liste annee2021 contenant des villes et la
température moyenne en juin. On tape les lignes suivantes :
1. annee2021 = [('Paris',22), ('Houston',25), ('Moscou',16)]
2. m = annee2021[0][1]
3. for i in range(len(annee2021)):
4. if annee2021[i][1] > m:
5. m = annee2021[i][1]
6. print(m)

Que s'affiche-t-il dans le shell ?


Réponses :
a) 22
b) ('Paris',22)
c) ('Houston',25)
d) 25

Exercice EC 4.4
1 min ● 3 points
Quel est le contenu de la variable diff à la fin de l'exécution du script
suivant ?
1. entiers = (10,6,1,12,15)
2. diff = entiers[2] - entiers[3]

Réponses :
a) 11
b) -11
c) 5
d) -5

Exercice EC 4.5
1 min ● 3 points
On remplit le dictionnaire bonbon :
1. bonbon = {'forme': 'rond', 'masse': 0.01,'couleur' :'rouge'}
2. print(bonbon.keys())

Qu'affiche la dernière instruction ?


Réponses :
a) dict_keys(['forme', 'masse', 'couleur'])
b) dict_keys(['rond', 0.01, 'rouge'])
c) 'rond'
d) 'rouge'

Exercice EC 4.6
1 min ● 3 points
On définit la liste d'entiers liste = [30,20,40,50]. Quelle est le contenu
de la variable liste[1] ?
Réponses :
a) 30
b) 20
c) 40
d) 50

Exercice EC 4.7
1 min ● 3 points
On considère la liste de listes suivante :
noel = [ ['J', 'O', 'J'], ['E', 'U', 'X'], ['N', 'O', 'E','L'] ]

Quelle instruction permet de modifier la liste noel afin qu'elle


contienne les lettres de la phrase JOYEUX NOEL ?
Réponses :
a) noel[0][2]='Y'
b) noel[1][2]='Y'
c) noel[2][2]='Y'
d) noel[0]='Y'

Exercice EC 4.8
1 min ● 3 points
On considère la liste de listes suivante :
noel = [ ['J', 'O', 'J'], ['E', 'U', 'X'], ['N', 'O', 'E','L'] ]

Quels éléments de la liste contiennent la lettre 'O'?


Réponses :
a) noel[0][1] et noel[0][2]
b) noel[0][1] et noel[2][1]
c) noel[0][-2] et noel[2][1]
d) noel[0][1] et noel[1][2]

Exercice EC 4.9
1 min ● 3 points
On considère la liste de listes suivante : serie = [['T', 'H', 'I','R',
'T', 'E', 'E', 'N'], ['R', 'E', 'A', 'S', 'O', 'N', 'S']]

Comment obtenir la liste : serie = ['T', 'H', 'I','R', 'T', 'E', 'E', 'N',
'R', 'E', 'A', 'S', 'O', 'N', 'S'] ?
Réponses :
a) serie = serie[0] + serie[1]
b) serie = serie[0] , serie[1]
c) serie = [serie[0] + serie[1]]
d) serie = [[serie[0] + serie[1]]]
Corrigé des exercices

Exercice 4.1

Il s'agit d'une application directe du cours :


1. L = [i**3 for i in range(4)]
2. print(L) # on obtient [0, 1, 8, 27]
3. print(8 in L) #affiche True
4.
5. L2 = [i*0.2 for i in range(4)]
6. print(L2) # on obtient [0.0, 0.2, 0.4, 0.6000000000000001]
7. print(0.6 in L2) #affiche False !

On remarque une erreur d'arrondi due à la manipulation de flottants


dans la seconde liste ainsi le second test avec in renvoie False : en
effet la liste constituée contient 0.6000000000000001 et non 0.6. Pour
régler ce problème, on peut modifier le programme avec :
1. L2 = [i*0.2 for i in range(3)] + [0.6]
2. print(L2) # on obtient [0.0, 0.2, 0.4, 0.6]
3. print(0.6 in L2) #affiche True

Exercice 4.2
1. X = [i/10 for i in range(1,21)] # i va de 1 à 21 exclu (donc 20)
2. print("X",X)
3.
4. #Méthode 1
5. Y = [(i/10)**3 for i in range(1,21)]
6. print("Y",Y)
7. #Méthode 2 avec X
8. Y = [i**3 for i in X] # i parcourt les éléments de X
9. print("Y",Y)
10.
11. Z = [1/i for i in X] # i parcourt les éléments de X
12. print("Z",Z)

Exercice 4.3

On tape les scripts dans l'éditeur :


1. #Script 1
2. a = [2,1,0.5]
3. a[1] = 2 #a contient [2,2,0.5]
4. del a[2] #a contient [2,2]
5. a.append(3) #a contient [2,2,3]
6. print(a) #a contient [2,2,3]
7.
8. #Script 2
9. a = [2,1,0.5]
10. a = [3] + a #a contient [3,2,1,0.5]
11. a[1] = 2 #pas de modification, a contient [3,2,1,0.5]
12. del a[2] #suppression a[2], a contient [3,2,0.5]
13. print(a) #a contient [3,2,0.5]

Exercice 4.4

On tape les scripts dans l'éditeur :


1. a = 2
2. V = [a] #V contient [2]
3. b = a**2
4. V.append(b) #V contient [2,4]
5. c = b**3
6. X = V + [c] #X contient [2,4,64]
7. print(X)
8.
9. V = []
10. a = 2
11. V.append(a) #V contient [2]
12. a = a**2
13. V.append(a) #V contient [2,4]
14. a = a**3
15. V.append(a) #V contient [2,4,64]
16. print(V)

1) Le script 2 crée un minimum de variables pour parvenir au même


résultat que script 1. On dit que la complexité spatiale (donc
l'encombrement mémoire) est meilleure dans le cas du script 2.
Cette méthode sera utilisée par la suite pour les boucles.
2) La première ligne du script 2 est essentielle car elle initialise la
liste V à une liste vide qui sera remplie au fur et à mesure. Sans elle,
on obtient un message d'erreur.
3) La liste V = [1,3,6,12,36] peut être créée avec :
1. V = []
2. a = 3
3. V.append(a)
4. a = a*2
5. V.append(a)
6. a = a*2
7. V.append(a)
8. a = a*3
9. V.append(a)
10. print(V)

Voire même :
1. V = []
2. a = 3
3. V.append(a)
4. V.append(a*2)
5. V.append(a*4)
6. V.append(a*12)
7. print(V)

Exercice 4.5

Il s'agit d'une application directe du cours :


1. velo = {"id" : 1211000, "typ" : "électrique","station" : "Place
d'Italie","statut" : "en panne"}
2. print(velo)
3.
4. velo["statut"] = "en déplacement"
5. print(velo)
6. print("dispo" in velo.values()) #renvoie False
Corrigé des exercices de type EC -
QCM

Exercice EC 4.1

a) 7
b) 10
c) 9
d) 6

Exercice EC 4.2

a) [2, 6, 8, 4]
b) [4, 6, 8, 4]
c) [2, 10, 8, 4]
d) [6, 6, 8, 4]

Exercice EC 4.3

a) 22
b) ('Paris',22)
c) ('Houston',25)
d) 25
Exercice EC 4.4

a) 11

b) –11
c) 5
d) –5

Exercice EC 4.5

a) dict_keys(['forme', 'masse', 'couleur'])


b) dict_keys(['rond', 0.01, 'rouge'])
c) 'rond'
d) 'rouge'

Exercice EC 4.6

a) 30
b) 20
c) 40
d) 50

Exercice EC 4.7

a) noel[0][2]='Y'
b) noel[1][2]='Y'
c) noel[2][2]='Y'
d) noel[0]='Y'

Exercice EC 4.8

a) noel[0][1] et noel[0][2]
b) noel[0][1] et noel[2][1]
c) noel[0][-2] et noel[2][1]
d) noel[0][1] et noel[1][2]

Exercice EC 4.9

a) serie = serie[0] + serie[1]


b) serie = serie[0] , serie[1]
c) serie = [serie[0] + serie[1]]
d) serie = [[serie[0] + serie[1]]]
Thème F
Langage et programmation
Chapitre 5
Les fonctions
Cours

1 Créer une fonction


Certaines fonctions préprogrammées ont déjà été utilisées dans les
chapitres précédents : à savoir print( ) et type( ). L'objectif est
maintenant d'écrire de nouvelles fonctions. En effet, lorsque certaines
suites d'instructions sont souvent utilisées au sein d'un programme, il
est utile de pouvoir y faire appel sans avoir à les réécrire. C'est à cette
occasion que la notion de fonction en Python prend tout son intérêt.

Un peu d'histoire
Avec ce chapitre on démarre l'écriture d'algorithmes. Le mot
« algorithme » vient du nom d'un mathématicien arabe du VIIIe siècle
après J.-C., Al-Khwarizmi. Ce mathématicien écrivit en langue arabe
le plus ancien traité d'algèbre «Al-Jabr» sur la résolution des
équations. Il y proposait les solutions en décrivant l'enchaînement
d'étapes à suivre pour résoudre les équations.
John McCarthy est l'auteur du langage Lisp (sorti en 1958), qui est à
l'origine des langages de programmation fonctionnels.
La programmation fonctionnelle est un mode de programmation qui
passe par l'évaluation de fonctions mathématiques.

Forme générale d'une fonction


1. def fonction(arguments d'entrée) :
2. """Documentation facultative affichée avec help(fonction)"""
3. instructions #précédées d'une indentation (4 espaces)
4. return sortie #plusieurs arguments de sortie possibles

La première ligne de la fonction est appelée sa signature ou son en-


tête. Cet en-tête contient le nom de la fonction (ici ajoute_1) et la liste
des arguments (appelés aussi paramètres) d'entrée (séparés par des
virgules).
Remarque
Attention à ne pas oublier les « : » suite au nom de la fonction et à l'indentation (la suite de
4 espaces) après les « : ».

Spécification d'une fonction


La spécification d'une fonction correspond à la description utile pour
pouvoir l'utiliser. Elle est composée de l'en-tête de la fonction et de sa
documentation.
1. def fonction(arg1,arg2,arg3, …) :
2. """Documentation facultative affichée avec help(fonction)"""
L'en-tête à lui seul ne permet pas à un autre utilisateur de comprendre
ce que fait la fonction que vous avez créée, mais la documentation
sert justement à cela. Cette documentation doit contenir :
● Une phrase qui indique à quoi sert votre fonction.
● D'autres phrases s'il existe des contraintes sur les paramètres en
entrée (comme strictement positifs etc.).
● Les types des arguments d'entrée.
● La description du (ou des) argument(s) éventuel(s) de sortie ainsi
que son (leur) type(s).
Exemples :
1. def ajoute_1(x) :
2. """Ajoute un à x, renvoie le résultat du calcul
3. x : un nombre (entier, flottant)
4. resultat : un nombre (entier, flottant)
5. """
6. resultat = x + 1
7. return resultat

Ou pour le calcul de la racine d'un nombre :


1. from math import sqrt
2. def racine(x) :
3. """Calcule la racine carrée d'un nombre, renvoie le résultat
4. x : un nombre positif ou nul (entier, flottant)
5. resultat : un flottant
6. """
7. resultat = sqrt(x)
8. return resultat

Les arguments d'une fonction


Une fonction peut comporter plusieurs arguments (appelés aussi
paramètres) d'entrée et de sortie. Il suffit de les séparer par une
virgule.
Exemples de fonctions sans argument d'entrée
1. def annee() : #pas d'argument d'entrée
2. return 2021

Cette fonction très simple renvoie l'année 2021. Pour l'appeler il suffit
de taper annee() dans le shell.
1. def puissances2() : #pas d'argument d'entrée
2. return (2**1, 2**2, 2**3, 2**4) #4 arguments de sortie

La fonction puissances2 renvoie plusieurs arguments de sortie sous la


forme du tuple : (2**1, 2**2, 2**3, 2**4). Pour appeler cette fonction il
suffit de taper puissances2() dans le shell.
Exemple de fonction avec un argument d'entrée, un de sortie
1. def ajoute_1(x) :
2. """ajoute 1 au seul argument d'entrée : x"""
3. resultat = x + 1
4. return resultat #un seul argument de sortie : resultat

Remarque
Lors du choix du nom de la fonction, ne pas prendre celui d'une variable déjà existante sous
peine d'obtenir des résultats aberrants. Le nom de fonction suivant n'est pas judicieux :
1. def calcul(x) :
2. """ calcul est aussi une variable : mauvais choix """
3. calcul = x + 1
4. return calcul
Celui-ci non plus :
5. calcul = 2
6. def calcul(x) :
7. """ calcul est déjà une variable ! """
8. res = x + 1
9. return res

Exemple de fonction sans argument de sortie


Certaines fonctions n'ont pas d'argument de sortie :
1. def ma_procedure(x) :
2. x = x + 1

Vocabulaire à connaître
Une fonction qui n'a pas d'argument de sortie est appelée procédure.

2 Notion de variable locale, variable globale

Variable locale
Une variable locale est une variable créée au sein d'une fonction, elle
ne sera pas accessible dans le programme principal.
1. def ajoute_1(x) :
2. resultat = x + 1 #resultat est une variable locale
3. return resultat

Ici, resultat, est une variable locale à la fonction. Celle-ci n'existe qu'au
sein de la fonction ajoute_1 et n'est pas visible dans le programme
principal. L'appel suivant : print(resultat) renvoie un message
d'erreur (variable resultat non définie) :
NameError: name 'resultat' is not defined

Variable globale
Une variable globale est une variable créée dans le programme
principal (c'est-à-dire à la racine du fichier .py créé), elle sera
accessible partout : dans les fonctions et dans le programme principal.
1. y = 2 #on déclare la variable globale y
2. def fct(x) :
3. return y+x #on se sert de y dans fct

y est une variable globale car déclarée dans le programme principal. y


est visible dans le programme principal, y compris au sein des
fonctions telles que fct.

3 Appeler une fonction

Appeler une fonction et effectuer un affichage

On a vu dans les paragraphes précédents que pour cela, il suffit


d'écrire le nom de la fonction et de lui fournir un (ou plusieurs)
argument(s) d'entrée qui peut (peuvent) être un nombre, un tuple, une
liste, un dictionnaire etc. ou une variable contenant un des types cités
juste avant. On applique ceci à la fonction ajoute_1 :
1. print(ajoute_1(2)) #affiche 3
2. y = 2 #on déclare la variable globale y
3. print(ajoute_1(y)) #affiche 3

Dans les deux cas, le résultat renvoyé par la fonction est affiché dans
le shell : 3
Attention : l'argument d'entrée fourni à la fonction doit posséder un
type compatible avec les commandes exécutées par la fonction.
Dans les lignes de code précédentes, le nombre 2 puis la variable
globale y sont des arguments d'entrée de la fonction ajoute_1. Tous
deux sont de type int qui est compatible avec la commande x+1
exécutée par la fonction ajoute_1.
En revanche, l'exemple suivant comporte une erreur de type
d'argument d'entrée :
1. print(ajoute_1([1,2,3])) #[1,2,3] n'est pas un nombre

D'où l'erreur : TypeError: can only concatenate list (not "int") to list

Appeler une fonction et effectuer un stockage du/des résultat(s)


Il est souvent utile de stocker le résultat de l'appel d'une fonction dans
une variable :
1. res = ajoute_1(2) #la nouvelle variable res peut être appelée
2. print("res réutilisée pour un calcul : ",2*res)

Le shell affiche 4. On a donc utilisé la nouvelle variable res (affectée


grâce au résultat renvoyé par ajoute_1(2)) pour effectuer un calcul.

Extraire un seul argument de sortie


On appelle la fonction puissances2 avec print(puissances2()).
Un tuple contenant quatre entiers s'affiche dans le shell : (2, 4, 8, 16)

On peut ne souhaiter utiliser que le premier élément du tuple (c'est-à-


dire 2) par exemple. Pour cela il suffit de stocker le résultat que
renvoie la fonction (donc le tuple) dans une nouvelle variable et
d'appeler l'élément du tuple qui nous intéresse :
1. res = puissances2()
2. print("Le 1er élément est :",res[0])
3. #Ou encore :
4. element1 = puissances2()[0]
5. print("Le 1er élément est :",element1)

Dans les deux cas, l'entier 2 s'affiche dans le shell.

4 Les assertions
Des assertions peuvent être utilisées pour garantir des préconditions
ou des post conditions sur les arguments de la fonction.
Exemple :
1. def racine(x) :
2. """Calcule la racine d'un nombre, renvoie le résultat
3. x : un nombre positif ou nul (entier, flottant)
4. resultat : un flottant
5. """
6. assert x>=0
7. resultat = sqrt(x)
8. return resultat

Si on fait appel à cette fonction en choisissant un nombre négatif,


donc en tapant racine(-1), le shell renvoie le message d'erreur :
line 6, in racine
assert x>=0
AssertionError

5 Jeux de tests
Une fois une fonction créée, il faut impérativement vérifier sa validité.
C'est-à-dire qu'elle effectue bien ce pour quoi elle a été conçue.
Pour assurer cette validation, on mettre en œuvre un jeu de tests sous
la forme d'une suite d'appels de la fonction définie. Ces tests doivent
envisager suffisamment de cas afin que le concepteur ait confiance
dans la validité de sa fonction. L'écriture du jeu de test se compose
d'une suite d'assertions.
Exemple :
1. def ajoute_1(x) :
2. return x + 1
3.
4. #Jeu de tests
5. assert ajoute_1(2) == 3
6. assert ajoute_1(-2) == -1

L'exécution de ces lignes ne renvoie rien car les tests effectués sont
vrais. En revanche si on écrit un test qui est faux (comme
assert ajoute_1(2) == -2), on obtient :
assert ajoute_1(-2) == 2
AssertionError

6 Points importants à propos des fonctions

Ne pas oublier les « : »


1. def fct(x) #oubli des :
2. return y+x

Le shell renvoie une erreur : SyntaxError: invalid syntax.

Ne pas oublier l'indentation


Pour rappel, les indentations sont la suite d'espaces devant les
instructions de la fonction.
1. def fct(x)
2. return y+x #oubli indentation

Le shell renvoie une erreur : IndentationError: expected an indented


block.

Ne pas appeler une variable locale dans le programme principal


1. def ajoute_1(x) :
2. resultat = x + 1 #resultat est une variable locale
3. return resultat
4. print(resultat)
Le shell renvoie une erreur car la variable resultat n'est pas visible
dans le programme principal : NameError: name 'resultat' is not defined.

Un print n'équivaut pas à un return


La fonction print( ) permet d'effectuer un affichage mais pas de
renvoyer un ou plusieurs argument(s) de sortie.
1. def ajoute_1(x) :
2. print(x+1)
3.
4. res = ajoute_1(y)
5. print(res)

Le shell affiche : None.


La commande print(x+1) en ligne 2 permet un affichage du résultat du
calcul x+1. Par contre, la fonction ajoute_1 telle que définie ci-dessus ne
renvoie pas d'argument de sortie. Le résultat du calcul x+1 n'est pas
stocké et ne peut pas être réemployé. Ceci explique pourquoi suite à
la ligne 4, la variable res ne contient rien et le shell affiche None.

Un return permet une sortie de fonction


Une fonction peut contenir plusieurs return, notamment dans le cas de
tests if multiples. Cependant dès qu'une instruction return est
exécutée, les lignes suivantes ne sont pas lues.
1. def ajoute_1(x) :
2. return x+1
3. print("Ne sera pas lu")
4.
5. print(ajoute_1(2))

L'affichage du résultat (c'est-à-dire 3) se fait dans le shell mais la


ligne 3 de la fonction n'est pas lue.

Respecter l'ordre et le type des arguments d'entrée


Il faut veiller à respecter l'ordre et le type des arguments d'une
fonction lorsque l'on fait appel à cette fonction.
Par exemple, la fonction ajoute_liste ci-dessous compte deux
arguments d'entrée : x est un nombre et L est une liste.
1. def ajoute_liste(x,L) :
2. """ Calcule x+1 et stocke le résultat dans L"""
3. L.append(x+1)
4. return L
5.
6. x = 2 #x est un nombre de type int
7. L = [] #est de type list
8. print("La liste renvoyée est : ", ajoute_liste(x,L))

L'affichage du résultat donne : La liste renvoyée est : [3]. Alors que si


l'on inverse l'ordre des arguments d'entrée :
9. print("La liste renvoyée est : ", ajoute_liste(L,x))

On obtient : TypeError: can only concatenate list (not “int”) to list.

En effet, les arguments x et L ne peuvent être permutés : ils ne jouent


pas le même rôle dans la fonction ajoute_liste et ne sont pas du même
type.
Exercices

Compétence attendue

➡ Savoir détecter des erreurs de syntaxe et de spécification.

Exercice 5.1
► Analyser

Choisir le programme correct permettant à partir d'un argument


d'entrée x de calculer . La fonction doit s'assurer que le

dénominateur n'est pas nul puis renvoyer le résultat.


a)
1. def F(x) :
2. """renvoie le résultat du calcul 1/(1+x)
3. x : un entier ou réel
4. """
5. assert (1+x) != 0
6. print 1/(1+x)
b)
1. def F(x) :
2. """renvoie le résultat du calcul 1/(1+x)
3. x : un entier ou réel
4. """
5. return 1/(1+x)
c)
1. def F(x)
2. """renvoie le résultat du calcul 1/(1+x)
3. x : un entier ou réel
4. """
5. assert (1+x) != 0
6. return 1/(1+x)
d)
1. def F(x) :
2. """renvoie le résultat du calcul 1/(1+x)
3. x : un entier ou réel
4. """
5. assert (1+x) != 0
6. return 1/(1+x)
e)
1. def F(x) :
2. """renvoie le résultat du calcul 1/(1+x)
3. x : un entier ou réel
4. """
5. assert (1+x) != 0
6. return 1/(1+x)

Compétence attendue

➡ Savoir prototyper une fonction, savoir créer une fonction.


➡ Utiliser des assertions.

Exercice 5.2
► Analyser
a) Écrire une fonction nommée suivant qui prend pour argument un
entier n et renvoie le suivant : n + 1. La fonction doit vérifier que n
est bien un entier. Tester la fonction dans la console.
b) Écrire une fonction nommée suivantbis qui prend pour argument un
entier n et renvoie les deux suivants : n + 1 et n + 2 sous la forme
d'une liste. La fonction doit vérifier que n est bien un entier. Tester
cette fonction dans la console. Accéder au premier élément de la
liste.

Exercice 5.3
► Traduire
Écrire une fonction surface permettant de calculer la surface d'un
rectangle. Elle admettra comme argument d'entrée deux variables l et
L (deux entiers ou flottants positifs ou nuls) correspondant aux deux
côtés du rectangle. La fonction doit vérifier que les arguments d'entrée
sont bien positifs ou nuls. Cette fonction doit renvoyer le résultat.

Compétence attendue

➡ Faire appel à des bibliothèques.

Exercice 5.4
► Traduire

Écrire une fonction perimetre permettant de calculer le périmètre d'un


cercle. Elle admettra comme argument d'entrée une variable r (un
entier ou flottant positif ou nul) correspondant au rayon du cercle. La
fonction doit vérifier que r est bien positif ou nul. Cette fonction doit
renvoyer le résultat.

Compétence attendue

➡ Faire appel à des bibliothèques. Écrire une fonction renvoyant un tuple.

Exercice 5.5
► Traduire, décomposer

Écrire une fonction qui admet comme argument une variable deg (qui
contient une valeur en degrés) et qui réalise les opérations suivantes :
● Convertir l'angle deg en radians et stocker cette grandeur dans une
variable rad.
● Calculer le sinus et le cosinus de rad, renvoyer le résultat de ces
deux calculs.
Appeler la fonction pour un angle dont la valeur est 90 degrés.

Compétence attendue

➡ Faire appel à des variables globales au sein d'une fonction.

Exercice 5.6
► Traduire, décomposer

On peut évaluer l'intensité de la pesanteur g selon l'altitude à laquelle


on se situe h avec :

● RTerre = 6 371 km
● G = 6,67 × 10−11 USI
● mTerre = 6,0 × 1024 kg
Écrire une fonction dans l'éditeur qui permet d'évaluer la constante g à
une altitude h quelconque. Les constantes seront définies dans le
programme principal (en dehors de la fonction). Appeler la fonction et
afficher le résultat pour h = 1 mètre de manière conviviale (c'est-à-dire
avec un peu de texte puis le résultat suivi de son unité SI).

Compétence attendue

➡ Utiliser des jeux de tests pour vérifier la validité d'une fonction.

Exercice 5.7
► Traduire, développer

Écrire une fonction G prenant pour arguments d'entrée deux entiers a


et b et renvoyant la valeur de G(a, b) = a + b − ab. La fonction doit
vérifier que les arguments d'entrée sont bien des entiers.
➡ Proposer un jeu de tests afin de vérifier la validité de la fonction.

Compétence attendue

➡ Repérer dans un nouveau langage de programmation les traits communs et les


traits particuliers à ce langage.

Exercice 5.8
► Développer

La fonction G de l'exercice précédent s'écrit comme suit en Scilab :


function res=G(a,b)
res = a+b-a*b
endfunction

Et en langage C :
int G(int a, int b)
{
int res = 0 ;
res = a+b -a*b ;
return res; // On retourne le résultat du calcul
}

➡ Comparer ces deux écritures à celle en Python.


Exercices-bilan

Exercice-bilan 5.1
45 min ● 10 points
À présent il est temps de laisser libre cours à votre imagination. Dans
le cadre d'un projet, on vous demande de mettre au point une
fonction.
La méthode de résolution de problème appliquée à l'informatique sera
utilisée :
1) Définir
● Quel problème tâche-t-on de résoudre ?
● Quelles sont les contraintes ?
● À quoi ressemble un succès ? Quel est votre objectif ?
2) Préparer
● Rechercher les solutions possibles.
● Élaborer un plan.
3) Essayer
● Mettre en œuvre votre plan.
4) Réfléchir
● Comparer le résultat à l'objectif.
● Quelles sont les améliorations possibles ?
Source : code.org
Il vous faut pour cela définir un problème, ce à quoi sert votre fonction.
Puis préparer une solution et pour cela trouver les arguments d'entrée
et de sortie de la fonction. Ensuite il vous faudra la tester dans
différentes situations. On vous demande ensuite de réfléchir au
résultat obtenu.
Attention, prenez bien soin de spécifier la fonction afin qu'un autre
utilisateur puisse s'en servir facilement.
En fin de séance, les différentes fonctions pourront être présentées à
la classe.

Exercice-bilan 5.2
5 min ● 5 points
Soit un vecteur de trois coordonnées représenté par une liste de trois
entiers.
➡ Écrire une fonction admet pour argument cette liste et qui renvoie
la norme du vecteur.

Exercice-bilan 5.3
10 min ● 5 points
Soit un vecteur de trois coordonnées représenté par une liste de trois
entiers.
➡ Écrire une fonction admet pour argument deux listes représentant
les coordonnées de deux vecteurs et qui renvoie le résultat du
produit scalaire de ces deux vecteurs.
Exercices de type EC - QCM

Pour chaque question, le candidat gagne 3 points s'il choisit la bonne


réponse, perd 1 point s'il choisit une réponse fausse. S'il ne répond
pas ou choisit plusieurs réponses, il ne gagne ni ne perd aucun point.

Exercice EC 5.1
1 min ● 3 points
On tape les lignes suivantes :
1. def F(n ):
2. n = n**2
3. return n+1
4.
5. print(F(3))

Que s'affiche-t-il dans le shell ?


Réponses :
a) 7
b) 10
c) 9
d) 6

Exercice EC 5.2
1 min ● 3 points
On tape les lignes suivantes :
1. def F(x,y):
2. return x/y
3.
4. print(F(2,0))

Que s'affiche-t-il dans le shell ?


Réponses :
a) 2
b) rien cela ne fonctionne pas
c) ZeroDivisionError: division by zero
d) 1

Exercice EC 5.3
1 min ● 3 points
On tape les lignes suivantes :
1. def F(n):
2. n = n**2
3. return n+1
4.
5. print(F(2))

Que s'affiche-t-il dans le shell ?


Réponses :
a) 7
b) 10
c) 9
d) 5

Exercice EC 5.4
1 min ● 3 points
On tape les lignes suivantes :
1. def F(x,y):
2. calcul = x+y
3. return calcul
4.
5. x = 1
6. y = 2
7. print(calcul)

Que dans le shell ?


Réponses :
a) 3
b) NameError: name 'calcul' is not defined
c) 1
d) 4
Corrigé des exercices

Exercice 5.1

Seul le programme e) est correct. Pour les autres il manque soit les
« : », soit l'indentation, soit l'assertion, soit le return.

Exercice 5.2
1. def suivant(n):
2. """renvoie le résultat du calcul n+1
3. n : un entier
4. """
5. return n+1
6.
7. print(suivant(2))
8.
9. def suivant_bis(n):
10. """renvoie n+1 et n+2 sous forme de liste
11. n : un entier
12. """
13. return [n+1,n+2]
14.
15. L = suivant_bis(2)
16. print("1er terme",L[0])

Exercice 5.3
1. def surface(l,L):
2. """renvoie le résultat du calcul l*L
3. l,L : des nombres postifs ou nuls
4. """
5. assert l>=0 and L>=0
6. return l*L
7.
8. print(surface(3,2))

Exercice 5.4
1. from math import pi
2.
3. def perimetre(r):
4. """renvoie le résultat du calcul du perimetre
5. r : un nombre postif ou nul
6. """
7. assert r>=0
8. return 2*pi*r
9.
10. print(perimetre(-1)) #affiche une assertion Error
11. print(perimetre(1)) #affiche 6.283185307179586

Exercice 5.5
1. from math import pi, sin, cos #pour pi, sin( ), cos( )
2.
3. def sincos(deg):
4. """renvoie le résultat des calculs du sin et cos
5. deg : un nombre
6. """
7. rad = deg*pi/180
8. sinus = sin(rad)
9. cosinus = cos(rad)
10. return sinus, cosinus
11.
12. angle = 90
13. si,co = sincos(angle) #affectation de deux variables
14. print("Le cosinus de l'angle vaut :",co)
15. print("Le sinus de l'angle vaut :",si)

Le shell affiche après exécution :


Le cosinus de l'angle vaut : 6.123233995736766e-17
Le sinus de l'angle vaut : 1.0

Exercice 5.6
1. R_Terre = 6371E3 #en m
2. G = 6.67E-11 #USI
3. m_Terre = 6.0E24 #kg
4.
5. def calcul_g(h):
6. """renvoie le résultat du calcul de g
7. h : un nombre
8. """
9. g = G*m_Terre/(R_Terre+h)**2
10. return g
11.
12. print("La valeur de g pour h = 1 m est :",calcul_g(1),"m/s^2")

Le shell affiche après exécution :


La valeur de g pour h = 1 m est : 9.859655431992135 m/s^2

Exercice 5.7
1. def G(a,b):
2. """renvoie le résultat du calcul de a+b-a*b
3. a,b : des entiers
4. """
5. assert type(a)==int and type(b)==int
6. return a+b-a*b
7. #Jeu de tests :
8. assert G(1,1) == 1
9. assert G(-1,1) == 1
10. assert G(1,-2) == 1

Exercice 5.8

En Scilab, tout comme en Python, il n'y a pas besoin de définir le type


des variables avant de s'en servir. Alors qu'en langage C, les
variables a et b sont déclarées au préalable au type integer ainsi que le
résultat res.
Il n'y a pas besoin de return en Scilab.
Il faut des accolades en C.
Pour les trois langages, une fonction, est un mécanisme qui reçoit un
ou des arguments en entrée et renvoie un ou plusieurs arguments en
sortie.
Corrigé des exercices-bilan

Exercice-bilan 5.2
1. from math import sqrt
2. def norme(v):
3. """renvoie le résultat du calcul de la norme du vecteur v
4. v : une liste
5. """
6. x = v[0]
7. y = v[1]
8. z = v[2]
9. return sqrt(x**2+y**2+z**2)

Ou bien plus court :


1. def norme(v):
2. """renvoie le résultat du calcul de la norme du vecteur v
3. v : une liste
4. """
5. return sqrt(v[0]**2+v[1]**2+v[2]**2)

Exercice-bilan 5.3
1. def prod_scalaire(u,v):
2. """renvoie le résultat du calcul du produit scalaire u.v
3. u,v : des listes
4. """
5. x1 = u[0]
6. y1 = u[1]
7. z1 = u[2]
8. x2 = v[0]
9. y2 = v[1]
10. z2 = v[2]
11. return x1*x2+y1*y2+z1*z2
Ou bien plus court :
1. def prod_scalaire(u,v):
2. """renvoie le résultat du calcul du produit scalaire u.v
3. u,v : des listes
4. """
5. return u[0]*v[0]+u[1]*v[1]+u[2]*v[2]
Corrigé des exercices de type EC -
QCM

Exercice EC 5.1

a) 7
b) 10
c) 9
d) 6

Exercice EC 5.2

a) 2
b) rien cela ne fonctionne pas
c) ZeroDivisionError: division by zero
d) 1

Exercice EC 5.3

a) 7
b) 10
c) 9
d) 5
Exercice EC 5.4

a) 3

b) NameError: name 'calcul' is not defined


c) 1
d) 4
Chapitre 6
Séquences conditionnelles et boucles
Cours

1 Les instructions conditionnelles

Un peu d'histoire

Charles Eric Leiserson est un informaticien américain. Il est réputé


comme l'un des coauteurs du livre Introduction to Algorithms. Ce livre
représente un des piliers de l'informatique et référence notamment les
instructions conditionnelles et les boucles.

Rappel sur les tests logiques


La notion de test logique a déjà été abordée dans le chapitre 1 lors de
la présentation des booléens. Pour rappel, voici différents tests
logiques :
Instruction Python Signification

a==b a est égal à b


a>b a est strictement supérieur à b

a<b a est strictement inférieur à b


a>=b a est supérieur ou égal à b
a<=b a est inférieur ou égal à b
a!=b a est différent de b
a<b and b>c a est inférieur à b ET b est supérieur à c
a<b or b>c a est inférieur à b OU b est supérieur à c

a<b ^ b>c a est inférieur à b « ou exclusif » b est supérieur à c


not(True) Le contraire de True
not(False) Le contraire de False

Certains de ces tests peuvent être appliqués aux listes. Par exemple,
si on définit :
1. li = [1,3,5]
2. liste = [1,3,5]
3. liste2 = [[1,3,5], [1,4,6]]

Tests logiques Signification Réponse

li == liste Identique à False


li != liste différente de True
1 in liste présent dans True
li in liste présent dans False

li in liste2 présent dans True

Instruction conditionnelle simple


Une instruction conditionnelle permet d'effectuer une instruction si une
expression logique (aussi appelée test) est vraie.
Si l'on souhaite n'effectuer une instruction que si un test est vrai, on
doit écrire une instruction conditionnelle simple. En pseudo-code cela
donne :

si test alors
instruction1
fin si

Et voici la syntaxe en Python :


1. if test :
2. instruction1

Exemple : on souhaite tester si la variable x est positive et afficher


le texte «x est positif» si le test x>0 renvoie True.
1. x = 1
2. if x > 0 :
3. print("x est positif")

Conseils
Ne pas oublier les « : » à la suite du test ni l'indentation suite aux « : »

Instruction conditionnelle avec alternative


Si on souhaite effectuer une instruction si un test est vrai, une autre si
ce test est faux, il faut proposer une instruction conditionnelle avec
alternative. Soit en pseudo code :

si test alors
instruction1
sinon alors
instruction2
fin si
Ce qui donne en Python :
1. if test :
2. instruction1
3. else :
4. instruction2

Remarque
Le if signifie si, le else signifie sinon.

Exemple : on souhaite tester si la variable x est positive et afficher


"x est positive" si le test x>0 renvoie True. Sinon, on affiche "x est
négatif ou nul".
1. x = 1
2. if x > 0 :
3. print("x est positif")
4. else :
5. print("x est négatif ou nul")

Conseils
Il ne faut pas placer de test à la suite du else. Ne pas oublier les « : » à la suite du
else.

Instruction conditionnelle imbriquée


Si on souhaite effectuer :
● une instruction1 si un test1 est vrai,
● une instruction2 (si test1 est faux) mais que test2 est vrai,
● ou enfin une instruction3 si test1 et test2 sont faux.
Dans ce cas, on doit écrire une instruction conditionnelle imbriquée.
En pseudo code, on peut traduire ceci comme suit :

si test1 alors
instruction1
sinon si test2 alors
instruction2
sinon alors
instruction3
fin si
Et en Python, cela se traduit par :
1. if test1 :
2. instruction1
3. elif test2 :
4. instruction2
5. else :
6. instruction3

Exemple : on souhaite tester si la variable x est positive, nulle ou


négative.
1. x = 1
2. if x > 0 :
3. print("x est positif")
4. elif x == 0 :
5. print("x est nul")
6. else :
7. print("x est négatif")

Remarque
Le elif signifie donc sinon si.

Remarque
Il est possible d'avoir une instruction conditionnelle au sein d'une autre instruction
conditionnelle.
1. if test1 :
2. if test2 :
3. instruction1
4. else :
5. instruction2

Implémentation d'une instruction conditionnelle au sein d'une


fonction
Le programme précédent peut être adapté au sein d'une fonction. Elle
peut par exemple renvoyer True si x est positif et False sinon.
1. def signe(x):
2. """Recherche si un nombre x est positif, nul ou négatif
3. Effectue un affichage, renvoie True si x est positif,
4. False sinon"""
5. if x>0:
6. print("x est positif")
7. return True
8. elif x==0:
9. print("x est nul")
10. return False
11. else :
12. print("x est négatif")
13. return False
14.
15. x = 1 #on déclare x
16. print(signe(x)) #on appelle la fonction et on l'applique à x

L'exécution affiche dans le shell :


x est positif
True

2 Les boucles for

Notion de boucle inconditionnelle

L'intérêt des boucles est d'effectuer, par exemple, un calcul, un


affichage, un test, plusieurs fois sans avoir à réécrire le programme.
Une boucle est donc une séquence d'instructions qui se répète. Cette
séquence doit pouvoir s'arrêter. La répétition de cette séquence peut
être soumise ou non à une condition : on parle de boucle
conditionnelle ou inconditionnelle. Les boucles for sont des boucles
inconditionnelles qui s'arrêtent une fois la fin de la séquence atteinte :
elles sont bornées.
Les boucles for sont particulièrement adaptées lorsque l'on connaît à
l'avance le nombre de fois qu'une séquence devra se répéter.

Les boucles for : itérable de type liste


Un itérable est une grandeur sur laquelle on peut itérer. En d'autres
termes, un itérable est un objet dont on peut parcourir les valeurs (et
dont on connaît à l'avance le nombre de valeurs). En pseudo code, on
peut écrire une boucle for qui itère sur une liste comme suit :

pour i allant de début d'une liste à fin d'une liste


instruction
fin pour

Ce qui se traduit en Python par :


1. for i in liste : #l'itérable est liste
2. instruction

Dans ce cas la variable i prend une à une les valeurs des éléments
de la liste.
Remarque
À remarquer les « : » et l'indentation essentielle suite aux « : ».

Par exemple pour un affichage des éléments d'une liste :


1. liste = [0,1,2,3,4]
2. for i in liste:
3. print("Élément de la liste :",i)

Ceci affiche dans le shell :


Élément de la liste : 0
Élément de la liste : 1
Élément de la liste : 2
Élément de la liste : 3
Élément de la liste : 4

Remarque
De la même manière, l'itérable peut être de type chaîne de caractères ou un dictionnaire.
1. for i in chaîne : #l'itérable est chaîne
2. instruction
3. for i in dictionnaire : #l'itérable est dictionnaire
4. instruction

Exemple : on veut calculer la moyenne d'une liste de nombres.


Pour cela on peut parcourir les éléments de la liste.
● Soit S une variable initialisée à 0, et n le nombre d'éléments de la
liste.
● On parcourt les éléments de liste, un à un grâce à une variable
i. À chaque itération, on ajoute i à la somme S.
● En fin de boucle, on renvoie S/n.
1. def moyenne(liste):
2. """Renvoie la moyenne de liste
3. liste est au format list"""
4. S = 0 #somme initialisée à 0
5. n = len(liste) #nb d'éléments
6. for i in liste : #parcourt les éléments un à un
7. S = S + i #on ajoute chaque élément à S
8. return S/n

On appelle cette fonction et on l'applique à une liste de notes :


1. notes = [12.1,13.0,9.2]
2. print("La moyenne vaut",moyenne(notes))

Et on obtient dans le shell :


La moyenne vaut 11.433333333333332

Exemple : on veut trouver le maximum d'une liste d'entiers. Pour


cela on peut à nouveau parcourir les éléments de la liste.
● Soit maxi une variable initialisée au premier élément de la liste, et
n le nombre d'éléments de la liste.
● On parcourt les éléments de liste, un à un grâce à une variable
i. À chaque itération, on compare i à maxi.
● En fin de boucle, on renvoie maxi.
1. def maximum(liste):
2. """Renvoie le maximum de liste
3. liste est au format list"""
4. maxi = liste[0] #1er élément de la liste
5. for i in liste : #i parcourt les éléments de liste
6. if i>maxi: #si la valeur rencontrée > maxi
7. maxi = i #on affecte la nouvelle valeur à maxi
8. return maxi
9.
10. notes = [12,13,8]
11. print("Le maximum est :",maximum(notes))

On obtient dans le shell :


Le maximum est : 13

Exemple : on veut déterminer si un entier x figure dans une liste


d'entiers.
● On parcourt les éléments de la liste, un à un grâce à une
variable i. À chaque itération, on compare i à x. On renvoie True
si x a été trouvé.
● En fin de boucle, on renvoie False si x n'a pas été trouvé.
1. def chercher(liste,x):
2. """ Renvoie True si x est dans la liste, False sinon
3. x un entier"""
4. for i in liste: #i parcourt les éléments de la liste
5. if i==x: #i comparé à x
6. return True
7. return False #toute la boucle a été effectuée sans trouver

On appelle cette fonction et on l'applique à une liste, on cherche


l'entier 7 :
1. liste = [0,1,2,3,4,5,6,7,8,9]
2. print (chercher(liste,7))

On obtient dans le shell : True.

Remarque
La recherche d'un élément avec for i in liste: implique que le programme va parcourir
un à un les éléments de la liste. Ceci revient à utiliser if i in liste: déjà vu dans le
chapitre précédent.
On a dit à cette occasion que comme une opération sur un ordinateur prend en moyenne
environ 10–9 s, si la liste contient 106 éléments, le programme mettra 10–3 s. Si la liste
contient 1012 éléments, le programme mettra 103 s, etc. Donc le temps de calcul est
proportionnel à la longueur de la liste. On dit que le coût en temps de la fonction chercher
est linéaire.

Les boucles for : itérable de type range( )


Ce type de boucle s'écrit comme suit en pseudo code :
pour i allant de debut à fin par pas de pas
instruction
fin pour

Les variables debut, fin et pas sont des entiers. debut est optionnel et
vaut 0 s'il est omis. De même, pas est optionnel et vaut 1 s'il est omis.
Ce qui donne en Python :
1. for i in range(debut,fin,pas) : #l'itérable est range( )
2. instruction

Par exemple, dans le script suivant i vaudra de 0 à 3 exclus (donc 2) :


1. n = 3
2. for i in range(n): #i vaut 0, puis 1, puis 2
3. print("i vaut :",i)

On obtient dans le shell :


i vaut : 0
i vaut : 1
i vaut : 2

Dans le script suivant i vaudra de 2 à 10 exclus (donc 2) par pas de


2:
1. for i in range(2,10,2): #i vaut 0, 2, 4, 6 puis 8
2. print("i vaut :",i)

On obtient dans le shell :


i vaut : 2
i vaut : 4
i vaut : 6
i vaut : 8

Exemple : on veut trouver le maximum d'une liste d'entiers ainsi


que l'indice du maximum. On doit parcourir les indices des
éléments de la liste.
1. def maximum_indice(liste):
2. """ Renvoie le maximum d'une liste et l'indice du maximum
3. liste au format list
4. maxi est un nombre
5. indice au format int"""
6. maxi=liste[0] #1er élément de la liste
7. indice = 0 #indice initialisé à 0
8. n = len(liste) #nb d'éléments
9. for i in range(n): #i parcourt les indices de liste
10. if liste[i]>maxi: #si la valeur rencontrée > maxi
11. maxi = liste[i] #affecte la nouvelle valeur à maxi
12. indice = i #on modifie l'indice du maximum
13. return maxi, indice

On appelle cette fonction et on l'applique à une liste de notes :


1. notes = [12,13,8,10,19,16]
2. #On stocke les valeurs du maximum et de l'indice :
3. maximum, ind = maximum_indice(notes)
4. print("Le maximum est :",maximum,"et l'indice :",ind)

On obtient dans le shell :


Le maximum est : 19 et l'indice : 4

Coût en temps
Si une fonction (comme somme définie ci-dessous) comporte une boucle
for qui effectue n opérations unitaires, son coût en temps est aussi
linéaire. On dit aussi que sa complexité temporelle est linéaire.
1. def somme(n):
2. """Renvoie la somme des n premiers entiers
3. som : un entier"""
4. som=0
5. for i in range(n): #effectue n itérations
6. som = som+1
7. return som

Il est possible de mesurer le temps de calcul que l'on notera Tn. Le


tracé de Tn en fonction de n donne un nuage de points proche d'une
droite. Les légers écarts à la linéarité peuvent s'expliquer par le fait
que la durée mesurée étant faible (de l'ordre de 0,001 s) celles-ci sont
assez imprécises :
Remarque
Ainsi les fonctions ou scripts impliquant une seule boucle for de l'ordre de n itérations (avec
n la dimension de l'itérable parcouru) ont un coût en temps linéaire. C'est le cas des
fonctions chercher, somme, maximum, maximum_indice, etc.

Les boucles for : construction d'une liste en compréhension


On peut faire appel à une boucle for afin de construire des listes.
Comme cela a été vu dans le chapitre sur les listes, les listes en
compréhension sont utiles pour construire une liste d'entiers ou même
de flottants.
1. L = [i for i in range(5)]
2. print(L)

Cette instruction affiche : [0, 1, 2, 3, 4] et 5 est exclu de cette liste.


Une autre façon de créer cette même liste serait d'écrire :
1. L = [] #liste vide
2. for i in range(5) : #i vaut 0 , puis 1, puis 2, puis 3, puis 4
3. L.append(i) #on ajoute i à la fin de la liste
4. print(L)

3 Les boucles while

Notion de boucle conditionnelle


La boucle while est une séquence d'instructions qui se répète et doit
pouvoir s'arrêter seule. Pour cela, l'exécution de la séquence est
soumise à une condition (aussi appelée test). Tant que la condition
(ou le test) renvoie True, les instructions de la boucle sont effectuées.
La boucle while est appelée pour cela une « boucle conditionnelle ».
La boucle while présente l'avantage (par rapport à la boucle for)
d'effectuer une boucle sans en connaître à l'avance le nombre
d'itérations : elle est non bornée. Une boucle while s'écrit comme suit
en pseudo code :

tant que test vrai


instruction1
fin tant que

Ceci donne en Python :


1. while test : #tant que le test est vrai
2. instruction1 #l'instruction1 est effectuée

Remarque
À remarquer les « : » et l'indentation essentielle suite aux « : ».

Exemple : J'ai planté en 2019 un sapin de Noël qui mesure


1,20 m. Il grandit de 30 cm par an. Je veux le couper quand il
dépassera 5 m. En quelle année devrai-je le couper ?
● Pour cela on initialise l'année et la hauteur du sapin.
● Puis on écrit une boucle while qui incrémente l'année et la
hauteur tant que la hauteur reste inférieure à 7 m.
1. h = 1.2 #initialisation de la hauteur
2. a = 2019 #initialisation de l'année
3. while h<7 :
4. a = a + 1 #incrémentation
5. h = h + 0.3 #incrémentation
6. print("Le sapin sera coupé en", a)
Le sapin sera coupé en 2039

Remarque
Contrairement aux boucles for, les boucles while ne s'incrémentent pas toutes seules. Il
faut initialiser le ou les paramètres en dehors de la boucle et le ou les incrémenter dans la
boucle.

Non terminaison d'une boucle while


Contrairement aux boucles for (inconditionnelles), les boucles while
(conditionnelles) ne s'arrêtent qu'une fois la condition non remplie (test
faux). Ainsi, une boucle while mal écrite peut engendrer une boucle
infinie et il faut alors interrompre l'exécution du programme.
Conseils
Il faut éviter les boucles infinies. On dit dans ce cas que la boucle while ne se termine
pas : sa terminaison n'est pas assurée. Pour cela, il faut choisir une condition qui ne
renvoie pas toujours True. Aussi, le programme suivant est à éviter :

1. i = 0
2. while i<5 :
3. print("Ne s'arrête jamais…")
4. i=i-1 #i sera toujours < 5 car négatif

La condition i<5 reste toujours vraie donc la boucle ne se termine pas.

Application aux suites


On cherche les termes strictement inférieurs à N = 10 d'une suite
croissante et divergente. On définit la suite (un) par :
En Python, pour calculer un nouveau terme, l'instruction est : u = 2*u+1.
On ne connaît pas à l'avance le nombre d'itérations qui vont devoir
être effectuées avant que u<N. Aussi, on définit une fonction suite qui
calcule et affiche les termes u grâce à une boucle while. Cette fonction
(donc procédure) ne renvoie rien mais crée un affichage de chacun
des termes de la suite.
1. def suite(N):
2. """ Affiche les termes de la suite u =2*u+1 qui sont < N
3. N est un nombre
4. Ne renvoie rien"""
5. u = 0 #initialisation
6. while u<N : #condition
7. print("u vaut :",u)
8. u = 2*u+1 #calcul de un+1
9. #on appelle suite pour N = 10
10. N = 10
11. suite(N)

On obtient :
u vaut : 0
u vaut : 1
u vaut : 3
u vaut : 7

Remplacement d'une boucle for par une boucle while


Soit une boucle for utilisée pour afficher « Bonjour » n fois :
1. n = 3 #nb affichage
2. for i in range(n): #i prend les valeurs 0,1,2
3. print("Bonjour")

Pour effectuer une boucle while avec un nombre d'itérations n connu à


l'avance, il suffit de créer un compteur (qui sera incrémenté de 1 à
chaque itération) et de fixer la condition compteur<n :
1. n = 3 #nb affichage
2. compteur = 0 #compteur initialisé à 0
3. while compteur<n : #Condition compteur<n
4. print("Bonjour")
5. compteur=compteur+1 #compteur incrémenté

Aussi la boucle while remplace la boucle for.


Remarque
Donc à nouveau, contrairement à la boucle for, la boucle while ne s'incrémente pas toute
seule. Il faut initialiser compteur en dehors de la boucle et l'incrémenter dans la boucle.

Coût en temps
Les fonctions ou scripts impliquant une seule boucle while qui effectue
de l'ordre de n itérations ont aussi un coût en temps linéaire : donc une
complexité temporelle linéaire. C'est le cas du programme suivant :
1. n = 1000000 #nb affichage
2. compteur = 0 #compteur initialisé à 0
3. while compteur<n : #condition compteur<n
4. print("Bonjour")
5. compteur=compteur+1 #compteur incrémenté

En effet n itérations de coût en temps unitaire de 10–9 s sont


effectuées. Aussi il faut s'attendre à un temps de calcul de l'ordre de
10−9 × 106 = 10−3 s.
Exercices

Compétence attendue

➡ Utiliser des instructions conditionnelles.

Exercice 6.1
► Concevoir

Écrire une fonction qui vérifie si un nombre est un entier ou un réel :


elle renvoie True dans ce cas, False sinon.

Exercice 6.2
► Concevoir, traduire

Créer une fonction permettant de tester la parité d'un entier. Cette


fonction doit renvoyer True si l'entier saisi est pair, False sinon. Pour
cela on peut utiliser le fait que si un entier a est divisible par n, le
résultat du reste de la division euclidienne vaudra 0 : soit en Python
a%n vaudra 0.

Exercice 6.3
► Analyser, traduire

On souhaite tester si une solution chimique est acide, basique ou


neutre. Pour cela on rappelle qu'une solution est dite :
● acide si pH < 7
● basique si pH > 7
● neutre si pH = 7
Créer une fonction permettant de tester si une solution est acide,
basique ou neutre et d'effectuer un affichage correspondant. Cette
fonction admet comme argument d'entrée une valeur pH et ne renvoie
rien. On vérifiera que pH est bien de type entier ou flottant.

Exercice 6.4
► Traduire

Écrire une fonction qui renvoie la valeur de la racine carrée d'un


nombre x s'il est positif ou nul et qui affiche un message d'erreur si ce
nombre est strictement négatif et renvoie False.

Compétence attendue

➡ Utiliser des boucles bornées, estimer leur complexité temporelle.

Exercice 6.5
► Traduire

Écrire une fonction qui cherche un élément x (un entier) dans une liste
d'entiers. La fonction doit renvoyer le booléen True si x se trouve dans
la liste, False sinon.
Pour cette fonction, indiquer la complexité temporelle si la liste
contient n entiers.

Exercice 6.6
► Traduire

Écrire une fonction qui compte le nombre d'éléments dans une liste,
ce sans faire appel à len( ).
Pour cette fonction, indiquer la complexité temporelle si la liste
contient n entiers.

Exercice 6.7
► Traduire
1) Écrire une fonction minimum qui prend en argument une liste d'entiers
et qui renvoie la plus petite valeur contenue dans la liste. Tester
cette fonction sur une liste d'entiers.
2) Modifier cette fonction (en une fonction que l'on appellera min2) pour
qu'elle renvoie l'indice de la première occurrence de la plus petite
valeur.
3) Modifier à nouveau cette fonction (en une fonction que l'on
appellera min3) pour qu'elle renvoie la liste des indices de la plus
petite valeur.
Indiquer la complexité temporelle de chaque fonction dans le cas
d'une liste de n entiers.

Compétence attendue

➡ Repérer dans un nouveau langage de programmation les traits communs et les


traits particuliers à ce langage.

Exercice 6.8
► Développer

On a vu dans le chapitre précédent comment écrire une fonction en


langage Scilab et en langage C. On va à présent s'intéresser à
l'écriture d'une instruction conditionnelle. On s'intéresse pour cela au
programme Python :
1. x = 1
2. if x > 0 :
3. print("x est positif")
4. else :
5. print("x est négatif ou nul")
Celui-ci donne en Scilab :
x = 1;
if x > 0 then
disp("x est positif")
else
disp("x est négatif ou nul")
end;

Et en langage C :
decimal x = 1 ;
if (x>0)
printf("x est positif") ;
else
printf("x est négatif ou nul") ;

➡ Comparer ces deux dernières écritures à celle en Python.

Exercice 6.9
► Développer

On souhaite comparer l'écriture d'une boucle dans divers langages.


On s'intéresse au programme Python :
1. for i in range(0,5):
2. print("i vaut :",i)

Celui-ci donne en Scilab :


for i=0:4
disp(“i vaut :”+string(i))
end;

Et en langage C :
int i ;
for (i =0 ; i <5 ; i++)
{
printf(("%d vaut :",i)
}

➡ Comparer ces deux dernières écritures à celle en Python.

Compétence attendue

➡ Utiliser des boucles non bornées. Estimer leur complexité temporelle.


Exercice 6.10
► Concevoir, traduire

Écrire un script qui affiche les termes inférieurs à 35 de la suite de


Fibonacci définie par :

Exercice 6.11
► Analyser, décomposer

La fonction recherche ci-dessous permet de déterminer si un entier


particulier, passé en paramètre, est présent dans une liste, elle aussi
passée en paramètre.
Préciser pour quelle raison cette première version de la fonction
recherche ne fonctionne pas lors des tests de validation. Proposer une
modification du corps de la fonction. Pour cette fonction appliquée à
une liste de n entiers, indiquer la complexité temporelle.
1. def recherche(liste,x):
2. n = len(liste)
3. i = 0
4. while i<n:
5. if liste[i]==x :
6. return True
7. return False
Exercices-bilan

Exercice-bilan 6.1
45 min ● 15 points
On considère une liste d'individus dont certains sont amis dans un
réseau social.

Personne 1er lien d'amitié avec 2nd lien d'amitié avec

Julie Tom Portillon


Tom Sam Julie
Sam Charlie Tom
Portillon Charlie Julie
Charlie Portillon

Chaque personne est représentée par un numéro :


Personne Numéro

Julie 1
Tom 2
Sam 3
Portillon 4

Charlie 5

Aussi le réseau d'amitié peut être représenté par une liste de listes
notée Facebk. Chaque sous liste appelée paire possède deux valeurs i,
j qui sont au format entier. Cette paire [i, j] représente un lien
d'amitié. Chaque lien d'amitié est représenté de manière unique dans
la liste Facebk. Le réseau d'amitié correspondant aux tableaux ci-
dessus donne donc :
Facebk = [[1,2],[1,4],[2,3],[3,5],[4,5]]
● Écrire une fonction lien(paire,i,j) où paire est une liste à deux
éléments et i et j sont deux entiers, et qui renvoie True si les deux
éléments contenus dans paire sont i et j dans un ordre quelconque ;
et renvoie False sinon.
● Écrire une fonction amis(Facebk,i,j) qui renvoie True s'il existe un lien
d'amitié entre les individus i et j dans le réseau Facebk; et renvoie
False sinon.
● Écrire une procédure ajout_amis(Facebk,i,j) qui modifie le réseau
Facebk pour y ajouter un lien d'amitié entre les individus i et j si ce
lien n'y figure pas déjà.
● Écrire une fonction liste_amis(Facebk,i) qui renvoie la liste des amis
de i dans le réseau Facebk.

Exercice-bilan 6.2
15 min ● 5 points
● Écrire une fonction vdif qui prend en paramètre deux listes de
nombres de même longueur et qui renvoie une nouvelle liste
constituée de la différence terme à terme de ces deux listes (la
première moins la deuxième) :
vdif([1,2,3],[4,5,6]) → [-3,-3,-3]

● Écrire une fonction vsom qui, cette fois, effectue la somme terme à
terme des éléments des deux listes. Cette fonction prend en
paramètre deux listes de nombres et doit renvoyer une nouvelle liste
contenant les sommes des termes des deux listes :
vsom([1,2,3],[4,5,6]) → [5,7,9]

Indiquer la complexité temporelle de ces fonctions dans le cas de


listes de n entiers.
Exercices de type EC - QCM

Pour chaque question, le candidat gagne 3 points s'il choisit la bonne


réponse, perd 1 point s'il choisit une réponse fausse. S'il ne répond
pas ou choisit plusieurs réponses, il ne gagne ni ne perd aucun point.

Exercice EC 6.1
1 min ● 3 points
On tape les lignes suivantes :
1. x,y,z = 1,5,3
2. def F(x,y,z):
3. if y<x :
4. x,y = y,x
5. if z<y :
6. y,z = z,y
7. return x,y,z
8. print(F(x,y,z))

Que s'affiche-t-il dans le shell ?


Réponses :
a) (1,5,3)
b) un tuple
c) (1,3,5)
d) (1,3,3)

Exercice EC 6.2
1 min ● 3 points
On tape les lignes suivantes :
1. x = 1
2. if x > 0 :
3. print("x est positif")
4. else :
5. print("x est négatif ou nul")

Choisir la ou les bonnes affirmations :


Réponses :
a) Les lignes 2 à 5 sont des instructions conditionnelles
b) Les lignes 2 à 5 sont des boucles conditionnelles
c) Les lignes 2 à 5 sont des instructions inconditionnelles
d) Les lignes 2 à 5 sont des boucles inconditionnelles

Exercice EC 6.3
1 min ● 3 points
On tape les lignes suivantes :
1. L = []
2. for i in range(5) :
3. … #on ajoute i à la fin de la liste

Quelle(s) instruction(s) peut/peuvent remplacer les pointillés afin que


la liste L contienne [0,1,2,3,4] ?
Réponses :
a) L.append(i)
b) L+(i)
c) L = L+[i]
d) L = [0,1,2,3,4]

Exercice EC 6.4
1 min ● 3 points
La fonction suivante doit renvoyer le maximum dans une liste
d'entiers :
1. def maximum(liste):
2. maxi = liste[0]
3. for … :
4. if i>maxi:
5. maxi = i
6. return maxi

Quelle instruction peut remplacer les pointillés afin que maximum renvoie
bien le maximum de la liste liste ?
Réponses :
a) i in range(liste) :
b) i in range(len(liste)) :
c) i in liste :
d) i in range(liste)
Corrigé des exercices

Exercice 6.1
1. def nombre(x):
2. """Renvoie True si x est un réel ou un entier, False sinon"""
3. if type(x)==int or type(x)==float :
4. return True
5. else:
6. return False
7.
8. print(nombre(-2.2))
9. print(nombre(4))
10. print(nombre("Bonjour"))

Exercice 6.2
1. def est_pair(a):
2. """ Renvoie True si a est pair, False sinon"""
3. if a%2==0 :
4. print ("a est pair")
5. return True
6. else:
7. print ("a est impair")
8. return False

On teste :
9. x = 4
10. print(est_pair(x)) #On obtient True

Exercice 6.3
1. def test_pH(pH):
2. """ teste la caractère acide, basique ou neutre d'une solution
3. Effectue un affichage, ne renvoie rien
4. Teste si pH est un entier ou un flottant"""
5. assert type(pH)==int or type(pH)==float
6. if pH<7:
7. print("solution acide")
8. elif pH>7:
9. print("solution basique")
10. else :
11. print("solution neutre")
On teste :
12. test_pH(1) #affiche acide
13. test_pH(8) #affiche basique
14. test_pH(7) #affiche neutre

Exercice 6.4
1. from math import sqrt
2. def racine(x):
3. """Renvoie la valeur de la racine carrée d'un nombre x si x>=0
4. affiche un message d'erreur si x<0, renvoie False"""
5. if x>=0 :
6. return sqrt(x)
7. else:
8. print ("Racine impossible")
9. return False
10.
11. print(racine(-2)) #message d'erreur, renvoie False
12. print(racine(4)) #renvoie 2.0

Exercice 6.5

On peut utiliser une boucle for qui parcourt les éléments de la liste.
1. def chercher(liste,x):
2. """ Renvoie True si x est dans liste, False sinon
3. x : un entier"""
4. for i in liste: #i parcourt les éléments de la liste
5. if i==x: #i comparé à x
6. return True
7. return False #toute la boucle a été effectuée sans trouver x

On teste :
8. liste = [0,1,2,3,4,5,6,7,8,9]
9. print (7,"est dans la liste :", chercher(liste,7)) #True

Cette fonction impliquant une seule boucle for de l'ordre de n itérations


(avec n la dimension de la liste parcourue) possède un coût en temps
linéaire (donc une complexité linéaire).
On peut utiliser x in liste :
10. def chercher(liste,x):
11. """ Renvoie True si x est dans la liste, False sinon
12. x : un entier"""
13. if x in liste: #" in " parcourt les éléments de la liste
14. return True
15. return False #toute la liste a été parcourue sans trouver x

On teste :
16. print (7,"est dans la liste :", chercher(liste,7)) #True

On a vu que le « x in liste » était de complexité linéaire. Aussi, cette


nouvelle fonction possède un coût en temps linéaire (donc une
complexité linéaire).

Exercice 6.6

On crée une fonction comptage qui prend comme argument d'entrée


une liste. Au sein de la fonction :
● On crée un compteur initialisé à zéro.
● On parcourt un à un chacun des éléments de la liste. À chaque
itération, compteur est incrémenté de 1.
● En fin de boucle, on renvoie la valeur de compteur.
1. def comptage(liste):
2. """ Renvoie le nombre d'élements d'une liste"""
3. compteur = 0
4. for i in liste: #i parcourt les éléments de la liste
5. compteur = compteur + 1 #compteur incrémenté
6. return compteur

On teste :
7. liste = [0,1,2,3,4,5,6,7,8,9]
8. print(comptage(liste)) #affiche 10
Cette fonction implique une seule boucle for de l'ordre de n itérations
(avec n la dimension de la liste parcourue) et possède un coût en
temps linéaire (donc une complexité linéaire).

Exercice 6.7

On crée une fonction minimum() très similaire à maximum() vue dans la


partie cours :
1. def minimum(liste):
2. """ Renvoie le minimum d'une liste d'entiers
3. mini : un entier"""
4. mini = liste[0] #1er élément de la liste
5. for i in liste: #i parcourt les indices de liste
6. if i<mini: #si la valeur rencontrée < mini
7. mini = i #on affecte la nouvelle valeur à mini
8. return mini
9.
10. L = [10,20,18,4,3,18]
11. print("Le minimum vaut :",minimum(L)) #affiche 3

Pour avoir accès au minimum et à l'indice du minimum :


1. def mini2(liste):
2. """ Renvoie le minimum d'une liste d'entiers ainsi que son indice
3. mini : un entier
4. indice : un entier"""
5. mini=liste[0] #1er élt de la liste
6. indice = 0 #indice initialisé à 0
7. n = len(liste) #nb d'éléments
8. for i in range(n): #i parcourt les indices de liste
9. if liste[i]<mini: #si la valeur rencontrée < mini
10. mini = liste[i] #on affecte la nouvelle valeur à mini
11. indice = i #on modifie l'indice du min
12. return mini, indice
13.
14. print("Minimum :",mini2(L)[0],"et son indice :",mini2(L)[1])
Minimum : 3 et son indice : 4

Pour avoir accès au minimum et à la liste des positions du minimum :


1. def mini3(liste):
2. """ Renvoie la liste des positions du minimum d'une liste
d'entiers
3. mini : un entier
4. indice : un entier"""
5. n = len(liste) #nb d'éléments
6. mini=liste[0] #1er élément de la liste
7. indice = 0 #indice initialisé à 0
8. pos = []
9. #recherche du minimum
10. for i in range(n): #i parcourt les indices de liste
11. if liste[i]<mini: #si la valeur rencontrée < mini
12. mini = liste[i] #on affecte la nouvelle valeur à mini
13. #recherche des positions du minimum
14. for i in range(n): #i parcourt les indices de liste
15. if liste[i]==mini: #si la valeur rencontrée est mini
16. pos.append(i) #on l'ajoute en fin de liste pos
17. return mini, pos
18.
19. L = [10,20,18,3,4,3,18]
20.
21. print("Minimum :",mini3(L)[0],"et la liste de ses
positions :",mini3(L)[1])
Minimum : 3 et la liste de ses positions : [3, 5]

Ces trois fonctions impliquent chacune une seule boucle for de l'ordre
de n itérations (avec n la dimension de la liste parcourue) et possèdent
chacune un coût en temps linéaire.

Exercice 6.8

● En Scilab et en C, les « ; » évitent un affichage systématique.


● La structure conditionnelle simple nécessite un if … then … end
contrairement à Python et C qui se contentent du if.
● Les « : » sont propres à Python.
● La structure d'affichage avec print, disp ou printf est assez similaire
dans les trois langages.

Exercice 6.9

● La boucle for utilise un range(0,5) en Python (donc 5 est exclus)


alors qu'en Scilab le vecteur k = 0:4 s'arrête bien à 4. En C les
bornes sont, elles aussi, assez explicites.
● Les « : » sont propres à Python.

Exercice 6.10

On initialise deux variables u0 et u1. Elles correspondent aux deux


premiers termes de la liste.
Puis tant que u1<35 :
● On affiche u1
● u0 ← u1
● u1 ← u0 + u1
1. u0,u1 = 0,1 #initialisation
2. print(u0, end =" ") #Affichage u0
3. #end permet d'éviter le retour à la ligne, ajoute un espace
4. while u1 < 35 : #les termes supplémentaires qui sont <35
5. print(u1, end =" ") #Affichage u1
6. u0, u1 = u1, u0+u1 #permutation de valeurs

Dans le shell :
0 1 1 2 3 5 8 13 21 34

Exercice 6.11

Il manque l'itération sur i qui permet de sortir de la boucle while : i


reste égal à 0, la condition i<n est toujours vraie. La version modifiée
donne :
1. def recherche(liste,x):
2. n = len(liste)
3. i = 0
4. while i<n:
5. if liste[i] == x :
6. return True
7. i = i+1
8. return False

Cette fonction impliquant une seule boucle while de l'ordre de n


itérations (avec n la dimension de la liste parcourue) possède elle
aussi un coût en temps linéaire.
Corrigé des exercices-bilan

Exercice-bilan 6.1
1. #Lien
2. def lien(paire,i,j):
3. """ Renvoie True si i et j sont dans paire, False sinon
4. paire : une liste de deux éléments
5. i,j : des entiers"""
6. return paire == [i,j] or paire == [j,i]
7.
8. #amis
9. def amis(Facebk,i,j):
10. """ Renvoie True si i et j sont amis dans Facebk, False sinon
11. Facebk : une liste de listes de deux éléments
12. i,j : des entiers
13. paire : une liste"""
14. for paire in Facebk:
15. test = lien(paire,i,j)
16. if test == True:
17. return test
18. return False
19.
20. Facebk = [[1,2],[1,4],[2,3],[3,5],[4,5]]
21. print(amis(Facebk,1,2)) #True car Julie et Tom sont amis
22. print(amis(Facebk,3,4)) #True car Sam et Portillon ne sont pas
amis
23.
24. #ajout_amis
25. def ajout_amis(Facebk,i,j):
26. """Modifie la liste Facebk si [i,j] n'y figure pas déjà
27. Facebk : une liste de listes de deux éléments
28. i,j : des entiers"""
29. if amis(Facebk,i,j)==False :
30. Facebk.append([i,j])
31.
32. Facebk = [[1,2],[1,4],[2,3],[3,5],[4,5]]
33. print(Facebk) #pour vérifier le contenu de Facebk
34. ajout_amis(Facebk,3,4)
35. print(Facebk) #[[1,2],[1,4],[2,3],[3,5],[4,5],[3,4]] : Sam et
Portillon sont bien amis à présent
36.
37. #liste_amis
38. def liste_amis(Facebk,i):
39. """Etablit la liste des amis de i dans le réseau Facebk
40. Facebk : une liste de listes de deux éléments
41. amis, paire : des listes
42. i,j : des entiers"""
43. liste=[]
44. for paire in Facebk:
45. if i in paire:
46. liste.append(paire) #On stocke les paires qui incluent i
47. amis=[]
48. for couple in liste:
49. for j in couple:
50. if j!=i:
51. amis.append(j) #On stocke les amis de i
52. return amis
53.
54. print(liste_amis(Facebk,2)) #Tom est bien ami avec Julie et Sam

Exercice-bilan 6.2
1. #Différence
2. def vdif(liste1, liste2) :
3. """Effectue la différence de deux listes terme à terme
4. liste1, liste 2 et liste 3 des listes """
5. n = len(liste1) #nombre éléments de liste1
6. liste3 = [] #liste3 vide
7. for i in range(n) : #i parcourt les indices de liste1
8. liste3.append(liste1[i]-liste2[i])
9. #ajoute en fin de liste3
10. return liste3
11.
12. liste1 = [1,2,3]
13. liste2 = [4,5,6]
14. print(vdif(liste1, liste2)) # [-3,-3,-3]
15.
16. #Somme
17. def vsom(liste1, liste2) :
18. """Effectue la somme de deux listes terme à terme
19. liste1, liste 2 et liste 3 des listes """
20. n = len(liste1) #nombre d'éléments de liste1
21. liste3 = [] #liste3 vide
22. for i in range(n) : #i parcourt les indices de liste1
23. liste3.append(liste1[i]+liste2[i])
24. #ajout en fin de liste3
25. return liste3
26.
27. print(vsom(liste1, liste2)) # [5,7,9]

Ces deux fonctions impliquent chacune une seule boucle for de l'ordre
de n itérations (avec n la dimension de la liste parcourue). En effet le
range(n) crée n valeurs. Les fonctions possèdent chacune un coût en
temps linéaire.
Corrigé des exercices de type EC -
QCM

Exercice EC 6.1

a) (1,5,3)
b) un tuple
c) (1,3,5)
d) (1,3,3)

Exercice EC 6.2

a) Les lignes 2 à 5 sont des instructions conditionnelles


b) Les lignes 2 à 5 sont des boucles conditionnelles
c) Les lignes 2 à 5 sont des instructions inconditionnelles
d) Les lignes 2 à 5 sont des boucles inconditionnelles

Exercice EC 6.3

a) L.append(i)
b) L+(i)
c) L = L+[i]
d) L = [0,1,2,3,4]
Exercice EC 6.4

a) i in range(liste) :
b) i in range(len(liste)) :
c) i in liste :
d) i in range(liste)
Thème G
Algorithmique
Chapitre 7
Recherche d'une valeur dans une
liste
Cours

1 Recherche séquentielle dans une liste

Parcours séquentiel d'une liste

La façon la plus simple de chercher une valeur dans une liste est de
parcourir un à un les éléments de la liste (de manière séquentielle) et
de comparer ces éléments à la valeur recherchée. Ceci a déjà été
effectué au chapitre précédent avec la fonction chercher de l'exercice
6.5 :
1. def chercher(liste,x):
2. """ Renvoie True si x est dans liste, False sinon
3. x : un entier
4. liste : une liste"""
5. for i in liste: #i parcourt les éléments de la liste
6. if i==x: #i comparé à x
7. return True
8. return False #toute la boucle a été effectuée sans trouver x

On teste :
9. liste = [0,1,2,3,4,5,6,7,8,9]
10. print (7,"est dans la liste :", chercher(liste,7)) #True

On peut aussi utiliser x in liste :


11. def chercher(liste,x):
12. """ Renvoie True si x est dans la liste, False sinon
13. x : un entier
14. liste : une liste"""
15. if x in liste: #" in " parcourt les éléments de la liste
16. return True
17. return False #toute la liste a été parcourue sans trouver x
On teste :
1. print (7,"est dans la liste :", chercher(liste,7)) #True

Il existe une version encore plus compacte avec :


1. def chercher(liste,x):
2. return x in liste

Complexité en temps
La fonction chercher impliquant une seule boucle for de l'ordre de n
itérations (avec n la dimension de la liste parcourue) ou bien faisant
appel à « x in liste » possède un coût en temps linéaire (donc une
complexité linéaire). Aussi le temps de calcul de cette fonction est
proportionnel à la longueur de la liste.
Il y a plus efficace, il s'agit de la recherche dichotomique. Cependant
la liste doit au préalable être triée.

2 Recherche dichotomique dans une liste triée

Un peu d'histoire

La recherche dichotomique est découverte en 1946 dans un article de


John Mauchly (ci-dessus) : un physicien américain qui a co-conçu
l'ENIAC, un des premiers ordinateurs.
Mais l'idée d'utiliser une liste triée pour faciliter la recherche date de
l'an –220 av. J.-C. dans la ville Mésopotamie : Babylone.

Le principe du diviser pour régner


La méthode du diviser pour régner (divide and conquer en anglais)
consiste en trois étapes :
● Diviser : découper un problème initial en sous-problèmes ;
● Régner : résoudre les sous-problèmes ;
● Combiner : calculer une solution au problème initial à partir des
solutions des sous-problèmes.
Cette méthode fournit des algorithmes efficaces comme la recherche
d'un élément dans un tableau trié (recherche dichotomique), le tri (tri
fusion, tri rapide), etc.

Principe de la recherche dichotomique


La recherche dichotomique permet de rechercher un entier (ou une
chaîne de caractères) dans une liste triée ainsi que sa position. Le
principe de la recherche dichotomique d'un entier v dans une liste triée
de n éléments est le suivant :
● si v est égal à la valeur au milieu de la liste notée liste[m], l'entier v
est trouvé, on renvoie sa position ;
● sinon si v < liste[m], on recommence la recherche dans la première
moitié de la liste : liste[0, … , m-1] ;
● sinon on recommence la recherche dans la seconde moitié de la
liste : liste[m, … , n-1].
Ce qui donne en pseudo-code :

debut ← 0
fin ← n-1
m ← int((debut+fin)/2)
tant que debut <= fin
si v = liste[m] alors
renvoyer m
sinon si liste[m] >v alors
fin ← m
sinon
debut ← m+1
fin si
m ← int((debut+fin)/2)
fin tant que

Remarque
debut, fin sont des indices. m est l'indice du milieu de la liste, on doit le transformer au
format entier avec int.

Si on déroule ce pseudo-code sur un exemple :

Soit en Python :
1. def dichotomie(liste,v):
2. """ Recherche l'entier v dans une liste triée
3. Renvoie la position de v s'il est dans liste, False sinon
4. liste : une liste triée
5. v : un entier"""
6. debut = 0 #indice de debut initialisé à 0
7. fin = len(liste)-1
8. #indice de fin initialisé à l'indice maximum de liste
9. m = int((debut+fin)/2) #renvoie la partie entière
10. while debut <= fin : #s'arrête dès que debut > fin
11. if liste[m] == v : #si v est trouvé
12. return m #on renvoie son indice
13. elif liste[m] > v :
14. fin = m-1 #on cherche dans la liste inférieure
15. else :
16. debut = m+1 #on cherche dans la liste supérieure
17. m = int((debut+fin)/2) #m actualisé
18. return False #on n'a pas trouvé v
19.
20. liste = [1,3,6,9]
21. print(dichotomie(liste,9)) #affiche 3
Coût en temps
On veut comparer l'ordre de grandeur des temps d'exécution Tn
rencontrés pour des algorithmes de recherche d'un entier
(quelconque) dans une liste triée. On détermine expérimentalement le
temps de calcul Tn pour des listes de longueurs n différentes : n = 102
et n = 105. Les calculs tournent sur un ordinateur pour lequel une
opération possède un temps unitaire de 10−9 s.
Type de recherche Tn si n = 102 Tn si n = 105

dichotomique 2.10−9 s 5.10−9 s

séquentielle 10−7 s 10−4 s

La recherche dichotomique a un coût en temps logarithmique, c'est-


à-dire que le temps de calcul est proportionnel à log(n). La recherche
séquentielle possède un temps de calcul proportionnel à n. La
recherche dichotomique est donc en moyenne plus rapide que la
recherche séquentielle : en effet log(n) < n.
Remarque
Bien sûr, si le nombre recherché est placé en début de liste, la recherche séquentielle est
plus avantageuse.

Terminaison de la boucle while


La condition d'arrêt est while debut <= fin. Or debut augmente par pas
de 1, fin diminue par pas de 1 donc à un moment debut devient
supérieur à fin. On sort alors de la boucle while. L'algorithme se
termine.
Exercices

Compétence attendue

➡ Écrire un algorithme de parcours séquentiel d'un tableau.


➡ Écrire un algorithme de recherche dichotomique dans un tableau trié.

Exercice 7.1
► Analyser, traduire

L'instruction random.randrange(n) effectue un tirage aléatoire d'un entier


compris entre 0 (inclus) et 100 exclus. On construit tout d'abord une
liste en compréhension de 100 éléments en effectuant 100 tirages
aléatoires. On trie les éléments de la liste avec L.sort( ).
1. import random as random
2. n = 100
3. L = [random.randrange(n) for i in range(n)]
4. L.sort()
5. print(L)

1) Rechercher la présence d'un entier quelconque dans L par une


méthode séquentielle de recherche. On doit utiliser une fonction qui
renvoie True si l'entier est présent dans la liste, False, sinon.
2) Rechercher à nouveau la présence d'un entier quelconque dans L
mais cette fois par dichotomie. La fonction utilisée doit renvoyer True
si l'entier est présent dans la liste, False, sinon.
3) Grâce à l'instruction time (dont l'utilisation est détaillée ci-dessous),
comparer le temps de calcul associé à chaque méthode de
recherche de l'entier 100000 dans une liste aléatoire de n = 106
éléments.
1. from time import time #on importe time
2. t0=time() #chronomètre lancé
3. #ligne de code à chronométrer
4. t1=time() #chronomètre arrêté
5. print("La durée du calcul en secondes est :",t1-t0)

Exercice 7.2
► Traduire, développer

On attribue un numéro à divers personnages :


Personne Numéro

Julie 1

Tom 2

Sam 3

Portillon 4

Charlie 5

Ceci se traduit par la liste :


Pers = [['Julie',1],['Tom',2],['Sam',3],['Portillon',4],['Charlie',5]]

➡ Écrire une fonction qui permet de rechercher de manière


séquentielle si un personnage de numéro x (un entier) quelconque
est présent dans la liste. Cette fonction doit renvoyer le nom du
personnage en question s'il est présent dans la liste, False sinon.
Exercices de type EC - QCM

Pour chaque question, le candidat gagne 3 points s'il choisit la bonne


réponse, perd 1 point s'il choisit une réponse fausse. S'il ne répond
pas ou choisit plusieurs réponses, il ne gagne ni ne perd aucun point.

Exercice EC 7.1
1 min ● 3 points
Citer un (ou plusieurs) inconvénient(s) à la recherche d'un entier dans
une liste par la méthode de dichotomie ?
Réponses :
a) La liste ne doit pas être trop longue (maximum 10000 termes).
b) La liste doit être triée.
c) La liste ne peut pas contenir des entiers négatifs.
d) La liste sera modifiée en fin de recherche.

Exercice EC 7.2
1 min ● 3 points
Quelle est le coût en temps de la fonction suivante ?
1. def chercher(liste,x):
2. if x in liste:
3. return True
4. return False

Réponses :
a) Il s'agit d'un coût logarithmique.
b) Il s'agit d'un coût linéaire
c) Il s'agit d'un coût quadratique.
d) Il s'agit d'un coût semi-logarithmique.

Exercice EC 7.3
1 min ● 3 points
Quelle est le coût en temps de la fonction suivante ?
1. def dichotomie(liste,v):
2. debut = 0
3. fin = len(liste)-1
4. m = int((debut+fin)/2)
5. while debut <= fin :
6. if liste[m] == v :
7. return m
8. elif liste[m] > v :
9. fin = m-1
10. else :
11. debut = m+1
12. m = int((debut+fin)/2)
13. return False

Réponses :
a) Il s'agit d'un coût logarithmique.
b) Il s'agit d'un coût linéaire
c) Il s'agit d'un coût quadratique.
d) Il s'agit d'un coût semi-logarithmique.

Exercice EC 7.4
1 min ● 3 points
On cherche l'entier 8 dans une liste L de n = 20000 termes triée :
L = [1, 4, 9, 8, 10, 12, 13, 15, 16, …, 100, …, 199999, 200000]

Il n'y a pas de doublons dans cette liste. Quelle sera la fonction la plus
rapide ?
1. def chercher(liste,v):
2. if v in liste:
3. return True
4. return False
5.
6. def dichotomie(liste,v):
7. debut = 0
8. fin = len(liste)-1
9. m = int((debut+fin)/2)
10. while debut <= fin :
11. if liste[m] == v :
12. return m
13. elif liste[m] > v :
14. fin = m-1
15. else :
16. debut = m+1
17. m = int((debut+fin)/2)
18. return False

Réponses :
a) La fonction chercher.
b) La fonction dichotomie.
c) Aucune des deux : le temps de calcul sera à peu près le même.
d) La fonction dichotomie qui fait appel à chercher.
Corrigé des exercices

Exercice 7.1

On crée la liste de nombres aléatoires :


1. import random as random
2. n = 100
3. L = [random.randrange(n) for i in range(n)]
4. L.sort()
5. print(L)

Cela donne par exemple :


[0, 1, 4, 4, 5, 7, 7, 7, 8, 8, 9, 9, 9, 11, 13, 15, 16, 17, 20, 23, 23, 24,
24, 25, 27, 28, 29, 29, 30, 30, 30, 31, 32, 34, 35, 35, 36, 37, 37, 38, 38,
39, 41, 42, 43, 44, 45, 45, 45, 47, 47, 48, 48, 49, 49, 51, 51, 53, 54, 57,
58, 59, 60, 60, 64, 69, 71, 72, 72, 73, 74, 75, 78, 79, 81, 82, 82, 84, 84,
85, 85, 85, 86, 86, 86, 87, 87, 87, 90, 91, 91, 92, 92, 92, 93, 93, 94, 97,
97, 98]
1) On crée une fonction de recherche séquentielle :
1. def chercher(liste,x):
2. """ Recherche l'entier v dans une liste
3. Renvoie la position de v s'il est dans liste, False sinon
4. liste : une liste"""
5. for i in liste: #i parcourt les éléments de la liste
6. if i==x:
7. return True #si ce return est effectué, on sort de la fonction
8. return False #toute la boucle a été effectuée sans trouver x
9. print(chercher(L,60)) #False

2) On crée une fonction de recherche dichotomique :


1. def dichotomie(liste,v):
2. """ Recherche l'entier v dans une liste triée
3. Renvoie la position de v s'il est dans liste, False sinon
4. liste : une liste triée
5. v : un entier"""
6. debut = 0 #indice de debut initialisé à 0
7. fin = len(liste)-1
8. #indice de fin initialisé à l'indice maximum de liste
9. m = int((debut+fin)/2) #renvoie la partie entière
10. while debut <= fin : #s'arrête dès que début > fin
11. if liste[m] == v : #si v est trouvé
12. return True #on renvoie True
13. elif liste[m] > v :
14. fin = m-1 #on cherche dans la liste inférieure
15. else :
16. debut = m+1#on cherche dans la liste sup.
17. m = int((debut+fin)/2)
18. return False #on n'a pas trouvé v
19. print(dichotomie(L,60))

Conseils
Se souvenir des fonctions du cours.

3) On crée une liste aléatoire de n = 106 termes, on mesure le temps


de calcul associé à chaque fonction :
1. n = 10**6
2. L = [random.randrange(n) for i in range(n)]
3. L.sort()
4. t0=time() #chronomètre lancé
5. dichotomie(L,100000)
6. t1=time() #chronomètre arrêté
7. print("La durée du calcul pour dichotomie est :",t1-t0,"s")
8.
9. t0=time() #chronomètre lancé
10. chercher(L,100000)
11. t1=time() #chronomètre arrêté
12. print("La durée du calcul pour trouver est :",t1-t0,"s")

On obtient :
La durée du calcul pour dichotomie est : 2.6941299438476562e-05 s
La durée du calcul pour chercher est : 0.013746976852416992 s

Donc la recherche dichotomique est bien plus rapide que la méthode


séquentielle pour la recherche du nombre 100000.
Remarque
Pour aller plus loin, on pourrait faire exécuter 100 fois (par exemple) la procédure pour 100
nombres différents et calculer le temps moyen nécessaire pour chacune des méthodes.
Exercice 7.2

On choisit un parcours séquentiel car la liste est courte donc le coût


en temps importe peu :
1. Pers = [['Julie',1],['Tom',2],['Sam',3],['Portillon',4],
['Charlie',5]]
2.
3. def trouver(liste,x):
4. """ Recherche l'entier x dans une liste de listes du type :
['Personnage',entier]
5. Renvoie le nom du personnage si x dans liste, False sinon
6. for i in liste: #i parcourt les éléments de la liste
7. if i[1]==x:
8. return i[0] #renvoie le nom du personnage
9. return False
10.
11. print(trouver(Pers,3)) #On obtient Sam

Conseils
Se souvenir qu'on accède au premier élément d'une liste avec liste[0], le second
avec liste[1].
Corrigé des exercices de type EC -
QCM

Exercice EC 7.1

a) La liste ne doit pas être trop longue (maximum 10000 termes).


b) La liste doit être triée.
c) La liste ne peut pas contenir des entiers négatifs.
d) La liste sera modifiée en fin de recherche.

Exercice EC 7.2

a) Il s'agit d'un coût logarithmique.


b) Il s'agit d'un coût linéaire
c) Il s'agit d'un coût quadratique.
d) Il s'agit d'un coût semi-logarithmique.

Exercice EC 7.3

a) Il s'agit d'un coût logarithmique.


b) Il s'agit d'un coût linéaire
c) Il s'agit d'un coût quadratique.
d) Il s'agit d'un coût semi-logarithmique.

Exercice EC 7.4
a) La fonction chercher.
b) La fonction dichotomie.
c) Aucune des deux : le temps de calcul sera à peu près le même.
d) La fonction dichotomie qui fait appel à chercher.

En effet l'entier est situé en début de liste.


Chapitre 8
Les méthodes de tri de listes
Cours

1 Nécessité de trier
Les méthodes de tri sont essentielles dans la
manipulation de données. En effet, une fois
des données stockées (comme des livres
rangés dans une bibliothèque, des mots
rangés dans un dictionnaire, des copies de
baccalauréat stockées dans un centre
d'examen), on souhaite y accéder et ce travail
est facilité lorsque les données sont triées.

En effet, pour rechercher un élément dans une


liste, il est beaucoup plus simple que ces
éléments soient ordonnés : pour rechercher un
livre à la bibliothèque, mieux vaut qu'ils soient
classés par ordre alphabétique, même chose
pour la recherche d'un mot dans un
dictionnaire.

Un peu d'histoire
Depuis les débuts de l'informatique, les algorithmes de tri ont fait
l'objet de nombreuses recherches.
Betty Holberton (née Snyder), qui a travaillé sur ENIAC et UNIVAC
(les premiers ordinateurs), compte parmi les auteurs des premiers
algorithmes de tri (vers 1951). De nouveaux algorithmes sont toujours
en cours d'invention, comme le Timsort assez récent
car datant de 2002.

Des algorithmes de tri variés


Il existe pour cela des dizaines d'algorithmes de tri et
leurs variantes. On utilisera dans ce livre des tris par
comparaisons qui s'appuient sur la comparaison deux
à deux des éléments d'une liste. Parmi les tris les plus
simples on nomme le tri par insertion et le tri par
sélection.
Les algorithmes de tri se distinguent de par leur :
● Complexité temporelle (donc leur coût en temps) : les plus lents sont
les tris par insertion et par sélection, les plus rapides, le tri rapide et
le tri fusion.
● Complexité spatiale (donc l'espace mémoire occupé) : Il est possible
de trier une liste en place (la liste à trier est alors modifiée) ou pas
en place (on crée une copie de la liste à trier, on ne trie que cette
copie). Si on ne souhaite pas conserver la liste d'origine, le tri en
place est préférable car il économise de l'espace mémoire.
Vocabulaire à connaître
Retenir la différence entre complexité spatiale et temporelle.

Le tri par insertion et le tri par sélection sont simples à écrire mais
assez peu performants d'un point de vue complexité temporelle. Il est
possible de les écrire en place et donc d'avoir une assez bonne
complexité spatiale.

Algorithmes de tri disponibles en Python


Python possède des méthodes associées aux listes qui permettent
d'effectuer un tri. Si t est une liste à trier :
>>> t.sort() #trie en place la liste t
>>> sorted(t) #renvoie une copie triée de la liste t

Remarque
Si la liste t est une liste de listes comme [[a1,b1],[a2,b2]]. Le tri s'applique par défaut aux
premiers éléments de chaque sous-liste : a1 et a2 ici.
2 Tri par insertion

Principe

Il s'agit du principe du tri d'un jeu de cartes (on range une carte
piochée dans son jeu déjà̀ classé). Pour l'appliquer, on parcourt les
éléments d'une liste et on insère successivement chaque élément
dans la liste déjà triée.
Cet algorithme est assez lent, en revanche le tri par insertion est
relativement efficace lorsqu'il s'agit de trier de courtes listes. Il est
assez simple à écrire. Il s'agit d'un tri en place.
Exemple : On veut trier les éléments 9, 3, 1 (un as), 6 représentés
par la liste [9,3,1,6]

Pour cela, on considère que la première carte 9 est à sa place


dans le jeu. Puis, on s'intéresse au 3 : on le permute avec le 9.
Puis, on s'intéresse au 1 (l'as) : on le permute avec le 9 et le 3.

Et enfin au 6 : on le permute avec le 9.

Soit le résultat final :


Pseudo-code
Le principe est le suivant : on écrit deux boucles qui s'appliquent à
une liste t de n éléments :
● une boucle for qui étudie les indices i de la liste t de 1 à n – 1 ;
● dans cette boucle est imbriquée une boucle while : on compare deux
éléments voisins de la liste. Tant que l'élément t[i] < t[i-1], on les
permute.
Ce, jusqu'à avoir trouvé la bonne place pour t[i].
On ne renvoie rien car la liste est triée en place.
Soit en pseudo-code :

n ← nombre d'éléments de t
pour i allant de 1 à n-1
tant que i > 0 et t[i] < t[i-1]
permuter t[i] et t[i-1]
i ← i - 1
fin tant que
fin pour

Tri par insertion en Python


Ce qui donne la procédure suivante en Python :
1. def tri_insertion(t):
2. """Procédure qui trie la liste t en place
3. t : une liste d'entiers
4. Ne renvoie rien"""
5. n = len(t)
6. for i in range(1,n):
7. while i>0 and t[i] < t[i-1]: #t[i] mal placé
8. t[i-1],t[i] = t[i],t[i-1] #permute t[i] et t[i-1]
9. i = i - 1 #on descend dans les indices
10. #pour continuer à tester si t[i] bien placé
Remarque
Il n'y a pas de return car cette fonction (procédure plus exactement du coup) ne renvoie
rien. Elle modifie t en place.

On applique cette procédure à la liste t avec tri_insertion(t) :


1. t = [9, 3, 1, 6]
2. tri_insertion(t)
3. print(t)

Pour vérifier l'impact sur la liste t, il faut un print(t), en effet la fonction


en elle-même ne renvoie rien. L'affichage donne : [1, 3, 6, 9]
Ainsi la liste t a été modifiée et triée.

Le tri étape par étape


Soit la liste t : les indices i vont de 0 à 3 et vont être parcourus par la
boucle for.
Il y a n = 4 éléments à trier.

Indice de lecture : i = 1

boucle for : t[1] analysé sur la boucle for : l'élément est jaune.
boucle while : en gris t[0] comparé à t[1]. Donc permutation entre le
« 3 » et le « 9 ».

Indice de lecture : i = 2

boucle for : t[2] analysé sur la boucle for.


boucle while : t[1]=9 comparé à t[2] = 1, on les permute. Puis t[0] = 3
comparé à « 1 », on les permute.

Indice de lecture : i = 3

boucle for : t[3] analysé sur la boucle for.


boucle while : t[2] est supérieur à « 6 », donc permutation.
t[1] est inférieur à « 6 » donc il n'y a pas permutation.

Fin de la boule for, le tri est fini :

Complexité temporelle
On s'intéresse au nombre de comparaisons effectuées.
● Dans le meilleur des cas : la liste est déjà triée par ordre croissant.
La boucle for effectue n – 1 itérations : on effectue n – 1
comparaisons. Soit de l'ordre de n opérations. On dit que le coût en
temps est linéaire.
● Dans le pire des cas : la liste est triée par ordre décroissant. La
boucle for effectue toujours n – 1 itérations (soit de l'ordre de n
opérations). i varie de 1 à n − 1. À chaque pas, la boucle while
effectue i comparaisons. Le nombre de comparaisons au total est :
1 + 2 + … + (n − 2) + (n − 1) : soit de l'ordre de n opérations
La boucle while étant imbriquée dans la boucle for, on effectue au
maximum de l'ordre de n × n opérations. On dit que le coût en
temps est quadratique.

Notion d'invariant de boucle


Vocabulaire à connaître
Un algorithme est correct (ou valide) s'il fait ce qu'on attend de lui : c'est-à-dire s'il renvoie
le résultat escompté.

Un invariant est une hypothèse pouvant être vraie ou fausse. Les


invariants de boucles servent, entre autres, à prouver la correction
(autrement dit la validité) d'un algorithme comportant une ou plusieurs
boucles for ou while.
Un invariant de boucle est une proposition qui :
● est vraie avant d'entrer dans la boucle (initialisation) ;
● reste vraie après une itération, si elle était vraie avant
(conservation) ;
● donne le résultat attendu en fin de boucle (terminaison).
Si, pour un algorithme donné, il existe un invariant, c'est-à-dire une
hypothèse H qui vérifie l'initialisation, la conservation, et la
terminaisson, alors on dit que l'algorithme est valide.

Validité du tri
On choisit comme invariant de boucle H : « la liste L[0:i+1] est triée
par ordre croissant à l'issue de l'itération i ».
Initialisation
Avant d'entrer dans la boucle, i = 0, la liste est constituée du terme au
rang 0 : [L[0]]. Ce qui est identique à L[0:0+1]. Cette liste constituée
d'un seul terme est forcément triée. Donc l'hypothèse H est vraie.
Conservation
On se place à la
fin de l'itération i. la liste
L[0:i+1] = [L[0], L[1], …,L[i]] est supposée triée dans l'ordre croissant
si H est vraie. On effectue un nouveau tour de boucle donc on se
place à l'itération i + 1. La boucle effectue le tri au rang i + 1 :
1. while i+1>0 and t[i+1] < t[i]: #au rang i+1 au lieu de i, teste si
t[i+1] mal placé
2. t[i],t[i+1]=t[i+1],t[i] #permute t[i+1] et t[i]
3. …

Alors la liste L[0:i+2] = [L[0], L[1], …, L[i], L[i+1]] devient triée dans
l'ordre croissant. L'hypothèse H reste vraie.
Terminaison
En sortie de boucle, i a pris sa dernière valeur i = n − 1, et la boucle
permet d'effectuer le tri au rang n − 1 :
1. while n-1>0 and t[n-1] < t[n-2]: #au rang n-1 au lieu de i, teste
si t[n-1] mal placé
2. t[n-2], t[n-1] = t[n-1], t[n-2] #permute t[n-1] et t[n-2]
3. …

La fonction ne contient pas de return mais le tri est effectué


directement sur la liste L qui est modifiée à chaque itération. La liste L
est donc triée dans l'ordre croissant et la fonction tri a rempli son
objectif. L'algorithme est valide.

3 Tri par sélection


Tout comme le tri par insertion, la complexité du tri par sélection est
quadratique. Il s'agit donc d'un algorithme assez lent : les algorithmes
de tri rapide et tri fusion sont bien plus performants lorsqu'il s'agit du tri
de longues listes.

Principe
On parcourt les éléments d'une liste et on cherche le minimum, on le
permute avec le premier élément de la liste. Puis on parcourt le reste
des éléments de la liste et on cherche le nouveau minimum, on le
permute avec le nouveau premier élément de la liste, etc.
Exemple : On veut trier les éléments 9, 3, 1 (un as), 6 représentés
par la liste [9,3,1,6] donc le jeu de cartes suivant :
Pour cela, on cherche le minimum (le « 1 » donc l'as). On le
permute avec le « 9 ».

Puis, le prochain minimum est le « 3 ». Il est bien placé donc pas


de permutation nécessaire.
Et enfin le prochain minimum est « 6 » : on le permute avec le
« 9 ».

Soit le résultat final :

Pseudo-code
Le principe est le suivant : on utilise deux fonctions afin de trier une
liste t de n éléments. La fonction minimum détermine l'indice du
minimum d'une liste t[j,n-1] donc comprise entre les indices j et n-1.
Soit le pseudo-code de la fonction minimum(t,j) :

indice ← j
mini ← t[j]
n ← nombre d'éléments de t
pour i allant de j+1 à n-1
si t[i] < mini
indice ← i
mini ← t[i]
fin si
fin pour
renvoyer indice

On se sert de cette fonction dans la fonction principale tri_selection


que l'on applique à la liste t.
Le principe de la fonction tri_selection est le suivant : on écrit une
boucle qui parcourt les indices j de la liste t allant de 0 à n-2.
● on cherche le minimum de la liste t[j,n-1]
● on permute ce minimum avec le premier élément de la liste t[j,n-1].
On ne renvoie rien car la liste est triée en place.
Soit le pseudo-code de la fonction tri_selection(t) :

n ← nombre d'éléments de t
pour i allant de 0 à n-2
i_min ← minimum(t,j)
si i différent de j alors
permuter t[i] et t[j]
fin si
fin pour

Tri par sélection en Python


On écrit donc la fonction minimum(t, j) en Python :
1. def minimum(t, j):
2. """ Recherche de l'indice du minimum d'une liste d'entiers
3. t : une liste d'entiers
4. indice : un entier"""
5. indice, mini = j, t[j]
6. n = len(t)
7. for i in range(j+1,n):
8. if t[i] < mini:
9. indice, mini = i, t[i]
10. return indice

On écrit ensuite la procédure tri_selection(t) en Python :


1. def tri_selection(t):
2. """ Procédure qui trie la liste t en place
3. t : une liste d'entiers
4. Ne renvoie rien"""
5. n = len(t)
6. for j in range(n-1):
7. indice = minimum(t, j)
8. if indice != j:
9. t[indice], t[j] = t[j], t[indice]

Remarque
Il n'y a pas de return car cette fonction ne renvoie rien. Elle modifie t en place.

On applique cette procédure à la liste t avec tri_insertion(t) :


1. t = [9, 3, 1, 6]
2. tri_selection(t)
3. print(t)

Pour vérifier l'impact sur la liste t, il faut bien un print(t), car tout
comme pour le tri par insertion, la fonction en elle-même ne renvoie
rien. L'affichage donne : [1, 3, 6, 9]
Ainsi la liste t a été modifiée et triée.

Complexité temporelle
On s'intéresse au nombre de comparaisons effectuées.
La liste est triée par ordre décroissant. La boucle for de tri_selection
effectue n − 1 itérations (soit de l'ordre de n opérations). À chaque
itération, la fonction minimum est appelée. Elle même effectue n − (j + 1)
itérations. Soit de l'ordre de n opérations.
On a globalement de l'ordre de n × n opérations. On dit que la
complexité est quadratique.

Validité du tri
En choisissant l'invariant de boucle H : « la liste L[0:i+1] est triée par
ordre croissant à l'issue de l'itération i », on peut montrer de la même
manière que pour le tri par insertion que cet algorithme est valide.
4 Ordre de grandeur des temps d'exécution
On peut illustrer l'ordre de grandeur des temps d'exécution Tn
rencontrés pour des algorithmes de tri vus dans ce chapitre et celui du
tri fusion non développé dans ce livre. Pour cela, il suffit de déterminer
expérimentalement le temps de calcul Tn pour des listes de longueurs
n différentes : on reprend ici n = 102 et n = 105 comme dans le
chapitre précédent. Les calculs tournent sur un ordinateur pour lequel
une opération possède un temps unitaire de 10−9 s.

Type de tri Tn si n = 102 Tn si n = 105

Insertion 10−5 s 10 s

Sélection 10−5 s 10 s

Fusion 2,0 × 10−7 s 5,0 × 10−4 s

On se rend compte que les tris par sélection et par insertion sont donc
simples mais assez lents en termes d'exécution en particulier pour
des listes longues.
Exercices

Compétence attendue

➡ Savoir mettre en œuvre une méthode de tri : tri par insertion ou tri sélection.

Exercice 8.1
► Analyser, concevoir

On donne le code suivant :


1. def tri(t):
2. n = len(t)
3. for i in range(1,n):
4. while i>0 and t[i] < t[i-1]:
5. …

➡ Le compléter afin de trier la liste [10,11,24,-2] et effectuer le tri.

Exercice 8.2
► Analyser, concevoir

On souhaite trier la liste de listes Pers selon le numéro situé en


deuxième position dans les sous-listes que contient Pers :
Pers = [['Portillon',4], ['Sam',3], ['Julie',1], ['Tom',2],
['Charlie',5]]

➡ Proposer une fonction mettant en œuvre un algorithme de tri au


choix permettant de trier la liste Pers.
Compétence attendue

➡ Concevoir un nouvel algorithme de tri.

Exercice 8.3
► Analyser, traduire

On souhaite cette fois trier la liste de listes Pers selon le numéro (donc
situé en deuxième position dans les sous-listes) :
Pers = [['Sam',3], ['Julie',1], ['Tom',2], ['Portillon',4],
['Charlie',5]]

Mais cette fois, seul un élément est mal trié. Il s'agit de la liste
['Sam',3] qui correspond à l'élément de Pers d'indice i=0, soit l'élément
Pers[0]. Proposer une fonction mettant en œuvre un algorithme de tri
conçu par vous-même permettant de trier la liste Pers. On ne replacera
que l'élément mal placé, sans trier toute la liste.
Pour cela, on pourra utiliser les lignes (dans l'ordre de votre choix) :
1. del Pers[0] #afin de supprimer l'élément mal placé et
2. Pers.insert(i, mal_placee) #afin d'insérer la liste mal_placee (à
déterminer) à l'indice i (à déterminer).
Exercices de type EC - QCM

Pour chaque question, le candidat gagne 3 points s'il choisit la bonne


réponse, perd 1 point s'il choisit une réponse fausse. S'il ne répond
pas ou choisit plusieurs réponses, il ne gagne ni ne perd aucun point.

Exercice EC 8.1
1 min ● 3 points
On dispose de la fonction suivante :
1. def mystere(t):
2. n = len(t)
3. for i in range(1,n):
4. while i>0 and t[i] < t[i-1]:
5. t[i-1],t[i] = t[i],t[i-1]
6. i = i - 1

De quel type d'algorithme s'agit-il ?


Réponses :
a) Il s'agit d'un tri à bulles
b) Il s'agit d'un algorithme de dichotomie
c) Il s'agit d'un tri par insertion
d) Il s'agit d'un tri par sélection

Exercice EC 8.2
1 min ● 3 points
On dispose de la fonction suivante :
1. def qui_suisje(t):
2. n = len(t)
3. for j in range(n-1):
4. indice = minimum(t, j)
5. if indice != j:
6. t[indice], t[j] = t[j], t[indice]
De quel type d'algorithme s'agit-il ?
Réponses :
a) Il s'agit d'un tri à bulles
b) Il s'agit d'un algorithme de dichotomie
c) Il s'agit d'un tri par insertion
d) Il s'agit d'un tri par sélection

Exercice EC 8.3
1 min ● 3 points
On dispose de la fonction de tri suivante :
1. def tri(t):
2. n = len(t)
3. for i in range(1,n):
4. while i>0 and t[i] < t[i-1]:
5. t[i-1],t[i] = t[i],t[i-1]
6. i = i - 1

Que renvoie cette fonction ?


Réponses :
a) Une liste triée
b) Un tuple
c) None
d) Une liste dans l'ordre alphabétique
Corrigé des exercices

Exercice 8.1

Il s'agit du tri par insertion.


1. def tri_insertion(t):
2. """ Procédure qui trie la liste t en place
3. t : une liste d'entiers
4. Ne renvoie rien"""
5. n = len(t)
6. for i in range(1,n):
7. while i>0 and t[i] < t[i-1]: #t[i] mal placé
8. t[i-1], t[i] = t[i], t[i-1] #permute t[i] et t[i-1]
9. i = i - 1 #on descend dans les indices pour continuer à tester si
t[i] bien placé
10.
11. t = [10, 11, 24, -2]
12. tri_insertion(t)
13. print(t)

On obtient la liste correctement triée : [-2, 10, 11, 24].

Exercice 8.2

Il suffit de voir qu'il suffit de comparer les éléments de la liste en indice


1. On choisit ici un tri par insertion.
1. def tri_Pers(t):
2. """ Procédure qui trie la liste t en place
3. t : une liste de listes
4. Ne renvoie rien"""
5. n = len(t)
6. for i in range(1,n):
7. while i>0 and t[i][1] < t[i-1][1]: #t[i] mal placé
8. t[i-1], t[i] = t[i], t[i-1] #permute t[i], t[i-1]
9. i = i - 1
10.
11. Pers = [['Sam',3], ['Julie',1], ['Tom',2], ['Portillon',4],
['Charlie',5]]
12. tri_Pers(Pers)
13. print(Pers)

Erreurs à éviter
Il ne faut pas permuter t[i][1] mais bien t[i], la sous-liste complète.

Exercice 8.3

On ne trie pas toute la liste, on replace l'élément mal placé.


1. def mini_tri(t):
2. """ Procédure qui remet l'élément mal placé en place
3. t : une liste de listes
4. mal_placee : une liste du type ['nom',entier]
5. Ne renvoie rien"""
6. mal_placee = t[0]#ligne de t à replacer
7. numero = mal_placee[1]#numero correspondant
8. del t[0]#supprime la ligne mal placée
9. i = len(t) #on démarre de la fin
10. while i > 0 and numero < t[i-1][1]:
11. i = i-1 #on cherche la bonne place
12. t.insert(i, mal_placee)#on insère la ligne en position i
13.
14. Pers = [['Sam',3], ['Julie',1], ['Tom',2], ['Portillon',4],
['Charlie',5]]
15. mini_tri(Pers)
16. print(Pers)
Corrigé des exercices de type EC -
QCM

Exercice EC 8.1

a) Il s'agit d'un tri à bulles


b) Il s'agit d'un algorithme de dichotomie
c) Il s'agit d'un tri par insertion
d) Il s'agit d'un tri par sélection

Exercice EC 8.2

a) Il s'agit d'un tri à bulles


b) Il s'agit d'un algorithme de dichotomie
c) Il s'agit d'un tri par insertion

d) Il s'agit d'un tri par sélection

Exercice EC 8.3

a) Une liste triée


b) Un tuple
c) None
d) Une liste dans l'ordre alphabétique

C'est une procédure, cette fonction de renvoie rien mais modifie la


liste « en place ».
Chapitre 9
Algorithme des k plus proches
voisins
Cours

1 Un peu d'histoire
Dans un rapport de la faculté de médecine aéronautique de la US Air
Force publié en 1951, Fix et Hodges introduisirent une méthode pour
la classification des motifs, connue depuis sous la règle des k plus
proches voisins (Fix & Hodges, 1951).

2 Principe
L'algorithme des k plus proches voisins s'écrit en abrégé k-NN ou
KNN, de l'anglais k-nearest neighbors. k est un nombre entier positif
généralement petit.
Il s'agit d'un des algorithmes de machine learning ou « apprentissage
machine » qui est essentiel dans le milieu de l'intelligence artificielle.
Le principe peut être résumé par « Dis-moi qui sont tes amis, et je te
dirai qui tu es ». Ou bien encore « Celui qui marche avec des hommes
sages sera sage, mais le compagnon d'imbéciles souffrira »
(proverbe).
Ce genre d'algorithme permet par exemple de prédire le
comportement d'une personne en s'intéressant à son milieu. Il peut
être utilisé par des géants de la vente comme Amazon, Netflix, iTunes
afin de prévoir si vous seriez ou non intéressé par un produit (ou un
film, une musique). En effet, en disposant de vos données (âge,
derniers achats etc.) et en les comparant à celle d'un client qui a
acheté un produit, un algorithme peut tâcher de prédire si vous seriez
intéressé ou non par le produit.
Les utilisations de k-NN sont encore plus larges que celles décrites ci-
dessus. De manière générale, cet algorithme peut être utilisé selon
deux objectifs :
● Pour effectuer une régression : on calcule la moyenne des valeurs
des k plus proches voisins d'un élément et on attribue cette
moyenne à l'élément étudié.
● Pour effectuer une classification : on cherche le résultat majoritaire
des classes d'appartenance des k plus proches voisins d'un
élément. On attribue la classe de l'élément suivant le résultat
obtenu. Si k = 1, alors l'élément est assigné à la classe de son
proche voisin.

3 Algorithme et fonctions
Dans le cadre du programme de NSI, on s'intéressera uniquement à
prédire la classe d'un nouvel élément (dont la position est connue)
faisant partie d'un ensemble de points dont les coordonnées et la
classe sont connues.
Aussi pour cet élément il faudra :
● Évaluer la distance qui sépare le nouvel élément de chacun des
autres points de l'ensemble. Chaque point de l'ensemble est
caractérisé par son indice noté i.
● Stocker ces valeurs de distance d dans une liste du type : [[d,i],[…],
[…], …]. Avec d la distance qui sépare le nouvel élément du point
d'indice i.
● Trier la liste selon les valeurs des distances d.
● Choisir les k premiers points de la liste triée (donc les k plus proches
voisins)
● Assigner une classe au nouvel élément en fonction de la majorité
des classes représentées parmi les k plus proches voisins.
On mettra en œuvre trois fonctions :
● Une fonction distance pour le calcul de la distance entre deux points
de coordonnées connues.
● Une fonction Kvoisins qui détermine les k plus proches voisins d'un
nouvel élément.
● Une fonction predire_classe qui détermine le résultat majoritaire des
classes d'appartenance des k plus proches voisins et assigne la
classe du nouvel élément à cette classe majoritaire.

4 Distance entre deux points

Principe

Suivant que l'on raisonne sur une, deux, trois dimensions, le calcul de
la distance entre deux points est plus ou moins simple.
Remarque
Pour simplifier les choses, on s'attachera dans ce livre à écrire un algorithme pour un
espace à une seule dimension.

Pour l'exemple ci-dessus, chaque forme géométrique possède une


coordonnée notée x. La distance d entre deux éléments de
coordonnées x1 et x2 est tout simplement :
Fonction distance
On peut écrire une fonction distance qui prend en arguments d'entrée
deux coordonnées x1 et x2 et qui renvoie la valeur de la distance entre
les deux points de coordonnées x1 et x2. Cela donne assez
simplement :
1. def distance(x1,x2):
2. """renvoie la distance entre 2 points de coordonnées x1 et x2
3. x1,x2 : deux flottants"""
4. return abs(x1-x2)
5.
6. print(distance(1.2,3.0))#affiche 1.8

5 Recherche des k plus proches voisins

Principe

On cherche les k plus proches voisins de l'élément rond vert (de


coordonnée x1 = 3). Si on choisit de lui appliquer un k-NN avec k = 3
(qui correspond au cercle en pointillés sur la figure ci-dessus), ses
trois plus proches voisins sont deux carrés et un triangle.
La liste des positions des éléments (le rond vert exclus) est :
L = [0.5,1.0,2.0,3.7,5.1,6.0,7.0]#espace 1D sans le rond vert
Erreur à éviter
Attention, le nouvel élément rond vert ne figure pas dans cette liste.

La liste des classes des éléments (le rond vert exclus) est :
Classes = ['T','C','C','T','T','C','C']#classes de l'espace 1D, 'C'
pour carré, 'T' pour triangle

Donc par exemple, l'élément de coordonnée 3.7 (et d'indice 3 car c'est
le quatrième et les indices en Python démarrent à 0) est un triangle.
L'élément de coordonnée 2.0 (et d'indice 2) est un carré. L'élément de
coordonnée 1.0 (et d'indice 1) est un carré. Ces trois éléments sont
les trois plus proches voisins du rond vert.
Il reste à présent à écrire une fonction Kvoisins qui prend en arguments
d'entrée une liste L de coordonnées des éléments (des flottants), un
entier k, et x la position d'un nouvel élément x et qui renvoie la liste des
indices dans L des k plus proches voisins de x. x ne fait pas partie de
la liste L.
Soit en pseudo-code :

n ← nombre d'éléments de L
listeDistanceIndice ← liste vide
pour i allant de 0 à n-1
d ← distance entre x et L[i]
ajouter [d,L[i]] en fin de listeDistanceIndice
fin pour
Trier listeDistanceIndice selon d
Voisins ← liste vide
pour i allant de 0 à k-1
ajouter listeDistanceIndice[i][1] à la fin de Voisins
fin pour
renvoyer Voisins
Fonction Kvoisins
Ce qui donne en Python :
1. def Kvoisins(L,k,x):
2. """renvoie la liste des indices des k plus proches voisins de x
3. x : la position de x, un flottant
4. L : une liste de positions (des flottants) correspondant aux
coordonnées des divers voisins de x
5. k : un entier
6. listeDistanceIndice : [[d,i],[],.] une liste des distances d des
éléments/x et leur indice i dans L
7. Voisins : une liste des indices des k + proches voisins"""
8. listeDistanceIndice = []
9. for i in range(len(L)):#on crée une liste [[d,i],[],.]
10. d = distance(x,L[i])
11. listeDistanceIndice.append([d,i])
12. listeDistanceIndice.sort()#on trie selon la distance (le
1er élément de chaque sous-liste [d,i]
13. Voisins = []#on crée une liste des indices des voisins
14. for i in range(k):#on crée une liste de k voisins
15. Voisins.append(listeDistanceIndice[i][1])#on ajoute l'indice à la
liste Voisins
16. return Voisins
17.
18. L = [0.5,1.0,2.0,3.7,5.1,6.0,7.0]#espace 1D sans le rond vert
19. Classes = ['T','C','C','T','T','C','C']#classes de l'espace 1D,
'C' pour carré, 'T' pour triangle
20. x = 3.0 #élément à classer
21. k = 3 #3 voisins
22. print("liste d'indices",Kvoisins(L,k,x)) #on veut la liste des
indices des voisins
23. print("liste des voisins",[L[i] for i in Kvoisins(L,k,x)])#on
veut la liste des positions des voisins

Ce qui donne bien dans le shell la liste des indices et les coordonnées
des trois plus proches voisins de x :
liste d'indices [3, 2, 1]
liste des voisins [3.7, 2.0, 1.0]

6 Attribution de classe
Principe

Pour le schéma ci-dessus : chaque point possède une classe « T »,


pour « triangle » ou « C » pour « carré ». On souhaite attribuer une
nouvelle classe à l'élément rond vert qui tienne compte de la classe
moyenne de ses plus proches voisins. Si on choisit de lui appliquer un
k-NN avec k = 3, le rond vert est affecté à la classe « C » car ses trois
plus proches voisins sont deux carrés et seulement un triangle.
Si cette fois k = 5, le rond vert est assigné à la classe « T » (en effet,
les 5 plus proches voisins sont 3 triangles contre deux carrés).
k-NN Classes des voisins Classe du nouvel élément

k=3 2 carrés, 1 triangle carré


k=5 3 triangles, 2 carrés triangle

Fonction classe
Il reste donc à écrire une fonction predire_classe qui détermine le
résultat majoritaire des classes d'appartenance des k plus proches
voisins et assigne la classe du nouvel élément à cette classe
majoritaire. Cette fonction admet en arguments d'entrée une liste L de
coordonnées des éléments (des flottants), une liste Classes des
classes des éléments (une liste de chaînes de caractères), un entier k,
et x la position d'un nouvel élément x.
Remarque
On s'intéresse au cas simplifié où il n'existe que deux classes d'appartenance possibles :
'C' et 'T'.

Soit en pseudo-code :
Voisins ← Kvoisins(L,k,x)
Classespossibles ← ['C', 'T']
decompte ← [0, 0]
pour v allant du debut à la fin de Voisins
si Classes[v] est un carré
ajouter 1 au 1er élément de decompte
sinon
ajouter 1 au 2-ième élément de decompte
fin si
fin pour
indice ← indice du maximum de decompte
renvoyer Classespossibles[indice]

Ce qui donne en Python :


1. def predire_classe(L,Classes,k,x):
2. """renvoie la classe du nouvel élément x
3. x : la position de x, un flottant
4. L : une liste de positions (des flottants) correspondant aux
divers éléments voisins de x
5. Classes : la liste des classes des divers éléments (liste de
chaines de caractères). 'C' pour carré, 'T' pour triangle
6. k : un entier
7. Voisins : une liste des indices des + proches voisins
8. Classespossibles : la liste des deux classes possibles
9. """
10. Voisins = Kvoisins(L,k,x)#liste des indices des k + proches
voisins
11. Classespossibles = ['C', 'T'] #liste des 2 classes possibles
12. decompte = [0, 0]#decompte des classes
13. for v in Voisins : #on parcourt les indices de k plus proches
voisins
14. if Classes[v] == 'C':#si c'est un carré
15. decompte[0] += 1 #on incrémente le 1er décompte
16. else :#si c'est un triangle
17. decompte[1] += 1 #on incrémente le 2-ieme décompte
18. plusGrandDecompte = decompte[0]#on initialise le plus grand
décompte au 1er élément de decompte
19. indice = 0 #on initialise l'indice du plus grand décompte
20. if decompte[1] > plusGrandDecompte:#si le 2nd élément de décompte
est plus grand que le 1er
21. indice = 1 #on modifie l'indice du plus grand décompte
22. return Classespossibles[indice] #on renvoie la classe de x
23.
24.
25. print("Classe du nouvel élément :",predire_classe(L,Classes,k,x))
#on veut la classe du nouvel élément

Ce qui donne bien 'C' pour « carré » dans le shell, ce qui avait été
anticipé précédemment.
Exercices

Compétence attendue

➡ Comprendre l'algorithme des plus proches voisins

Exercice 9.1
► Concevoir, mobiliser
Pour la répartition ci-dessus, la classe des points 1 à 4 est connue :
elle est de type triangle ou carré.
➡ Sans coder, appliquer la méthode k-NN avec k = 3 successivement
aux points 5 à 8 afin de donner leur classe.

Exercice 9.2
► Concevoir, mobiliser

Pour la nouvelle répartition ci-dessus, il faut déterminer la classe du


rond vert sachant que ses voisins sont de classe triangle ou carré.
➡ Sans coder, lui appliquer un k-NN avec k = 5 puis k = 7 afin de
déterminer la nouvelle classe du rond vert (parmi triangle ou carré).

Compétence attendue

➡ Écrire un algorithme qui prédit la classe d'un élément en fonction de la classe


majoritaire de ses k plus proches voisins.

Exercice 9.3
► Traduire, développer
La fonction Kvoisins élaborée dans la partie cours de ce chapitre peut
être réécrite sans faire appel à une méthode de tri :
1. def Kvoisins(L,k,x):
2. listeDistances = []
3. for i in range(len(L)):
4. listeDistances.append(distance(x,L[i]))
5. Voisins = []
6. for i in range(k) :
7. d = distance(L[0],x)
8. for j in range(len(L)):
9. if listeDistances[j] != 0 and listeDistances[j] < d and j not in
Voisins:
10. d = listeDistances[j]
11. indice = j
12. Voisins.append(indice)
13. return Voisins

➡ Expliquer pas à pas ce que fait cette fonction et la tester pour la


liste :
L = [0.5,1.0,2.0,3.7,5.1,6.0,7.0] et l'élément de coordonnée x = 3.0.

Compétence attendue

➡ Écrire un algorithme de calcul de distance.

Exercice 9.4
► Traduire, développer

Soit un espace à deux dimensions. Chaque point est repéré par ses
coordonnées [x,y]. On rappelle que la distance qui sépare deux points
de coordonnées c1 = [x1,y1] et c2 = [x2,y2] peut être calculée comme
suit :

➡ Écrire une fonction distance_2D qui admet pour arguments d'entrée


deux listes c1 et c2 contenant les coordonnées de deux points 1 et 2
et renvoyant la distance séparant ces deux points.
Exercices-bilan

Exercice-bilan 9.1
30 min ● 10 points
Écrire une fonction lePlusProcheVoisin qui prend en argument d'entrée
une liste L de données (chaque donnée correspond à une
coordonnée) et x la coordonnée d'un l'élément x et qui renvoie l'indice
dans L du plus proche voisin de x (situé à une distance non nulle).
On pourra faire appel pour cela à une fonction distance qui pour deux
points de coordonnées x1 et x2, renvoie la distance que sépare ces
deux points.
Par exemple pour L = [10.0,6.0,1.0,7.0] et x = 5.0, alors
lePlusProcheVoisin(L,x) doit renvoyer 1 qui est l'indice de la coordonnée
x = 6.0 dans la liste L.
Aide
On pourra s'appuyer sur le principe des fonctions maximum et minimum élaborées au
chapitre 6.

Exercice-bilan 9.2
30 min ● 10 points
Pour la répartition ci-dessus, la classe des points 0 à 7 est connue :
elle est de type triangle 'T', carré 'C' ou rond 'R'.
● À partir de l'image ci-dessus, sans coder, appliquer un k-NN avec
k = 3 au point 8 afin de déterminer la nouvelle classe de ce point
(parmi triangle 'T', carré 'C' ou rond 'R').
On va à présent coder la méthode k-NN afin de résoudre le problème.
● Écrire une liste L des coordonnées des points 0 à 7. On peut
considérer que la coordonnée du point 0 vaut 0.0, celle du point 1
vaut 1.0.
● Écrire une liste Classes correspondant aux classes des points 0 à 7.
● On souhaite écrire un programme permettant de mettre en œuvre la
méthode k-NN avec k = 3 au point 8 de coordonnée x=3.0. Le but est
d'attribuer sa classe. On pourra faire appel aux fonctions Kvoisins()
et distance de ce chapitre ainsi qu'à la fonction suivante de prédiction
de classe (valable pour trois classes possibles) :
1. def predire_classe(L,Classes,k,x):
2. """renvoie la classe du nouvel élément x
3. x : la position de x, un flottant
4. L : une liste de positions (des flottants) correspondant aux
divers éléments voisins de x
5. Classes : la liste des classes, 'C' pour carré, 'T' pour triangle,
'R' pour rond
6. k : un entier
7. Voisins : une liste des indices des plus proches voisins
8. Classespossibles : la liste des classes possibles
9. """
10. Voisins = Kvoisins(L,k,x)#liste des indices des k plus proches
voisins
11. Classespossibles = ['C','T','R'] #liste classes possibles
12. decompte = [0,0,0]#decompte des classes
13. for v in Voisins : #on parcourt les indices des k plus proches
voisins
14. for i in range(len(Classespossibles)):#on parcourt les indices
des classes possibles
15. if Classes[v] == Classespossibles[i]:
16. decompte[i] += 1
17. plusGrandDecompte = decompte[0]
18. indice = 0
19. for i in range(1,len(Classespossibles)):
20. if decompte[i] > plusGrandDecompte:
21. plusGrandDecompte = decompte[i]
22. indice = i
23. return Classespossibles[indice]

Exercice-bilan 9.3
30 min ● 10 points
Un vaisseau spatial est positionné
proche du soleil, sa coordonnée est
fixée à x = 0. On suppose les planètes
du système solaire alignées sur un
même axe Ox et repérables par leur
coordonnée x. On dispose d'une liste :
planetes = du type
[['Mercure',0.39],['Terre',1.0],['Venus',0.72]]
['nom',coordonnée]. Chaque coordonnée x est en unité astronomique
UA.
Le vaisseau va parcourir les trois planètes une à une en choisissant à
chaque fois la planète la plus proche de lui-même. Construire la liste
représentant la trajectoire du vaisseau : on veut obtenir une liste de
noms.
Aide
On pourra se servir de l'instruction planete.pop(i) qui permet de supprimer l'élément
d'indice i de la liste planete.
Il est possible de reprendre la fonction lePlusProcheVoisin en l'adaptant au
problème étudié.
Exercices de type EC - QCM

Pour chaque question, le candidat gagne 3 points s'il choisit la bonne


réponse, perd 1 point s'il choisit une réponse fausse. S'il ne répond
pas ou choisit plusieurs réponses, il ne gagne ni ne perd aucun point.

Exercice EC 9.1
1 min ● 3 points

Pour la répartition ci-dessus, la classe des points 0 à 7 est connue :


elle est de type triangle 'T', carré 'C' ou rond 'R'.
Si on appliquer un algorithme des k plus proches voisins avec k = 3 au
point 8 afin de déterminer la nouvelle classe de ce point (parmi
triangle 'T', carré 'C' ou rond 'R') on obtient :
Réponses :
a) 'T'
b) 'C'
c) 'R'
d) impossible de conclure : il y a autant de 'T' que de 'R'

Exercice EC 9.2
1 min ● 3 points
L'algorithme des k plus proches voisins est un algorithme de :
Réponses :
a) tri
b) recherche d'une valeur dans une liste
c) classification
d) calcul de maximum très efficace
Corrigé des exercices

Exercice 9.1

Pour un k-NN avec k = 1 :


La classe de 5 devient : triangle.
La classe de 6 devient : triangle.
La classe de 7 devient : carré.
La classe de 8 devient : triangle car 5 est le plus proche voisin.
Pour un k-NN avec k = 3 :
La classe de 5 devient : triangle car ses trois plus proches voisins sont
1, 4 et 2.
La classe de 6 devient : triangle car ses trois plus proches voisins sont
1, 4 et 5.
La classe de 7 devient : carré car ses trois plus proches voisins sont
5, 2 et 3.
La classe de 8 devient : triangle car ses trois plus proches voisins sont
4, 5 et 7.

Exercice 9.2

Si on choisit d'appliquer un k-NN avec k = 3 au rond vert (ceci


correspond au cercle en ligne pleine), il est affecté à la classe
« triangle » car il y a deux triangles et seulement un carré dans le
cercle considéré.
Si k = 5 (cercle en ligne pointillée) le rond vert est assigné à la classe
« carré » (en effet, il y a 3 carrés contre deux triangles dans le cercle).
k-NN Classes des voisins Classe du nouvel élément

k=3 2 triangles, 1 carré Triangle


k=5 3 carrés, 2 triangles Carré

Exercice 9.3

Le programme est commenté ci-dessous :


1. def Kvoisins(L,k,x):
2. """renvoie la liste des indices des k plus proches voisins de x
3. x : la coordonnée de x, un flottant
4. L : une liste de coordonnées (des flottants) correspondant aux
divers éléments voisins de x
5. k : un entier
6. listeDistanceIndice : [[d,indice],[],.] une liste des distances
des éléments/x et leur indice
7. Voisins : une liste des indices des + proches voisins"""
8. listeDistances = []
9. for i in range(len(L)):#on crée une liste de distances
10. listeDistances.append(distance(x,L[i]))
11. Voisins = []#on crée une liste des indices des voisins
12. for i in range(k):#on répète la recherche k fois
13. d = distance(L[0],x)#on initialise à la distance par rapport au
1er élément de L
14. for j in range(len(L)):#on parcourt les indices de L pour
chercher le plus proche voisin
15. if listeDistances[j] != 0 and listeDistances[j] < d and j not in
Voisins: #si la distance de j est <d et j pas déjà dans Voisins
16. d = listeDistances[j]
17. indice = j
18. Voisins.append(indice)
19. return Voisins

On teste :
1. L = [0.5,1.0,2.0,3.7,5.1,6.0,7.0]
2. x = 3.0 #élément à classer
3. k = 3 #3 voisins
4. print("liste d'indices",Kvoisins(L,k,x)) #on veut la liste des
indices des voisins
5. print("liste des voisins",[L[i] for i in Kvoisins(L,k,x)])#on veut
la liste des coordonnées des voisins

Et on obtient :
liste d'indices [3, 2, 1]
liste des voisins [3.7, 2.0, 1.0]

Exercice 9.4

On écrit le programme :
1. from math import sqrt
2.
3. def distance_2D(c1,c2):
4. """renvoie la distance séparant deux points
5. c1, c2 : deux listes de coordonnées du type [x,y]"""
6. [x1,y1] = c1
7. [x2,y2] = c2
8. return sqrt((x1-x2)**2+(y1-y2)**2)

On le teste :
1. c1 = [1.0,1.0]
2. c2 = [0.0,0.0]
3. print(distance_2D(c1,c2))

On obtient bien dans le shell :


1.4142135623730951
Corrigé des exercices-bilan

Exercice-bilan 9.1

Afin de chercher le plus proche voisin, on écrit tout d'abord une


fonction distance(x1,x2) :
1. def distance(x1,x2):
2. """renvoie la distance entre 2 points de coordonnées x1 et x2
3. x1,x2 : deux flottants"""
4. return abs(x1-x2)

Puis la fonction de recherche du plus proche voisin


lePlusProcheVoisin(L,x) que l'on applique à la liste proposée dans
l'énoncé :
1. def lePlusProcheVoisin(L,x):
2. """renvoie l'indice du plus proche voisin de x
3. L : une liste de coordonnées
4. lePlusPres : un indice donc un entier
5. distanceMin : un flottant"""
6. lePlusPres = 0
7. distanceMin = distance(L[0],x)#on initialise à la distance par
rapport au 1er élément de L
8. for i in range(len(L)): #on parcourt les indices de L
9. di = distance(L[i], x)#di : distance entre L[i] et x
10. if di != 0 and di < distanceMin:#on cherche le minimum
11. lePlusPres = i
12. distanceMin = di
13. return lePlusPres #on renvoie l'indice du plus près
14.
15. L = [10.0,6.0,1.0,7.0]
16. print(lePlusProcheVoisin(L,5.0))

On obtient bien l'indice 1 qui correspond à l'élément de coordonnée


x = 6.0.
Exercice-bilan 9.2

● Les trois plus proches voisins du point 8 sont : 5 (classe rond 'R'), 2
(classe carré 'C') et 7 (classe rond 'R'). La classe majoritaire est
rond. Ainsi 8 sera de classe rond : 'R'.
● La liste L donne L = [0,1,3.6,4.3,2.0,2.7,1.2,3.9]
Erreur à éviter
Attention à respecter l'ordre des points !

● La liste des classes donne :


Classes = ['R','T','C','C','C','R','R','R']

● Pour le programme complet cela donne :


1. L = [0,1,3.6,4.3,2.0,2.7,1.2,3.9]
2. Classes = ['R','T','C','C','C','R','R','R']
3. x = 3.0
4.
5. def distance(x1,x2):
6. return abs(x1-x2)
7.
8. def Kvoisins(L,k,x):
9. listeDistanceIndice = []
10. for i in range(len(L)):
11. d = distance(x,L[i])
12. listeDistanceIndice.append([d,i])
13. listeDistanceIndice.sort()
14. Voisins = []
15. for i in range(0,k):
16. Voisins.append(listeDistanceIndice[i][1])
17. return Voisins
18.
19. def predire_classe(L,Classes,k,x):
20. Voisins = Kvoisins(L,k,x)
21. Classespossibles = ['C','T','R']
22. decompte = [0,0,0]
23. for v in Voisins :
24. for i in range(len(Classespossibles)):
25. if Classes[v] == Classespossibles[i]:
26. decompte[i] += 1
27. plusGrandDecompte = decompte[0]
28. indice = 0
29. for i in range(1,len(Classespossibles)):
30. if decompte[i] > plusGrandDecompte:
31. plusGrandDecompte = decompte[i]
32. indice = i
33. return Classespossibles[indice]
34.
35. print("liste d'indices",Kvoisins(L,k,x)) #on veut la liste des
indices des voisins de x
36. print("Classe du nouvel
élément :",predire_classe(L,Classes,k,x))#on veut la classe du
nouvel élément x

Ce qui donne dans le shell :


liste d'indices [5, 2, 7]
Classe du nouvel élément : R

Ceci est tout à fait concordant avec le résultat trouvé précédemment :


le point 8 sera de classe rond 'R' car ses plus proches voisins sont les
points 5, 2 et 7 et la classe majoritaire est rond.

Exercice-bilan 9.3

On initialise les listes et la position du vaisseau :


1. planetes =[['Mercure',0.39],['Terre',1.0],['Venus',0.72]]
2. x = 0
3. trajectoire = ['Soleil']

On écrit une fonction distance et on adapte celle de recherche de


l'indice du plus proche voisin. En effet, la coordonnée est à présent à
l'indice 1 de la liste planetes :
1. def distance(x1,x2):
2. return abs(x1-x2)
3.
4. def lePlusProcheVoisin(L,x):
5. """renvoie l'indice du plus proche voisin de x
6. L : une liste de listes du type ['nom', coordonnee]
7. lePlusPres : un indice donc un entier
8. distanceMin : un entier ou un flottant"""
9. lePlusPres = 0
10. distanceMin = distance(L[0][1],x)#on initialise à la distance par
rapport au 1er élément de L
11. for i in range(len(L)): #on parcourt les indices de L
12. di = distance(L[i][1], x)#on calcule la distance entre L[i][1] et
x
13. if di != 0 and di < distanceMin:#on cherche le minimum
14. lePlusPres = i
15. distanceMin = di
16. return lePlusPres #on renvoie l'indice du plus près

On écrit une fonction trajet qui cherche le meilleur trajet et renvoie la


liste trajectoire :
17. def trajet(planetes,x):
18. """renvoie une liste trajectoire de noms corespondant à la
trajectoire optimisée du vaisseau
19. planetes : une liste de listes du type ['nom', coordonnee]
20. x : la coordonnée du vaisseau"""
21. while planetes !=[] : #tant qu'il reste des planètes à découvrir
22. i = lePlusProcheVoisin(planetes,x) #indice du plus proche voisin
du vaisseau
23. trajectoire.append(planetes[i][0]) #on ajoute le nom de la
planete à la trajectoire
24. x = planetes[i][1] #on actualise la position du vaisseau
25. planetes.pop(i) #on supprime la planète déjà parcourue
26. return trajectoire
27.
28. print(trajet(planetes,x))

On applique ce programme et on obtient le trajet optimisé :


['Soleil', 'Mercure', 'Venus', 'Terre']
Corrigé des exercices de type EC -
QCM

Exercice EC 9.1

a) 'T'
b) 'C'
c) 'R'
d) impossible de conclure : il y a autant de ‘T’ que de ‘R’
Les trois plus proches voisins du point 8 sont : 5 (classe rond 'R'), 2
(classe carré 'C') et 7 (classe rond 'R'). La classe majoritaire est rond.
Ainsi 8 sera de classe rond : 'R'.

Exercice EC 9.2

a) tri
b) recherche d’une valeur dans une liste
c) classification
d) calcul de maximum très efficace
Chapitre 10
Algorithmes gloutons
Cours

1 Notion d'algorithme glouton


Un algorithme glouton est une technique algorithmique permettant de
résoudre un problème. D'autres techniques existent comme celle du
« diviser pour régner » déjà envisagée dans le chapitre 7.
Un algorithme glouton va aborder la résolution d'un problème en
plusieurs étapes. À chaque étape, il va adopter un choix qui lui
semble optimal. Ce, dans l'espoir qu'à la fin de la résolution, le résultat
obtenu soit lui-même optimal. Mais un algorithme glouton ne repart
jamais en arrière afin de modifier ses choix (le choix qui semble le
meilleur à un instant t est définitif) donc il se peut que le résultat final
ne soit pas optimal…

2 Le problème du rendu de monnaie


Les algorithmes gloutons servent principalement à résoudre des
problèmes d'optimisation. Il existe de multiples exemples.

Principe
Un des grands classiques est le problème du rendu de monnaie où
l'on souhaite rendre une somme en utilisant le moins de pièces (ou de
billets) possibles. Le principe de l'algorithme consiste à répéter le
choix de la pièce de plus grande valeur qui ne dépasse pas la
somme restante.
Remarque
On dit qu'il s'agit d'un algorithme glouton car il choisit la pièce la plus grosse à chaque étape
sans réfléchir à la suite.

Exemple : Prenons par exemple le système de pièces européen


qui contient les pièces suivantes en centimes : 1, 2, 5, 10, 20, 50,
100 (1 €), 200 (2 €), 500 (billet de 5 €), etc.). On souhaite rendre la
somme de 8 euros (soit 800 centimes). La solution optimale est de
rendre un billet de 5 euros, une pièce de 2 euros et une autre de
1 euro. Mais il existe d'autres méthodes non optimales comme
rendre huit pièces d'un euro…

Résultat optimal ou non


Suivant le système de pièces, l'algorithme glouton est optimal ou non.
Dans le système de pièces européen, on peut montrer que
l'algorithme glouton donne toujours une solution optimale.
Dans le système de pièces [4,3,1], l'algorithme glouton n'est pas
optimal. En effet, il donne pour 6 : 4+1+1, alors que 3+3 est optimal.

Pseudo-code
En pseudocode, on peut écrire :

n ← longueur de la liste pieces


Pour i allant de 0 à n-1
Tant que somme >= pieces[i]
somme ← somme - pieces[i]
choisies[i] ← choisies[i] + 1
Renvoyer choisies

Fonction rendu_monnaie
La fonction rendu_monnaie suivante permet pour un montant appelé somme
que l'on doit rendre et une liste de pièces disponibles pieces, de
renvoyer la liste des pièces à rendre (la liste choisies).
Remarque
On suppose que l'on dispose d'un nombre de pièces illimité. Dans cette liste choisies, un 1
en indice i indique que la pièce d'indice i est retenue, un 2 que la pièce d'indice i est
retenue deux fois, etc. et un 0 qu'elle n'est pas retenue.

1. def rendu_monnaie(somme,pieces):
2. """Fournit la solution au problème du rendu de monnaie
3. somme : la somme à rendre, un entier
4. pieces : les types de pièces possibles, une liste d'entiers
classée dans le sens décroissant
5. choisies : une liste indiquant le nombre de pièces choisies pour
chacune des pièces
6. """
7. n = len(pieces)
8. choisies = [0]*n #liste de compteurs des pièces choisies
9. for i in range(n):#pour i allant de 0 à n-1
10. while somme >= pieces[i] :
11. somme = somme-pieces[i]#mise à jour de la somme à rendre
12. choisies[i] = choisies[i] + 1 #on augmente de 1 le compteur de la
pièce choisie
13. return choisies

On teste cette fonction pour le cas où l'on souhaite rendre 8 euros


(800 centimes) dans le cadre du système européen de monnaie :
14. pieces = [500,200,100,50,20,10,5,2,1]
15. somme = 800
16. print("Les pièces choisies sont :")
17. print(rendu_monnaie(somme,pieces))

Le shell affiche :
Les pièces choisies sont :
[1, 1, 1, 0, 0, 0, 0, 0, 0]

Il faut donc une pièce de 500 (billet de 5 euros), une pièce de 200
(2 euros) et une pièce de 100 (1 euro).
Cette fois on souhaite rendre 7 euros (700 centimes) :
18. somme = 700
19. print("Les pièces choisies sont :")
20. print(rendu_monnaie(somme,pieces))

Le shell affiche :
Les pièces choisies sont :
[1, 1, 0, 0, 0, 0, 0, 0, 0]

Il faut donc une pièce de 500 (billet de 5 euros), et une pièce de 200
(2 euros).
Cette fois on souhaite rendre 6 euros à partir des pièces fictives
4 euros, 3 euros, 1 euro :
1. pieces = [4,3,1]
2. somme = 6
3. print("Les pièces choisies sont :")
4. print(rendu_monnaie(somme,pieces))

Le shell affiche :
Les pièces choisies sont :
[1, 0, 2]

Il faut donc une pièce de 4 euros, et deux d'un euro. Alors qu'en effet
deux pièces de 3 euros seraient un rendu plus optimal car moins de
pièces seraient rendues.
Remarque
Il existe d'autres méthodes de programmation plus complexes du rendu de monnaie
(comme la programmation dynamique) mais elles ne seront pas développées dans cet
ouvrage car hors programme de NSI.

Mise en place d'un test


Même si un algorithme glouton appliqué au rendu de monnaie ne
garantit pas une solution optimale, on peut tout de même s'assurer
que la somme finale vaut bien zéro : cela assurerait que le client soit
satisfait. À cet effet, on peut mettre en place un test en fin de boucle
for avec assert somme == 0.

Cela donne du coup :


1. def rendu_monnaie(somme,pieces):
2. n = len(pieces)
3. choisies = [0]*n
4. for i in range(n):
5. while somme >= pieces[i] :
6. somme = somme - pieces[i]
7. choisies[i] = choisies[i] + 1
8. assert somme == 0
9. return choisies

Pour les trois exemples abordés précédemment, le test ne renvoie


pas d'erreur. En effet, la somme obtenue est bien nulle en fin
d'algorithme. Par exemple pour rendre 6 euros, si on rend 4 euros et
deux fois un euro, la somme finale vaut bien zéro.
Par contre si on souhaite rendre 31 euros (somme = 31) à partir des
pièces suivantes : pieces = [10,5,2]
L'appel de rendu_monnaie(somme,pieces) va renvoyer l'erreur suivante :
assert somme == 0
AssertionError

En effet, il fallait nécessairement une pièce d'un euro dans la caisse


afin de rendre la somme indiquée !

3 Le problème du sac à dos

Principe

Le problème du sac à dos, (aussi noté KP pour « knapsack problem »


en anglais) est lui aussi un problème d'optimisation. Il permet de
résoudre le problème du remplissage d'un sac à dos. On dispose pour
cela de plusieurs objets (chaque objet possède une valeur et un
poids). Seulement le sac ne peut supporter plus d'un certain poids.
Aussi on va devoir choisir tout ou partie des objets. Les objets mis
dans le sac à dos doivent maximiser la valeur totale dans le sac, sans
toutefois dépasser le poids maximum.
L'algorithme glouton consiste à choisir à chaque étape du remplissage
l'objet de plus grande valeur. On répète les étapes de remplissage
juste avant que le poids maximal soit atteint. On supposera dans cet
ouvrage que chaque objet existe de manière unique.
Remarque
On dit à nouveau qu'il s'agit d'un algorithme glouton car il choisit (tel un brigand) l'objet de
plus grande valeur à chaque étape sans réfléchir à la suite.

Par exemple pour le problème illustré ci-dessus, on doit choisir parmi


les objets : goûter, jumelles, livre, chat en peluche mais le sac à dos
ne doit pas peser plus de 5 kg. Le problème est assez simple à
présenter mais pas à résoudre.
La solution la plus simple est d'utiliser un algorithme glouton mais il
faut garder en tête qu'elle ne renvoie pas toujours une solution
optimale.
Pour cela, on choisit d'abord :
● Les jumelles (de valeur 5), le sac pèse alors 0,5 kg.
● Le chat en peluche (de valeur 3), le sac pèse 4,5 kg.
● On ne peut pas prendre le goûter (valeur 2) car il ferait dépasser les
5 kg !
● On prend donc l'objet de valeur suivante : le livre et le poids du sac
à dos vaut 4,7 kg .
● L'algorithme s'arrête.

Un peu d'histoire

Richard Karp, diplômé de Harvard, a travaillé sur les domaines de


l'algorithmique et de la complexité. Le problème du sac à dos est l'un
des vingt et un problème qu'il expose dans un article de 1972.

Pseudo-code
On dispose d'une liste de valeur des objets et de leur poids du type :
objets = [[valeur,poids],[…,…],…]

Soit objets = [[2,1],[5,0.5],[1,0.2],[3,4]]

Donc l'objet de valeur 2 pèse 1 kg, etc. On note le poids du sac P et le


poids maximal poids_max.
En pseudocode, on peut écrire :

Trier la liste objets par ordre décroissant selon la valeur de


chaque objet
P ← 0
n ← nombre d'objets
objets_choisis ← n*[0]
Pour i allant de 0 à n-1
si P + objet_choisis[i][1] <= poids_max alors
objet_choisis[i] ← 1
P ← P + objets[i][1]
Renvoyer objets_choisis

Fonction remplir_sac
On trie d'abord la liste objets selon les valeurs décroissantes puis on
remplit le sac. Ce qui donne en Python :
1. def remplir_sac(objets,poids_max):
2. """Fournit la solution au problème du sac à dos
3. poids_max : un flottant à ne pas excéder
4. objets : une liste de listes du type [valeur,poids] triée par
ordre décroissant de valeurs
5. objets_choisis : une liste de 1 ou de 0 indiquant si tel ou tel
objet est retenu
6. """
7. P = 0 #on initialise P
8. n = len(objets) #nombre d'objets
9. objets_choisis = [0]*n #on initialise la liste
10. for i in range(n):
11. if P + objets[i][1] <= poids_max :
12. objets_choisis[i] = 1 #objet choisi
13. P = P + objets[i][1] #le poids du sac est augmenté
14. return objets_choisis

On crée la liste objets, on lance la fonction


remplir_sac(objets,poids_max) :
1. objets = [[2,1],[5,0.5],[1,0.2],[3,4]]
2. objets = list(reversed(sorted(objets)))#liste objets classée dans
l'ordre décroissant des valeurs
3. print(objets)
4. poids_max = 5.0
5. print("Les objets choisis sont :")
6. print(remplir_sac(objets,poids_max))
Remarque
La liste objets n'étant pas triée, on l'a triée par ordre décroissant de valeur qui est le
premier élément de la liste objets.

Ce qui donne dans le shell la liste triée tout d'abord et les objets
choisis :
[[5, 0.5], [3, 4], [2, 1], [1, 0.2]]

Les objets choisis sont :


[1, 1, 0, 1]

Remarque
Dans la liste objets_choisis, un 1 en indice i indique que l'objet d'indice i est retenu, un
0 qu'il n'est pas retenu.

Aussi, on retient : les jumelles (de valeur 5), le chat (de valeur 3), le
livre (valeur 1). Cette solution est celle à laquelle nous sommes déjà
parvenus en déroulant l'algorithme.
Exercices

Compétence attendue

➡ Résoudre un problème grâce à un algorithme glouton : problèmes du sac à dos et


du rendu de monnaie.

Exercice 10.1
► Traduire, analyser

On travaille à la caisse dans un magasin lors des fêtes de Noël. On


doit rendre 99 euros au premier client. Pour cela on dispose des
pièces et billets suivants (en euros) dans la caisse :
1. pieces = [50,20,10,5,2,1]

La caisse ne contient que deux exemplaires de chaque.


Puis on doit rendre 19 euros au client suivant.
➡ Indiquer quelles pièces/billets rendre aux deux clients et s'il y a un
souci. On utilisera pour cela un algorithme glouton du type rendu de
monnaie.

Exercice 10.2
► Traduire, analyser

Avant de partir en vacances pour les Caraïbes, on doit remplir sa


valise. Seulement la compagnie d'aviation n'accepte pas les bagages
de plus de 23 kg. Voici la liste des bagages suivante :
objets = [[6,5.0,'chaussures'],[5,5.0,'habits'],[4.5,2.0,'trousse
toilette'], [4,2.0,'crèmes'],[3,8.0,'livres'],[1,2.0,'palmes tuba'],
[0.5,3.0,'parasol']]

Elle est du type [[valeur,poids,'nom objet'],…]

Ainsi les chaussures ont la valeur 6.0 et pèsent 5 kg.


On remarquera que cette liste est triée par ordre décroissant de
valeur.
➡ Remplir la valise avec en priorité les articles de plus grande valeur.
On utilisera pour cela un algorithme glouton du type sac à dos.
Exercices-bilan

Exercice-bilan 10.1
15 min ● 10 points
On souhaite remplir un camion de déménagement de 5 m3, pour cela
on dispose d'une liste de meubles et de leur volume en mètres cubes :
meubles = [['armoire',3],['fauteuil',1.1],['lave vaisselle',1.0],
['lit',0.9],['machine',0.2]]

Par exemple, en lisant la liste ci-dessus, l'armoire occupe un volume


de 3 m3.
On souhaite privilégier le remplissage du camion avec les meubles de
plus gros volume principalement, le reste logera dans une voiture.
➡ Construire une fonction renvoyant une liste de noms de meubles à
choisir en appliquant un algorithme glouton.

Exercice-bilan 10.2
15 min ● 10 points
On considère qu'un après-midi actif dure 6 h, on souhaite effectuer un
maximum de choses dans cet après-midi. Ces choses sont classées
par ordre croissant de durée dans la liste suivante :
durees = [1,2,3,4,5]

Donc la première chose à faire prend 1 h, la seconde 2 h, etc.


➡ Construire une fonction renvoyant le nombre maximal de choses
que l'on peut effectuer en 6 h sachant qu'une chose ne doit être
effectuée qu'une seule fois.
Exercices de type EC - QCM

Pour chaque question, le candidat gagne 3 points s'il choisit la bonne


réponse, perd 1 point s'il choisit une réponse fausse. S'il ne répond
pas ou choisit plusieurs réponses, il ne gagne ni ne perd aucun point.

Exercice EC 10.1
1 min ● 3 points
L'algorithme glouton est un algorithme de :
Réponses :
a) tri
b) recherche d'une valeur dans une liste
c) résolution de problème
d) calcul de maximum très efficace

Exercice EC 10.2
1 min ● 3 points
On souhaite rendre 8 euros (800 centimes) dans le cadre du système
européen de monnaie. On dispose de différentes pièces stockées
dans la liste pieces :
1. pieces = [500,200,100,50,20,10,5,2,1]
2. somme = 800

L'algorithme glouton permet de rendre les pièces suivantes :


Réponses :
a) une pièce de 500 (billet de 5 euros), une pièce de 200 (2 euros) et
une pièce de 100 (1 euro).
b) une pièce de 500 (billet de 5 euros), trois pièces de 100 (1 euro).
c) huit pièces de 100 (1 euro).
d) ce n'est pas possible.

Exercice EC 10.3
1 min ● 3 points
On souhaite rendre 7 euros (700 centimes) dans le cadre du système
européen de monnaie. On dispose de différentes pièces stockées
dans la liste pieces :
1. pieces = [500,200,100,50,20,10,5,2,1]
2. somme = 700

L'algorithme glouton permet de rendre les pièces suivantes :


Réponses :
a) une pièce de 500 (billet de 5 euros), deux pièces de 100 (chacune
1 euro).
b) une pièce de 500 (billet de 5 euros), une pièce de 200 (2 euros)
c) sept pièces de 100 (chacune de 1 euro).
d) ce n'est pas possible.
Corrigé des exercices

Exercice 10.1

On utilise la fonction rendu_monnaie déjà écrite dans ce chapitre. On


l'applique à la liste de pièces/billets de départ :
1. def rendu_monnaie(somme,pieces):
2. n = len(pieces)
3. choisies = [0]*n
4. for i in range(n):
5. while somme >= pieces[i] :
6. somme = somme - pieces[i]
7. choisies[i] = choisies[i] + 1
8. assert somme == 0
9. return choisies
10.
11. pieces = [50,20,10,5,2,1]
12. somme = 99
13. print("Les pièces choisies sont :")
14. print(rendu_monnaie(somme,pieces))
Les pièces choisies sont :
[1, 2, 0, 1, 2, 0]

Donc après le premier client il ne reste plus de billets de 20 euros ni


de pièces de 2 euros. On relance la fonction en tenant compte du fait
qu'il manque cela dans la caisse :
1. pieces = [50,10,5,1]
2. somme = 19
3. print("Les pièces choisies sont :")
4. print(rendu_monnaie(somme,pieces))
Les pièces choisies sont :
[0, 1, 1, 4]
Ce n'est pas possible, on ne dispose pas de quatre pièces d'un euro.
Le second client ne sera pas satisfait.

Exercice 10.2

La fonction est remplir_sac développée dans ce chapitre. On l'applique


à la liste d'objets fournie dans l'énoncé.
1. def remplir_sac(objets,poids_max):
2. P = 0 #on initialise P
3. n = len(objets) #nombre d'objets
4. objets_choisis = [0]*n #on initialise la liste
5. for i in range(n):
6. if P + objets[i][1] <= poids_max :
7. objets_choisis[i] = 1 #objet choisi
8. P = P + objets[i][1] #le poids est augmenté
9. return objets_choisis
10.
11. objets = [[6,5.0,'chaussures'],[5,5.0,'habits'],[4.5,2.0,'trousse
toilette'],[4,2.0,'crèmes'],[3,8.0,'livres'],[1,2.0,'palmes tuba'],
[0.5,3.0,'parasol']]
12.
13. poids_max = 23.0
14. print("Les objets choisis sont :")
15. print(remplir_sac(objets,poids_max))
Les objets choisis sont :
[1, 1, 1, 1, 1, 0, 0]

On dirait donc que nous ne pourrons emmener palmes, tuba ou


parasol !
Corrigé des exercices-bilan

Exercice-bilan 10.1

On écrit tout d'abord une fonction de remplissage du camion :


1. def remplir_camion(meubles,V_max):
2. """Fournit la solution au problème du camion
3. V_max : un flottant à ne pas excéder
4. meubles : une liste de listes du type [['nom',volume],…] triée par
ordre décroissant de volume
5. choisis : une liste de noms (des chaînes de caractères)
6. """
7. V = 0 #on initialise le volume
8. n = len(meubles) #nombre d'objets
9. choisis = [] #on initialise la liste choisis
10. for i in range(n):
11. if V + meubles[i][1] <= V_max :
12. choisis.append(meubles[i][0]) #nom du meuble ajouté à la liste
choisis
13. V = V + meubles[i][1] #le volume est augmenté
14. return choisis

Puis on applique à la liste qui est déjà triée par ordre décroissant de
volume :
15. meubles = [['armoire',3],['fauteuil',1.1],['lave vaisselle',1.0],
['lit',0.9],['machine',0.2]]
16. V_max = 5.0
17. print("Les meubles choisis sont :")
18. print(remplir_camion(meubles,V_max))

Ce qui donne dans le shell :


Les meubles choisis sont :
['armoire', 'fauteuil', 'lit']

Exercice-bilan 10.2
Contrairement à l'algorithme glouton classique, on privilégie cette fois
les durées les plus courtes (et non les plus longues) : en effet on veut
effectuer un maximum de choses. Aussi il est bien que la liste durees
soit classée par ordre croissant et non décroissant.
La fonction donne :
1. def journee(durees):
2. """Renvoie le nombre de choses faisables
3. durees : une liste de durées triée par ordre croissant
4. T : un entier, le temps écoulé
5. nb_choses : un entier correspondant au nombre de choses effectuées
6. """
7. n = len(durees) #nombre de choses à faire
8. nb_choses = 0 #on initialise le nombre de choses effectuées
9. T = 0 #on initialise le temps écoulé
10. for i in range(n):
11. if T + durees[i] <= Tmax :
12. nb_choses +=1 #on ajoute une chose faire
13. T = T + durees[i] #le temps écoulé est augmenté
14. return nb_choses

On la teste :
1. durees = [1,2,3,4,5]
2. Tmax = 6
3. print("On peut faire le nombre de choses suivantes :")
4. print(journee(durees))

On obtient dans le shell :


On peut faire le nombre de choses suivantes :
3

Donc à savoir une chose de 1 h, une autre de 2 h puis une dernière


de 3 h.
Corrigé des exercices de type EC -
QCM

Exercice EC 10.1

a) tri
b) recherche d’une valeur dans une liste
c) résolution de problème
d) calcul de maximum très efficace

Exercice EC 10.2

a) une pièce de 500 (billet de 5 euros), une pièce de 200 (2 euros) et


une pièce de 100 (1 euro).
b) une pièce de 500 (billet de 5 euros), trois pièces de 100 (chacune
de 1 euro).
c) huit pièces de 100 (chacune de 1 euro).
d) ce n’est pas possible.

Exercice EC 10.3

a) une pièce de 500 (billet de 5 euros), deux pièces de 100 (chacune 1


euro).
b) une pièce de 500 (billet de 5 euros), une pièce de 200 (2 euros)
c) sept pièces de 100 (chacune de 1 euro).
d) ce n’est pas possible.
Thème C
Traitement de données
en tables
Chapitre 11
Traitement de données
en tables
Cours

1 Notion de base de données

Un peu d'histoire

En 1965, Charles Bachman a mis au point


l'architecture ANSI/Sparc, une structure de
gestion des bases de données, celle-ci est
encore en vigueur actuellement. Il a reçu
d'autre part le prix Turing en 1973 (haute
récompense dans le milieu de l'informatique)
pour ses « contributions exceptionnelles à la
technologie des bases de données ».

Stockage de données dans une table


Comme vous avez déjà certainement eu l'occasion de le voir en
utilisant les logiciels classiques comme Excel ou Regressi, il est fort
utile de stocker des données dans des tables. Ceci facilite l'accès aux
informations, le tri des données, le tracé de graphiques. Mais il existe
des moyens plus performants pour accéder à des données. Ce sont
les bases de données relationnelles (BDR) qui seront étudiées en
classe de Terminale. Il s'agit d'un ensemble de tables contenant des
données reliées entre elles par des relations. On peut extraire des
informations par le biais de requêtes exprimées dans un langage
appelé SQL (Structured Query Language).
Exemple d'une table issue d'une base de données classique
Dans cette base, les albums peuvent être comparés à des tables qui
contiennent différentes catégories d'information comme le nom, la
durée des pistes de lecture, le nom de l'artiste, le nom de l'album, le
genre de musique…
Vocabulaire à connaître
Chaque colonne de la base de données est appelée un attribut.

L'intérêt de stocker les informations en table est que l'on peut


exprimer la requête suivante par exemple :
« Sélectionner tous les titres du genre R&B/Soul »

Table sous forme de liste de listes


Sans pour autant faire appel au langage SQL ou à un système de
gestion de base de données (cela sera fait en classe de terminale),
l'idée du programme de première NSI est de constituer une table sous
forme de liste de listes en Python, puis d'extraire des informations de
cette table. Pour l'album de musique « Good Things » précédent, un
extrait sous forme de liste de listes en Python pourrait donner :
GoodThings = [[1,'I Need a Dollar','4:04','Aloe Blacc','Good
Things','R&B/Soul','Fichier audio MPEG'],
[1,'I Need a Dollar','4:04','Aloe Blacc','Good
Things','R&B/Soul','Fichier audio AAC achete'],
[2,'Green Lights','2:56','Aloe Blacc','Good
Things','R&B/Soul','Fichier audio AAC achete']]

Remarque
La liste de listes ci-dessus est aussi appelée table.
2 Rappel sur l'indexation de tables
Dans le chapitre 4, on a vu la notion d'indexation de liste et celle des
listes de listes. On peut noter i les indices (ou index) des listes et j les
sous-indices. Les indices démarrent à 0 en Python. On peut aussi
utiliser des indices (index) négatifs qui démarrent à −1 à partir de la fin
d'une liste.
Par exemple si on définit liste ci-dessous :

liste[-1] qui équivaut à liste[2] vaut [2,1,3],


liste[0][1] vaut 2

Remarque
Donc si on veut appeler l'élément de la liste d'indice i et de sous-indice j, on doit taper :
liste[i][j]

3 Construire une table à partir d'un fichier


Plutôt que de saisir manuellement la table sous forme de liste de listes
(ce qui peut être long et pas très efficace), il est possible d'extraire des
informations à partir d'un fichier texte .txt (ou d'un fichier .csv) si celui-
ci existe déjà.
Ce type de fichier de données peut être téléchargé sur internet,
généré par un tableur, etc. ou tout simplement créé manuellement.
Voici quelques exemples de contenus de fichiers .txt dont l'on peut
extraire les informations :
On pourrait extraire les valeurs de tension et d'intensité à partir du
fichier précédent afin de calculer la puissance correspondant à
chaque couple de données.
Les données écrites dans un fichier sont au format chaîne de
caractères. Chaque retour à la ligne est représenté par un retour
chariot. Ce dernier "\n", ne compte que pour un seul caractère.
Sur chaque ligne, les données sont séparées soit par des espaces
" ", des tabulations "\t", des virgules "," ou des points-virgules ";".

On peut à partir du fichier "GoodThings.txt" ci-dessus extraire toutes les


données et les stocker dans une liste de listes nommée album.
On fera appel pour cela à diverses méthodes relatives aux fichiers en
Python.
Pour cela, le pseudo-code sera :

Indiquer le chemin d'accès de "GoodThings.txt" à lire


Ouvrir "GoodThings.txt"
Stocker son contenu dans la variable donnees
Fermer "GoodThings.txt"
Créer une liste album vide
Pour element parcourant donnees
Enlever le "\n" en fin de ligne
Découper la ligne à chaque tabulation, former une liste
Ajouter cette liste à la liste album

Le code Python donnerait :


1. from os import chdir #on importe chdir de la bibliothèque os
2. chdir("/Users/…/") #on indique le chemin d'accès où le fichier
GoodThings.txt a été enregistré
3. fichier = open("GoodThings.txt", "r") #ouverture du fichier
GoodThings.txt en mode lecture avec "r"
4. donnees = fichier.readlines() #on lit le contenu du fichier, on
stocke dans la variable donnees
5. fichier.close()#fermeture du fichier GoodThings.txt
6.
7. #stockage sous forme de tableau
8. album = []
9. for element in donnees :
10. element = element.rstrip("\n") #enlever le retour chariot
11. ligne = element.split("\t") #découper à chaque tabulation
12. album.append(ligne) #ajouter ligne à album

Vocabulaire à connaître
La variable fichier est appelée un descripteur de fichier.

Remarques
La méthode chdir permet de changer de répertoire de lecture.
Ne pas oublier de refermer le fichier sous peine de détériorer son contenu ou causer des
erreurs.

Pour afficher le contenu de la liste de listes formée, on peut taper :


1. print("album",album)

Ce qui donne dans le shell :


album [['1', 'I Need a Dollar', '4:04', 'Aloe Blacc', 'Good Things',
'R&B/Soul', 'Fichier audio MPEG'], ['1', 'I Need a Dollar', '4:04',
'Aloe Blacc', 'Good Things', 'R&B/Soul', 'Fichier audio AAC achete'],
['2', 'Green Lights', '2:56', 'Aloe Blacc', 'Good Things', 'R&B/Soul',
'Fichier audio AAC achete']]

Remarque
Chaque ligne de cette table album est appelée un enregistrement. Par exemple le premier
enregistrement de la table s'affiche grâce à l'instruction print(album[0]) et donne :
['1', 'I Need a Dollar', '4:04', 'Aloe Blacc', 'Good Things', 'R&B/Soul',
'Fichier audio MPEG']
Pour afficher le deuxième (indice 1) et le troisième (indice 2) éléments
de la première ligne (donc l'enregistrement d'indice 0) de la liste
album, il suffit de taper :
1. print(album[0][1])
2. print(album[0][2])

Ce qui donne le nom de la première chanson de l'album et sa durée :


I Need a Dollar
4:04

Remarque
Toutes les données stockées dans un fichier .txt ou .csv sont bien au format chaîne de
caractères. Si on souhaite effectuer des calculs par la suite, il faut veiller à convertir les
données au format integer ou float (si elles s'y prêtent bien sûr : c'est-à-dire si elles
correspondent à l'origine à un nombre).

4 Recherche dans une table

Recherche d'un enregistrement selon un critère simple

Une fois la table album construite, on doit pouvoir y effectuer des


recherches.
Par exemple, on peut chercher toutes les informations relatives à la
chanson dont le titre est 'Green Lights'. Pour cela :
● On parcourt tous les éléments de la liste de listes album ;
● Si le titre d'un enregistrement est le bon, on affiche toutes les
informations relatives à l'enregistrement.
1. for i in album :
2. if i[1] == 'Green Lights':
3. print("L'enregistrement cherché est :",i)

Ce qui donne :
L'enregistrement cherché est : ['2', 'Green Lights', '2:56', 'Aloe
Blacc', 'Good Things', 'R&B/Soul', 'Fichier audio AAC achete']

Recherche d'un enregistrement selon un critère multiple


De même, on peut choisir d'afficher tous les enregistrements dont le
style est 'R&B/Soul' ET dont le format est 'Fichier audio MPEG'. Pour
cela :
● On parcourt tous les éléments de la liste de listes album ;
● Si le titre d'un enregistrement contient 'R&B/Soul' ET 'Fichier audio
MPEG', on affiche toutes les informations relatives à l'enregistrement.
1. for i in album :
2. if 'R&B/Soul' in i and 'Fichier audio MPEG' in i :
3. print("L'enregistrement cherché est :",i)

Ce qui donne :
L'enregistrement cherché est : ['1', 'I Need a Dollar', '4:04', 'Aloe
Blacc', 'Good Things', 'R&B/Soul', 'Fichier audio MPEG']

Création d'une table sans doublon


Imaginons à présent la nouvelle table GoodThings_double :
1. GoodThings_double = [[1,'I Need a Dollar','4:04','Aloe
Blacc','Good Things','R&B/Soul','Fichier audio MPEG'],
2. [1,'I Need a Dollar','4:04','Aloe Blacc','Good
Things','R&B/Soul','Fichier audio AAC achete'],
3. [2,'Green Lights','2:56','Aloe Blacc','Good
Things','R&B/Soul','Fichier audio AAC achete'],[2,'Green
Lights','2:56','Aloe Blacc','Good Things','R&B/Soul','Fichier audio
AAC achete']]

Cette table contient des lignes identiques ce qui pose un problème.


On va créer une nouvelle table sans_doublon qui ne contiendra aucun
doublon.
Pour cela :
● On crée une liste vide sans_doublon ;
● On parcourt tous les enregistrements de la table GoodThings_double ;
● Si l'enregistrement n'est pas dans la liste sans_doublon, on l'y ajoute.
1. sans_doublon = [] #liste vide
2. for i in GoodThings_double : #on parcourt la table
3. if i not in sans_doublon : #si i pas dans sans_doublon
4. sans_doublon.append(i) #on ajoute i
5. print(sans_doublon)

La liste contient sans_doublon alors :


[[1,'I Need a Dollar','4:04','Aloe Blacc','Good
Things','R&B/Soul','Fichier audio MPEG'],
[1,'I Need a Dollar','4:04','Aloe Blacc','Good
Things','R&B/Soul','Fichier audio AAC achete'],
[2,'Green Lights','2:56','Aloe Blacc','Good
Things','R&B/Soul','Fichier audio AAC achete']]

5 Tri d'une table

Rappel sur les méthodes de tri

Dans le chapitre 8, on a vu comment trier une liste et une liste de


listes. Pour rappel Python possède des méthodes associées aux listes
qui permettent d'effectuer un tri. Si t est une liste (de nombres ou de
chaînes de caractères) à trier :
>>> t.sort() #trie en place la liste t
>>> sorted(t) #renvoie une copie triée de la liste t

Remarque
Si la liste t est une liste de listes comme [[a1,b1],[a2,b2]]. Le tri s'applique par défaut
aux premiers éléments de chaque sous-liste : a1 et a2 ici.

Pour illustrer cela, on s'intéresse à la table constituée par des valeurs


de tension et d'intensité :

Ce fichier texte lu, on peut former une table regroupant les données :
mesures = [['1.378', '1.772'], ['1.379', '1.785'], ['1.395', '1.835'],
['1.396', '1.842'], ['1.378', '1.780'], ['1.369', '1.782'], ['1.378',
'1.811'], ['1.368', '1.784'], ['1.361', '1.779'], ['1.369', '1.792']]

Remarque
Toutes les données issues du fichier .txt sont au format chaîne de caractères.

Tri selon les valeurs situées en première colonne


Si on souhaite classer les données par ordre de valeur de tension
croissante, il suffit de taper :
1. T = sorted(mesures)
2. print("mesures triées",T)

Une fois les données triées selon les valeurs de tension, cela donne :
[['1.361', '1.779'], ['1.368', '1.784'], ['1.369', '1.782'], ['1.369',
'1.792'], ['1.378', '1.772'], ['1.378', '1.780'], ['1.378', '1.811'],
['1.379', '1.785'], ['1.395', '1.835'], ['1.396', '1.842']]

Remarque
Le tri s'effectue sans problème lorsqu'on l'applique à des nombres mais aussi à des chaînes
de caractères.

Tri selon les valeurs situées dans une colonne quelconque


Imaginons que l'on souhaite trier selon les valeurs d'intensité. Il faut
pour cela importer itemgetter de la bibliothèque operator afin de
spécifier la colonne selon laquelle on trie :
1. from operator import itemgetter
2. T2 = sorted(mesures, key=itemgetter(1))
3. print("mesures triées selon I",T2)

On trie donc selon la colonne d'indice 1 qui correspond aux intensités.


Cela donne :
mesures triées selon I [['1.378', '1.772'], ['1.361', '1.779'],
['1.378', '1.780'], ['1.369', '1.782'], ['1.368', '1.784'], ['1.379',
'1.785'], ['1.369', '1.792'], ['1.378', '1.811'], ['1.395', '1.835'],
['1.396', '1.842']]
6 Fusion de tables

Fusion de deux tables dont les attributs sont identiques

Soit deux tables mesures1 et mesures2 contenant les enregistrements


suivants :
1. mesures1 = [['1.378', '1.772'], ['1.379', '1.785'], ['1.395',
'1.835'], ['1.396', '1.842'], ['1.378', '1.780'], ['1.369',
'1.782']]
2. mesures2 = [['1.378', '1.811'], ['1.368', '1.784'], ['1.361',
'1.779'], ['1.369', '1.792']]

On constate que chaque table contient des enregistrements de


tension et intensité : leurs attributs sont identiques. Il s'agit tout
simplement d'ajouter des enregistrements à la suite de la première
table mesures1. On propose deux méthodes simples afin de fusionner
les deux tables et former une nouvelle table mesures :
1. #Méthode 1
2. mesures = mesures1 + mesures2 #on concatène les deux tables
3. print(mesures)
4.
5. #Méthode 2
6. mesures = mesures1.copy() #on copie mesures1
7. for i in mesures2 : #pour chaque enregistrement de mesures2
8. mesures.append(i) #on l'ajoute à mesures
9. print(mesures)

Dans les deux cas, la table fusionnée (mesures) donne :


[['1.378', '1.772'], ['1.379', '1.785'], ['1.395', '1.835'], ['1.396',
'1.842'], ['1.378', '1.780'], ['1.369', '1.782'], ['1.378', '1.811'],
['1.368', '1.784'], ['1.361', '1.779'], ['1.369', '1.792']]

Fusion de deux tables d'attributs différents


On dispose cette fois de deux tables U et I. Chaque table est une liste
de listes. Chaque sous liste contient un identifiant de mesure (un
entier) et une valeur de mesure au format chaîne de caractères.
Donc U = [[identifiant,'mesureU'],…], I = [[identifiant,'mesureI'],…]

Soit :
1. U = [[9, '1.361'], [8, '1.368'], [6, '1.369'], [10, '1.369'], [1,
'1.378'], [5, '1.378'], [7, '1.378'], [2, '1.379'], [3, '1.395'],
[4, '1.396']]
2.
3. I = [[1, '1.772'], [9, '1.779'], [5, '1.780'], [6, '1.782'], [8,
'1.784'], [2, '1.785'], [10, '1.792'], [7, '1.811'], [3, '1.835'],
[4, '1.842']]

On veut fusionner les tables U et I selon la valeur de leur identifiant.


C'est-à-dire que l'on souhaite obtenir : [[1,'1.378', '1.772'],
[2,'1.379', '1.785'], …]

Remarque
C'est l'identifiant, attribut commun aux deux tables qui permet de les fusionner de manière
intelligente.

Vocabulaire à connaître
On appelle domaine de valeurs, l'ensemble des valeurs que peut prendre un attribut.
Par exemple :
Identifiant = { 1 ; 2 ; 3 ; …} ;
mesureU = { '1.378', '1.379', '1.395' ; …} ;
mesureI = { '1.772', '1.779', '1.780'; …} ;

On ne garde qu'une seule colonne correspondant à l'identifiant. On


souhaite obtenir une table triée selon la valeur de l'identifiant.
Pour cela, le pseudo-code sera :

On trie la liste U selon la valeur de l'identifiant


On copie la liste U triée dans une nouvelle liste mesures
Pour i parcourant les valeurs des indices de mesures :
Pour j parcourant les valeurs des indices de I :
Si l'identifiant est identique
on ajoute la valeur d'intensité à l'enregistrement mesures[i]

Ce qui donne en Python :


4. U_triee = sorted(U)
5. mesures = U_triee.copy() #on copie U_triee
6. for i in range(len(mesures)) : #pour chaque indice de mesures
7. for j in range(len(I)) : #pour chaque indice de I
8. if mesures[i][0] == I[j][0]: #si l'identifiant est identique
9. mesures[i].append(I[j][1]) #on ajoute j à mesures
10. print(mesures)
On obtient bien la liste de mesures du type :
mesures = [[identifiant,'mesureU', 'mesureI'],…]

Soit :
[[1, '1.378', '1.772'], [2, '1.379', '1.785'], [3, '1.395', '1.835'],
[4, '1.396', '1.842'], [5, '1.378', '1.780'], [6, '1.369', '1.782'],
[7, '1.378', '1.811'], [8, '1.368', '1.784'], [9, '1.361', '1.779'],
[10, '1.369', '1.792']]
Exercices

Compétence attendue

➡ Importer une table depuis un fichier texte tabulé ou un fichier CSV.

Exercice 11.1
► Traduire

On reprend le fichier du cours :

➡ Écrire pour ce fichier le code Python permettant d'obtenir la table


ci-dessous.
[[1.378, 1.772], [1.379, 1.785], [1.395, 1.835], [1.396, 1.842],
[1.378, 1.78], [1.369, 1.782], [1.378, 1.811], [1.368, 1.784], [1.361,
1.779], [1.369, 1.792]]

On remarque que chaque mesure est au format float.

Compétence attendue
➡ Rechercher les lignes d'une table vérifiant des critères exprimés en logique
propositionnelle.

Exercice 11.2
► Traduire

On considère une liste d'individus issus d'un dessin animé et dont


certains sont amis.

Une représentation simplifiée, réduite à deux tables liens et individus,


de la base de données est donnée ci-après.
Dans la table individus, chaque personne est représentée par un
identifiant. Elle contient les colonnes :
● id, un entier identifiant chaque individu ;
● prenom, une chaîne de caractères donnant le prénom de l'individu.
Prénom id

Julie 1
Tom 2
Sam 3
Portillon 4

Charlie 5

Ceci donne la table en Python :


individus = [['Julie',1],
['Tom',2],['Sam',3],['Portillon',4]],['Charlie',5]]
La table liens répertorie les liens d'amitié entre individus et contient les
colonnes :
● id1, entier identifiant le premier individu du lien d'amitié ;
● id2, entier identifiant le deuxième individu du lien d'amitié.
id1 id2

1 2
2 3
3 5
4 5

Ceci donne la table en Python :


liens = [[1,2],[2,3],[3,5],[4,5]]

➡ Écrire un script Python qui renvoie le prénom de l'individu


d'identifiant 5.
➡ Écrire un script Python qui renvoie les prénoms des amis de
l'individu d'identifiant 5.

Compétence attendue

➡ Rechercher les lignes d'une table vérifiant des critères exprimés en logique
propositionnelle.
➡ Trier une table suivant une colonne.
➡ Construire une nouvelle table en combinant les données de deux tables.

Exercice 11.3
► Décomposer, traduire

Pour suivre la propagation des épidémies, de nombreuses données


sont recueillies par les institutions internationales comme l'O.M.S. Par
exemple, pour le paludisme, on dispose de la table palu qui recense le
nombre de nouveaux cas confirmés et le nombre de décès liés au
paludisme ; certaines lignes de cette table sont données en exemple
(on précise que iso est un identifiant unique pour chaque pays) :

Cette table peut être représentée par une liste de listes palu :
palu = [['Bresil','BR',2009,309316,85],
['Bresil','BR',2010,334667,76],['Kenya','KE',2010,898531,26017],
['Mali','ML',2011,307035,2128]]

La table demographies recense la population totale de chaque pays ;


certaines lignes de cette table sont données en exemple :

Cette table peut être représentée par une liste de listes demographies :
demographies = [['BR',2009,193020000],
['BR',2010,194946000],['KE',2010,40909000],['ML',2011,33987000]]
1) Grâce à un script Python, extraire (sans doublon) le nom des pays
référencés dans la table palu et les classer par ordre alphabétique.
2) Écrire un script Python qui partir des deux tables palu et demographies,
permet de créer la nouvelle table :
repartition = [['nom', annee, cas, pop],.]
C'est-à-dire :
repartition = [['Bresil',2009,309316,193020000], ['Bresil',2010,334667,
194946000],['Kenya',2010,898531,40909000],['Mali',2011,307035, 33987000]]
Attention, il faut fusionner en partie les tables palu et demographies
pour les lignes dont le pays et l'année sont identiques bien sûr.
Source : concours Mines-Ponts 2016
Exercices-bilan

Exercice-bilan 11.1
30 min ● 10 points

On étudie les données retransmises par une bouée. Les relevés de la


campagne de mesure sont écrits dans un fichier texte dont le contenu
est défini comme suit :
● La première ligne : le titre 'Mesures'
● Les lignes suivantes contiennent les mesures du déplacement
vertical de la bouée (en mètre). Chaque ligne comporte 8 caractères
(dont le caractère de fin de ligne). Par exemple, on trouvera dans le
fichier texte les lignes suivantes :
Mesures
+0.7657
+0.6754
-0.0126

Les données se trouvent dans le répertoire de travail sous forme d'un


fichier donnees.txt. Proposer une suite d'instructions permettant de
créer à partir de ce fichier une liste de flottants liste_niveaux contenant
les valeurs du niveau de la mer. On prendra garde à ne pas insérer
dans la liste la première ligne du fichier.

Exercice-bilan 11.2
15 min ● 10 points
On dispose de la table de mesures suivante :
[[1.378, 1.772], [1.379, 1.785], [1.395, 1.835], [1.396, 1.842],
[1.378, 1.78], [1.369, 1.782], [1.378, 1.811], [1.368, 1.784], [1.361,
1.779], [1.369, 1.792]]

Cette table est constituée par des valeurs de tension U et d'intensité I


du type [[U, I],…]
➡ Écrire une fonction U_max qui renvoie la valeur maximale de la
tension.
➡ Écrire une fonction U_moy qui renvoie la valeur moyenne de la
tension.

Exercice-bilan 11.3
10 min ● 5 points
On dispose de la table de mesures suivante :
[[1.378, 1.772], [1.379, 1.785], [1.395, 1.835], [1.396, 1.842],
[1.378, 1.78], [1.369, 1.782], [1.378, 1.811], [1.368, 1.784], [1.361,
1.779], [1.369, 1.792]]

Cette table est constituée par des valeurs de tension U et d'intensité I


du type [[U, I],…]
➡ Écrire une fonction tri_insertion qui trie la table par ordre de valeur
de tension croissante en appliquant la méthode du tri par insertion.
Exercices de type EC - QCM

Pour chaque question, le candidat gagne 3 points s'il choisit la bonne


réponse, perd 1 point s'il choisit une réponse fausse. S'il ne répond
pas ou choisit plusieurs réponses, il ne gagne ni ne perd aucun point.

Exercice EC 11.1
1 min ● 3 points
Qu'est-ce que le format csv d'un fichier ?
Réponses :
a) un format d'image RGB
b) Il signifie « coma separated values » : cela signifie que les données
stockées dans le fichier sont séparées par des virgules
c) un format de « lecture simple » d'un fichier (read only)
d) un format de fichier créé sous Word

Exercice EC 11.2
1 min ● 3 points
On donne un extrait de fichier :
“1”,”I Need a Dollar”,”4:04”,”Aloe Blacc”,”Good
Things”,”R&B/Soul”,”Fichier audio”,”MPEG”
De quel format s'agit-il ?
Réponses :
a) le format .png
b) le format .txt
c) le format .xls
d) le format .csv

Exercice EC 11.3
1 min ● 3 points
On dispose de la liste suivante : individus = [['Julie',1],
['Tom',2],['Sam',3],['Portillon',4],['Charlie',5]]

De quel type de liste s'agit-il ?


Réponses :
a) une liste de chaînes de caractères
b) une liste de listes
c) une liste d'entiers
d) ce n'est pas une liste

Exercice EC 11.4
1 min ● 3 points
Soit la liste qui attribue un numéro à chaque personne :
individus = [['Julie',1],
['Tom',2],['Sam',3],['Portillon',4],['Charlie',5]]

Comment modifier le numéro de Sam en 1 ?


Réponses :
a) individus[2][1]=1
b) individus[1][1]=1
c) individus[1][1]==1
d) Sam = 1

Exercice EC 11.5
1 min ● 3 points
Soit la liste qui attribue un numéro à chaque personne :
individus = [['Julie',1],
['Tom',2],['Sam',3],['Portillon',4],['Charlie',5]]
individu = ['Nicolas',6]

Comment fusionner les listes individus et individu en la liste individus ?


Réponses :
a) individus = individus + individu
b) individus = individus + [individu]
c) individus = [individus] + [individu]
d) individus = individus.append(individu)
Corrigé des exercices

Exercice 11.1

Pour cela on commence à lire les données du fichier et on les passe


au format flottant. Puis on les stocke dans une table :
1. from os import chdir #on importe chdir de la bibliothèque os
2. chdir("…/") #on indique le chemin d'accès où le fichier a été
enregistré
3. fichier = open("mesures.txt", "r") #ouverture du fichier en mode
lecture avec "r"
4. donnees = fichier.readlines() #on lit le contenu du fichier, on
stocke dans donnees
5. fichier.close()#fermeture du fichier
6.
7. mesures = []
8. for i in range(1,len(donnees)):#on saute la 1ere ligne qui
contient le titre
9. donnees[i] = donnees[i].rstrip("\n")#on enlève le saut à la ligne
10. ligne = donnees[i].split("\t")#on découpe selon la tabulation
11. for j in range(len(ligne)) : #on parcourt la ligne
12. ligne[j] = float(ligne[j]) #conversion en flottant
13. mesures.append(ligne) #on ajoute ligne à mesures
14. print(mesures)

On obtient bien la table demandée : c'est une liste de listes qui


contient des flottants.
[[1.378, 1.772], [1.379, 1.785], [1.395, 1.835], [1.396, 1.842],
[1.378, 1.78], [1.369, 1.782], [1.378, 1.811], [1.368, 1.784], [1.361,
1.779], [1.369, 1.792]]

Exercice 11.2
On définit les tables puis on cherche le nom dont l'identifiant vaut 5 :
1. individus = [['Julie',1],['Tom',2],['Sam',3],['Portillon',4],
['Charlie',5]]
2. liens = [[1,2],[2,3],[3,5],[4,5]]
3.
4. for i in individus :
5. if i[1]== 5 :
6. print(i[0])

On obtient le nom Charlie.


Puis on crée une liste des identifiants des amis de Charlie. Puis
comme on l'a fait précédemment, on affiche les prénoms
correspondants.
1. #On crée une liste avec les identifiants des amis de Charlie
2. liste_amitie = []
3. for l in liens :
4. if 5 in l and l[0]!= 5 :
5. liste_amitie.append(l[0])
6. print(liste_amitie)
7.
8. #pour chaque identifiant ami
9. for id in liste_amitie :
10. for i in individus : #on parcourt individus
11. if i[1]== id :
12. print(i[0]) #on affiche le prénom de l'ami

Cela donne Sam et Portillon.

Exercice 11.3

On définit les tables puis on cherche les noms des pays :


1. palu = [['Bresil','BR',2009,309316,85],
['Bresil','BR',2010,334667,76],
['Kenya','KE',2010,898531,26017],['Mali','ML',2011,307035,2128]]
2. demographies = [['BR',2009,193020000],['BR',2010,194946000],
['KE',2010,40909000],['ML',2011,33987000]]
3.
4. #1
5. palu.sort()
6. pays = []
7. for i in palu :
8. if i[0] not in pays : #pas de doublon
9. pays.append(i[0])
10. print(pays)

Cela donne sans doublon :


['Bresil', 'Kenya', 'Mali']
1. #2
2. n = len(palu)
3. repartition = []*n #on copie palu
4. for i in range(len(palu)) : #pour chaque indice de palu
5. for j in range(len(demographies)) : #pour chaque indice de
demographie
6. if palu[i][1] == demographies[j][0] and palu[i][2] ==
demographies[j][1] : #si le pays ET l'année sont les mêmes
7. repartition.append([palu[i][0],palu[i][2],palu[i]
[3],demographies[j][2]]) #on ajoute les donnees à repartition
8. print(repartition)

Ce qui donne bien :


[['Bresil', 2009, 309316, 193020000], ['Bresil', 2009, 309316,
194946000], ['Bresil', 2010, 334667, 193020000], ['Bresil', 2010,
334667, 194946000], ['Kenya', 2010, 898531, 40909000], ['Mali', 2011,
307035, 33987000]]
Corrigé des exercices-bilan

Exercice-bilan 11.1

La lecture d'un fichier texte peut se faire de la manière suivante :


1. f = open('donnees.txt') # Ouverture du descripteur de fichier
2. L = f.readlines() # Lecture du fichier
3. liste_niveaux = [] # Définition de la nouvelle liste vierge
4. for i in range(1,len(L)): # On saute la 1ère ligne de texte
5. liste_niveaux.append(float(L[i])) # et on convertit le reste en
flottants
6. f.close() # Fermeture du descripteur de fichier

Exercice-bilan 11.2

Les fonctions maximum et moyenne ont déjà été développées dans le


chapitre 6. Il suffit d'y faire appel en remarquant que la tension est
l'élément d'indice 0 de la liste mesures.
1. mesures = [[1.378, 1.772], [1.379, 1.785], [1.395, 1.835],
[1.396, 1.842], [1.378, 1.78], [1.369, 1.782], [1.378, 1.811],
[1.368, 1.784], [1.361, 1.779], [1.369, 1.792]]
2.
3. def maximum(liste):
4. maxi=liste[0][0] #1ere valeur de tension de la liste
5. n = len(liste) #nb d'éléments
6. for i in liste : #i parcourt les éléments de liste
7. if i[0]>maxi: #si la valeur rencontrée > maxi
8. maxi = i[0] #on affecte la nouvelle valeur à maxi
9. return maxi
10.
11. print("Le maximum des tensions est :",maximum(mesures), "V")
12.
13. def moyenne(liste):
14. """Renvoie la moyenne de liste
15. liste est au format list"""
16. S = 0 #somme initialisée à 0
17. n = len(liste) #nb d'éléments
18. for i in liste : #parcourt les valeurs
19. S = S + i[0] #on ajoute chaque note à S
20. return S/n
21.
22. print("La tension moyenne est :",moyenne(mesures), "V")

On obtient :
Le maximum des tensions est : 1.396 V
La tension moyenne est : 1.3771 V

Exercice-bilan 11.3

La fonction tri_insertion a déjà été développée dans le chapitre 8. On


y fait appel en l'adaptant : on remarque que la tension est l'élément
d'indice 0 de la liste mesures.
1. def tri_insertion(t):
2. """ Procédure qui trie la liste de listes t en place selon le
1er élément de chaque sous-liste
3. t : une liste de listes de flottants
4. Ne renvoie rien"""
5. n = len(t)
6. for i in range(1,n):
7. while i>0 and t[i][0] < t[i-1][0]: #t[i] mal placé
8. t[i-1], t[i] = t[i], t[i-1]
9. #permute t[i] et t[i-1]
10. i = i - 1
11. #on descend dans les indices pour continuer à tester si t[i] bien
placé
12.
13. mesures = [[1.378, 1.772], [1.379, 1.785], [1.395, 1.835],
[1.396, 1.842], [1.378, 1.78], [1.369, 1.782], [1.378, 1.811],
[1.368, 1.784], [1.361, 1.779], [1.369, 1.792]]
14. tri_insertion(mesures)
15. print(mesures)

Cela donne bien la liste triée par ordre de tension croissante :


[[1.361, 1.779], [1.368, 1.784], [1.369, 1.782], [1.369, 1.792],
[1.378, 1.772], [1.378, 1.78], [1.378, 1.811], [1.379, 1.785], [1.395,
1.835], [1.396, 1.842]]
Corrigé des exercices de type EC -
QCM

Exercice EC 11.1

a) un format d'image RGB


b) Il signifie « coma separated values » : cela signifie que les données
stockées dans le fichier sont séparées par des virgules
c) un format de « lecture simple » d'un fichier (read only)
d) un format de fichier créé sous Word

Exercice EC 11.2

a) le format .png
b) le format .txt
c) le format .xls
d) le format .csv

Exercice EC 11.3

a) une liste de chaînes de caractères


b) une liste de listes
c) une liste d'entiers
d) ce n'est pas une liste
Exercice EC 11.4

a) individus[2][1]=1
b) individus[1][1]=1
c) individus[1][1]==1
d) Sam = 1

Exercice EC 11.5

a) individus = individus + individu


b) individus = individus + [individu]
c) individus = [individus] + [individu]
d) individus = individus.append(individu)
Thème E
Architectures matérielles et
systèmes d'exploitation
Chapitre 12
Architectures matérielles et
systèmes d'exploitation
Cours

1 Modèle d'architecture séquentielle (von Neumann)

Un peu d'histoire

L'architecture de von Neumann a été conçue en juin


1945 par le mathématicien John von Neumann dans
le cadre du projet EDVAC (Electronic Discrete
Variable Automatic Computer) : il s'agit de l'un des
tous premiers ordinateurs.
Ce modèle d'architecture reste d'actualité : il régit
toujours l'architecture des ordinateurs malgré
quelques évolutions.

Principe
Le schéma d'architecture de von Neumann est séparé en quatre
éléments :
● L'unité arithmétique et logique : elle effectue les opérations de
base.
● L'unité de commande : elle est en charge du séquençage ou
découpage des opérations.
● La mémoire : elle contient les données, les programmes et indique
à l'unité de commande quelles opérations effectuer.
● Les entrées et sorties : assurent la communication avec l'extérieur.
2 L'ordinateur

L'ordinateur avant et maintenant

En 1953, le premier ordinateur à transistors (un composant


électronique) a été développé. Il est suivi en 1958 par l'invention du
circuit intégré : ce dernier réunit en un petit volume plusieurs
transistors et divers composants. Puis en 1969 est inventé le
microprocesseur, permettant à des milliers de transistors de
fonctionner de concert au sein d'un même ordinateur.
Aussi, les ordinateurs de nos jours sont bien plus compacts que les
premiers qui sont apparus dans les années 1950.

Les ordinateurs comportent à présent des processeurs multiples, on


trouvera pour cela des unités séparées ou de « cœurs » (core en
anglais) multiples à l'intérieur d'une même puce. Ce principe permet
d'atteindre une puissance globale de calcul élevée.
Exemple : les microprocesseurs Core 2 sont des processeurs
fabriqués par Intel® et existant en versions solo ou multi-cœurs
(deux ou quatre).

De quoi est constitué un ordinateur ?


Un ordinateur fixe est composé d'au moins un écran, un clavier, un
dispositif de pointage, et d'une unité centrale.

Un ordinateur portable est la fusion d'une unité centrale, d'un dispositif


de pointage (qui devient un trackpad, mais on peut aussi ajouter une
souris), un clavier, et un écran, auxquels s'ajoute une batterie.

Il existe de nos jours des ordinateurs portables qui se transforment en


tablette tactile et peuvent être donc utilisés sans clavier et sans souris.

Des périphériques variés peuvent être connectés à un ordinateur :


imprimante, webcam, enceintes, lecteur CD externe, casque audio…
Les périphériques communiquent avec l'ordinateur soit par câble (ils
se branchent principalement en USB ou par ondes radio (wifi,
bluetooth)), les casques audios fonctionnent souvent grâce à une
prise jack ou en bluetooth. Il existe une autre génération de ports
appelés les ports USB-C qui assurent, via un seul connecteur,
l'alimentation électrique, le transfert de données et la sortie vidéo.

Les composants de l'ordinateur


Si on démonte un ordinateur on
peut découvrir les composants
suivants :
1. L'écran ou moniteur
2. La carte mère
3. L'unité centrale
(microprocesseur)
4. La mémoire vive (RAM)
5. Les cartes périphériques
6. Le bloc d'alimentation
7. Le lecteur DVD/CD
8. Le disque dur
9. Le dispositif de pointage (souris ici)
10. Le système de saisie (clavier ici)
1. L'écran ou moniteur
2. La carte mère : elle regroupe l'ensemble des composants internes
de l'ordinateur et gère les interfaces avec les périphériques. On y
retrouve les ports USB.
3. L'unité centrale (microprocesseur) : le processeur permet de
traiter les données qui lui sont fournies sous forme binaire. Sa
puissance a une influence sur la vitesse d'exécution des logiciels et
des opérations.
4. La mémoire vive (Random Access Memory : RAM) : elle stocke
temporairement les données en cours d'exécution d'une opération.
Ainsi, si la RAM est élevée, l'ordinateur sera plus rapide en exécution
car il évitera de faire appel au disque dur qui est plus lent. La RAM se
vide dès que l'on éteint l'ordinateur.
5. Les cartes périphériques (carte graphique, carte son, carte
réseau) : une carte graphique (ou vidéo) et une carte son sont bien
souvent intégrées à la carte mère mais d'autres plus performantes
peuvent être ajoutées à l'ordinateur. Ces cartes permettent d'améliorer
la rapidité et la qualité de lecture de fichiers contenant de la vidéo ou
du son.

Pour le cas des ordinateurs fixes récents, la connexion au réseau


internet s'effectue soit via wifi, soit :
– Grâce à une carte réseau qui peut
être insérée dans un connecteur
(appelé PCI de l'anglais Peripheral
Component Interconnect et depuis
2004 les PCI Express abrégés PCIe)
libre sur la carte mère.
– Grâce à la carte mère : en effet, de nombreux modèles de cartes
mères disposent d'une interface réseau intégrée. Dans ce cas, on
branche directement le câble réseau sur la carte mère.
Pour les ordinateurs portables, d'autres possibilités existent pour les
relier à internet : carte réseau au standard PC Card, Interface réseau
(Wi-Fi ou Ethernet) déjà intégrée au portable, carte réseau
connectée en USB.
6. Le bloc d'alimentation : il est aussi équipé d'un ventilateur
permettant le refroidissement de l'alimentation en cas de surchauffe.
7. Le lecteur/graveur de DVD/CD : permet de lire ou graver un CD
ou DVD de données.
8. Le disque dur : contrairement à la RAM (Random Access
Memory), les données stockées sur un disque dur sont permanentes.
Elles ne sont pas effacées à l'arrêt de l'ordinateur. C'est donc sur le
disque dur que le système d'exploitation, les logiciels, les documents,
les photos, la musique sont conservés.
9. Le dispositif de pointage : possibilité d'avoir une souris branchée
en USB ou en fonctionnement bluetooth ou bien un trackpad pour les
ordinateurs portables.
10. Le système de saisie : un clavier externe ou bien un pupitre
industriel dans le cas d'une machine dans l'industrie.

3 Transmission de données dans un réseau

Les paquets de données

Il a été vu en seconde que les données circulent sur Internet sous


forme de paquets de taille fixe, ce, quel que soit le type de données
transportées : texte, images, sons, vidéos etc. Les datagrammes sont
des données auxquelles on a ajouté des en-têtes correspondant à des
informations sur leur transport (telles que l'adresse IP du destinataire
et de l'émetteur).
Les routeurs effectuent ensuite l'analyse des données contenues dans
les paquets grâce au protocole TCP.

Le protocole TCP/IP
L'ensemble des données transférées sur Internet est transféré grâce à
un protocole de communication universalisé : il s'agit du protocole
TCP/IP (ce qui signifie en anglais Transmission Control
Protocol / Internet Protocol). Pour rappel, ce sont des règles que les
machines suivent afin d'effectuer des tâches.
IP : Internet Protocol
Le protocole IP permet d'identifier et de nommer de façon uniforme
tous les éléments (téléphones, ordinateurs portables, tablettes et
objets connectés) qui sont reliés à Internet. Le protocole IP permet
l'élaboration et le transport des datagrammes IP (aussi appelés
paquets de données).
TCP : Transmission Control Protocol
Le protocole TCP est responsable de la mise en place de la
connexion et du contrôle de la transmission. Il s'agit d'un protocole de
remise fiable. Ce protocole s'assure que le destinataire a bien reçu les
données. En effet, lors du routage, un paquet peut ne pas arriver pour
cause de panne de ligne ou de routeur. Le protocole TCP assure alors
la fiabilité du transport des paquets.
Le protocole TCP fonctionne en trois phases :
● L'établissement de la connexion ;
● Les transferts de données ;
● La fin de la connexion.
Certains mécanismes sont mis en œuvre afin d'assurer la robustesse
et la fiabilité du transfert de données. En particulier, les numéros de
séquence sont utilisés afin d'ordonner les segments TCP reçus et de
détecter les données perdues, les sommes de contrôle (ou
checksum en anglais) permettent par exemple la détection d'erreurs,
et d'autres mécanismes permettent la détection des segments perdus
ou retardés.
En revanche, il n'y a pas de garantie temporelle d'arrivée des paquets
ce qui peut nuire à la qualité du streaming du son, de la vidéo : ceci
explique les soucis occasionnels de visionnage d'une vidéo en
streaming…

4 Architecture d'un réseau

Le réseau

Il a été vu en classe de seconde qu'Internet est constitué de la


multitude de réseaux répartis dans le monde entier et qui sont
interconnectés. Chaque réseau est rattaché à une entité (une école,
une institution, un fournisseur d'accès etc.). Afin de pouvoir
communiquer entre eux, les réseaux s'échangent des données, soit
en établissant une liaison directe, soit en se rattachant à ce qui
s'appelle un nœud d'échange.

Le routeur
Chaque réseau est donc connecté à un ou plusieurs
autres réseaux. Au sein de ces réseaux, les
routeurs sont chargés du trafic.
Le routeur s'occupe du routage des paquets de
données de leurs émetteurs vers leurs destinataires.
Ce dernier est conçu afin de transférer des paquets vers un autre
routeur selon sa carte locale (ou table de routage, il s'agit d'un
schéma des meilleures routes vers les autres réseaux) et la
destination prévue, au mieux, selon un ensemble de règles (le
protocole TCP/IP dont nous avons parlé dans les paragraphes
précédents). Un routeur doit être connecté à au moins deux réseaux
informatiques afin de transférer des paquets d'information.
Pour plus de confort, on utilise à présent des routeurs wifi dans nos
maisons et nos lieux de travail, dans les restaurants etc… : ceci
permet d'avoir accès à Internet sur son téléphone, sa tablette, son
ordinateur portable.
Exemple d'une installation à domicile
5 Systèmes d'exploitation

Une multitude de systèmes d'exploitation possibles

Parmi les logos ci-dessous, quels sont ceux que vous connaissez ?

Réponse : ce sont ceux de Apple en bleu, vert et arc-en-ciel, Debian,


Ubuntu, Fedora, Freespire, Konqueror, Linux, Mandriva, Vista,
Windows Media Center et Microsoft Windows.
Vocabulaire à connaître
Un système d'exploitation est un ensemble de programmes qui dirige l'utilisation des
capacités d'un ordinateur par des logiciels applicatifs.

Fonctions du système d'exploitation


Le système d'exploitation d'un ordinateur est un ensemble de
programmes qui remplissent deux grandes fonctions. Ils permettent :
● de gérer les ressources de l'installation matérielle en assurant leurs
partages entre un ensemble d'utilisateurs ;
● d'assurer des services en présentant aux utilisateurs une interface
plus conviviale que celle de la machine physique.

Interface Homme-Machine (IHM)


Le système d'exploitation reçoit les informations envoyées par les
logiciels, et les place sur une image numérique qui sera envoyée au
matériel par l'intermédiaire d'un pilote. D'autre part, un autre
ensemble de programmes reçoit les manipulations effectuées par
l'usager par l'intermédiaire de pilotes et les transmettent au logiciel
concerné. Ces deux ensembles constituent alors l'Interface Homme-
Machine qui permet à un usager de dialoguer avec la machine.

6 Quelques commandes Unix


La console (ou terminal) Unix permet d'utiliser des centaines de
commandes très utiles dans la gestion de fichiers, de recherches, la
gestion de processus, la gestion de réseaux etc.
Cet ouvrage va en détailler seulement quelques-unes. Voici un
exemple de terminal Unix sous Mac :

Notion de chemin d'accès


Pour connaitre le répertoire où est stocké un fichier il suffit d'effectuer
un clic droit sur ledit fichier, aller dans propriétés (sur PC) ou dans Lire
les informations (sous Mac) puis d'accéder à l'emplacement.
Par exemple :
/Users/eleve/Desktop

Indique que le fichier est stocké dans le répertoire (aussi appelé


dossier) Desktop (le bureau) situé lui-même dans le répertoire eleve
dans le répertoire Users.

Les commandes de base


La commande ls
Elle signifie « list » et permet de « lister » un répertoire : cela signifie
connaitre tout ce qu'il contient. Par exemple :
● ls -a
affiche tous les fichiers et répertoires y compris les cachés du
répertoire courant
● ls /travail/

affiche le contenu du répertoire /travail/

La commande cd
Elle signifie « change directory » et permet de changer de répertoire,
ce afin de se promener dans l'arborescence des répertoires.
Exemples :
● cd
permet de revenir au répertoire /home/utilisateur (identique à cd ~)
● cd –
permet de revenir au répertoire précédent
● cd ..
permet de remonter au répertoire parent
● cd /
permet de remonter à la racine de l'ensemble du système de
fichiers
● cd /Users/eleve/Desktop
se place dans le répertoire /Users/eleve/Desktop
La commande pwd
Elle signifie « print working directory » et permet d'afficher le chemin
absolu du répertoire courant (où on se situe).

La commande clear
Elle signifie « nettoyer » et permet de nettoyer le terminal, ce afin d'y
voir plus clair.

Les commandes de gestion de fichiers


La commande cat
Elle permet la lecture du contenu d'un fichier texte.
Exemple : cat monfichier.txt permet de lire le fichier monfichier.txt
situé dans le répertoire courant.
La commande mkdir
Elle signifie « make directory » et permet de créer un répertoire (aussi
appelé dossier) dans le répertoire courant.
Exemple : mkdir nouveau_dossier
Dans l'image précédente, on se situe dans un dossier tests_Unix
initialement vide. Puis on crée nouveau_dossier et on teste son
existence avec ls -a.
La commande cp
Elle signifie « copy » et permet de créer une copie d'un fichier.
Exemple : cp fichier1 fichier2
Dans le répertoire courant, on crée le fichier fichier2 qui est une
copie de fichier1.
La commande mv
Elle signifie « move » et permet de déplacer un fichier (ou un dossier).
Elle permet aussi de renommer un fichier.
Exemple : mv fichier1 fichier2
Dans le répertoire courant, on modifie le nom du fichier fichier1 en
fichier2.

Les commandes du système


La commande chmod
Elle signifie « change mode » et permet de modifier les droits sur un
fichier (ou un dossier).
On peut ajouter des lettres :
● r pour « read », donc le droit de lire le fichier ou dossier.
● w pour « write », donc le droit d'écrire dans le fichier ou dossier.
● x comme « execution », donc le droit d'exécuter le fichier ou dossier

On peut ajouter des signes :


● + pour ajouter les droits.
● – pour enlever les droits.

Exemples :
● chmod u+rw fichier
Ajoute ( + ) l'autorisation de lecture ( r ) et écriture ( w ) du
fichier fichier à l'utilisateur ( u )
● chmod -R u+rw dossier
Ajoute ( + ) l'autorisation de lecture ( r ) et écriture ( w ) du
répertoire dossier à l'utilisateur ( u )
● chmod ugo+x fichier
Ajoute ( + ) l'autorisation d'exécution ( x ) (c'est-à-dire ouverture) du
fichier fichier à tous (utilisateur ( u ), groupe ( g ) autres ( o )).
● chmod go-wx fichier
Supprime ( – ) l'autorisation d'écriture ( w ) et l'exécution ( x ) de
fichier au groupe ( g ) et aux autres ( o ).
La commande ps
Elle signifie « processes snapshot » et permet d'afficher les processus
en cours.
Exemples :
● ps -u
Affiche tous les processus de l'utilisateur u
● ps -A
Affiche tous les processus en cours : attention la liste est longue
dans ce cas !

Les commandes du réseau


La commande traceroute
Elle permet de tracer la route d'un paquet jusqu'à sa destination. On
peut utiliser un nom de domaine ou une adresse IP.
Exemples : traceroute www.editions-ellipses.fr équivaut à
traceroute 195.154.29.58
Exercices

Compétence attendue

➡ Utiliser les commandes de base en ligne de commande.

Exercice 12.1
► Analyser, mobiliser

L'objectif de cet exercice est de taper quelques lignes de commande


dans une fenêtre de commande de vérifier les informations de votre
d'ordinateur.
1) Pour vérifier le nom d'hôte de votre système d'exploitation, dans
une invite de commande, entrer :
hostname

2) Vérifier les informations de nom d'ordinateur (il s'agit d'un


ordinateur sous Windows) :
a) Cliquer à l'aide du bouton droit de la souris sur Poste de travail.
b) Cliquer sur Propriétés.
c) Cliquer sur l'onglet Nom de l'ordinateur.
d) Vérifier que la zone Nom complet de l'ordinateur affiche le nom de
domaine complet de l'ordinateur.

Compétence attendue

➡ Comprendre comment les données sont transmises dans un réseau.


➡ Utiliser un simulateur d'Internet.
Exercice 12.2
► Analyser, mobiliser

Vous avez vu en seconde que retenir l'adresse IP d'un site web, d'un
ordinateur n'était pas une chose évidente pour un humain. Pour cela,
il est utile de connaître son adresse symbolique ou nom d'hôte.
Il existe deux méthodes simples qui consistent à utiliser soit :
● une fenêtre de commande sur votre ordinateur dans laquelle on
tapera la commande nslookup suivie de l'adresse IP que l'on
souhaite traduire en nom d'hôte ou inversement le nom d'hôte à
traduire en adresse IP ;
● un site internet de résolution de noms d'hôte tel que
http://reverseip.domaintools.com ou bien encore https://www.ip-
tracker.org/lookup/reverse-ip.php

Exemple : dans votre fenêtre de commande puis sur internet,


rechercher l'adresse IP de www.wikipedia.fr.

Exercice 12.3
► Mobiliser, développer
Cet exercice est une activité débranchée qui s'effectue à plusieurs.
On a vu précédemment que dans un réseau les ordinateurs
s'identifient non pas grâce à des noms mais à des adresses IP. Ceci
leur permet d'échanger des paquets de données. Retenir ces
adresses IP ne pose pas de souci pour un ordinateur mais pour un
humain c'est plus compliqué, c'est pourquoi vous devez disposer
d'une feuille sur laquelle vous allez inscrire une adresse au format
111. 1. 28. XX en remplaçant XX par les entiers de votre choix.
➡ Instructions :
● Vous avez en votre possession un petit papier qui correspond à
votre adresse IP, prenez une autre feuille sur laquelle vous allez
pouvoir noter celles de vos camarades.
● Aussi, votre mission est de passer voir vos camarades un à un
et de noter leur adresse IP. Vous avez 5 min !

Exercice 12.4
► Mobiliser

Avez-vous une idée du nombre d'équipements connectés à votre


routeur à domicile ? Vous trouvez peut-être que votre accès à Internet
est un peu lent en ce moment ? Si vous avez plusieurs ordinateurs,
des tablettes, etc. dans une même maison, c'est peut-être une raison.
La plupart des routeurs disposent d'une interface Web sur laquelle
vous pouvez vous connecter pour accéder aux informations du
routeur, telles que les périphériques qui y sont actuellement
connectés. Pour cela dans la barre de recherche de notre navigateur
Web (Safari, Firefox, etc.) taper 192.168.0.1 ou 192.168.1.1.

Exercice 12.5
► Décomposer

Dans le cadre d'une enquête scientifique, vous devez retrouver


l'expéditeur d'un email anonyme…
Ceci peut se faire grâce à l'adresse IP de l'expéditeur. Puis grâce à un
site web du type IPlocation, on peut retrouver le nom d'hôte de
l'expéditeur et l'endroit dont l'email a été envoyé.
➡ Choisissez un mail dans votre messagerie et à vous de jouer !

Compétence attendue

➡ Utiliser un simulateur d'Internet pour comprendre le transfert de données.

Exercice 12.6
► Décomposer
Cet exercice est une activité connectée qui s'effectue à plusieurs.
L'objectif est d'utiliser le simulateur du
site code.org (organisation à but non
lucratif qui a pour objectif la promotion
de l'informatique dans les écoles, les
inscriptions et l'utilisation du site sont
gratuites) afin d'illustrer comment les
messages sont transférés par paquets
via Internet et ce grâce aux
adresses IP.
1) Pour utiliser le simulateur d'Internet,
votre enseignant devra se créer un
compte sur code.org. Puis chaque
élève de la classe doit aussi se créer
un compte afin de se connecter à la
session de la classe (dont l'identifiant lui sera communiqué par le
professeur).
2) Puis pour accéder au simulateur d'internet, vous devez vous rendre
sur le lien : https://studio.code.org/s/netsim afin d'obtenir l'affichage :
3) Puis se rendre sur 10. Simulateur d'Internet en libre accès.
4) Cliquer sur le 1.
Il vous suffit alors vous et vos camarades connectés, de rejoindre un
routeur. Vous pouvez ensuite échanger des messages entre vous via
ce routeur, ce en sélectionnant l'adresse IP de votre camarade
destinataire. Les messages envoyés sont au format ASCII mais aussi
illustrés en binaire.
Dans l'exemple ci-dessous :
● L'élève 15 d'adresse IP 1.3 et l'élève 24 d'adresse IP 1.2 sont
connectés au routeur 1.
● L'élève 15 d'adresse IP 1.3 a envoyé le message ASCII 'Bonjour !' à
l'élève 24 d'adresse IP 1.2.
Il existe des possibilités multiples, notamment d'ajouter un DNS afin
de ne pas utiliser les adresses IP mais plutôt les noms des élèves
pour communiquer.

Compétence attendue

➡ Connaître les différents types de systèmes d'exploitation.

Exercice 12.7
► Analyser, développer
Effectuer une recherche afin de répondre aux questions :
1) Actuellement quel est le système d'exploitation le plus utilisé sur
ordinateur ? Et sur téléphone portable ?
2) Qu'est-ce qui les distingue ?
3) Quelles sont les différences entre les systèmes d'exploitation libres
et propriétaires ?
4) Citer un système d'exploitation libre.
Exercices de type EC - QCM

Pour chaque question, le candidat gagne 3 points s'il choisit la bonne


réponse, perd 1 point s'il choisit une réponse fausse. S'il ne répond
pas ou choisit plusieurs réponses, il ne gagne ni ne perd aucun point.

Exercice EC 12.1
1 min ● 3 points
Dans un terminal Unix, on tape :
ls -a

Que s'affiche-t-il ?
Réponses :
a) l'adresse IP
b) le nom de domaines
c) la liste des adresses IP
d) la liste des fichiers et dossiers dans le répertoire courant

Exercice EC 12.2
1 min ● 3 points
Dans un terminal Unix, on tape :
cd ..

Que se passe-t-il ?
Réponses :
a) on peut lire un CD
b) on retourne au répertoire précédent
c) on passe au répertoire parent (de niveau supérieur)
d) donne la classe du dossier

Exercice EC 12.3
1 min ● 3 points
Que signifie RAM ?
Réponses :
a) Read Access Memory
b) Random Access Memory
c) Read All Memory
d) Random Read memory

Exercice EC 12.4
1 min ● 3 points
Parmi les choix suivants, lequel n'est pas un système d'exploitation ?
Réponses :
a) Windows
b) Linux
c) Microsoft
d) MacOS

Exercice EC 12.5
1 min ● 3 points
Que permet de faire la commande Unix :
chmod u+rw fichier

Réponses :
a) supprime l'accès au fichier fichier à l'utilisateur
b) donne les droits de lecture et écriture du fichier fichier à l'utilisateur
c) supprime les droits de lecture et écriture du fichier fichier à
l'utilisateur
d) donne les droits de lecture et exécution du fichier fichier à
l'utilisateur

Exercice EC 12.6
1 min ● 3 points
Quel élément n'appartient pas à l'architecture de Von Neumann ?
Réponses :
a) les entrées et sorties
b) l'unité arithmétique et logique
c) la mémoire centrale
d) l'unité d'affichage

Exercice EC 12.7
1 min ● 3 points
À quoi sert la commande Unix suivante ?
traceroute 195.154.29.58

Réponses :
a) à tracer la route d'un paquet jusqu'à la destination d'adresse IP
195.154.29.58
b) à modifier l'adresse IP 195.154.29.58
c) à tracer la route de l'adresse IP 195.154.29.58
d) à retrouver le nom de domaine correspondant à l'adresse IP
195.154.29.58
Corrigé des exercices

Exercice 12.1

Par exemple : si l'ordinateur a pour nom Cendrillon, le système affiche


le résultat suivant :
Cendrillon.local

Exercice 12.2

Les résultats donnent pour une fenêtre de commande :

Les résultats donnent pour le site reverseIP :


Exercice 12.3

Il n'existe pas de corrigé unique pour cet exercice. L'essentiel est de


noter que vos camarades et vous aurez peut-être des listes
d'adresses IP différentes pour la classe : ainsi les données auront pu
être corrompues lors de leur transfert.

Exercice 12.4

Cela donne par exemple :


Exercice 12.5

On choisit un email quelconque à localiser (qui n'a rien d'inconnu


finalement mais il est intéressant de savoir de quel endroit il a été
envoyé) :
Dans votre boite de messagerie, effectuer un clic droit sur le message
et sélectionner « source du message » (ou « voir l'entête » ou « voir le
message complet » suivant votre messagerie).

Dans les données, qui apparaissent, il faut identifier l'adresse IP de


l'expéditeur.
Une fois l'adresse IP trouvée, il suffit de faire une recherche sur un
site web localisant les adresses IP tel que IPlocation :
Exercice 12.6

Il n'existe pas de corrigé unique pour cet exercice. Essayez d'envoyer


divers messages.
Corrigé des exercices de type EC -
QCM

Exercice EC 12.1

a) À l'adresse IP
b) le nom de domaines
c) la liste des adresses IP
d) la liste des fichiers et dossiers dans le répertoire courant

Exercice EC 12.2

a) on peut lire un CD
b) on retourne au répertoire précédent
c) on passe au répertoire parent (de niveau supérieur)
d) donne la classe du dossier

Exercice EC 12.3

a) Read Access Memory


b) Random Access Memory
c) Read All Memory
d) Random Read memory
Exercice EC 12.4

a) Windows
b) Linux
c) Microsoft
d) MacOS

Exercice EC 12.5

a) supprime l'accès au fichier fichier à l'utilisateur


b) donne les droits de lecture et écriture du fichier fichier à l'utilisateur
c) supprime les droits de lecture et écriture du fichier fichier à
l'utilisateur
d) donne les droits de lecture et exécution du fichier fichier à
l'utilisateur

Exercice EC 12.6

a) les entrées et sorties


b) l'unité arithmétique et logique
c) la mémoire centrale
d) l'unité d'affichage

Exercice EC 12.7

a) à tracer la route d'un paquet jusqu'à la destination d'adresse IP


195.154.29.58
b) à modifier l'adresse IP 195.154.29.58
c) à tracer la route de l'adresse IP 195.154.29.58
d) à retrouver le nom de domaine correspondant à l'adresse IP
195.154.29.58
Thème D
Interactions entre l'homme
et la machine
sur le Web
Chapitre 13
Interactions entre l'homme
et la machine sur le Web
Cours

1 Interaction avec l'utilisateur dans une page Web

Événements

En classe de seconde, vous avez eu l'occasion de créer une page


web en langage HTML et de modifier son aspect grâce au langage
CSS. L'objectif à présent est de voir de manière très succincte (toutes
les possibilités ne seront pas abordées) comment la page web peut
interagir avec l'utilisateur via des clics, des réactions au survol de la
souris, effectuer des apparitions de fenêtres, etc. Le langage
JavaScript, étudié sommairement ici, permet notamment de permettre
en place ce que l'on nomme des événements.
L'objectif de ce chapitre n'est pas l'apprentissage exhaustif de
JavaScript mais de vous donner un aperçu de ses possibilités dans le
but d'utiliser ce langage dans vos projets.
Les scripts JavaScript peuvent être directement écrits dans une page
HTML ou importés. Ils sont interprétés directement par le navigateur
qui charge une page HTML.

Les types d'événements les plus communs


Événement Description

onchange Un élément HTML a été modifié.

onclick L'utilisateur a cliqué sur un élément HTML.

onmouseover L'utilisateur a survolé avec la souris au-dessus d'un élément HTML.


onmouseout L'utilisateur a enlevé la souris alors qu'elle était au-dessus d'un élément HTML.

onkeydown L'utilisateur a enfoncé une touche clavier.

onload La page a fini d'être chargée.

On insistera sur les clics dans ce chapitre car ce sont les plus visuels.

Les clics : créer un affichage au clic


Par exemple on peut créer un bouton qui permet de faire afficher la
date lorsque l'utilisateur clique sur un bouton :
1. <!DOCTYPE html>
2. <html>
3. <body>
4.
5. <h2>Mon premier bouton</h2>
6.
7. <button type="button"
8. onclick="document.getElementById('demo').innerHTML = Date()">
9. Cliquez sur le bouton pour afficher la date et l'heure.</button>
10.
11. <p id="demo"></p>
12.
13. </body>
14. </html>

Les clics : modifier du contenu HTML au clic


On peut aussi modifier du texte HTML au clic. Ici le contenu HTML de
la balise de paragraphe <p> </p> (nommée "demo" grâce à l'identifiant
id="demo") a été modifié en "Et hop, cela a changé !" :
1. <!DOCTYPE html>
2. <html>
3. <body>
4.
5.
6. <h2>Modifier du texte HTML</h2>
7.
8. <p id="demo">JavaScript peut changer le contenu HTML.</p>
9.
10. <button type="button"
onclick='document.getElementById("demo").innerHTML = "Et hop, cela
a changé !"'>Cliquez ici !</button>
11.
12.
13. </body>
14. </html>

Les clics : cacher du contenu HTML au clic


1. <!DOCTYPE html>
2. <html>
3. <body>
4.
5. <h2> Cacher du texte HTML </h2>
6.
7. <p id="demo">JavaScript peut cacher des éléments HTML.</p>
8.
9. <button type="button"
onclick="document.getElementById('demo').style.display='none'">Cliquez
ici !</button>
10.
11. </body>
12. </html

2 Interaction client-serveur

Objectif

L'objectif est à présent de voir ce qui se passe lorsqu'un utilisateur


soumet un formulaire : on souhaite savoir où les données vont et
comment elles sont récupérées une fois à destination.

Architecture client-serveur
Comme cela a déjà été abordé en classe de seconde, on sait que le
Web est basé sur une architecture client/serveur. Ceci peut être
résumé par le schéma ci-dessous où un client (généralement un
navigateur Web) envoie une requête à un serveur (le plus souvent un
serveur Web) en utilisant le protocole
HTTP. Le serveur répond à la requête
en utilisant le même protocole.

Formulaire HTML et HTTP


Pour le client (l'utilisateur, par le biais
du navigateur web par exemple), un formulaire HTML est en fait un
moyen convivial (« user friendly » en anglais) de configurer une
requête HTTP pour envoyer des données à un serveur.
Aussi HTTP peut être considéré comme un langage qui va permettre
au client de communiquer avec un serveur connecté au réseau (le
serveur HTTP installé sur le serveur d'un site). Dans le paragraphe
suivant, nous expliquerons comment effectuer une requête via un
formulaire HTML.

3 Formulaire d'une page Web

Définition de la méthode d'envoi des données

L'élément <form> permet de définir la méthode d'envoi des données.


Elle fait appel à deux attributs qui sont action et method.
L'attribut action permet d'indiquer où les données sont envoyées. Sa
valeur doit être une URL valide. Si rien n'est indiqué, les données
seront envoyées à l'URL de la page contenant le formulaire.
Par exemple, ci-dessous les données seront envoyées à l'URL
http://mon_site_web.com :
<form action="http://mon_site.com">

La méthode GET
Il s'agit de la méthode la plus fréquente pour demander une
ressource. Une requête GET est sans effet sur la ressource.
Exemple :
1. <form action="http://mon_site.com" method="get">
2. <div>
3. <label for="rep1">Question 1 ?</label>
4. <input name="rep1" id="rep1" value="A">
5. </div>
6. <div>
7. <label for="rep2">Question 2 ?</label>
8. <input name="rep2" value="B">
9. </div>
10. <div>
11. <button>Envoyer</button>
12. </div>
13. </form>

Lorsque l'on soumet le formulaire, l'URL www.mon_site.com/?


rep1=A&rep2=B apparaît dans la barre du navigateur. Ce qui équivaut
à la requête HTTP :
1. GET /?rep1=A&rep2=B HTTP/1.1
2. Host: mon_site.com

Avec cette méthode, les données du formulaire seront encodées dans


une URL construite par le navigateur du client et transmises ainsi au
serveur. C'est par exemple ce que fait Google® lors d'une recherche
web (https://www.google.fr/search?q=GET%20ou%20POST). La
longueur de l'URL pouvant parfois être limitée, on ne pourra pas
transmettre de longs formulaires par cette méthode.
Par ailleurs, les données transitent du client vers le serveur de
manière explicite dans l'URL construite. On ne doit donc pas utiliser
cette méthode pour envoyer des données sensibles au serveur.

La méthode POST
Cette méthode doit être utilisée lorsqu'une requête doit modifier la
ressource.
Si un formulaire est envoyé avec cette méthode, les données sont
ajoutées au corps de la requête HTTP. On reprend l'exemple
précédent que l'on modifie avec la méthode POST.
Exemple :
1. <form action="http://mon_site.com" method="post">
2. <div>
3. <label for="rep1">Question 1 ?</label>
4. <input name="rep1" id="rep1" value="A">
5. </div>
6. <div>
7. <label for="rep2">Question 2 ?</label>
8. <input name="rep2" value="B">
9. </div>
10. <div>
11. <button>Envoyer</button>
12. </div>
13. </form>

Quand le formulaire est soumis, aucune donnée n'est ajoutée à l'URL.


Ce qui équivaut à la requête HTTP suivante où les données sont
incorporées au corps de requête :
1. POST / HTTP/1.1
2. Host: mon_site.com
3. Content-Type: application/x-www-form-urlencoded
4. Content-Length: 13
5.
6. rep1=A&rep2=B

L'en-tête Content-Length indique la taille du corps, et l'en-tête + indique


le type de ressource envoyées au serveur.
Les données ne transitent pas, mais devront être récupérées et
traitées par un langage autre que HTML (PHP ou JavaScript).
Exercices
Compétence attendue

➡ Utiliser les événements en JavaScript. Reconnaître une portion de code.

Exercice 13.1
► Traduire

La ligne suivante doit permettre de créer un bouton qui affiche Bonjour


lorsque l'on clique dessus. Remplir le trou :
<button _________ ="alert('Bonjour')">Cliquez SVP.</button>

La ligne suivante doit permettre de créer un bouton qui affiche Bonjour


lorsque l'on passe la souris dessus. Remplir le trou :
<button _________ ="alert('Bonjour')">Cliquez SVP.</button>

La ligne suivante doit permettre de créer un bouton qui affiche Bonjour


lorsque l'on enlève la souris de dessus. Remplir le trou :
<button _________ ="alert('Bonjour')">Cliquez SVP.</button>

Exercice 13.2
► Analyser

Dans les portions de codes suivantes, identifier les portions liées à du


JavaScript et des événements :
► Code 1
1. <!DOCTYPE html>
2. <html>
3. <body>
4.
5. <h2> Cacher du texte HTML </h2>
6.
7. <p id="demo">JavaScript peut cacher des éléments HTML.</p>
8.
9. <button type="button"
onclick="document.getElementById('demo').style.display='none'">Cliquez
ici !</button>
10.
11. </body>
12. </html

► Code 2
13. <!DOCTYPE html>
14. <html>
15. <body>
16.
17. <h2>Modifier du texte HTML</h2>
18.
19. <p id="demo">JavaScript peut changer le contenu HTML.</p>
20.
21. <button type="button"
onclick='document.getElementById("demo").innerHTML = "Et hop, cela
a changé !"'>Cliquez ici !</button>
22.
23. </body>
24. </html>

Compétence attendue

➡ Créer des événements simples en JavaScript.

Exercice 13.3
► Mobiliser, traduire

➡ Écrire une portion de code qui au clic d'un bouton modifie du texte
HTML. On pourra afficher « Avant », avant le clic et « Après »
ensuite.

Exercice 13.4
► Mobiliser, traduire
➡ Écrire une portion de code qui au clic d'un bouton efface du texte
HTML. On pourra afficher « Avant », avant le clic et rien ensuite.
Exercices de type EC - QCM

Pour chaque question, le candidat gagne 3 points s'il choisit la bonne


réponse, perd 1 point s'il choisit une réponse fausse. S'il ne répond
pas ou choisit plusieurs réponses, il ne gagne ni ne perd aucun point.

Exercice EC 13.1
1 min ● 3 points
Choisir la balise HTML permettant à l'utilisateur de saisir du texte dans
un formulaire en respectant la norme HTML :
Réponses :
a) <'saisir votre texte'>
b) <form>
c) <input type = « texte »/>
d) <input txt/>

Exercice EC 13.2
1 min ● 3 points
Que permet d'obtenir la méthode GET du protocole HTTP ?
Réponses :
a) une ressource
b) envoyer une adresse IP
c) envoyer un fichier
d) un nom de domaine
Exercice EC 13.3
1 min ● 3 points
Que fait la commande suivante ?
<button onmouseover ="alert('Bonjour')">Cliquez SVP.</button>

Réponses :
a) de créer un bouton qui affiche 'Bonjour' lorsque l'on passe la souris
dessus.
b) de créer un bouton qui affiche 'Bonjour' lorsque l'on clique dessus.
c) de créer une action qui affiche 'Bonjour'.
d) de créer un formulaire qui démarre par 'Bonjour'.

Exercice EC 13.4
1 min ● 3 points
Que fait la commande suivante ?
<button onclick ="alert('Bonjour')">Cliquez SVP.</button>

Réponses :
a) de créer un bouton qui affiche 'Bonjour' lorsque l'on passe la souris
dessus.
b) de créer un bouton qui affiche 'Bonjour' lorsque l'on clique dessus.
c) de créer une action qui affiche 'Bonjour'.
d) de créer un formulaire qui démarre par 'Bonjour'.

Exercice EC 13.5
1 min ● 3 points
Dans le langage HTML, quel est le type des instructions <body>
et </body> ?
Réponses :
a) Ce sont des balises.
b) Ce sont des formes.
c) Ce sont des bannières.
d) Ce sont des actions.
Corrigé des exercices

Exercice 13.1
<button onclick ="alert('Bonjour')">Cliquez SVP.</button>
<button onmouseover ="alert('Bonjour')">Cliquez SVP.</button>
<button onmouseout ="alert('Bonjour')">Cliquez SVP.</button>

Exercice 13.2

► Code 1
<button type="button"
onclick="document.getElementById('demo').style.display=
'none'">Cliquez ici !</button>

► Code 2
<button type="button"
onclick='document.getElementById("demo").innerHTML = "Et hop, cela a
changé !"'>Cliquez ici !</button>

Exercice 13.3

Par exemple :
1. <!DOCTYPE html>
2. <html>
3. <body>
4.
5.
6. <p id="demo">Avant </p>
7.
8. <button type="button"
onclick='document.getElementById("demo").innerHTML =
"Après !"'>Cliquez ici !</button>
9.
10.
11. </body>
12. </html>

Exercice 13.4

Cela donne par exemple :


1. <!DOCTYPE html>
2. <html>
3. <body>
4.
5. <p id="demo">Avant</p>
6.
7. <button type="button"
onclick="document.getElementById('demo').style.display='none'">Cliquez
ici !</button>
8.
9. </body>
10. </html
Corrigé des exercices de type EC -
QCM

Exercice EC 13.1

a) <'saisir votre texte'>


b) <form>
c) <input type = « texte »/>
d) <input txt/>

Exercice EC 13.2

a) une ressource
b) envoyer une adresse IP
c) envoyer un fichier
d) un nom de domaine

Exercice EC 13.3

a) de créer un bouton qui affiche 'Bonjour' lorsque l'on passe la souris


dessus.
b) de créer un bouton qui affiche 'Bonjour' lorsque l'on clique dessus.
c) de créer une action qui affiche 'Bonjour'.
d) de créer un formulaire qui démarre par 'Bonjour'.
Exercice EC 13.4

a) de créer un bouton qui affiche 'Bonjour' lorsque l'on passe la souris


dessus.
b) de créer un bouton qui affiche 'Bonjour' lorsque l'on clique dessus.
c) de créer une action qui affiche 'Bonjour'.
d) de créer un formulaire qui démarre par 'Bonjour'.

Exercice EC 13.5

a) Ce sont des balises.


b) Ce sont des formes.
c) Ce sont des bannières.
d) Ce sont des actions.
Chapitre 14
Questionnaire à choix multiples
type EC
Exercices de type EC - QCM

Exercice EC 14.1
2h
Pour chacune des questions, il n'y a qu'une seule bonne réponse. Le
candidat gagne 3 points pour la réponse correcte, perd 1 point pour
une réponse fausse, et obtient un résultat nul pour absence de
réponse ou une réponse multiple. Sur chacune des sept parties, si le
total des points obtenu par le candidat est négatif, son résultat est
évalué à 0.

► Thème A : types de base


1) Convertir en base décimale le nombre binaire 1110 :
Réponses :
a) 3
b) 14
c) 7
d) 19
2) Convertir en base binaire le nombre décimal 135 :
Réponses :
a) 10000111
b) 11100001
c) 111000010
d) 1110010
3) La valeur 85 donne en binaire :
Réponses :
a) 10000101
b) 1010101
c) 01010101
d) 10000100
4) Quand on compare deux nombres entiers en Python, le résultat
est :
Réponses :
a) un flottant
b) un entier
c) un booléen
d) une chaîne de caractères
5) En informatique, le codage des caractères repose sur l'association
d'un caractère à un nombre. Plusieurs codes existent. Trouver
l'intrus :
Réponses :
a) ISO-8859-1
b) UTF-8
c) UCI
d) ASCII
6) On suppose que le nombre pi et la fonction sinus sin sont importés
de la bibliothèque math. Indiquer ce qui s'affiche après avoir exécuté
les lignes de code suivantes :
x = sin(2*pi)
print(x==0)

Réponses :
a) True
b) False
c) x==0
d) un message d'erreur

► Thème B : types construits


1) On considère la fonction python suivante :
def somme(L):
S=0
for i in range(len(L)-1:
S=S+L[i]
return S
Parmi les affirmations suivantes, indiquer celle ou celles qui sont
vraies.
Réponses :
a) somme([1,2,3,4]) renvoie 10
b) somme([1,2,3,4]) renvoie 6
c) somme([1,2,3,4]) renvoie un message d'erreur
d) S est une variable globale
2) On tape les lignes suivantes :
liste1 = [i**2 for i in range(4)]
print(liste1)

Le résultat affiché est :


Réponses :
a) [0,1,4,9]
b) [0,1,4,9,16]
c) [1,4,9,16,25]
d) [0,1,2,4,9,16,25]
3) On tape les lignes suivantes :
liste = [[1,2],[1],[2,1,3]]
print(liste[2])

Le résultat affiché est :


Réponses :
a) [2,1,3]
b) [2]
c) 2
d) 1,3
4) On tape les lignes suivantes :
liste = [[1,2],[1],[2,1,3]]
print(liste[2][2])

Le résultat affiché est :


Réponses :
a) [2,1,3]
b) 3
c) 2
d) 1,3
5) On tape les lignes suivantes :
repertoire = {'nom': 'Alex', 'numero de tel': '06 67 65 13 21'}

Comment afficher le numéro de téléphone d'Alex ?


Réponses :
a) print('numero de tel d'Alex ?')
b) print(«numero de tel d'Alex ?»)
c) print([«numero de tel»])
d) print(repertoire[«numero de tel»])
6) Soit le dictionnaire :
repertoire = {'nom': 'Alex', 'numero de tel': '06 67 65 13 21'}

'nom' et 'numero de tel' sont appelés des :


Réponses :
a) clés
b) attributs
c) types
d) thèmes

► Thème C : Traitement des données en table


1) Soit la liste de données :
valeurs = [[1.379, 1.772], [1.378, 1.785], [1.395, 1.835]]

Qu'obtient-on si on tape dans le shell :


T = sorted(valeurs)
print(T)

Réponses :
a) Un message d'erreur
b) [[1.378, 1.772], [1.378, 1.772], [1.395, 1.835]]
c) [1.378, 1.772]
d) [[1.378, 1.785], [1.379, 1.772], [1.395, 1.835]]
2) Soit la liste :
GoodThings = [[1,'I Need a Dollar','4:04','Aloe Blacc','Good
Things','R&B/Soul','Fichier audio MPEG'],
[1,'I Need a Dollar','4:04','Aloe Blacc','Good Things','R&B/Soul','Fichier
audio AAC achete']]
De quel type de liste s'agit t'il ?
Réponses :
a) Une liste de chaînes de caractères
b) Une liste de dictionnaires
c) Une liste de listes
d) Une liste de données binaires
3) Soit une liste qui contient deux enregistrements audios :
GoodThings = [[1,'I Need a Dollar','4:04','Aloe Blacc','Good
Things','R&B/Soul','Fichier audio MPEG'],
[1,'I Need a Dollar','4:04','Aloe Blacc','Good Things','R&B/Soul','Fichier
audio AAC achete']]
Comment afficher le type de fichier audio de chacun des deux
enregistrements ?
Réponses :
a) print(GoodThings[0], GoodThings[1])
b) print(GoodThings[6], GoodThings[6])
c) print(GoodThings[6])
d) print(GoodThings[0][6], GoodThings[1][6])

► Thème D : interactions entre l'homme et la machine sur le Web


1) L'évènement suivant permet de détecter si l'utilisateur a cliqué sur
un élément HTML :
Réponses :
a) overmouse
b) onclick
c) click
d) onload

2) L'évènement suivant permet de détecter si l'utilisateur a survolé


avec la souris un élément HTML :
Réponses :
a) overmouse
b) onclick
c) click
d) onload
3) L'évènement suivant permet de détecter si l'utilisateur a enfoncé
une touche clavier :
Réponses :
a) overmouse
b) onclick
c) click
d) onkeydown
4) À quoi servent les lignes suivantes ?
1. <button type="button"
2. onclick="document.getElementById('demo').innerHTML = Date()">
3. Cliquez sur le bouton pour afficher la date et l'heure.</button>

Réponses :
a) Cela crée un bouton qui permet de faire afficher la date lorsque
l'utilisateur clique sur le bouton.
b) Cela crée une fenêtre qui permet de faire afficher la date.
c) Cela crée une démonstration.
d) Cela permet de récupérer la date.

► Thème E : Architectures matérielles et systèmes d'exploitation


1) Parmi la liste suivante de systèmes d'exploitation se cache un
intrus, le trouver :
Réponses :
a) Ubuntu
b) Linux
c) MacOS
d) Java
2) Parmi la liste suivante de périphériques d'un ordinateur se cache un
intrus, le trouver :
Réponses :
a) clavier
b) souris
c) carte mère
d) imprimante
3) Le schéma d'architecture de Von Neumann est constitué (entre
autres) des éléments suivants :
Réponses :
a) la mémoire
b) la souris
c) les entrées et les sorties
d) l'imprimante
4) En 1953 est développé le premier ordinateur constitué
principalement de :
Réponses :
a) transistors
b) condensateurs
c) diodes
d) ALI

► Partie F : Langages et programmation


1) L'affectation d'une variable consiste toujours à :
Réponses :
a) incrémenter la variable en question.
b) renommer la variable en question.
c) comparer la valeur de cette variable à une autre valeur.
d) associer une valeur à une variable.

2) Après avoir exécuté le code suivant, quelles valeurs contiennent les


variables a et b ?
a = 13
b = 4
b = a
a = b

Réponses :
a) a = 13 et b = 13
b) a = 4 et b = 4
c) a = 4 et b = 13
d) a = 13 et b = 4.
3) Après avoir exécuté les lignes suivantes, quelles valeurs
contiennent les variables a et b ?
a = 13
b = 4
def somme(a,b) :
a = a+b
b = 2*a
return a
Réponses :
a) a = 13 et b = 4
b) a = 17 et b = 4
c) a = 17 et b = 26
d) a = 13 et b = 26.
4) Après avoir exécuté les lignes suivantes, quelles valeurs
contiennent les variables a et b ?
a = 13
b = 4
for i in range(b):
a = a+b
Réponses :
a) a = 13 et b = 4.
b) a = 29 et b = 4.
c) a = 17 et b = 26.
d) a = 29 et b = 26.

5) Qu'affiche le programme suivant :


x = 1
if x = True :
for i in range(5):
n = n + 4
else :
for i in range(4):
n = n + 4
Réponses :
a) 10.
b) 20.
c) rien.
d) 11.
6) Soit la fonction :
def rem(L):
n = len(L)
a = L[-1]
L = L[0:n-1]
n = len(L)
for i in range(n):
b = L[-1]
L = L[0:n-1]
L.append(a)
a = b
On définit L = [1,2,3,4,5,6].
Réponses :
a) L'instruction rem(L) renvoie [1,2,3,4,5].
b) L'instruction rem(L) renvoie [2,3,4,5,6].
c) L'instruction rem(L) ne renvoie rien.
d) L'instruction rem(L) provoque un message d'erreur.

► Thème G : Algorithmique
1) Dans la fonction de la question précédente :
Réponses :
a) a est une variable globale.
b) a et b sont des variables globales.
c) L'instruction rem(L) modifiera une liste L auparavant définie et non
vide.
d) L'instruction rem(L) ne modifiera pas une liste L auparavant définie
et non vide.
2) On considère une liste L remplie de 1 et de taille n, où n est un entier
naturel non nul donné. On applique l'algorithme de tri par insertion
(par ordre croissant) sur la liste L. Combien de comparaisons entre
éléments de la liste L seront effectuées dans le pire des cas ? On
donnera un ordre de grandeur.
Réponses :
a) de l'ordre de n.
b) de l'ordre de n2.
c) de l'ordre de n3.
d) de l'ordre de 10.
3) La fonction suivante correspond à un algorithme :
1. def inconnue(t):
2. n = len(t)
3. for i in range(1,n):
4. while i>0 and t[i] < t[i-1]:
5. t[i-1],t[i] = t[i],t[i-1]
6. i = i - 1

Réponses :
a) de tri à bulles.
b) de tri par insertion.
c) de tri par sélection.
d) de tri fusion.
4) La fonction précédente renvoie :
Réponses :
a) une liste triée.
b) une liste non triée.
c) elle ne renvoie rien.
d) une boucle infinie.
5) Pour le schéma ci-dessous, on applique l'algorithme des k plus
proches voisins au rond vert. On choisit k = 3 et on cherche la
nouvelle classe du rond vert :

Réponses :
a) la classe rond.
b) la classe losange.
c) la classe carré.
d) la classe triangle.
6) La fonction suivante permet de :
1. def mystere(liste,x):
2. if x in liste:
3. return True
4. return False

Réponses :
a) trier une liste selon un critère x.
b) trouver le maximum x dans une liste.
c) chercher un élément x dans une liste de manière séquentielle.
d) chercher un élément x dans une liste de manière dichotomique.
Corrigé des exercices de type EC -
QCM

Exercice EC 14.1

Les bonnes réponses sont indiquées en gras.

► Thème A : types de base


1) Convertir en base décimale le nombre binaire 1110 :
Réponses :
a) 3
b) 14
c) 7
d) 19.
2) Convertir en base binaire le nombre décimal 135 :
Réponses :
a) 10000111
b) 11100001
c) 111000010
d) 1110010.
3) La valeur 85 donne en binaire :
Réponses :
a) 10000101
b) 1010101
c) 01010101
d) 10000100.
4) Quand on compare deux nombres entiers en Python, le résultat
est :
Réponses :
a) un flottant.
b) un entier.
c) un booléen.
d) une chaîne de caractères.
5) En informatique, le codage des caractères repose sur l'association
d'un caractère à un nombre. Plusieurs codes existent. Trouver
l'intrus :
Réponses :
a) ISO-8859-1
b) UTF-8
c) UCI
d) ASCII.
6) On suppose que le nombre pi et la fonction sinus sin sont importés
de la bibliothèque math. Indiquer ce qui s'affiche après avoir exécuté
les lignes de code suivantes :
Réponses :
a) True
b) False
c) x==0
d) un message d'erreur.

► Thème B : types construits


1) On considère la fonction python suivante :
def somme(L) :
S=0
for i in range(len(L)-1) :
S=S+L[i]
return S
Parmi les affirmations suivantes, indiquer celle ou celles qui sont
vraies.
Réponses :
a) somme([1,2,3,4]) renvoie 10.
b) somme([1,2,3,4]) renvoie 6.
c) somme([1,2,3,4]) renvoie un message d'erreur.
d) S est une variable globale.
2) On tape les lignes suivantes :
liste1 = [i**2 for i in range(4)]
print(liste1)

Le résultat obtenu est :


Réponses :
a) [0,1,4,9]
b) [0,1,4,9,16]
c) [1,4,9,16,25]
d) [0,1,2,4,9,16,25]
3) On tape les lignes suivantes :
liste = [[1,2],[1],[2,1,3]]
print(liste[2])

Le résultat affiché est :


Réponses :
a) [2,1,3]
b) [2]
c) 2
d) 1,3
4) On tape les lignes suivantes :
liste = [[1,2],[1],[2,1,3]]
print(liste[2][2])

Le résultat affiché est :


Réponses :
a) [2,1,3]
b) 3
c) 2
d) 1,3

5) On tape la ligne suivante :


repertoire = {'nom': 'Alex', 'numero de tel': '06 67 65 13 21'}

Comment afficher le numéro de téléphone d'Alex ?


Réponses :
a) print('numero de tel d'Alex ?')
b) print(«numero de tel d'Alex ?»)
c) print([«numero de tel»])
d) print(repertoire[«numero de tel»])
6) Soit le dictionnaire :
repertoire = {'nom': 'Alex', 'numero de tel': '06 67 65 13 21'}

'nom' et 'numero de tel' sont appelés des :


Réponses :
a) clés
b) attributs
c) types
d) thèmes

► Thème C : Traitement des données en table


1) Soit la liste de données :
valeurs = [[1.379, 1.772], [1.378, 1.785], [1.395, 1.835]]

Qu'obtient-on si on tape :
T = sorted(mesures)
print(T)

Réponses :
a) Un message d'erreur
b) [[1.378, 1.772], [1.378, 1.772], [1.395, 1.835]]
c) [1.378, 1.772]
d) [[1.378, 1.785], [1.379, 1.772], [1.395, 1.835]]
2) Soit la liste :
GoodThings = [[1,'I Need a Dollar','4:04','Aloe Blacc','Good
Things','R&B/Soul','Fichier audio MPEG'],
[1,'I Need a Dollar','4:04','Aloe Blacc','Good Things','R&B/Soul','Fichier
audio AAC achete]]
De quel type de liste s'agit t'il ?
Réponses :
a) Une liste de chaînes de caractères.
b) Une liste de dictionnaires.
c) Une liste de listes.
d) Une liste de données binaires.
3) Soit une liste qui contient deux enregistrements audios :
GoodThings = [[1,'I Need a Dollar','4:04','Aloe Blacc','Good
Things','R&B/Soul','Fichier audio MPEG'],
[1,'I Need a Dollar','4:04','Aloe Blacc','Good Things','R&B/Soul','Fichier
audio AAC achete']]
Comment afficher le type de fichier audio des chacun des deux
enregistrements ?
Réponses :
a) print(GoodThings[0], GoodThings[1])
b) print(GoodThings[6], GoodThings[6])
c) print(GoodThings[6])
d) print(GoodThings[0][6], GoodThings[1][6])

► Thème D : interactions entre l'homme et la machine sur le Web


1) L'évènement suivant permet de détecter si l'utilisateur a cliqué sur
un élément HTML :
Réponses :
a) overmouse
b) onclick
c) click
d) onload
2) L'évènement suivant permet de détecter si l'utilisateur a survolé
avec la souris un élément HTML :
Réponses :
a) overmouse
b) onclick
c) click
d) onload
3) L'évènement suivant permet de détecter si l'utilisateur a enfoncé
une touche clavier :
Réponses :
a) overmouse
b) onclick
c) click
d) onkeydown
4) À quoi servent les lignes suivantes ?
1. <button type="button"
2. onclick="document.getElementById('demo').innerHTML = Date()">
3. Cliquez sur le bouton pour afficher la date et l'heure.</button>

Réponses :
a) Cela crée un bouton qui permet de faire afficher la date
lorsque l'utilisateur clique sur le bouton.
b) Cela crée une fenêtre qui permet de faire afficher la date.
c) Cela crée une démonstration.
d) Cela permet de récupérer la date.

► Thème E : Architectures matérielles et systèmes d'exploitation


1) Parmi la liste suivante de systèmes d'exploitation se cache un
intrus, le trouver :
Réponses :
a) Ubuntu
b) Linux
c) MacOS
d) Java
2) Parmi la liste suivante de périphériques d'un ordinateur se cache un
intrus, le trouver :
Réponses :
a) clavier
b) souris
c) carte mère
d) imprimante
3) Le schéma d'architecture de Von Neumann est constitué (entre
autres) des éléments suivants :
Réponses :
a) la mémoire
b) la souris
c) les entrées et les sorties
d) l'imprimante
4) En 1953 est développé le premier ordinateur constitué
principalement de :
Réponses :
a) transistors
b) condensateurs
c) diodes
d) ALI

► Partie F : Langages et programmation


1) L'affectation d'une variable consiste toujours à :
Réponses :
a) incrémenter la variable en question.
b) renommer la variable en question.
c) comparer la valeur de cette variable à une autre valeur.
d) associer une valeur à une variable.
2) Après avoir exécuté́ le code suivant, quelles valeurs contiennent les
variables a et b ?
a = 13
b = 4
b = a
a = b

Réponses :
a) a = 13 et b = 13.
b) a = 4 et b = 4.
c) a = 4 et b = 13.
d) a = 13 et b = 4.
3) Après avoir exécuté les lignes suivantes, quelles valeurs
contiennent les variables a et b ?
a = 13
b = 4
def somme(a,b) :
a = a+b
b = 2*a
return a
Réponses :
a) a = 13 et b = 4.
b) a = 17 et b = 4.
c) a = 17 et b = 26.
d) a = 13 et b = 26.
4) Après avoir exécuté les lignes suivantes, quelles valeurs
contiennent les variables a et b ?
a = 13
b = 4
for i in range(b):
a = a+b
Réponses :
a) a = 13 et b = 4.
b) a = 29 et b = 4.
c) a = 17 et b = 26.
d) a = 29 et b = 26.
5) Qu'affiche le programme suivant ?
x = 1
if x = True :
for i in range(5):
n = n + 4
else :
for i in range(4):
n = n + 4
Réponses :
a) 10.
b) 20.
c) rien.
d) 11.

6) Soit la fonction :
def rem(L):
n = len(L)
a = L[-1]
L = L[0:n-1]
n = len(L)
for i in range(n):
b = L[-1]
L = L[0:n-1]
L.append(a)
a = b
On définit L = [1,2,3,4,5,6].
Réponses :
a) L'instruction rem(L) renvoie [1,2,3,4,5].
b) L'instruction rem(L) renvoie [2,3,4,5,6].
c) L'instruction rem(L) ne renvoie rien.
d) L'instruction rem(L) provoque un message d'erreur.

► Thème G : Algorithmique
1) Dans la fonction de la question précédente :
Réponses :
a) a est une variable globale.
b) a et b sont des variables globales.
c) L'instruction rem(L) modifiera une liste L auparavant définie et non
vide.
d) L'instruction rem(L) ne modifiera pas une liste L auparavant
définie et non vide.
2) On considère une liste L remplie de 1 et de taille n, où n est un entier
naturel non nul donné. On applique l'algorithme de tri par insertion
(par ordre croissant) sur la liste L. Combien de comparaisons entre
éléments de la liste L seront effectuées dans le pire des cas ? On
donnera un ordre de grandeur.
Réponses :
a) de l'ordre de n.
b) de l'ordre de n2.
c) de l'ordre de n3.
d) de l'ordre de 10.
3) La fonction suivante correspond à un algorithme :
1. def inconnue(t):
2. n = len(t)
3. for i in range(1,n):
4. while i>0 and t[i] < t[i-1]:
5. t[i-1],t[i] = t[i],t[i-1]
6. i = i - 1

Réponses :
a) de tri à bulles.
b) de tri par insertion.
c) de tri par sélection.
d) de tri fusion.
4) La fonction précédente renvoie :
Réponses :
a) une liste triée.
b) une liste non triée.
c) elle ne renvoie rien.
d) une boucle infinie.
5) Pour le schéma ci-dessous, on applique l'algorithme des k plus
proches voisins au rond vert. On choisit k = 3 et on cherche la
nouvelle classe du rond vert :
Réponses :
a) la classe rond.
b) la classe losange.
c) la classe carré.
d) la classe triangle.
6) La fonction suivante permet de :
1. def mystere(liste,x):
2. if x in liste:
3. return True
4. return False

Réponses :
a) trier une liste selon un critère x.
b) trouver le maximum x dans une liste.
c) chercher un élément x dans une liste de manière
séquentielle.
d) chercher un élément x dans une liste de manière dichotomique.
Table des matières

Avant-propos
Introduction
Les compétences en NSI
1 Les compétences
2 Récapitulatif des exercices illustrant les compétences

Thème A
Types de base
Chapitre 1
Premiers pas en Python
Cours
1 Un peu d'histoire de Python

2 L'environnement Pyzo
Les différentes fenêtres de Pyzo
Premiers calculs dans le shell
Premiers programmes dans l'éditeur
3 Quelques types de base : les integers et les flottants
Les integers
Les flottants
4 La bibliothèque math et ses fonctions
5 Les variables en Python
Affectation d'une ou plusieurs variables
Mots réservés et caractères à éviter
Modification du contenu d'une variable
Permutation de deux variables
6 Un autre type de base : les booléens
Valeurs booléennes : True et False
Table de l'expression booléenne : a and b
Table de l'expression booléenne : a or b
Table de l'expression booléenne : a xor b
Exercices
Exercices de type EC - QCM
Corrigé des exercices
Corrigé des exercices de type EC - QCM
Chapitre 2
Représentation des nombres
Cours
1 Écriture d'un entier positif dans une base b ≥ 2
Les bases
Passage d'un nombre de la base 10 à la base 2 (écriture binaire)
2 Représentation binaire d'un entier relatif
Un peu d'histoire des nombres
Notion de bit de signe
Écriture d'un entier positif en binaire sur n bits
Somme et produit de deux nombres binaires
Écriture d'un entier négatif en binaire sur n bits (méthode du complément à deux)
3 Représentation en base hexadécimale
Codage en base 16
Conversion d'un octet en base hexadécimale
4 Représentation approximative des nombres réels
Écriture à virgule flottante
Nombres à virgule flottante : les flottants
Dépassement de capacité
Arrondis et conséquence
Exercices
Corrigé des exercices
Corrigé des exercices de type EC - QCM
Chapitre 3
Représentation d'un texte en machine
Cours
1 Le code ASCII
Un peu d'histoire
La table ASCII
Limitations

2 La norme ISO-8859-1
Nécessité
Limitations
3 La norme Unicode
Nécessité d'une norme internationale
Convertisseur de texte en Unicode
Les erreurs d'encodage : incompatibilité de normes
Exercices
Corrigé des exercices
Corrigé des exercices de type EC - QCM

Thème B
Types construits
Chapitre 4
Les types de données construits
Cours
1 Les p-uplets
Créer un p-uplet
Notion d'indexation
2 Les listes
Créer une liste
Lire et modifier les éléments d'une liste grâce à leurs index
Construire une liste par compréhension
Opérations sur les listes
Ajout d'un élément en fin de liste
Recherche d'un élément dans une liste avec in
Quelques commandes à retenir
3 Les dictionnaires
Créer un dictionnaire
Accéder aux valeurs d'un dictionnaire
Parcourir les clés ou les valeurs d'un dictionnaire
Exercices
Corrigé des exercices
Corrigé des exercices de type EC - QCM

Thème F
Langage et programmation
Chapitre 5
Les fonctions
Cours
1 Créer une fonction
Un peu d'histoire
Forme générale d'une fonction
Spécification d'une fonction
Les arguments d'une fonction
2 Notion de variable locale, variable globale
Variable locale
Variable globale
3 Appeler une fonction
Appeler une fonction et effectuer un affichage
Appeler une fonction et effectuer un stockage du/des résultat(s)
Extraire un seul argument de sortie
4 Les assertions
5 Jeux de tests
6 Points importants à propos des fonctions
Ne pas oublier les « : »
Ne pas oublier l'indentation
Ne pas appeler une variable locale dans le programme principal
Un print n'équivaut pas à un return
Un return permet une sortie de fonction
Respecter l'ordre et le type des arguments d'entrée
Exercices
Exercices-bilan
Corrigé des exercices
Corrigé des exercices-bilan
Corrigé des exercices de type EC - QCM
Chapitre 6
Séquences conditionnelles et boucles
Cours
1 Les instructions conditionnelles
Un peu d'histoire
Rappel sur les tests logiques
Instruction conditionnelle simple
Instruction conditionnelle avec alternative
Instruction conditionnelle imbriquée
Implémentation d'une instruction conditionnelle au sein d'une fonction
2 Les boucles for
Notion de boucle inconditionnelle
Les boucles for : itérable de type liste
Les boucles for : itérable de type range( )
Coût en temps
Les boucles for : construction d'une liste en compréhension
3 Les boucles while
Notion de boucle conditionnelle
Non terminaison d'une boucle while
Application aux suites
Remplacement d'une boucle for par une boucle while
Coût en temps
Exercices
Exercices-bilan
Corrigé des exercices
Corrigé des exercices-bilan
Corrigé des exercices de type EC - QCM

Thème G
Algorithmique
Chapitre 7
Recherche d'une valeur dans une liste
Cours
1 Recherche séquentielle dans une liste
Parcours séquentiel d'une liste
Complexité en temps
2 Recherche dichotomique dans une liste triée
Un peu d'histoire
Le principe du diviser pour régner
Principe de la recherche dichotomique
Coût en temps
Terminaison de la boucle while
Exercices
Corrigé des exercices
Corrigé des exercices de type EC - QCM
Chapitre 8
Les méthodes de tri de listes
Cours
1 Nécessité de trier
Un peu d'histoire
Des algorithmes de tri variés
Algorithmes de tri disponibles en Python
2 Tri par insertion
Principe
Pseudo-code
Tri par insertion en Python
Le tri étape par étape
Complexité temporelle
Notion d'invariant de boucle
Validité du tri
3 Tri par sélection
Principe
Pseudo-code
Tri par sélection en Python
Complexité temporelle
Validité du tri
4 Ordre de grandeur des temps d'exécution
Exercices
Corrigé des exercices
Corrigé des exercices de type EC - QCM
Chapitre 9
Algorithme des k plus proches voisins
Cours
1 Un peu d'histoire
2 Principe
3 Algorithme et fonctions

4 Distance entre deux points


Principe
Fonction distance
5 Recherche des k plus proches voisins
Principe
Fonction Kvoisins
6 Attribution de classe
Principe
Fonction classe
Exercices
Exercices-bilan
Corrigé des exercices
Corrigé des exercices-bilan
Corrigé des exercices de type EC - QCM
Chapitre 10
Algorithmes gloutons
Cours
1 Notion d'algorithme glouton
2 Le problème du rendu de monnaie
Principe
Résultat optimal ou non
Pseudo-code
Fonction rendu_monnaie
Mise en place d'un test
3 Le problème du sac à dos
Principe
Un peu d'histoire
Pseudo-code
Fonction remplir_sac
Exercices
Exercices-bilan
Corrigé des exercices
Corrigé des exercices-bilan
Corrigé des exercices de type EC - QCM
Thème C
Traitement de donnéesen tables
Chapitre 11
Traitement de données en tables
Cours
1 Notion de base de données
Un peu d'histoire
Stockage de données dans une table
Table sous forme de liste de listes

2 Rappel sur l'indexation de tables


3 Construire une table à partir d'un fichier
4 Recherche dans une table
Recherche d'un enregistrement selon un critère simple
Recherche d'un enregistrement selon un critère multiple
Création d'une table sans doublon
5 Tri d'une table
Rappel sur les méthodes de tri
Tri selon les valeurs situées en première colonne
Tri selon les valeurs situées dans une colonne quelconque
6 Fusion de tables
Fusion de deux tables dont les attributs sont identiques
Fusion de deux tables d'attributs différents
Exercices
Exercices-bilan
Corrigé des exercices
Corrigé des exercices-bilan
Corrigé des exercices de type EC - QCM

Thème E
Architectures matérielles et systèmes d'exploitation
Chapitre 12
Architectures matérielles et systèmes d'exploitation
Cours
1 Modèle d'architecture séquentielle (von Neumann)
Un peu d'histoire
Principe

2 L'ordinateur
L'ordinateur avant et maintenant
De quoi est constitué un ordinateur ?
Les composants de l'ordinateur
3 Transmission de données dans un réseau
Les paquets de données
Le protocole TCP/IP
4 Architecture d'un réseau
Le réseau
Le routeur
5 Systèmes d'exploitation
Une multitude de systèmes d'exploitation possibles
Fonctions du système d'exploitation
Interface Homme-Machine (IHM)
6 Quelques commandes Unix
Notion de chemin d'accès
Les commandes de base
Les commandes de gestion de fichiers
Les commandes du système
Les commandes du réseau
Exercices
Corrigé des exercices
Corrigé des exercices de type EC - QCM

Thème D
Interactions entre l'homme et la machine sur le Web
Chapitre 13
Interactions entre l'homme et la machine sur le Web
Cours
1 Interaction avec l'utilisateur dans une page Web
Événements
Les types d'événements les plus communs
Les clics : créer un affichage au clic
Les clics : modifier du contenu HTML au clic
Les clics : cacher du contenu HTML au clic
2 Interaction client-serveur
Objectif
Architecture client-serveur
Formulaire HTML et HTTP
3 Formulaire d'une page Web
Définition de la méthode d'envoi des données
La méthode GET
La méthode POST
Exercices
Corrigé des exercices
Corrigé des exercices de type EC - QCM
Chapitre 14
Questionnaire à choix multiples type EC
Exercices de type EC - QCM
Corrigé des exercices de type EC - QCM

Vous aimerez peut-être aussi