Banque d’exercices
Cette page regroupe les exercices proposés au gré de la formation.
Certains des exercices sont des classiques revisités et d’autres sont librement inspirés d”ici et de là
Exercice 1 : double
Énoncé
Section Introduction aux fonctions
Écrire la fonction double(x)
qui renvoie le double de x
.
Vérifier les résultats de cette fonction avec assert
, par exemple:
assert double(21) == 42
assert double(0) == 0
assert double(-99) == -198
assert double(3150) == 6300
Voir ce qui se passe avec
assert double(5)==9
Solution
[5]:
def double(x):
return 2*x
[6]:
assert double(21) == 42
assert double(0) == 0
assert double(-99) == -198
assert double(3150) == 6300
[7]:
assert double(5)==9
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
Cell In[7], line 1
----> 1 assert double(5)==9
AssertionError:
Exercice 2 : conversion de température
Énoncé
Section Introduction aux fonctions
Écrire la fonction to_celsius(temp)
qui renvoie en °C la température temp
donnée en °F.
La formule est donnée par $ Celsius = :nbsphinx-math:frac{5}{9}`(Fahrenheit - 32) $ <https://fr.wikipedia.org/wiki/Degr%C3%A9_Fahrenheit>`__.
Écrire la fonction inverse to_farenheit(temp)
.
Vérifier les résultats :
assert to_celsius(32) == 0
assert to_farenheit(100) == 212
assert to_celsius(-40) == -40
assert to_farenheit(-40) == -40
assert to_celsius(to_farenheit(15.)) == 15.
Solution
[15]:
def to_celsius(temp):
return 5/9 * (temp-32)
def to_farenheit(temp):
return temp * 9/5 +32
[16]:
assert to_celsius(32) == 0
assert to_farenheit(100) == 212
assert to_celsius(-40) == -40
assert to_farenheit(-40) == -40
assert to_celsius(to_farenheit(15.)) == 15.
Exercice 3 : conversion de secondes
Énoncé
Section Introduction aux fonctions
Écrire une fonction h_m_s(seconds)
qui convertit un nombre total de secondes h_m_s(seconds)
en heures, minutes et secondes sous la forme d’une chaine de caractères. Les nombres seront des entiers, et les secondes restantes seront arrondies à l’entier inférieur.
Vérifier les résultats :
assert h_m_s(0) == '0h 0m 0s'
assert h_m_s(60) == '0h 1m 0s'
assert h_m_s(3600) == '1h 0m 0s'
assert h_m_s(5700) == '1h 35m 0s'
assert h_m_s(18453) == '5h 7m 33s'
assert h_m_s(60.12586) == '0h 1m 0s'
Étape 2
Section Structure de contrôle
Mettre à jour la fonction pour qu’elle n’affiche les heures et minutes que si nécessaire.
assert h_m_s(0) == '00s'
assert h_m_s(60) == '01m 00s'
assert h_m_s(3600) == '1h 00m 00s'
assert h_m_s(5700) == '1h 35m 00s'
assert h_m_s(18453) == '5h 07m 33s'
assert h_m_s(60.12586) == '01m 00s'
Étape 3
Section Utilisation avancée des chaines de caractères
Mettre à jour la fonction afin qu’elle affiche les minutes et les secondes sur 2 caractères.
assert h_m_s(0) == '00s'
assert h_m_s(60) == '01m 00s'
assert h_m_s(3600) == '1h 00m 00s'
assert h_m_s(5700) == '01h 35m 00s'
assert h_m_s(18453) == '05h 07m 33s'
assert h_m_s(60.12586) == '01m 00s'
Solution (étape 1)
[34]:
def h_m_s(seconds):
seconds = int(seconds)
hours = seconds//3600
seconds = seconds%3600
minutes = seconds//60
seconds = seconds%60
result = str(hours) + 'h ' + str(minutes) + 'm ' + str(seconds) + 's'
return result
[35]:
assert h_m_s(0) == '0h 0m 0s'
assert h_m_s(60) == '0h 1m 0s'
assert h_m_s(3600) == '1h 0m 0s'
assert h_m_s(5700) == '1h 35m 0s'
assert h_m_s(18453) == '5h 7m 33s'
assert h_m_s(60.12586) == '0h 1m 0s'
Solution (étape 2, avec if
)
[36]:
def h_m_s(seconds):
seconds = int(seconds)
hours = seconds//3600
seconds = seconds%3600
minutes = seconds//60
seconds = seconds%60
if hours > 0:
result = str(hours) + 'h ' + str(minutes) + 'm '
elif minutes > 0:
result = str(minutes) + 'm '
else:
result = ''
result = result + str(seconds) + 's'
return result
[37]:
assert h_m_s(0) == '0s'
assert h_m_s(60) == '1m 0s'
assert h_m_s(3600) == '1h 0m 0s'
assert h_m_s(5700) == '1h 35m 0s'
assert h_m_s(18453) == '5h 7m 33s'
assert h_m_s(60.12586) == '1m 0s'
Solution (étape 3, avec f-string
)
[38]:
def h_m_s(seconds):
seconds = int(seconds)
hours = seconds//3600
seconds = seconds%3600
minutes = seconds//60
seconds = seconds%60
if hours > 0:
hours = f'{hours}h '
else:
hours = ''
if minutes > 0 or hours:
minutes = f'{minutes:>02}m '
else:
minutes = ''
seconds = f'{seconds:>02}s'
return f'{hours}{minutes}{seconds}'
[39]:
assert h_m_s(0) == '00s'
assert h_m_s(60) == '01m 00s'
assert h_m_s(3600) == '1h 00m 00s'
assert h_m_s(5700) == '1h 35m 00s'
assert h_m_s(18453) == '5h 07m 33s'
assert h_m_s(60.12586) == '01m 00s'
Exercice 4 : liste de zéros
Énoncé
Section Les conteneurs de base
Créer une fonction make_zeros_list(nzeros)
qui renvoie une liste avec nzeros
0 sous la forme de flottants.
La fonction s’assurera que nzeros
est un entier positif mais traitera le cas nzeros=0
.
Vérifier les résultats :
assert make_zeros_list(5) == [0., 0., 0., 0., 0.]
assert make_zeros_list(1) == [0.]
assert make_zeros_list(0) == []
Solution
[1]:
def make_zeros_list(nzeros):
assert isinstance(nzeros, int)
assert nzeros >= 0
return [0.]*nzeros
[2]:
assert make_zeros_list(5) == [0., 0., 0., 0., 0.]
assert make_zeros_list(1) == [0.]
assert make_zeros_list(0) == []
Exercice 5 : compte occurences
Énoncé
Section Structure de contrôle
Ecrire une fonction compte_occurences(chaîne)
qui compte le nombre d’occurrences de chaque caractère dans la chaîne de caractères chaîne
. La fonction retournera un dict
où les clés seront les caractères rencontrés et les valeurs, le nombre d’occurences de chaque caractère.
Vérifier les résultats :
assert compte_occurences('python') == {'h': 1,'n': 1, 'o': 1, 'p': 1, 't': 1, 'y': 1}
assert compte_occurences('cool') == {'c': 1, 'l': 1, 'o': 2}
Étape 2
Section Utilisation avancée des conteneurs
Mettre à jour la fonction en utilisant une/des méthode(s) des dictionnaires.
Vérifier les résultats (identiques aux précédents)
Bonus
Section Qu’est-ce qu’un module ?
La librairie standard ne proposerait-elle pas déjà quelque chose? Au hasard, module collections?
Vérifier les résultats (identiques aux précédents)
Solution (étape 1)
[2]:
def compte_occurences(chaîne):
mon_dico = {}
for char in chaîne:
if char in mon_dico:
mon_dico[char] += 1
else:
mon_dico[char] = 1
return mon_dico
[3]:
assert compte_occurences('python') == {'h': 1,'n': 1, 'o': 1, 'p': 1, 't': 1, 'y': 1}
assert compte_occurences('cool') == {'c': 1, 'l': 1, 'o': 2}
Solution (étape 2, avec méthode)
[25]:
def compte_occurences(chaîne):
mon_dico = {}
for char in chaîne:
mon_dico[char] = mon_dico.get(char, 0) + 1
return mon_dico
def compte_occurences(chaîne):
# Variante
mon_dico = {}
for char in chaîne:
mon_dico.setdefault(char, 0)
mon_dico[char] += 1
return mon_dico
[26]:
assert compte_occurences('python') == {'h': 1,'n': 1, 'o': 1, 'p': 1, 't': 1, 'y': 1}
assert compte_occurences('cool') == {'c': 1, 'l': 1, 'o': 2}
Solution (bonus)
[68]:
from collections import Counter as compte_occurences
[69]:
assert compte_occurences('python') == {'h': 1,'n': 1, 'o': 1, 'p': 1, 't': 1, 'y': 1}
assert compte_occurences('cool') == {'c': 1, 'l': 1, 'o': 2}
Pourtant, ce que retourne la fonction n’est pas un dictionnaire?
[70]:
compte_occurences('python')
[70]:
Counter({'p': 1, 'y': 1, 't': 1, 'h': 1, 'o': 1, 'n': 1})
Mais, Python s’occupe de la conversion derrière le rideau lors du test de comparaison!
[71]:
dict(compte_occurences('python'))
[71]:
{'p': 1, 'y': 1, 't': 1, 'h': 1, 'o': 1, 'n': 1}
Exercice 6 : suite de Collatz
Énoncé
Section Structure de contrôle
Construire une fonction collatz(n)
qui, partant d’un nombre entier n
, construit la suite de Collatz qui est définie selon :
| u(n)/2 si u(n) est pair
u(n+1) = |
| 3u(n)+1 sinon
La fonction vérifiera que n
est un entier positif et retournera une liste avec les valeurs de la suite.
NB: arrêter la boucle de construction dès lors que u(n) = 1
(conjecture de Collatz)
Vérifier les résultats :
assert collatz(1) == [1]
assert collatz(10) == [10, 5, 16, 8, 4, 2, 1]
assert collatz(11) == [11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]
assert collatz(12) == [12, 6, 3, 10, 5, 16, 8, 4, 2, 1]
assert len(collatz(256)) == 9
assert len(collatz(257)) == 123
Bonus
Section Les générateurs
gen_collatz(n)
.Solution
[45]:
def collatz(n):
assert isinstance(n, int)
assert n > 0
sequence = [n]
while n != 1:
is_even = n%2==0
if is_even:
n //= 2
else:
n = 3*n+1
sequence.append(n)
return sequence
[46]:
assert collatz(1) == [1]
assert collatz(10) == [10, 5, 16, 8, 4, 2, 1]
assert collatz(11) == [11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]
assert collatz(12) == [12, 6, 3, 10, 5, 16, 8, 4, 2, 1]
assert len(collatz(256)) == 9
assert len(collatz(257)) == 123
Solution (bonus)
[2]:
def gen_collatz(n):
assert isinstance(n, int)
assert n > 0
yield n
while n != 1:
is_even = n%2==0
if is_even:
n //= 2
else:
n = 3*n+1
yield n
[4]:
assert list(gen_collatz(1)) == [1]
assert list(gen_collatz(10)) == [10, 5, 16, 8, 4, 2, 1]
assert list(gen_collatz(11)) == [11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]
assert list(gen_collatz(12)) == [12, 6, 3, 10, 5, 16, 8, 4, 2, 1]
assert len(list(gen_collatz(256))) == 9
assert len(list(gen_collatz(257))) == 123
assert max(gen_collatz(10)) == 16
assert max(gen_collatz(11)) == 52
assert max(gen_collatz(12)) == 16
Exercice 7 : statistiques d’un échantillon
Énoncé
Section Lire et écrire des fichiers
Créer une fonction get_stats(fname)
qui renvoie les minimum, maximum, moyenne et écart-type d’une liste de nombres lus dans un fichier de nom fname
.
Le résultat se fera sous la forme d’un dictionnaire de clés 'min'
, 'max'
, 'mean'
, 'std'
.
NB :
les fonctions
min
,max
,mean
,std
peuvent être importées depuis le module numpyon admettra que le fichier d’entrée n’a qu’une seule valeur par ligne, du type :
3548.279704
3589.7804263
3095.09156402
...
Vérifier les résultats :
assert get_stats('demo_stats.txt') # s'assure que la fonction ne retourne pas un dictionnaire vide
assert get_stats('demo_stats.txt')['min'] == 2561.50070722
assert get_stats('demo_stats.txt')['max'] == 3722.25284478
assert np.allclose(get_stats('demo_stats.txt')['mean'], 3150)
assert np.allclose(get_stats('demo_stats.txt')['std'], 314)
Solution
[54]:
import numpy as np
def get_stats(fname):
values = []
with open(fname) as rd:
for line in rd:
values.append(float(line.strip()))
return dict(
min=np.min(values),
max=np.max(values),
mean=np.mean(values),
std=np.std(values)
)
[66]:
assert get_stats('demo_stats.txt') # s'assure que la fonction ne retourne pas un dictionnaire vide
assert get_stats('demo_stats.txt')['min'] == 2561.50070722
assert get_stats('demo_stats.txt')['max'] == 3722.25284478
assert np.allclose(get_stats('demo_stats.txt')['mean'], 3150)
assert np.allclose(get_stats('demo_stats.txt')['std'], 314)
Bonus
Ne pas réinventer la roue, des librairies font très bien le travail!
[67]:
import pandas as pd
values = pd.read_csv('demo_stats.txt', names=['Sample'])
values.describe()
[67]:
Sample | |
---|---|
count | 50.000000 |
mean | 3150.000000 |
std | 317.187899 |
min | 2561.500707 |
25% | 2950.424439 |
50% | 3160.149710 |
75% | 3414.406663 |
max | 3722.252845 |
Exercice 8 : filtrage de liste
Énoncé
Section Listes en intension
Créer une fonction keep_positive(values)
qui recoit une liste de valeurs et renvoie une liste similaire mais avec seulement les valeurs positives.
Vérifier les résultats :
assert keep_positive([4, 5, 2, 9]) == [4, 5, 2, 9]
assert keep_positive([1, -2, 3, -4]) == [1, 3]
assert keep_positive([-1, -2]) == []
Solution
[8]:
keep_positive = lambda values: [v for v in values if v>=0]
[9]:
assert keep_positive([4, 5, 2, 9]) == [4, 5, 2, 9]
assert keep_positive([1, -2, 3, -4]) == [1, 3]
assert keep_positive([-1, -2]) == []
Exercice 9 : matrice de zéros
Enoncé
Section Noms et objets non immuables
make_zeros_matrix(nrows, ncols)
qui produit une liste de nrows
listes, chacune remplie de ncols
zéros.Une idée pourrait être la suivante:
# It's a trap !
def make_zeros_matrix(nrows, ncols):
return [[0] * ncols] * nrows
Mais il s’avère que la matrice produite a un problème… lequel ?
Vérifier les résultats :
assert make_zeros_matrix(1, 1) == [[0]]
assert make_zeros_matrix(4, 0) == [[], [], [], []]
assert make_zeros_matrix(0, 4) == []
assert make_zeros_matrix(3, 2) == [[0, 0],
[0, 0],
[0, 0]]
mat = make_zeros_matrix(2, 3)
assert mat == [[0, 0, 0],
[0, 0, 0]]
mat[0][0] = 1
assert mat == [[1, 0, 0],
[0, 0, 0]]
Solution
[20]:
def make_zeros_matrix(nrows, ncols):
matrix = []
for _ in range(nrows):
matrix.append([0] * ncols)
return matrix
[21]:
assert make_zeros_matrix(1, 1) == [[0]]
assert make_zeros_matrix(4, 0) == [[], [], [], []]
assert make_zeros_matrix(0, 4) == []
assert make_zeros_matrix(3, 2) == [[0, 0],
[0, 0],
[0, 0]]
mat = make_zeros_matrix(2, 3)
assert mat == [[0, 0, 0],
[0, 0, 0]]
mat[0][0] = 1
assert mat == [[1, 0, 0],
[0, 0, 0]]
Quel est le problème avec la suggestion de l’énoncé ?
La structure imbriquée construite contient en fait UNE SEULE LISTE POUR TOUTES LES LIGNES !!!
Modifier une ligne va modifier cette liste, et donc modifier toutes les lignes…
[2]:
def wrong_make_zeros_matrix(nrows, ncols):
return [[0] * ncols] * nrows
wrong_mat = wrong_make_zeros_matrix(2, 3)
wrong_mat[0][0] = 1
assert wrong_mat == [[1, 0, 0],
[1, 0, 0]] # <- cette ligne ne devrait pas être modifiée !
La preuve en images ci-dessous
[1]:
from IPython.display import IFrame
IFrame("https://pythontutor.com/iframe-embed.html#code=def%20wrong_make_zeros_matrix%28nrows,%20ncols%29%3A%0A%20%20%20%20return%20%5B%5B0%5D%20*%20ncols%5D%20*%20nrows%0A%0Awrong_mat%20%3D%20wrong_make_zeros_matrix%282,%203%29%0Awrong_mat%5B0%5D%5B0%5D%20%3D%201&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false",
width='100%', height=300)
[1]: