Algorithmique et Applications en CPES2

publicité
Instruction Répétitive
1
CPES 1re année
2016-2017
PSL
Informatique
Exercices sur les instructions répétitives
Exercices préparées par V. Gabrel, E. Lazard, M. Manouvrier et C. Murat 1
Les instructions répétitives (boucles) permettent de répéter un bloc d’instructions. La syntaxe d’une instruction répétitive est :
while expression_booleenne :
BlocInstruction
Exercice 1
Soit le programme Python suivant :
i=int(input("debut : "))
j=int(input("fin : "))
while (i!=j):
if (i%7==0):
print(i, " est multiple de 7")
i+=1
1. Que fait ce programme dans le cas général ?
2. Que se passe-t-il si on entre une valeur de i strictement plus grande que j ? Comment
pourrait-on améliorer ce programme ?
Correction
1. Le programme fait saisir deux variables entières i et j. Puis affiche tous les multiples de
7 entre i et j (j exclus et si i est inférieur à j).
2. Si i est supérieur à j le programme va tourner indéfiniment (la boucle tant que s’exécutera tant que i est supérieur à j, ce qui sera toujours le cas). Pour améliorer le programme,
il faut changer la condition et mettre tant que i < j.
Exercice 2
Étant donnée f (x) = x3 − 3x2 + 1, une fonction continue et strictement croissante sur l’intervalle [2; 3], l’algorithme ci-dessous permet de déterminer la valeur approchée de x telle que
f (x) = 0 par une méthode dichotomique avec une précision .
1. Cours également dispensé en 1ère année de licence Mathématique-Informatique-Économie (MIE) à l’Université Paris-Dauphine
2
Instruction répétitive
VARIABLES
precision EST_DU_TYPE NOMBRE
a,b,m EST_DU_TYPE NOMBRE
f_m,f_b EST_DU_TYPE NOMBRE
DEBUT_ALGORITHME
LIRE precision
a <- 2
b <- 3
TANT_QUE (b-a > precision) FAIRE
DEBUT_TANT_QUE
m
<- (a+b)/2
f_m <- (m**3) - 3*(m**2) + 1
f_b <- (b**3) - 3*(b**2) + 1
SI (f_m*f_b > 0) ALORS
DEBUT_ALORS
b <- m
FIN_ALORS
SINON
DEBUT_SINON
a <- m
FIN_SINON
FIN_TANT_QUE
ECRIRE a
ECRIRE " <= solution <= "
ECRIRE b
FIN_ALGORITHME
Programmer en Python cet algorithme.
precision=float(input())
a = 2
b = 3
while (b-a > precision):
m=(a+b)/2
f_m=(m**3) - 3*(m**2) + 1
f_b = (b**3) - 3*(b**2) + 1
if (f_m*f_b > 0):
b = m
else:
a = m
print(a, ’<= solution <=’, b)
>>> (executing lines 1 to 12 of "<tmp 1>")
0.00001
2.8793792724609375 <= solution <= 2.8793869018554688
Instruction Répétitive
3
Exercice 3
Écrire un programme en Python qui saisit un réel x ≥ 0 et un entier n ≥ 0, et affiche la valeur
de xn (sans utiliser l’opérateur puissance). Tester votre programme pour les valeurs suivantes :
x = 4 n = 3, x = 5 n = 0, x = 0 n = 0.
Correction
x=int(input(’entrez x’))
n=int(input(’entrez n’))
resul=1
while n>0:
resul=resul*x
n-=1
print(resul)
Exercice 4
∗
Soit pour tout n ∈ N , Sn =
n
X
1
, écrire un programme déterminant la plus petite valeur de
k
k=1
n pour laquelle Sn > A, A étant un réel entré par l’utilisateur. N’essayez pas votre programme
avec des valeurs de A supérieures à 20.
A=float(input("A = "))
n=1
un=1
while un <= A :
n+=1
un = un + 1/n
print(n,un)
Quand A = 10, n = 12367 et S1 2367 = 10.000043008275778
Exercice 5
Soit la suite définie par u0 = 0, et pour tout n ∈ N, un+1 =
√
3un + 4.
1. Écrire un programme demandant à l’utilisateur un entier n et affichant tous les termes
de la suite jusqu’à un .
2. Modifier votre programme pour qu’il affiche le plus petit entier n pour lequel un > 4−,
où > 0. Que trouve-t-on pour = 10−8 = 1.e − 8 ?
Exercice 6
Écrire un algorithme en pseudo-langage puis en Python, qui saisit un entier (supposé strictement
positif), affiche la somme de tous ses diviseurs stricts et précise si ce nombre est premier. Par
exemple, si l’on saisit 8, il affiche 7 (car somme de ses diviseurs stricts qui sont 1, 2 et 4).
4
Instruction répétitive
Correction
VARIABLES
n EST_DU_TYPE NOMBRE // entier saisi par l’utilisateur
d EST_DU_TYPE NOMBRE // diviseur
somme EST_DU_TYPE NOMBRE
DEBUT_ALGORITHME
LIRE n
d <- 1
somme <- 0
TANT_QUE (d<n) FAIRE
DEBUT_TANT_QUE
SI ((n%d)==0) ALORS
DEBUT_ALORS
somme <- somme+d
FIN_ALORS
d <- d+1
FIN_TANT_QUE
SI ((somme==1) ET (n!=1)) ALORS
DEBUT_ALORS
ECRIRE "Ce nombre est premier."
FIN_ALORS
SINON
DEBUT_SINON
ECRIRE "La somme des diviseurs est :"
ECRIRE somme
FIN_SINON
FIN_ALGORITHME
Exemples d’exécution :
Exemple d’exécution avec n=5
d <- 2
somme = 1
(d<n): n%d ==1
d<-3
(d<n): n%d ==2
d<-4
(d<n): n%d ==1
d<-5
(d==n) on sort du tant que
somme==1 on affiche "Ce nombre est premier"
Exemples d’exécution avec n=8
d = 2
somme = 1
(d<n): n%d ==0
somme=1+2
Instruction Répétitive
5
d=3
(d<n): n%d ==2
d=4
(d<n): n%d ==0
somme=3+4
d=5
(d<n): n%d ==3
d=6
(d<n): n%d ==2
d=7
(d<n): n%d ==1
d=8
(d==n) on sort du tant que
somme!=1 on affiche "La somme des diviseurs est 7
Autre solution :
VARIABLES
k EST_DU_TYPE NOMBRE // compteur
s EST_DU_TYPE NOMBRE // somme des diviseurs
n EST_DU_TYPE NOMBRE // entier saisi par l’utilisateur
DEBUT_ALGORITHME
LIRE n
k <- 1
s <- 0
TANT_QUE (k<n) FAIRE
DEBUT_TANT_QUE
SI ((n/k)==PARTIE_ENTIERE(n/k)) ALORS
DEBUT_ALORS
// Si k est un diviseur de n
s <- s+k
FIN_ALORS
k <- k+1
FIN_TANT_QUE
ECRIRE s
SI ((s==1) et (n!=1)) ALORS
DEBUT_ALORS
ECRIRE n
ECRIRE " est premier."
FIN_ALORS
SINON
DEBUT_SINON
ECRIRE "La somme des diviseurs est "
ECRIRE s
FIN_SINON
FIN_ALGORITHME
NB (pour nous uniquement) : dans le logiciel d’AlgoBox, l’instruction PARTIE_ENTIERE
est : floor(x).
6
Instruction répétitive
Exercice 7
Un entier est dit parfait s’il est égal à la somme de ses diviseurs stricts (6 par exemple est
parfait). Écrire un algorithme qui saisit un entier n (supposé strictement positif) et affiche tous
les nombres parfaits inférieurs ou égaux à n.
Correction
VARIABLES
n EST_DU_TYPE NOMBRE
d EST_DU_TYPE NOMBRE
somme EST_DU_TYPE NOMBRE
DEBUT_ALGORITHME
LIRE n
TANT_QUE (n>1) FAIRE
DEBUT_TANT_QUE
d <- 1
somme <- 0
TANT_QUE (d<n) FAIRE
DEBUT_TANT_QUE
SI ((n%d)==0) ALORS // Si d est un diviseur de n
DEBUT_ALORS
somme <- somme+d
FIN_ALORS
d <- d+1
FIN_TANT_QUE
SI (somme==n) ALORS
DEBUT_ALORS
ECRIRE somme
FIN_ALORS
n <- n-1
FIN_TANT_QUE
FIN_ALGORITHME
Nombres parfaits : 6, 28, 496, 8128 ... A tester en TP.
Autre solution :
VARIABLES
n EST_DU_TYPE
i EST_DU_TYPE
s EST_DU_TYPE
k EST_DU_TYPE
NOMBRE
NOMBRE
NOMBRE
NOMBRE
//
//
//
//
DEBUT_ALGORITHME
LIRE n
i <- 1
TANT_QUE (i<=n) FAIRE
Entier saisi par l’utilisateur
compteur
somme des diviseurs
compteur
Instruction Répétitive
7
DEBUT_TANT_QUE
s <- 0
k <- 1
TANT_QUE (k<i) FAIRE
DEBUT_TANT_QUE
SI ((i/k)==PARTIE_ENTIERE(i/k)) ALORS
DEBUT_ALORS
// Si k diviseur de i
s <- s+k
FIN_ALORS
k <- k+1
FIN_TANT_QUE
SI (s==i) ALORS
DEBUT_ALORS
ECRIRE s
FIN_ALORS
i <- i+1
FIN_TANT_QUE
FIN_ALGORITHME
Exercice 8
A l’aide de 2 boucles TANT_QUE emboîtées, écrire un algorithme qui affiche :
1
1
1
1
2
3
4
5
3
5
7
9
4
7
10
13
5
9
13
17
Correction
On remarque que la ligne 1 correspond à 5 entiers dont la différence deux à deux vaut 1, la ligne
2 correspond à 5 entiers dont la différence deux à deux vaut 2, la ligne 3 correspond à 5 entiers
dont la différence deux à deux vaut 3, etc.
Dans l’algorithme on utilise donc 3 variables, nbLignes qui va représenter le numéro de la
ligne courante, i qui correspond à l’entier à afficher et nbCol qui correspond au numéro de la
colonne courante.
VARIABLES
nbLignes EST_DU_TYPE NOMBRE // numéro de la ligne courante
i EST_DU_TYPE NOMBRE // entier à afficher
nbCol EST_DU_TYPE NOMBRE // numéro de la colonne courante
DEBUT_ALGORITHME
nbLignes <- 1
TANT_QUE (nbLignes<=4) FAIRE
DEBUT_TANT_QUE
nbCol <- 1
i <- 1
8
Instruction répétitive
TANT_QUE (nbCol<=5) FAIRE
DEBUT_TANT_QUE
ECRIRE i
ECRIRE " "
i <- i+nbLignes
nbCol <- nbCol+1
FIN_TANT_QUE
ECRIRE "Saut-de-ligne"
nbLignes <- nbLignes+1
FIN_TANT_QUE
FIN_ALGORITHME
Exercice 9
Écrire un algorithme qui saisit un entier strictement positif n, puis n entiers, et qui vérifie si la
suite des n entiers saisis est triée de façon croissante.
Par exemple, si la valeur saisie pour n est 7 et les 7 valeurs saisies sont : -1, 3, 7, 8, 11, 234, 300,
le programme affichera "les 7 valeurs sont triées de façon croissante", alors que le programme
affichera "les 7 valeurs ne sont pas triées" si les entiers saisis sont : 1, 2, 7, -2, 4, 5, 200.
Correction
VARIABLES
n EST_DU_TYPE
i EST_DU_TYPE
p EST_DU_TYPE
c EST_DU_TYPE
b EST_DU_TYPE
NOMBRE
NOMBRE // compteur
NOMBRE // nombre précédemment saisi
NOMBRE // nombre courant saisi
BOOLEEN // vrai tant que la suite est triée
DEBUT_ALGORITHME
n <- 0
TANT_QUE (n<=0) FAIRE // pour forcer l’utilisateur
à saisir un entier positif
DEBUT_TANT_QUE
LIRE n
FIN_TANT_QUE
LIRE c
i <- 1 // On a déjà saisi un entier - reste à en saisir (n-1)
b <- VRAI
TANT_QUE (i<n) FAIRE
DEBUT_TANT_QUE
p <- c // on stocke l’entier précédemment saisi
LIRE c
SI (p>c) ALORS // si l’utilisateur a saisi un entier
inférieur à l’entier précédemment saisi
DEBUT_ALORS
b <- FAUX // Les valeurs ne sont pas ordonnées
Instruction Répétitive
9
de manière croissante.
FIN_ALORS
i <- i+1
FIN_TANT_QUE
ECRIRE "Les "
ECRIRE n
SI (b==VRAI) ALORS
DEBUT_ALORS
ECRIRE " valeurs sont triées de façon croissante."
FIN_ALORS
SINON
DEBUT_SINON
ECRIRE " valeurs ne sont pas triées."
FIN_SINON
FIN_ALGORITHME
Exercice 10
Écrire un algorithme qui saisit un entier strictement positif n, puis n entiers strictement positifs,
et qui vérifie si parmi les n entiers saisis, la somme des entiers pairs est égale à la somme des
entiers impairs. Le programme doit refuser les valeurs négatives ou nulles.
Par exemple, si la valeur saisie pour n est 5 et les 5 valeurs saisies sont 2, 3, 2, 3, 2, l’algorithme
affichera "la somme des nombres pairs est égale à la somme des nombre impairs", alors que
l’algorithme affichera "la somme des nombres pairs n’est pas égale à la somme des nombres
impairs" si les valeurs saisies sont 2, 3, 4, 3, 1. Si la valeur saisie pour n (ou une des n valeurs)
est par exemple -2, l’algorithme demandera à nouveau d’insérer une valeur, jusqu’à ce que
celle-ci soit strictement positive.
Correction
VARIABLES
n EST_DU_TYPE NOMBRE
s_i EST_DU_TYPE NOMBRE // sommes de entiers impairs
s_p EST_DU_TYPE NOMBRE // sommes de entiers pairs
i EST_DU_TYPE NOMBRE // compteur
e EST_DU_TYPE NOMBRE // entier saisi
DEBUT_ALGORITHME
n <- 0
s_i <- 0
s_p <- 0
TANT_QUE (n<=0) FAIRE
DEBUT_TANT_QUE
ECRIRE "Saisir une valeur positive non nulle :"
LIRE n
FIN_TANT_QUE
i <- 0
10
Instruction répétitive
TANT_QUE (i<n) FAIRE
DEBUT_TANT_QUE
e <- 0
TANT_QUE (e<=0) FAIRE
DEBUT_TANT_QUE
ECRIRE "Saisir un entier positif non nul :"
LIRE e
FIN_TANT_QUE
SI ((e%2)==0) ALORS // si e est pair
DEBUT_ALORS
s_p <- s_p+e
FIN_ALORS
SINON
DEBUT_SINON
s_i <- s_i+e
FIN_SINON
i <- i+1
FIN_TANT_QUE
SI (s_i==s_p) ALORS
DEBUT_ALORS
ECRIRE "La somme des nombres pairs est égale à
la somme des nombre impairs."
FIN_ALORS
SINON
DEBUT_SINON
ECRIRE "La somme des nombres pairs n’est pas égale à
la somme des nombres impairs."
FIN_SINON
FIN_ALGORITHME
Les chaînes de caractères en Python
11
CPES 1re année
2016-2017
PSL
Informatique
Les chaînes de caractères en Python
Exercices préparées par V. Gabrel, E. Lazard, M. Manouvrier et C. Murat 2
Exercice 1
Décrire ce que fait le programme Python ci-dessous :
print("Entrer une chaine de caracteres :")
ch=input()
i=0
l=len(ch)
chNew=""
while i<l:
if (ch[i]=="," or ch[i]==";" or ch[i]=="."):
chNew=chNew+"p"
else:
chNew=chNew+ch[i]
i+=1
print(chNew)
Lorsque l’utilisateur saisit au clavier :
En Python, les caractères de ponctuation ;,. sont faciles à manipuler.
indiquer ce que va faire ce programme.
Écrire une nouvelle version beaucoup plus simple de ce programme Python en utilisant des
méthodes de chaînes.
Correction
Ce programme Python lit une chaîne de caractères ch, et affiche la chaîne obtenue en remplaçant les signes de ponctuations ",", ";" et "." par le caractère "p". Le programme affiche
donc :
En Pythonp les caractères de ponctuation ppp sont faciles à manipulerp
Avec les méthodes de chaînes, on obtient :
2. Cours également dispensé en 1ère année de licence Mathématique-Informatique-Économie (MIE) à l’Université Paris-Dauphine
12
Les chaînes de caractères en Python
print("Entrer une chaine de caracteres :")
ch=input()
ch=ch.replace(",","p")
ch=ch.replace(";","p")
ch=ch.replace(".","p")
print(ch)
Ou même :
print("Entrer une chaine de caracteres :")
ch=input()
ch=ch.replace(",","p").replace(";","p").replace(".","p")
print(ch)
Exercice 2
1. Écrire un programme Python qui lit une chaîne de caractères s, affiche sa longueur, puis
affiche s avec tous les espaces du début, intermédiaires et de la fin, supprimées.
2. Écrire un nouveau programme Python qui permet, non pas simplement d’afficher s,
mais de modifier s en enlevant tous les espaces du début, intermédiaires et de la fin.
Correction
print("Entrer une chaine de caracteres :")
ch=input()
print("La longueur de la chaine est : ", len(ch))
print(ch.replace(" ",""))
print("Entrer une chaine de caracteres :")
ch=input()
print("La longueur de la chaine est : ", len(ch))
ch=ch.replace(" ","")
print(ch)
Exercice 3
Écrire un algorithme en pseudo-code, puis un programme Python, qui lit une chaîne de caractères, puis lit une ou plusieurs valeurs entières et qui, pour chacune de ces valeurs v, remplace le
caractère situé en position v par le caractère ’?’. Ce programme se termine par l’affichage de la
nouvelle chaîne. Attention : il faut bien vérifier que les valeurs v correspondent à des positions
valides pour la chaîne de caractères lue.
Correction
print("Entrer une chaîne de caractères")
s=input()
l=len(s)
Les chaînes de caractères en Python
13
rep=’o’
while (rep==’o’):
print("Donner une valeur entière")
v=int(input())
if (v>=0 and v<l):
s=s[:v]+"?"+s[v+1:]
else:
print(v," n’est pas une position valide car
n’appartient pas à [0,", l,"]", sep=’’)
print("Voulez-vous continuer ? (o/n)")
rep=input()
print(s)
Exercice 4
Écrire un algorithme en pseudo-code, puis un programme Python, qui lit une chaîne de caractères et teste si c’est un palindrome. Un palindrome est une chaîne de caractères dont l’ordre
des lettres reste le même qu’on la lise de la gauche vers la droite ou de la droite vers la gauche.
C’est par exemple le cas de la chaîne "kayak". On supposera que la chaîne de caractères lue
ne contient que des caractères minuscules non accentués, et qu’elle ne contient ni espace, ni
caractère de ponctuation.
Correction
print("Entrer une chaîne de caractères")
ch=input()
debut=0
fin=len(ch)-1
while ((debut<fin) and (ch[debut]==ch[fin])):
debut=debut+1
fin=fin-1
if (debut >= fin):
print(ch, " est un palindrome")
else:
print(ch, " n’est pas un palindrome")
Autre programme :
print("Entrer une chaîne de caractères")
ch=input()
if (ch == ch[::-1]):
print(ch, " est un palindrome")
else:
print(ch, " n’est pas un palindrome")
14
Les chaînes de caractères en Python
Exercice 5
Écrire un programme Python qui lit une chaîne de caractères ch et qui affiche la chaîne de caractères obtenue en ignorant les mots de longueur inférieure ou égale à 3 dans ch. Par exemple,
si la chaîne lue est "bonjour les amies !" l’algorithme affichera "bonjour amies".
On définira un mot comme toute suite de caractères quelconques ne contenant pas d’espace.
Correction
print("Entrer une chaîne de caractères")
ch=input()
i=0
while (i<len(ch)):
mot=""
while ((i<len(ch)) and (ch[i] != " ")):
mot = mot + ch[i]
i = i+1
if (len(mot) >= 3): print(mot,end=" ")
i += 1
Exercice 6
Écrire un programme Python qui lit une chaîne de caractères et qui affiche cette chaîne avec
les suites de caractères identiques remplacées par un seul caractère. Par exemple, on donnera la
chaîne "abbcdebbb" et votre programme devra afficher "abcdeb."
Correction
print("Entrer une chaîne de caractères")
ch=input()
resul=ch[0]
i=1
while i<len(ch):
if (ch[i-1]!=ch[i]): resul = resul + ch[i]
i+=1
print(resul)
Exercice 7
Écrire un programme Python qui lit deux chaînes de caractères ch1 et ch2, et qui détermine un
entier N tel que ch1 est égale à N concaténations successives de ch2 avec elle-même. Si cette
propriété est satisfaite le programme affichera N, dans le cas contraire, le programme affichera
"non". On suppose que l’utilisateur saisira toujours des chaînes de caractères ch1 et ch2 non
vides ne contenant pas d’espace. Le tableau ci-dessous donne des exemples de valeurs que le
programme doit afficher.
Les chaînes de caractères en Python
15
ch1
ch2 valeur affichée
"ababab" "ab"
3
"ab"
"ab"
1
"abhabab" "ab"
non
"aaaa"
"aa"
2
"aaa"
"aa"
non
"aaa"
"a"
3
Correction
Une première solution très simple :
ch1 = input("ch1=")
ch2 = input("ch2=")
print ("oui" if ch1 == ch2*(len(ch1)//len(ch2)) else "non")
Et une deuxième qui construit la chaîne à tester :
ch1 = input("ch1=")
ch2 = input("ch2=")
N = len(ch1)//len(ch2)
ch = ""
i = 0
while i<N:
ch= ch + ch2
i += 1
print ("oui" if ch1 == ch else "non")
Exercice 8
Écrire un programme Python qui saisit une chaîne de caractères ch et qui affiche la liste des
mots de ch ainsi que les positions de début de chacun des mots dans ch (chaque mot pouvant
se répéter plusieurs fois). Par exemple, pour ch=" ab cda fg ab fg cda h cda ", le
programme doit afficher :
"ab" 1, 11
"cda" 4, 19, 25
"fg" 8, 16
"h" 23
Attention, plusieurs espaces peuvent se trouver entre deux mots consécutifs, ainsi qu’avant
le premier mot et après le dernier mot.
Exercice 9 :
Écrire en Python un programme qui lit une chaîne de caractères (supposée sans espace et de longueur au moins égale à 3) et l’affiche sous la forme d’un N. Si l’on saisit par exemple "abcde",
alors le programme doit afficher :
16
Les chaînes de caractères en Python
a
a
bb b
c c c
d dd
e
e
Correction
str = input("chaine : ")
lg = len(str)
str_a_afficher=’’
i=0
while (i<lg):
if i == 0 or i == lg-1:
str_a_afficher = (str[i]+’ ’ * (lg-2)+str[i])
else:
str_a_afficher = (str[i] + ’ ’ * (i-1) + str[i]
+ ’ ’ * (lg-2-i) + str[i])
i+=1
print(str_a_afficher)
ou encore
str = input("chaine : ")
lg = len(str)
ligne=0
while (ligne < lg):
col=0
while (col < lg):
if (col == 0 or col == lg-1 or ligne == col):
print(str[ligne], end=’’)
else:
print (’ ’, end=’’)
col+=1
print()
ligne+=1
Exercice 10 : Formater l’affichage des nombres
L’insertion d’une valeur numérique x dans une chaîne de caractères ch à l’indice p se fait
simplement comme suit :
ch[:p] + str(x) + ch[p:]
Dans cette expression, on utilise la convertion explicite du type de x en string, la concaténation et le slicing. Par exemple, exécuter les instructions suivantes :
x=1/3
ch=’bonjour’
ch=ch[0:2]+str(x)+ch[2:]
print(ch)
Les chaînes de caractères en Python
17
Il n’est alors pas possible de paramétrer finement le format obtenu pour la valeur numérique (le
nombre de chiffres après la virgule par exemple).
Pour réaliser un paramétrage plus fin, il existe en Python la méthode de chaîne appelée
format. La syntaxe pour appliquer la méthode format à la chaîne ch est
ch.format(arguments)
Dans l’exemple précédent, pour obtenir le même résultat, on peut exécuter l’affectation
ch=’bo{}njour’.format(1/3)
La méthode format remplace dans une chaîne de caractères les symboles {} par l’argument
donné entre parenthèses. Il existe différentes options d’affichage des nombres :
— {:.4f} : écriture en virgule flottante, fixe à 4 le nombre de chiffres après la virgule.
— {:.5e} : écriture en notation scientifique, fixe à 5 le nombre de chiffres après la virgule.
— {:<15.2e} : fixe la longueur de la chaîne (elle est remplie par des espaces), et justifie
à gauche. Le 2e a la même signification que plus haut.
— {:>15.2e} : fixe la longueur de la chaîne, et justifie à droite.
— {:^15.2e} : fixe la longueur de la chaîne, centre.
1. (Dans l’interpréteur) Exécuter print(’bo{:.2f}njo{}ur’.format(1/3,2/7))
puis essayez les différents formats d’affichage.
2. Ecrire un programme affichant toutes les valeurs de la suite un définie par la récurrence
u0 = 1 et pour tout n > 0, un+1 = sin(un ) jusqu’à obtenir une valeur inférieure ou égale
à 2.10−2 . L’affichage devra être fait sous le format un = v où n et v sont remplacées par
leur valeur.
import math
u=1
n=0
while u>2*10**(-2):
print(’u{}={}’.format(n,u))
u=math.sin(u)
n+=1
Fin pour n=7492
18
Modules externes et projet de Casino
CPES 1re année
2016-2017
PSL
Informatique
Modules externes et projet de Casino
Exercices préparées par V. Gabrel, E. Lazard, M. Manouvrier et C. Murat 3
Les modules externes
Les modules externes, appelés également bibliothèques (de library en anglais), sont des
programmes Python qui contiennent des fonctions et méthodes qu’il est possible d’appeler dans
vos programmes. Les développeurs de Python ont rendu disponibles de nombreux modules. La
plupart de ces modules sont disponibles dans les versions standards de Python.
Voici une liste non exhaustive des modules utiles :
— math : contient des fonctions et constantes math de base (sin, cos, exp, logarithme,
racine carrée, puissance, π...) ;
— os : contient des fonctions et constantes permettant d’interagir avec le système d’exploitation ;
— random : contient des fonctions et constantes permettant de générer des nombres aléatoires ;
— time : permet d’accéder à l’heure de l’ordinateur et aux fonctions gérant le temps ;
— calendar : fonctions de calendrier ;
— numpy : algèbre linéaire, calcul numérique.
Ces modules ne sont pas immédiatement accessibles. Pour appeler n’importe quelle fonction
d’un module (par exemple le module random) dans votre programme Python, il faut avoir au
préalable importé ce module grâce à l’instruction :
import random
Il est possible d’obtenir de l’aide sur un module. Après avoir importé le module, il suffit
d’exécuter la commande :
help(nomModule)
Si on veut connaître la liste des fonctions/méthodes/constantes incluses dans un module, on
peut utiliser la commande dir :
dir(nomModule)
Vous pouvez alors appeler n’importe laquelle des fonctions incluses dans ce module. Et
par exemple si on veut générer aléatoirement un nombre entier compris entre 2 et 19, il suffit
d’exécuter :
random.randint(2,19)
La forme générale d’un appel de fonction d’un module préalablement importé est donc :
3. Cours également dispensé en 1ère année de licence Mathématique-Informatique-Économie (MIE) à l’Université Paris-Dauphine
Modules externes et projet de Casino
19
import nomModule
nomModule.nomFonction(...)
En effet, l’instruction import nomModule crée ce que l’on appelle un espace de nom
appelé nomModule, contenant les variables et les fonctions du module. Quand on appelle
nomModule.nomFonction(...), on précise à Python qu’il faut exécuter la fonction de
nom nomFonction contenue dans l’espace de noms nomModule. Cela signifie aussi que
dans une autre partie de votre programme, vous pourriez utiliser l’identificateur nomFonction
sans qu’il y ait de confusion (nomFonction 6= nomModule.nomFonction).
Il existe un autre moyen, qui ne procède pas de la même façon, d’importer une fonction
particulière d’un module :
from nomModule import nomFonction
Et pour appeler cette fonction, il suffira alors d’utiliser son nom (sans rappeler le nom du module
en préfixe). Par exemple,
from random import randint
randint(2,19)
Dans ce cas, la fonction randint() du module random a été « chargée » dans l’interpréteur au même plan que toutes les fonctions existantes, comme print() par exemple :
print() et randint() appartiennent alors au même espace de noms.
De cette façon, on peut également importer toutes les fonctions d’un module avec l’instruction suivante :
from nomModule import *
Attention si, avec cette méthode, on importe des fonctions portant le même nom provenant
de modules différents, c’est la dernière fonction du dernier module importé qui sera alors la
seule accessible.
Exercice 1
1. Écrire un programme Python qui permet de calculer et écrire le cosinus de π/2 (module
math).
2. Écrire un programme Python qui permet d’écrire une série de 10 nombres réels aléatoires compris entre 10 et 50 (inclus) avec 1 seconde d’intervalle entre chaque écriture
(modules random et time).
3. Écrire un programme Python qui permet de déterminer votre jour de naissance (module
calendar).
Correction
1. import math
print(math.cos(math.pi/2))
20
Modules externes et projet de Casino
2. import time
import random
cpt=0
while cpt<10:
print(random.uniform(10,50))
cpt+=1
time.sleep(1)
3. import calendar
j=calendar.weekday(1997,8,14)
print(calendar.day_name[j])
Exercice 2 : évaluation de π par la méthode de Monte-Carlo
Soit un cercle de rayon r = 1 inscrit dans un carré de coté l = 2. L’aire du carré vaut 4 et
l’aire du cercle vaut π. En choisissant N points aléatoires (à l’aide d’une distribution uniforme)
à l’intérieur du carré, la probabilité que chacun de ces points se trouve aussi dans le cercle est
p=
π
aire du cercle
=
aire du carré
4
Soit n, le nombre de points tirés aléatoirement se trouvant effectivement dans le cercle, on
a:
p=
π
n
=
N
4
d’où
n
N
Déterminer une approximation de π par cette méthode. Pour cela, on procède en N itérations :
à chaque itération, choisir aléatoirement les coordonnées d’un point entre -1 et 1 (fonction
uniform() du module random), calculer la distance entre ce point et le centre du cercle,
déterminer si cette distance est inférieure au rayon du cercle égal à 1, et si c’est le cas, incrémenter le compteur n de 1. Quelle est la qualité de l’approximation de π pour N = 50,
N = 500, N = 5000 et N = 50 000 ?
π =4×
Correction
import random
import math
print("Donner N:")
N=int(input())
n=0
i=0
while (i<N):
abs=random.uniform(-1,1)
ord=random.uniform(-1,1)
d=math.sqrt(math.pow(abs,2)+math.pow(ord,2))
if d<=1:
n+=1
Modules externes et projet de Casino
21
i += 1
print("La valeur exacte de pi est :", math.pi)
print("La valeur approximée de pi avec", N,"points est :", 4*n/N)
Exercice 3 : à vous de jouer !
Écrire un programme de jeu de roulette (très simplifié) dans lequel le joueur peut miser une certaine somme sur un numéro et gagner ou perdre de l’argent si ce numéro est tiré aléatoirement.
Le joueur peut enchainer plusieurs parties mais, il est contraint de s’arrêter s’il ne lui reste plus
d’argent !
Voici la règle du jeu :
Le joueur mise une certaine somme sur un numéro compris entre 0 et 49 (50 numéros en
tout) en déposant cette somme sur le numéro choisi sur la table de jeu : il donne donc sa mise
au croupier. La roulette est constituée de 50 cases allant de 0 à 49. Les numéros pairs sont de
couleur noire, les numéros impairs sont de couleur rouge. Le croupier lance la roulette, lâche la
bille et quand la roulette s’arrête, relève le numéro de la case dans laquelle la bille s’est arrêtée.
Le numéro sur lequel s’est arrêtée la bille est, naturellement, le numéro gagnant. Si le numéro
gagnant est celui sur lequel le joueur a misé (probabilité de 1/50, plutôt faible), le croupier lui
remet 3 fois la somme misée. Dans le cas contraire, si le numéro gagnant a la même couleur que
celui sur lequel le joueur a misé, le croupier lui remet 1,5 fois la somme misée ; sinon, lorsque le
joueur a misé sur le mauvais numéro de mauvaise couleur, le joueur perd définitivement sa mise.
Écrire dans un premier temps en pseudo-langage l’algorithme conforme à la règle du jeu.
Ensuite, traduire cet algorithme en Python. Dans votre programme, il faut lire différentes valeurs (et vérifier leur cohérence vis-à-vis des valeurs attendues) : le budget initial du joueur, le
numéro choisi par le joueur, le fait qu’il souhaite ou non continuer de jouer.
Remarque : avec cette règle du jeu, si le joueur mise sur la bonne couleur mais pas le bon numéro, son bénéfice est de 50% de la somme misée. Au bout de nombreuses parties, on risque
d’arriver à des nombres flottants avec beaucoup de chiffres après la virgule. Alors autant arrondir au nombre supérieur. Ainsi, si le joueur mise 3 euros sur la bonne couleur mais pas le bon
numéro, il gagne 2 euros et le croupier lui rend 3 + 2 = 5 euros. Pour cela, on va utiliser une
fonction du module math nommée ceil.
Correction
import math
import random
budgetInit=int(input("Budget Initial (en euros) : "))
if (budgetInit > 0):
budget=budgetInit
jouer=True
while jouer:
numero=int(input("Choisissez un chiffre compris entre 0 et 49 : "))
while (numero<0 or numero>49):
22
Modules externes et projet de Casino
print("Vous devez choisir un chiffre compris entre 0 et 49 !")
numero=int(input("Choisissez un chiffre compris entre 0 et 49 : "))
print("Votre mise (comprise entre 1 et ",budget,") : ",end="")
mise=int(input())
while (mise > budget):
print("Vous n’avez plus assez d’argent !
Nouvelle mise ( <",budget,") : ")
mise=int(input())
budget-=mise
bille=random.randrange(0,49)
print("Numero gagnant : ",bille)
if (bille == numero):
budget+=3*mise
print("Vous gagnez :", 3*mise, " et votre budget est de", budget)
elif (bille%2 == numero%2):
budget+=math.ceil(1.5*mise)
print("Vous gagnez",math.ceil(1.5*mise),
"et votre budget est de",budget)
else:
print("Vous perdez", mise, "euros et il vous reste", budget)
rep=input("Continuez (O/N) ? ")
if (rep==’N’ or budget==0): jouer=False
if (budgetInit < budget):
print("Vous avez gagne", budget-budgetInit, "euros.")
else:
if (budget == 0):
print("Vous ne pouvez pas rejouer ! Il ne vous reste plus rien !!")
else:
print("Vous avez perdu", budgetInit-budget, "euros.")
else:
print("Vous ne pouvez pas jouer !")
Fonctions
23
CPES 1re année
2016-2017
PSL
Informatique
Fonctions
Exercices préparées par V. Gabrel, E. Lazard, M. Manouvrier et C. Murat 4
Exercice 1 : utilisation de fonctions Python existantes
La liste des fonctions Python existantes (dont print() et input() par exemple) est disponible à l’adresse suivante :
https://docs.Python.org/3/library/functions.html
Dans l’interpréteur de commandes taper les instructions suivantes :
abs(-5)
help(abs)
max(5,12)
help(max)
min(5,12)
help(min)
Exercice 2
Écrire en pseudo-langage, puis en Python, une fonction prenant 2 arguments de type entier et
retournant le maximum des 2. NB : Comme le montre l’exercice précédent, il existe une fonction
max en Python. Vous devez donc, dans cet exercice, écrire une fonction similaire portant un
autre nom que la fonction Python existante.
Correction
FONCTION maximum(n1 EST_DU_TYPE NOMBRE, n2 EST_DU_TYPE NOMBRE)
EST_DE_TYPE NOMBRE
DEBUT_FONCTION
IF (n1>n2)
DEBUT_ALORS
RENVOYER n1
FIN_ALORS
SINON
DEBUT_ALORS
RENVOYER n2
FIN_ALORS
FIN_FONCTION
4. Cours également dispensé en 1ère année de licence Mathématique-Informatique-Économie (MIE) à l’Université Paris-Dauphine
24
Fonctions
def maximum(a,b):
if(a>b): return a
else: return b
Exercice 3
Écrire en Python une fonction qui prend en argument la date du jour (dans 3 variables jourSysteme,
moisSysteme, annéeSysteme), une date de naissance (dans 3 variables jourNais,
moisNais, annéeNais) et calcule et renvoie l’âge d’une personne.
L’âge d’une personne se calcule par la formule :
(jourSysteme - jourNais + (moisSysteme - moisNais) * 365.25/12 +
(anneeSysteme - annNais) *365.25) / 365.25).
Vous pouvez importer le module time 5 pour obtenir la date système.
Correction
def age(jourSysteme,moisSysteme,anneeSysteme,jourNais,
moisNais,annNais):
return round((jourSysteme - jourNais + (moisSysteme - moisNais)
* 365.25/12
+ (anneeSysteme - annNais) *365.25) / 365.25)
jourS=int(input("Quel jour somme-nous aujourd’hui (ex. 27) :"))
moisS=int(input("Quel mois somme-nous aujourd’hui (ex. 6) :"))
anneeS=int(input("En quelle année somme-nous aujourd’hui
(ex. 2016) :"))
jourN=int(input("Quel est le jour de votre date de naissance
(ex. 19) :"))
moisN=int(input("Quel est le mois de votre date de naissance
(ex. 6) :"))
anneeN=int(input("En quelle année ête-vous né(e) (ex. 1999) :"))
print("Vous avez/allez avoir :", age(jourS,moisS,anneeS,
jourN,moisN,anneeN), "ans")
ou avec le module time :
def ageAvecTime(jourNais,moisNais,annNais):
return round((time.localtime (time.time()).tm_mday - jourNais
+ (time.localtime (time.time()).tm_mon - moisNais)
* 365.25/12
+ (time.localtime (time.time()).tm_year - annNais)
* 365.25) / 365.25)
5. cf. https://docs.python.org/3/library/time.html
Fonctions
25
jourN=int(input("Quel est le jour de votre date de naissance
(ex. 19) :"))
moisN=int(input("Quel est le mois de votre date de naissance
(ex. 6) :"))
anneeN=int(input("En quelle année ête-vous né(e) (ex. 1999) :"))
print("Vous avez/allez avoir :", ageAvecTime(jourN,moisN,anneeN),
"ans")
Exercice 4
Écrire en pseudo-langage puis en Python :
a) une fonction qui calcule le cube d’un entier n passé en paramètre ;
b) une fonction qui calcule le volume d’une sphère de rayon r passé en paramètre en appelant la fonction cube() précédente. Pour rappel : le volume d’une sphère se calcule
par la formule :
(4/3) ∗ π ∗ r3
Correction
FONCTION cube(n EST_DU_TYPE NOMBRE) // Fonction sans variable locale
EST_DE_TYPE NOMBRE
DEBUT_FONCTION
RENVOYER n^3
FIN_FONCTION
FONCTION volumeSphere(r EST_DU_TYPE NOMBRE)
EST_DE_TYPE NOMBRE
DEBUT_FONCTION //Avec appel de la fonction cube
RENVOYER 4 * 3.1416 * cube(r)/3
FIN_FONCTION
Dans l’exemple précédent, la fonction volumeSphere appelle la fonction cube en lui passant en paramètre la valeur de r (la valeur de r est copiée dans la valeur de l’argument n de la
fonction cube).
from math import
*
def cube(n):
return n**3
def volumeSphere(r):
return (4/3) * pi * cube(r)
r=int(input(’Saisir un rayon :’))
print("Le volume de la sphere vaut :", volumeSphere(r))
26
Fonctions
Exercice 5
Écrire en Python une fonction permettant d’afficher une table de multiplication avec 3 arguments : base, debut et fin, la fonction affichant le résultat de la multiplication de base par
tous les entiers situés entre debut et fin. Par exemple l’appel de tableMulti(8, 13,
17) devra afficher :
Fragment
13 x 8 =
14 x 8 =
15 x 8 =
16 x 8 =
17 x 8 =
de la table de multiplication par 8 :
104
112
120
128
136
Correction
def tableMulti(base,debut,fin):
print("Fragment de la table de multiplication par", base, ":")
n=debut
while(n<=fin):
print(n, "x", base, "=", n * base)
n=n+1
tableMulti(8, 13, 17)
Exercice 6
Écrire 3 fonctions qui permettent de calculer le Plus Grand Commun Diviseur (PGCD) de deux
nombres a et b (avec a ≥ b).
1. La première fonction pgcdParDiviseurs(a,b), avec a ≥ b, calculera les diviseurs de chacune des variables et affichera le plus grand diviseur commun.
Par exemple, si on appelle pgcdParDiviseurs(63,42), les diviseurs de 63 étant
1;3;7;9;21;63 et ceux de 42 étant 1;2;3;6;7;14;21;42, on doit obtenir :
Le plus grand diviseur commun de 63 et 42 est: 21
2. La deuxième fonction pgcdParDifferences(a,b), avec a ≥ b, utilisera l’algorithme des différences. Si un nombre est un diviseur de 2 nombres a et b, alors il est
aussi un diviseur de leur différence a − b.
Par exemple, si calcule le PGCD de 60 et 36. 60 - 36 = 24, donc le PGCD de
60 et 36 est un diviseur de 24. On effectue une nouvelle soustraction entre le résultat obtenu à la soustraction précédente et le plus petit des 2 termes de la soustraction
précédente : 36 - 24 = 12. Par conséquent, le PGCD de 60 et 36 est un diviseur de 12. On arrête l’algorithme dès que la soustraction donne un résultat nul. Le
PGCD correspond au résultat juste au dessus du zéro. Par conséquent, si on appelle
pgcdParDifferences(60,36), on doit obtenir :
Fonctions
60
36
24
12
27
-
36
24
12
12
=
=
=
=
24
12
12
0
Le plus grand diviseur commun de 60 et 36 est: 12
3. La troisième fonction pgcdParEuclide(a,b), avec a ≥ b, utilisera l’algorithme
d’Euclide. L’algorithme d’Euclide pour calculer le Plus Grand Commun Diviseur (PGCD)
de deux entiers a et b (avec a ≥ b) consiste à effectuer une suite de divisions euclidiennes :
— étape 1 : effectuer la division euclidienne de a par b ; on obtient r le reste ; si r est
égal à 0, alors fin et le PGCD est égal à b, sinon aller à l’étape 2,
— étape 2 : a reçoit alors la valeur de b et b reçoit la valeur de r et aller à l’étape 1.
Cette méthode est plus rapide en général.
Par exemple, si on appelle pgcdParEuclide(561,357), on doit obtenir :
561 divisé par 357 donne 1 en quotient et 204 en reste donc
561 = 357 x 1 + 204
357 divisé par 204 donne 1 en quotient et 153 en reste donc
357 = 204x1 + 153
204 divisé par 153 donne 1 en quotient et 51 en reste donc
204 = 153x1 + 51
153 divisé par 51 donne 1 en quotient et 0 en reste donc
153 = 51x3+ 0
Le plus grand diviseur commun de 561 et 357 est: 51
Correction
FONCTION pgcdParDiviseurs(a EST_DE_TYPE NOMBRE, b EST_DE_TYPE NOMBRE)
EST_DE_TYPE NOMBRE
VARIABLES LOCALES
pgcd EST_DE_TYPE NOMBRE
cpt EST_DE_TYPE NOMBRE
DEBUT_FONCTION
pgcd <- 1
POUR cpt ALLANT de 0 A b
DEBUT_POUR
SI (((a % cpt)==0) ET ((b % cpt)==0) ET (cpt>pgcd))
DEBUT_ALORS
pgcd <- cpt
FIN_ALORS
FIN_POUR
RETOURNER pgcd
FIN_FONCTION
FONCTION maximum(n1 EST_DU_TYPE NOMBRE, n2 EST_DU_TYPE NOMBRE)
EST_DE_TYPE NOMBRE
28
Fonctions
DEBUT_FONCTION
IF (n1>n2)
DEBUT_ALORS
RENVOYER n1
FIN_ALORS
SINON
DEBUT_ALORS
RENVOYER n2
FIN_ALORS
FIN_FONCTION
FONCTION minimum(n1 EST_DU_TYPE NOMBRE, n2 EST_DU_TYPE NOMBRE)
EST_DE_TYPE NOMBRE
DEBUT_FONCTION
IF (n1<n2)
DEBUT_ALORS
RENVOYER n1
FIN_ALORS
SINON
DEBUT_ALORS
RENVOYER n2
FIN_ALORS
FIN_FONCTION
FONCTION pgcdParDifferences(a EST_DE_TYPE NOMBRE)
EST_DE_TYPE NOMBRE
VARIABLES LOCALES
diff EST_DE_TYPE NOMBRE
DEBUT_FONCTION
diff <- a-b
TANT_QUE (diff>0)
DEBUT_TANT_QUE
a <- maximum(diff,b)
b <- minimum(diff,b)
diff <- a-b
FIN_TANT_QUE
RETOURNER a
FIN_FONCTION
FONCTION pgcdParEuclide(a EST_DE_TYPE NOMBRE)
EST_DE_TYPE NOMBRE
VARIABLES LOCALES
reste EST_DE_TYPE NOMBRE
DEBUT_FONCTION
reste <- a%b
TANT_QUE (reste!=0)
DEBUT_TANT_QUE
a <- b
Fonctions
b <- reste
reste <- a%b
FIN_TANT_QUE
RETOURNER b
FIN_FONCTION
DEBUT_ALGORITHME
pgcdParDiviseurs(26,15)
pgcdParDifferences(56,20)
pgcdParEuclide(758,306)
FIN_ALGORITHME
29
30
Listes en Python
PSL
Informatique
CPES 1re année
2016-2017
Listes en Python
Exercices préparées par V. Gabrel, E. Lazard, M. Manouvrier et C. Murat 6
Exercice 1 : à la découverte des listes
Exécuter dans l’interpréteur les instructions suivantes et analyser le résultat :
L = [1,2,3,’toto’,8,True]
L[0]
L[4]
len(L)
L[len(L)]
L[-1]
L[1:-2]
L[1:5:2]
L[:5:-1]
L.append(3)
L.append([3])
L += 4
L += [4]
L.count(’toto’)
L.count(3)
L.index(’toto’)
L.index(3)
’toto’ in L
[1,2,3] in L
[1,3,2] in L
list(range(10))
list(range(1,11))
list(range(1,11,2))
L = list(range(101,1,-1))
sum(range[1,6])
Remarque : En tapant help(list) dans l’interpréteur Python, on obtient toutes les fonctions sur les listes.
Exercice 2 :
Considérer le programme Python suivant :
6. Cours également dispensé en 1ère année de licence Mathématique-Informatique-Économie (MIE) à l’Université Paris-Dauphine
Listes en Python
31
def f(k,taille,Liste):
for j in range(k+1,taille):
if Liste[k]>Liste[j]:
x=Liste[k]
Liste[k]=Liste[j]
Liste[j]=x
L=[]
n=int(input())
for i in range(n):
L.append(int(input()))
for i in range(n-1):
f(i,n,L)
print(L)
Sans exécuter le programme répondez aux questions suivantes :
1. Dans la fonction f, à quoi sert la variable x ? Quels sont les types des arguments de f ?
2. Décrire ce que réalise la fonction f.
3. Que permet de faire le bloc d’instructions suivant :
for i in range(n):
L.append(int(input()))
4. Que permet de faire le bloc d’instructions suivant :
for i in range(n-1):
f(i,n,L)
Pourquoi la dernière valeur à considérer pour i dans cette boucle doit-elle être n-2 ?
5. Que va afficher le programme si l’utilisateur saisit d’abord 6 puis 14 3 54 2 1 5 ?
Correction
1. A échanger les éléments d’indice k et l dans la liste L.
Les arguments de la fonctionf() sont un entier k, indice dans une liste, une taille de
liste et une liste (d’entiers).
2. La fonction positionne à la position d’indice k le plus petit entier situé entre les positions
k+1 et taille-1.
3. Il permet de saisir n entiers dans la liste.
4. Il permet de trier la liste petit à petit en mettant le plus petit entier (parmi ceux situés
entre les positions 0 et (taille-1)) à la position 0, puis le plus petit entier (parmi
ceux situés entre les positions 1 et (taille-1)) à la position 1, etc.
La boucle s’arrête à n-2, car le dernier échange positionne correctement les entiers
situés entre les positions (taille-2) et (taille-1).
5. [1 2 3 5 14 54]
Si le print(L) avait été mis dans le for, on aurait eu :
[1, 14, 54, 3, 2, 5]
[1, 2, 54, 14, 3, 5]
[1, 2, 3, 54, 14, 5]
32
Listes en Python
[1, 2, 3, 5, 54, 14]
[1, 2, 3, 5, 14, 54]
Exercice 3
1. Dans le module random se trouve une fonction nommée randint. Utilisez-la pour
écrire une fonction, appelée listeAlea, qui renvoie une liste de 100 entiers tirés au
hasard entre 0 et 99.
2. Ecrire une fonction, appelée absent, qui prend en argument une liste l crée avec la
fonction listeAlea et, renvoie le nombre d’entiers compris entre 0 et 99 qui n’appartiennent pas à l.
3. Dans le programme principal, recommencer ce tirage aléatoire 1000 fois et calculer, et
afficher, la moyenne du nombre d’absents.
4. Comparer à la valeur théorique.
import random
def listeAlea():
L=[]
for i in range(100):
L.append(random.randint(0,99))
return L
def nbreAbsent(L):
nb=0
for i in range(100):
if not(i in L): nb+=1
return nb
moyenne=0
for essai in range(1000):
l=listeAlea()
moyenne+=nbreAbsent(l)
print(moyenne/1000)
Nbre moyen = 36.444
Nbre théorique =
proba d’être absent pA = 0.3660323412732292
=> 100*pA=36.60323412732292
Exercice 4
1. Écrire une fonction qui prend trois arguments n, m et p et qui affiche les m premiers
multiples de n de la façon suivante : les multiples sont séparés par des ; et on passera à
la ligne tous les p multiples.
Listes en Python
33
2. Dans le programme principal, appeler cette fonction pour afficher les 20 premiers multiples de 7 en passant à la ligne tous les 3 multiples.
Exemple d’exécution :
Combien de multiples de 7 voulez-vous afficher ? 20
Vous irez à la ligne après ...
(nombre strictement positif svp) : 3
7;14;21
28;35;42
49;56;63
70;77;84
91;98;105
112;119;126
133;140;
Exercice 5 : somme de deux listes
Soit deux listes d’entiers L1 et L2. Ecrire une fonction qui prend L1 et L2 en arguments et
renvoie la liste LRES qui contient la somme des éléments de même rang de la liste L1 et de la
liste L2 auxquels on ajoute les derniers éléments de la liste la plus longue.
Appeler votre fonction pour afficher la somme de [1,2,3,4,5] et [2,15,18] qui devrait donner
[3,17,21,4,5].
Correction
l1=[1, 2, 3,4,5]
l2=[2,15,18]
lres=list()
i=0
while i<len(l1) and i<len(l2):
lres.append(l1[i]+l2[i])
i+=1
if i==len(l1):
lres.extend(l2[i:])
else:
lres.extend(l1[i:])
print(lres)
Exercice 6 : une suite
Soit la suite U définie comme suit : Un = 5Un−1 + 10Un−2 avec U0 = 1 et U1 = 2.
Écrire la fonction, appelée suiteU, qui prend en argument n et qui renvoie la liste [U0 , U1 , ..., Un−1 , Un ].
Ecrire votre programme principal qui lit n ≥ 2 saisi par l’utilisateur et appelle la fonction
suiteU pour afficher les n premiers termes de la suite U .
34
Listes en Python
Correction
n=int(input())
serie=[1,2]
for i in range(2,n+1):
serie.append(5*serie[i-1]+10*serie[i-2])
print(serie)
Exercice 7 : suppression dans une liste
Étant donnés une liste L et un élément x, écrire une fonction qui permet de supprimer toutes les
occurences de l’élément x dans la liste L.
Tester votre fonction pour l’élément 0 dans la liste L = [0, 1, 2, 0, 0, 4].
Correction
#Première correction
L=[0,1,2,0,0,4]
x=int(input("Quelle est la valeur à supprimer ? "))
i=0
while i<len(L):
if L[i]==x: L.pop(i)
else : i=i+1
print("verif", L)
Attention : bien expliquer que l’on ne peut pas utiliser une boucle for ici car len(L) est
évalué uniquement au premier passage de la boucle, par la suite si la liste L est modifiée, alors
len(L) n’est pas mis à jour.
#Seconde correction
L=[0,1,2,0,0,4]
x=int(input("Quelle est la valeur à supprimer ? "))
while x in L:
L.remove(x)
print("verif", L)
Exercice 8
Écrire une fonction en Python qui saisit une liste de listes de nombres. Puis, écrire une fonction
qui prend en argument une liste de listes et retourne la somme de la liste de nombres la plus
longue (s’il y en a plusieurs, on prendra la première).
Par exemple, pour la liste [[1, 2, 3], [], [2, 3, 0, 4], [2, 5], [6, 0, 2, 4]], le programme affichera 9.
Correction
L=[[1,2,3],[],[2,3,0,4],[2,5],[6,0,2,4]]
longueur=0
total=0
Listes en Python
35
for j in range(len(L)):
taille=len(L[j])
if taille>longueur:
somme=0
for i in range(taille):
somme+=L[j][i]
longueur=taille
total=somme
print("la liste ", L[j], "contient ",taille,
" éléments dont la somme est ", somme)
print("la plus longue liste contient ", longueur,
" éléments dont la somme est ", total)
Exercice 9 : gestion des notes
Après un examen, les notes des étudiants sont les suivantes : Florian : 2, Antoine : 12, Charles1 :
15, Robert : 0, Charles2 : 8, Erwan : 7, Jean : 20, Xavier : 11, Didier : 20, Alain : 0, Hadi : 12.
1. Utiliser des listes pour stocker les noms des étudiants et les notes associées.
2. Ecrire une fonction qui prend en argument la liste de note et qui calcule et retourne la
moyenne de l’examen.
3. Ecrire une fonction qui prend en argument la liste de noms et la liste de notes et retourne
la liste des mentions : « admis » si la note est supérieure ou égale a 10, ou bien « recalé
» sinon.
4. Ecrire une fonction qui prend en argument la liste de noms et la liste des mentions et
renvoie la liste des étudiants ayant réussi leur examen.
5. Dans votre programme principal, appeler ces fonctions pour : afficher la moyenne et
afficher la liste des étudiants ayant réussi leur examn.
Correction
Noms=["Florian","Antoine","Charles1","Robert","Charles2", "Erwan","Jean",
"Xavier","Didier","Alain","Hadi"]
Notes=[2,12,15,0,8,7,20,11,20,0,12]
total=len(Noms)
print(Noms)
print(Notes)
moyenne=0
for i in Notes:
moyenne+=i
moyenne=moyenne/len(Notes)
print("la moyenne est ", moyenne)
admis=[]
recale=[]
for i in range(total):
if Notes[i]>=10:
print(Noms[i], "est admis avec ", Notes[i])
36
Listes en Python
admis.append(Noms[i])
else:
print(Noms[i], "est recalé avec ", Notes[i])
if Notes[i]!=0: recale.append(Noms[i])
print("les étudiants recalés sont finalement : ", recale)
total = int(input("Combien d’étudiants et de notes à saisir en plus?"))
for i in range(total):
nom=input("Quel est le nom de l’étudiant?")
note=int(input("Quelle est sa note?"))
Noms.append(nom)
Notes.append(note)
Fonctions - Récursion
37
CPES 1re année
2016-2017
PSL
Informatique
Fonctions - Récursion 7
Exercice 1
Que font ces deux programmes et qu’affichent-ils ?
# Programme 1
def f(n):
global c, p
c = n+1
return p*2
# Programme 2
def f(n):
global c, p
c = n+1
p = p*2
return p
c = 0
p = 1
c = 0
p = 1
for i in range(10):
n = f(i)
print(c, n)
for i in range(10):
n = f(i)
print(c, n)
Correction
Les deux programmes effectuent dix fois une boucle et affiche la valeur de c puis la valeur
de retour de la fonction f(). La variable globale c est modifiée dans la fonction et prend
simplement la valeur du paramètre +1 : comme le paramètre est égal à l’indice de boucle (de
0 à 9), la variable c va aller de 1 à 10. On a donc dix lignes d’affichées, commençant par les
nombres de 1 à 10.
La fonction f() du programme 1 renvoie la valeur de p*2 mais comme la variable globale
p n’est jamais modifiée, cette valeur vaut toujours 1 ∗ 2 = 2 ; c’est donc ce nombre qui s’affiche
sur les dix lignes.
Au contraire, dans le second programme, la variable globale p est modifiée et multipliée
par 2 à chaque passage dans la fonction avant d’être renvoyée. Elle prend donc les valeurs
successives 2, 4, 8... et c’est aussi ce qui est affiché : les nombres de 1 à 10 suivis des puissances
de 2 de 21 à 210 .
Exercice 2
Que font ces deux programmes et qu’affichent-ils ?
7. Exercices préparées par V. Gabrel, E. Lazard, M. Manouvrier et C. Murat
38
Fonctions - Récursion
# Programme 1
def gp():
global p
return p
# Programme 2
def gp():
global p
return p
def f(n):
global c
c = n+1
p = gp()*2
return p
def f(n):
global c, p
c = n+1
p = gp()*2
return p
c = 0
p = 1
c = 0
p = 1
for i in range(10):
n = f(i)
print(c, n)
for i in range(10):
n = f(i)
print(c, n)
Correction
L’affichage est exactement le même que dans l’exercice précédent. Le programme 2 fonctionne de la même manière : la fonction gp() renvoie la valeur de p qui est ensuite multipliée
par 2 dans f() et remise dans la variable globale p : celle-ci croit donc comme les puissances
de 2. Le programme 1 semble identique, à l’exception de la variable p qui n’est plus globale
dans la fonction f() ! C’est donc une variable locale qui prend simplement la valeur de la variable globale p (renvoyée par gp() et toujours égale à 1 car jamais modifiée) multipliée par
2.
Exercice 3
1. Écrire une fonction récursive, appelée sommeRec(), qui prend comme argument une
valeur entière n, et qui calcule la somme des n premiers entiers. Appeler cette fonction
pour qu’elle calcule la somme des entiers allant de 0 à 100.
2. Transformer la fonction sommeRec() afin qu’elle admette 2 arguments debut et fin,
et qu’elle calcule la somme des entiers variant de la valeur entière debut à la valeur
entière fin. Appeler cette fonction pour calculer la somme des entiers variant de 50 à
100.
Correction
1. def sommeRec(n):
if (n > 1):
return n + sommeRec(n - 1)
else:
return 1
Appel : x = sommeRec(100).
Fonctions - Récursion
39
2. def sommeRec(debut, fin):
if (fin >= debut):
return fin + sommeRec(debut, fin - 1)
else:
return 0
ou
def sommeRec(debut, fin):
if (fin >= debut):
return debut + sommeRec(debut + 1, fin)
else
return 0
Appel : x = sommeRec(50,100)...
Exercice 4
Les n premiers nombres de Fibonacci sont définis par :
F ib(0) = F ib(1) = 1, F ib(i) = F ib(i − 1) + F ib(i − 2) si i ≥ 2
1. Programmer la fonction itérative FibIt() calculant les n premiers nombres de Fibonacci.
2. Programmer la fonction récursive FibRec() calculant les n premiers nombres de Fibonacci.
3. A l’aide de la bibliothèque time et de la fonction clock(), comparer les temps de
calcul de FibIt(n) et FibRec(n) pour n=35 puis n=70. Que constatez-vous ?
4. Écrire et programmer une version récursive Fib2Rec() ne faisant que n appels récursifs seulement. Toujours à l’aide de la fonction clock(), mesurer le temps de calcul
de Fib2Rec(n) pour n=35 puis n=70. Que constatez-vous ?
Correction
def fibo(n):
if (n<2): return 1
else:
i=2
f0=1
f1=1
while(i<=n):
tmp = f0 + f1
f0 = f1
f1 = tmp
i+=1
return f1
def fiboRec(n):
40
Fonctions - Récursion
if(n<2): return 1
else :
return (fiboRec(n-1)+ fiboRec(n-2))
def fiboRec2(n,a,b):
if(n<2): return a
else :
return fiboRec2(n-1,b+a,a)
tps=time.clock()
resul=fibo(35)
print(resul, time.clock()-tps)
tps=time.clock()
resul=fiboRec(35)
print(resul, time.clock()-tps)
tps=time.clock()
resul=fiboRec2(35,1,1)
print(resul,time.clock()-tps)
Exercice 5
Écrire une fonction récursive calcDiff() qui prend en argument une liste d’entiers t et qui
calcule et affiche un entier de la façon suivante : à partir de t, on calcule la liste des différences
de 2 éléments consécutifs de t (à savoir t[i+1]-t[i]), et on recommence sur cette liste des
différences (comportant un élément en moins que t) jusqu’à obtenir une liste d’un seul élément.
Par exemple, partant de la liste [3,5,10], la fonction doit afficher 3 (en passant par le calcul de
la liste intermédiaire [2,5]).
Correction
def calculDiff(t):
if len(t)>1:
diff=[]
for i in range(0,len(t)-1):
diff.append(t[i+1]-t[i])
return calculDiff(diff)
else: return t[0]
print(calculDiff([3,5,10]))
Exercice 6
1. Écrire une fonction prenant un entier a et un entier positif n et qui retourne an de manière
itérative.
2. Écrire une fonction récursive calculant cette même puissance.
Fonctions - Récursion
41
3. Sachant que a0 = 1 et
n
a =
(a(n/2) )2
si n est pair
(n−1)/2) 2
a × (a
) si n est impair
écrire une deuxième fonction récursive plus maline calculant cette même puissance.
4. Afficher les puissances de 2 de 20 à 230 en appelant les deux fonctions récursives cidessus. On affichera également pour chaque puissance le nombre d’appels à chaque
fonction, comptabilisés à l’aide d’une variable globale.
Correction
def puissance(a, n):
global appels
appels += 1
if (n==0):
return 1
else:
return a*puissance(a, n-1)
def puissance2(a, n):
global appels
appels += 1
if (n==0):
return 1
elif (n%2==0): #n pair
i = puissance2(a, n/2)
return i*i
else: #n impair
i = puissance2(a, (n-1)/2)
return a*i*i
for p in range(31):
appels = 0
print("2 puissance", p, "=", puissance(2, p),
"(en", appels, "appels)")
appels = 0
print("2 puissance2", p, "=", puissance2(2, p),
"(en", appels, "appels)")
42
Algorithmes de recherche
CPES 1re année
2016-2017
PSL
Informatique
Algorithmes de recherche
Exercice 1 : Recherche séquentielle dans un tableau
Soit T un tableau de n éléments de type NOMBRE (dont certains sont éventuellement identiques) et soit v une valeur de type NOMBRE.
1. Ecrire un algorithme qui renvoie le plus petit indice i tel que T[i] soit égal à v ou -1
s’il n’en existe pas (le tableau est parcouru par indice croissant).
2. Donner la complexité de cet algorithme en fonction de n.
3. Traduire en Python l’algorithme proposé question 1.
4. Ecrire un algorithme qui renvoie le plus grand indice i tel que T[i] soit égal à v ou -1
s’il n’en existe pas (le tableau est parcouru par indice croissant).
5. Donner la complexité de ce programme en fonction de n.
6. Quel est l’inconvénient de ce programme par rapport au précédent ?
7. En Python, la boucle while permet de réaliser des boucles dont l’indice est décroissant.
Utiliser ce type de boucle pour proposer un programme plus efficace pour trouver le plus
grand indice.
Exercice 2 : Recherche dichotomique dans un tableau trié
On suppose maintenant que le tableau T est trié. Pour trouver un indice de v dans T (retourne
-1 si v n’est pas un élément de T), on peut alors appliquer l’approche dichotomique suivante :
calculer l’indice du milieu = d(n − 1)/2e et comparer v avec T[milieu].
s’il y a égalité, renvoyer milieu.
sinon si v < T[milieu] et milieu > 0, rechercher v dans le sous-tableau indicé de 0
à milieu-1. Sinon si v > T[milieu] et milieu < n-1, rechercher v dans le soustableau indicé de milieu+1 à n-1.
1.
2.
3.
4.
Ecrire cet algorithme en pseudo-code (sans utiliser la récursivité). Donner sa complexité.
Modifier cet algorithme pour qu’il renvoie le plus petit indice.
Modifier cet algorithme pour qu’il renvoie le plus grand indice.
Modifier cet algorithme pour qu’il renvoie le nombre d’indices i tels que T[i] soit égal
à v.
5. Programmer en python l’algorithme de la question 2.
6. Ecrire une version récursive de cette recherche dichotomique dans un tableau trié.
7. Générer aléatoirement dix tableaux de taille 1000 jusqu’à 1000000 par pas de 100000 et,
pour chaque taille de tableaux comparer les temps de calcul moyens de vos programmes
de recherche séquentielle d’une part, et de recherche dichotomique d’autre part. Que
constatez-vous ?
Algorithme de recherche
43
Algorithme en pseudo-code :
VARIABLE
T EST_DE_TYPE tableau de n NOMBRE
deb, fin, v EST_DE_TYPE NOMBRE
DEBUT_ALGO
deb=0
fin=n
TANT_QUE deb<fin FAIRE
m=floor((deb+fin)/2)
SI T[m]==v ALORS renvoyer m
SINON
DEBUT_SINON
SI v<T[m] ALORS fin=m
SINON deb=m+1
FIN_SINON
FIN_TANT_QUE
renvoyer -1
FIN_ALGO
Complexité : soit k le nombre d’itérations de la boucle tant que. Dans le pire de cas v
n’appartient pas au tableau et on va rechercher dans un tableau de taille n/2 jusqu’a ce qu’il ne
reste plus que 1 éléments :
(((n/2)/2)/2.... = 1
n/2k = 1
n = 2k
log2 n = k
import math
import random
import time
def recherche(T,v):
deb=0
fin=len(T)
while deb<fin:
if T[deb]==v:
return deb
deb+=1
return -1
def rechercheDichoIt(T,v):
deb=0
fin=len(T)
while deb<fin:
m=math.floor((fin+deb)/2)
if T[m]==v:
i=m
44
Algorithmes de recherche
while T[i-1]==v: i-=1
return i
else:
if v<T[m]: fin=m-1
else : deb=m+1
return -1
def rechercheDichoRec(T,deb,fin,v):
if deb==fin: return -1
else:
m=math.floor((fin+deb)/2)
if T[m]==v:
i=m
while T[i-1]==v: i-=1
return i
else:
if v<T[m]: return rechercheDichoRec(T,deb,m,v)
else : return rechercheDichoRec(T,m+1,fin,v)
Résultats :
>>> (executing lines 1 to 69 of "algoRecherche.py")
Taille = 1000 Seq = 0.05 DichIt = 0.01 DichRec = 0.01 Index = 0.01
Taille = 101000 Seq = 4.14 DichIt = 0.06 DichRec = 0.06 Index = 0.57
Taille = 201000 Seq = 8.49 DichIt = 0.13 DichRec = 0.12 Index = 1.19
Taille = 301000 Seq = 16.00 DichIt = 0.20 DichRec = 0.19 Index = 2.18
Taille = 401000 Seq = 23.99 DichIt = 0.27 DichRec = 0.26 Index = 3.24
Taille = 501000 Seq = 31.71 DichIt = 0.27 DichRec = 0.28 Index = 4.35
Taille = 601000 Seq = 20.12 DichIt = 0.44 DichRec = 0.43 Index = 3.01
Taille = 701000 Seq = 31.35 DichIt = 0.45 DichRec = 0.45 Index = 4.28
Taille = 801000 Seq = 40.95 DichIt = 0.48 DichRec = 0.48 Index = 5.64
Taille = 901000 Seq = 62.57 DichIt = 0.53 DichRec = 0.57 Index = 8.54
Taille = 1001000 Seq = 77.49 DichIt = 0.75 DichRec = 0.75 Index = 10.39
Représentation des nombres
45
CPES 1re année
2016-2017
PSL
Informatique
Représentation des nombres
Exercices préparées par V. Gabrel, E. Lazard, M. Manouvrier et C. Murat 8
Exercice 1
1. Quelle est l’écriture décimale du nombre qui s’écrit 11001 en binaire ? Quelle est l’écriture binaire du nombre décimal 555 ?
2. Quelle est l’écriture décimale du nombre qui s’écrit 11001000 en binaire dans la représentation en complément à 2 ? Quelle est l’écriture binaire du nombre décimal -555 dans
la représentation en complément à 2 sur 12 bits ?
3. On considère les deux nombres binaires 11001000 et 01001000 écrits dans la représentation en complément à 2. Calculer (en binaire) la somme de ces deux nombres et vérifier
que le résultat binaire obtenu correspond à la somme des deux valeurs décimales correspondant aux deux nombres binaires.
Correction
1. 110112 = 2510 ; 55510 = 1000101011
2. 11001000 est négatif. Son complément à 2 vaut 00111000 soit 56. Donc 110010002 =
−5610 en représentation complément à 2. On sait que 55510 = 001000101011 (bien
prendre les 12 bits), donc on prend le complément à un qui vaut 110111010100 et on
ajoute 1 ce qui donne 1101110101012 = −55510
3. On a bien
1
+
1
11 1
0 1
0 0
0
0
0
01 1
0 1
1 0
0
0
0
0
0
0
0
0
0
Et on vérifier bien que −56 + 72 = 16
Exercice 2
1. Donner sur 8 bits les représentations complément à 2 des nombres décimaux 45, 73, 84,
–99, –102 et –118.
2. Effectuer la soustraction 122−43 dans la représentation en complément à 2 en n’utilisant
que l’addition.
8. Cours également dispensé en 1ère année de licence Mathématique-Informatique-Économie (MIE) à l’Université Paris-Dauphine
46
Représentation des nombres
Correction
S et V
45 0010 1101
73 0100 1001
1.
84 0101 0100
-99 1110 0011
-102 1110 0110
-118 1111 0110
Comp. à 1
0010 1101
01001 001
0101 0100
1001 1100
1001 1001
1000 1001
Comp. à 2
0010 1101
0100 1001
0101 0100
1001 1101
1001 1010
1000 1010
2. 122 − 43 = 122 + (−43)
122 :
−43 :
79 :
01111010
11010101
01001111
Exercice 3
Écrire un algorithme qui attend une valeur décimale (qu’on supposera positive ou nulle) et affiche son écriture binaire. Pour ce faire, on utilisera un algorithme itératif qui effectue en boucle
les divisions successives par 2 et construit une chaîne portant le résultat à afficher à la fin.
Implémenter votre algorithme en Python. Proposer également une version récursive de votre
algorithme.
Correction
Attention, il faut penser au cas particulier 0.
VARIABLES
N, TMP EST_DU_TYPE NOMBRE
S EST_DU_TYPE CHAINE_CARACTERES
DEBUT_ALGORITHME
ECRIRE "Valeur décimale ?"
LIRE N
SI (N == 0) ALORS
DEBUT_ALORS
S <- "0"
FIN_ALORS
SINON
DEBUT_SINON
S <- ""
TMP <- N
TANT_QUE (TMP>0) FAIRE
DEBUT_TANT_QUE
S <- TMP%2 + S
TMP <- TMP//2
FIN_TANT_QUE
FIN_SINON
ECRIRE N, " s’écrit ", S, " en binaire"
Représentation des nombres
47
FIN_ALGORITHME
La version itérative :
TMP = N = int(input("Entrez une valeur decimale : "))
if N == 0:
s = "0"
else:
s = ""
while (TMP>0) :
s = str(TMP%2) + s
TMP //= 2
print(N, "s’ecrit", s, "en binaire.")
Et la version récursive :
def f(N):
if (N==0):
print("0")
elif (N==1):
print("1", end="")
else:
f(N//2)
print(N%2, end="")
N = int(input("Entrez une valeur decimale : "))
f(N)
Exercice 4
Écrire un algorithme qui attend une chaîne uniquement composée de symboles binaires (c’està-dire de ’0’ et de ’1’) et affiche la valeur décimale correspondante en supposant que la chaîne
représente un nombre positif ou nul.
Correction
VARIABLES
N EST_DU_TYPE NOMBRE
S EST_DU_TYPE CHAINE_CARACTERES
DEBUT_ALGORITHME
ECRIRE "CHAINE BINAIRE ?"
LIRE S
N <- 0
POUR i ALLANT_DE 0 A LONGUEUR(S)-1
DEBUT_POUR
N <- N*2
SI (S[i] == "1") FAIRE
48
Représentation des nombres
DEBUT_ALORS
N <- N + 1
FIN_ALORS
FIN_POUR
ECRIRE "Valeur décimale : ", N
FIN_ALGORITHME
Traduire votre algorithme en Python.
Correction
s = input("Chaine binaire ?")
N = 0
for bit in s:
N *= 2
if bit == "1":
N += 1
print ("Valeur decimale : ", N)
Exercice 5
On considère la suite numérique :
9
3
3
Un+1 = − Un2 + Un −
8
4
8
1. Montrer que si U0 = 3 ou si U0 = 13 , la suite est constante.
2. Ecrire une fonction en Python qui prend U0 en argument, et qui calcule et affiche les 70
premiers termes de la suite.
3. Appeler cette fonction avec comme argument 3, puis comme argument 1/3 ; comment
interprétez-vous les résultats ?
Correction
1. On calcule simplement U1 et, dans les deux cas, on aboutit à U1 = U0 . La suite est donc
constante.
2. def itere(U0):
u = U0
for i in range(70):
print("U", i, " = ", u, sep="")
u = -3.0*u*u/8.0 + 9.0*u/4.0 - 3.0/8.0
print("Calcul pour U0 = 3")
itere(3.0)
print("\nEt pour U0 = 1/3")
itere(1.0/3.0)
Le comportement est sans surprise pour U0 = 3, on obtient bien la valeur 3 pour les 70
premières itérations. En revanche, lorsque U0 = 13 , les premières valeurs tournent autour
de 1/3 puis s’en éloignent et la valeur calculée finit par converger vers 3.
Représentation des nombres
49
3. La suite est de la forme Un+1 = f (Un ) et, si elle converge, c’est vers un point fixe
de f , c’est-à-dire une solution de l’équation f (X) = X. En résolvant cette équation du
second degré, on trouve que f admet deux points fixes, 3 et 1/3. Le point fixe 3 est stable
(la dérivée de f en 3 vaut 0), ce qui implique que le calcul est numériquement stable :
si on itère f à partir d’une valeur proche de 3, les valeurs successivement obtenues se
rapprochent du point fixe 3 ; c’est bien ce que l’on obtient avec le programme précédent.
En revanche, le point fixe 1/3 est instable (la dérivée de f en 1/3 vaut 2). En d’autres
termes, des itérations commencées à une valeur proche de 1/3 s’en éloignent. Dans le
programme précédent, on démarre les itérations avec la valeur 1/3 ; on devrait donc rester
sur le point fixe, mais 1/3 n’est pas exactement représentable en puissances négatives de
2. Par conséquent, le programme débute le calcul avec une valeur binaire très proche de
1/3 mais pas parfaitement égale à 1/3. Cela suffit pour faire diverger le calcul vers l’autre
point fixe, 3.
Exercice 6
On considère la fonction
f (n) =
1
1+ 2
n
n2
On peut écrire :
n2
n2 !!
1
1
lim 1 + 2
= lim exp ln
1+ 2
∞
∞
n
n
1
2
= lim exp n ln 1 + 2
∞
n
1
≈ lim exp(n2 × 2 )
∞
n
≈ exp(1) = e
Écrire une fonction Python qui calcule la valeur de f (n) pour un n donné en paramètre. (On
rappelle que ** est l’opérateur puissance.)
Écrire une boucle qui calcule et affiche f (n) pour n allant de 1 à 100 millions par pas de
200 000. Qu’observe-t-on ?
Correction
def f(n):
return (1+1/(n*n))**(n*n)
for i in range(1,100000000, 200000):
print(f(i))
Le calcul converge tout de suite vers e mais se met ensuite à osciller autour de cette valeur,
avec une amplitude de plus en plus grande. Les valeurs croissent ensuite pour arriver un peu
au-dessus de 7.35, puis le calcul donne systématiquement 1.0.
Le souci intervient lorsque n est trop grand et que le calcul flottant de 1/n2 provoque des
erreurs d’arrondi qui finissent par s’accumuler. La valeur finale s’explique par le fait que la mise
à la puissance finale finit par dépasser la précision de la représentation.
50
Représentation des nombres
Exercice 7
Les calculs sur des nombres entiers s’effectuent exactement (la taille de représentation n’est pas
limitée) alors que les calculs sur des nombres réels sont approchés (un nombre réel se représente
sur huit octets).
En effectuant une boucle, écrire un programme Python qui compare la valeur exacte de 3i
et la partie entière de 3.0i et indique à quel exposant elles diffèrent.
Correction
i=1
while 3**i == int(3.0**i):
i+=1
print("Les deux valeurs diffèrent pour l’exposant", i,
":", 3**i, "et", int(3.0**i))
Fichiers
51
CPES 1re année
2016-2017
PSL
Informatique
Lire et écrire dans des fichiers
Exercices préparées par V. Gabrel, E. Lazard, M. Manouvrier et C. Murat 9
Un fichier est une suite d’informations enregistrée de manière permanente sur le disque. Il
peut contenir le code d’un programme (c’est-à-dire la suite d’instructions machine le composant) ; on parle alors de fichier exécutable. Il peut aussi contenir des données qui vont être lues
par un programme.
Il existe beaucoup de formats de fichiers différents. Dans un fichier de format texte, toutes les
informations sont écrites sous la forme de caractères imprimables (c’est-à-dire lettres, chiffres,
symboles de ponctuation...) séparés par des espaces, des tabulations et des caractères de fin de
ligne. L’avantage de ces fichiers est qu’il est possible de les ouvrir dans n’importe quel logiciel
(par exemple un éditeur de texte) : comme tous ces caractères sont imprimables, le texte du
fichier est directement lisible à l’écran.
Attention à ne pas confondre le format du fichier et l’utilisation qu’un logiciel en fait. Ainsi,
un logiciel de traitement de texte, comme Microsoft Word, va afficher le contenu d’un de ses fichiers comme du texte à l’écran mais le fichier lui-même n’est pas au format texte. Il contient en
fait de nombreuses informations supplémentaires utilisées par le logiciel : polices de caractères
utilisées, taille, largeur de page, illustrations... Il n’est donc pas possible d’afficher directement
le contenu brut du fichier à l’écran.
Un fichier permet de garder des informations et données de manière permanente sur le
disque. Un programme Python doit donc être capable d’y écrire des données, de les modifier et
de les relire plus tard.
L’utilisation d’un fichier se fait toujours de la même manière :
1. il faut tout d’abord « ouvrir » le fichier, c’est-à-dire le désigner par son nom afin que le
système nous permette d’y avoir accès ;
2. on peut ensuite lire ou écrire dans le fichier ; éventuellement s’y déplacer pour récupérer
une information particulière ;
3. enfin le fichier doit être « fermé », signalant ainsi au système que l’on a fini de l’utiliser
et qu’il peut valider et reporter les éventuelles données modifiées sur le disque.
Un fichier peut se trouver sur n’importe quel support de mémorisation : disque dur, clé
USB, CD/DVD... On pourra toujours considérer le contenu d’un fichier comme une suite de
caractères, ce qui signifie que vous pouvez traiter ce contenu, ou une partie quelconque de
celui-ci, à l’aide des fonctions servant à traiter les chaînes de caractères.
Où sont mes fichiers ?
Il existe deux moyens de désigner un fichier par son nom : indiquer son « nom absolu »
(c’est-à-dire la suite des répertoires formant le chemin depuis la racine de l’arborescence des
fichiers jusqu’au fichier lui-même) ou son « chemin relatif » depuis le répertoire courant.
9. Cours également dispensé en 1ère année de licence Mathématique-Informatique-Économie (MIE) à l’Université Paris-Dauphine
52
Fichiers
Lors du lancement de l’interpréteur, le répertoire courant est normalement initialisé à la
racine du dossier personnel de l’utilisateur. Cela signifie que tout fichier uniquement désigné par
son nom sera créé ou ouvert dans ce répertoire. Si l’on souhaite regrouper ses fichiers Python
dans un sous-dossier, il est plus simple de désigner ce sous-dossier comme le répertoire courant.
On peut le faire une bonne fois pour toute dans l’interpréteur de commandes à l’aide de la
fonction chdir() (signifiant CHange DIRectory) du module os :
>>> from os import chdir
>>> chdir("nomNouveauRépertoireCourant")
On peut indiquer le nouveau répertoire courant soit par son chemin absolu, soit par son
chemin relatif à partir du répertoire courant précédent. Notons que la fonction getcwd()
(GET Current Working Directory) du module os permet de connaître le répertoire courant.
Une fois cette commande chdir() exécutée dans l’interpréteur, le répertoire courant est
positionné à sa nouvelle valeur pour tous les prochains fichiers que l’on serait amené à exécuter. Il sera alors très facile de ne plus s’en occuper et, dans le code, de désigner les fichiers
simplement par leur nom.
Écriture dans un fichier
Sous Python, l’accès aux fichiers est assuré par l’intermédiaire d’un objet-fichier que l’on
crée à l’aide de la fonction open(). Après avoir appelé cette fonction, on peut lire et écrire
dans le fichier en utilisant les fonctions spécifiques de cet objet-fichier.
L’exemple ci-dessous montre comment ouvrir un fichier « en écriture », y enregistrer deux
chaînes de caractères, puis le refermer. Notons bien que si le fichier n’existe pas encore, il sera
créé automatiquement. Par contre, si le nom utilisé concerne un fichier préexistant qui contient
déjà des données, les caractères qui y seront enregistrés viendront s’ajouter à la suite de ceux
qui s’y trouvent déjà.
>>>
>>>
>>>
>>>
f = open("test.txt", "a")
f.write("Bonjour\n")
f.write("Ceci est un test d’ecriture")
f.close()
— La première ligne crée l’objet-fichier f, lequel fait référence à un fichier véritable (sur
le disque) dont le nom est "test.txt".
La fonction open() attend deux arguments, qui doivent être des chaînes de caractères.
Le premier argument est le nom du fichier à ouvrir, et le second est le mode d’ouverture.
Ici, "a" indique qu’il faut ouvrir ce fichier en mode « ajout » (append), ce qui signifie
que les données à enregistrer seront ajoutées à la fin du fichier, à la suite de celles qui
s’y trouvent déjà.
Nous aurions pu utiliser aussi le mode "w" (pour write) ; Python crée alors toujours
un nouveau fichier (vide) et l’écriture des données commence à partir du début de ce
nouveau fichier ; s’il existe déjà un fichier de même nom, celui-ci est préalablement
effacé.
— La fonction write() réalise l’écriture proprement dite. Les données à écrire doivent
être fournies en argument. Ces données sont enregistrées dans le fichier les unes à la suite
des autres (c’est la raison pour laquelle on parle de fichier à accès séquentiel). Chaque
nouvel appel à write() continue l’écriture à la suite de ce qui est déjà enregistré.
Fichiers
53
— La fonction close() referme le fichier. Celui-ci est désormais disponible pour tout
usage.
Lecture depuis un fichier
Nous pouvons maintenant ouvrir de nouveau le fichier, mais cette fois « en lecture », de
manière à pouvoir y relire les informations qui ont été enregistrées dans l’étape précédente :
>>> inF = open("test.txt", "r")
>>> s = inF.read()
>>> print(s)
Bonjour
Ceci est un test d’ecriture
>>> inF.close()
La fonction read() lit les données présentes dans le fichier et les transfère dans une variable de type « chaîne » (string). Si on utilise cette fonction sans argument, la totalité du fichier
est transférée.
— Le fichier que nous voulons lire s’appelle "test.txt". L’instruction d’ouverture de
fichier devra donc nécessairement faire référence à ce nom-là. Si le fichier n’existe pas,
nous obtiendrons un message d’erreur.
Par contre, nous ne sommes tenus à aucune obligation concernant le nom à choisir pour
l’objet-fichier. C’est un nom de variable quelconque. Ainsi, dans notre première instruction, nous avons choisi de créer un objet-fichier inF, faisant référence au fichier réel
"test.txt", lequel est ouvert en lecture (argument "r").
— read() lit l’intégralité du fichier et renvoie le résultat comme une chaîne. Ici, même si
l’écriture s’est faite par deux write() successifs, l’ensemble du fichier, donc les deux
chaînes (avec le \n intermédiaire), est récupéré par le read().
— La fonction read() peut également être utilisée avec un argument. Celui-ci indiquera
combien de caractères doivent être lus, à partir de la position déjà atteinte dans le fichier :
>>> inF = open(’test.txt’, ’r’)
>>> s = inF.read(7)
>>> print(s)
Bonjour
>>> s = inF.read(15)
>>> print(s)
Ceci est un te
S’il ne reste pas assez de caractères au fichier pour satisfaire la demande, la lecture
s’arrête tout simplement à la fin du fichier :
>>> s = inF.read(100)
>>> print(s)
st d’ecriture
Si la fin du fichier est déjà atteinte, read() renvoie une chaîne vide :
54
Fichiers
>>> s = inF.read(100)
>>> print(s)
>>> inF.close()
Travailler ligne par ligne avec les fichiers textes
Un fichier texte est un fichier qui contient des caractères imprimables et des espaces organisés en lignes successives, ces lignes étant séparées les unes des autres par un caractère spécial
appelé « marqueur de fin de ligne » 10 .
Il est très facile de traiter ce genre de fichiers sous Python. Les instructions suivantes créent
un fichier texte de quatre lignes :
>>>
>>>
>>>
>>>
f = open("fichierTexte.txt", "w")
f.write("Ceci est la ligne un\nVoici la ligne deux\n")
f.write("Voici la ligne trois\nVoici la ligne quatre\n")
f.close()
Notons le marqueur de fin de ligne ’\n’ inséré dans les chaînes de caractères, aux endroits
où l’on souhaite séparer les lignes de texte dans l’enregistrement. Sans ce marqueur, les caractères seraient enregistrés les uns à la suite des autres.
Lors des opérations de lecture, les lignes d’un fichier texte peuvent être extraites séparément
les unes des autres. La fonction readline(), par exemple, ne lit qu’une seule ligne à la fois
(en incluant le caractère de fin de ligne) :
>>> f = open("fichierTexte.txt","r")
>>> t = f.readline()
>>> print(t)
Ceci est la ligne un
>>> print(f.readline())
Voici la ligne deux
La fonction readlines() transfère toutes les lignes restantes dans une liste de chaînes :
>>> t = f.readlines()
>>> print(t)
[’Voici la ligne trois\n’, ’Voici la ligne quatre\n’]
>>> f.close()
— On peut bien évidemment parcourir la liste (à l’aide d’une boucle while/for par
exemple) pour en extraire les chaînes individuelles.
— La fonction readlines() permet de lire l’intégralité d’un fichier en une instruction
seulement. Cela n’est possible toutefois que si le fichier à lire n’est pas trop gros (puisqu’il est copié intégralement dans une variable, c’est-à-dire dans la mémoire vive de
l’ordinateur, il faut que la taille de celle-ci soit suffisante).
— Notons que readline() est une fonction qui renvoie une chaîne de caractères, alors
que la fonction readlines() renvoie une liste. À la fin du fichier, readline()
renvoie une chaîne vide, tandis que readlines() renvoie une liste vide.
10. Suivant le système d’exploitation utilisé, le codage correspondant au marqueur de fin de ligne peut être
différent. Il n’y a pas à se préoccuper de ces différences : lors des opérations d’écriture, Python utilise la convention
en vigueur sur le système d’exploitation ; pour la lecture, Python interprète correctement chacun des codages.
Fichiers
55
Se déplacer dans un fichier
Les opérations de lecture/écriture se font de manière séquentielle, le « curseur » se positionnant toujours à la fin des données lues ou écrites. Il est cependant possible de naviguer à
l’intérieur d’un fichier et de positionner le curseur à un endroit quelconque des données en spécifiant son décalage (en nombre de caractères) par rapport à l’origine du fichier à l’aide de la
fonction seek() :
>>> f = open("fichierTexte.txt", "r")
>>> f.seek(14)
# -> 14 caractères après le début
>>> print(f.readline()) # on lit le reste de la ligne
gne un
>>> f.seek(38)
# -> 38 caractères depuis le début
>>> print(f.readlines()) # et on lit le reste du fichier
[’ux\n’, ’Voici la ligne trois\n’, ’Voici la ligne quatre\n’]
Exercice 1
Écrire une fonction copieFichier(source, destination) qui recopie le contenu
d’un fichier texte nommé source dans un fichier nommé destination. Écrire cette fonction de deux manières différentes : soit en lisant le fichier source d’un bloc, soit ligne par ligne.
Correction
def copieFichier(source, destination):
inFile = open(source, "r")
total = inFile.read()
inFile.close()
outFile = open(destination, "w")
outFile.write(total)
outFile.close()
def copieFichier_2(source, destination):
inFile = open(source, "r")
outFile = open(destination, "w")
while 1:
line = inFile.readline()
if line == ’’:
break
outFile.write(line)
inFile.close()
outFile.close()
Exercice 2
Reprendre le programme précédent qui effectue la recopie ligne par ligne et le modifier pour
qu’il ne recopie que les lignes qui ne commencent pas par le caractère ’#’.
56
Fichiers
Correction
def copieFichier(source, destination):
inFile = open(source, "r")
outFile = open(destination, "w")
while 1:
line = inFile.readline()
if line == ’’:
break
if line[0] != ’#’:
outFile.write(line)
inFile.close()
outFile.close()
Exercice 3
Écrire un programme qui génère automatiquement un fichier texte contenant les tables de multiplication de 2 à 30 (chacune d’entre elles incluant 20 termes seulement).
Correction
f=open("table.txt", "w")
for i in range(2, 31):
for j in range (1, 21):
f.write(str(i*j)+’ ’)
f.write(’\n’)
f.close()
Exercice 4
Écrire un programme qui recopie un fichier texte en triplant tous les espaces entre les mots.
Correction
def espaces(source, destination):
inFile = open(source,"r")
outFile= open(destination, "w")
while 1:
line = inFile.readline()
if line == ’’:
break
outFile.write(line.replace(" ", "
inFile.close()
outFile.close()
"))
Fichiers
57
Exercice 5
Un fichier texte est mis à disposition dont chaque ligne est la représentation d’une valeur numérique de type réel (mais sans exposants). Par exemple :
14.896
7894.6
123.278
Écrire un programme qui recopie ces valeurs dans un autre fichier en les arrondissant au
nombre entier le plus proche (on pourra utiliser la fonction round()).
Correction
def nombresArrondis(source, destination):
inFile = open(source, "r")
outFile = open(destination, "w")
while 1:
line = inFile.readline()
if line == ’’:
break
outFile.write(str(round(float(line))) + ’\n’)
inFile.close()
outFile.close()
Exercice 6
Créer un fichier nommé "NotesGr1.txt" qui contiendra les notes d’algorithmique des étudiants du groupe 1 de première année. Le format est le suivant : chaque ligne correspond à un
étudiant ; elle commence par son nom, suivi d’une tabulation, puis son prénom, et une tabulation
précédera la note de l’étudiant (valeur décimale entre 0 et 20). Vous créerez quelques étudiants
dans ce fichier en ne respectant aucun ordre particulier, ni alphabétique ni en fonction de la
note.
1. Écrire une fonction lectureFichier(nom) qui ouvre le fichier texte dont le nom
est passé en argument et renvoie une liste composée de toutes les lignes du fichier.
2. Écrire une fonction ecritureFichier(nom, liste) qui ouvre le fichier dont le
nom est passé en argument et y écrit la liste de chaînes passée en paramètre, un élément
par ligne.
3. Écrire une fonction triFichier() qui lit le fichier nommé "NotesGr1.txt" et
crée un nouveau fichier "NotesGr1_trie.txt" qui contient les notes de tous les
étudiants suivant le même format mais trié par ordre alphabétique de nom. On pourra
bien sûr utiliser les deux fonctions précédemment définies.
4. Généraliser la fonction précédente en écrivant une fonction triNFichiers(N) qui lit
N fichiers "NotesGr1.txt" à "NotesGrN.txt" et écrit sur le disque un unique fichier "NotesAmphi_trie.txt" compilant toutes les notes et toujours trié par ordre
alphabétique de nom.
58
Fichiers
5. On souhaite maintenant effectuer le même travail mais en triant le fichier final suivant
un ordre croissant des notes. Proposer des modifications aux deux premières fonctions
pour ce faire. Les problèmes à résoudre sont : comment extraire la note de la ligne ?
comment composer la liste de tous les étudiants pour effectuer le tri ? comment réécrire
les informations dans le fichier final ?
Correction
def lectureFichier(nom):
f=open(nom, "r")
total = []
while 1:
l = f.readline()
if l == ’’:
break
total.append(l)
f.close()
return total
def ecritureFichier(nom, liste):
f=open(nom, "w")
for l in liste:
f.write(l)
f.close()
def triFichier():
total = lectureFichier("NotesGr1.txt")
total.sort()
ecritureFichier("NotesGr1_trie.txt", total)
def triNFichiers(N):
s = "NotesGr"
total = []
for i in range(1,N+1):
total += lectureFichier(s+str(i)+’.txt’)
total.sort()
ecritureFichier("NotesAmphi_trie.txt", total)
Il faut créer une nouvelle liste dans laquelle chaque élément a maintenant la note en premier,
ce qui va permettre d’effectuer le tri. Ensuite, la réécriture oblige de nouveau à remettre les
éléments dans le bon ordre.
def lectureFichier2(nom):
f=open(nom, "r")
total = []
while 1:
l = f.readline()
if l == ’’:
break
Fichiers
L = l.split(’\t’)
newLL = [float(L[2])] + [L[0]] + [L[1]]
total.append(newLL)
f.close()
return total
def ecritureFichier2(nom, liste):
f=open(nom, "w")
for l in liste:
f.write(l[1]+’\t’+l[2]+’\t’+str(l[0])+’\n’)
f.close()
def triNFichiers(N):
s = "NotesGr"
total = []
for i in range(1,N+1):
total += lectureFichier2(s+str(i)+’.txt’)
total.sort()
ecritureFichier2("NotesAmphi_trie.txt", total)
triNFichiers(2)
59
Téléchargement