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,stdpeuvent ê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]: