Séance 1 — Héron d'Alexandrie
Décomposition fonctionnelle et tests unitaires (assert)
- Choisir une première valeur d'essai.
- Améliorer l'essai : il devient la moyenne entre l'essai précédent et x / essai.
- Vérifier si l'approximation est suffisamment précise.
- Recommencer tant que ce n'est pas le cas.
Q1 moyenne
Écrire une fonction moyenne(a, b) qui calcule la moyenne de deux nombres.
Voir la réponse
def moyenne(a: float, b: float) -> float:
"""Calcule et retourne la moyenne des deux nombres a et b."""
return (a + b) / 2
assert moyenne(12, 16) == 14
assert moyenne(0, 8) == 4
Q2 valeur_absolue
Écrire une fonction valeur_absolue(x) qui retourne |x| sans utiliser abs.
Voir la réponse
def valeur_absolue(x: float) -> float:
"""Calcule et retourne la valeur absolue du nombre x."""
if x >= 0:
return x
else:
return -x
assert valeur_absolue(3) == 3
assert valeur_absolue(-3) == 3
Q3 puissance
Écrire une fonction puissance(x, n) qui calcule x^n sans utiliser ** ni pow.
assert puissance(2, 8) == 256
Voir la réponse
def puissance(x: float, n: int) -> float:
"""Calcule et retourne x^n = x . x . ... . x (n fois)."""
res = 1
for _ in range(1, n + 1):
res *= x
return res
assert puissance(2, 8) == 256
assert puissance(0, 2) == 0
assert puissance(3, 0) == 1
Q4 amelioration_essai
Améliorer un essai : moyenne entre essai et x/essai.
Voir la réponse
def amelioration_essai(essai: float, x: float) -> float:
"""Moyenne entre essai (strictement positif) et x/essai."""
return moyenne(essai, x / essai)
assert amelioration_essai(1, 2) == 1.5
assert amelioration_essai(2, 1) == 1.25
Q5 est_suffisamment_bon
Un essai est « suffisamment bon » si |essai² − x| < 0.001.
Voir la réponse
def est_suffisamment_bon(essai: float, x: float) -> bool:
"""Retourne True si |essai^2 - x| < 0.001."""
tolerance = 0.001
return valeur_absolue(puissance(essai, 2) - x) < tolerance
assert est_suffisamment_bon(1.9, 4) == False
assert est_suffisamment_bon(1.9999, 4) == True
Q6 test — algorithme complet
Assembler les briques précédentes dans une boucle while.
Voir la réponse
def test(essai: float, x: float) -> float:
"""Retourne la racine carrée de x en partant d'une valeur d'essai."""
while not est_suffisamment_bon(essai, x):
essai = amelioration_essai(essai, x)
return essai
assert test(2, 4) == 2
assert test(1, 4) == 2.0000000929222947
not mal placé, ou une fonction d'amélioration qui ne fait plus varier l'essai (boucle infinie).Q7 racine_carree
Simplifier l'appel précédent avec un essai de départ toujours égal à 1.
Voir la réponse
def racine_carree(x: float) -> float:
"""Retourne la racine carrée de x (essai initial = 1)."""
return test(1, x)
assert racine_carree(4) == 2.0000000929222947
assert racine_carree(9) == 3.00009155413138
Q8 main — liste en compréhension
Afficher la liste des racines carrées de tous les nombres pairs entre 1 et 100.
Voir la réponse
def main():
return [racine_carree(i) for i in range(1, 101) if i % 2 == 0]
print(main())
🎯 Défis bonus
Pour les élèves qui terminent en avance.
Bonus 1 — Tolérance paramétrable
Faire en sorte que le seuil de précision (0.001) soit passé en argument.
Voir la réponse
def racine_carree_tolerance(x: float, tolerance: float) -> float:
essai = 1
while valeur_absolue(puissance(essai, 2) - x) >= tolerance:
essai = amelioration_essai(essai, x)
return essai
Bonus 2 — Racine cubique
Généraliser la méthode (Newton) : essai ← (2×essai + x/essai²) / 3.
Voir la réponse
def racine_cubique(x: float) -> float:
essai = 1
tolerance = 0.001
while valeur_absolue(puissance(essai, 3) - x) >= tolerance:
essai = (2 * essai + x / puissance(essai, 2)) / 3
return essai
Séance 2 — Structures de boucle
Révisions : for, while, boucles imbriquées
Bloc A — Boucles simples et accumulateur
Ex 1 multiplication
Retourne les 10 premiers termes de la table de a.
multiplication(7) → '7 14 21 28 35 42 49 56 63 70 '
Voir la réponse
def multiplication(a: int) -> str:
chaine_retour = ""
nbre_tours_boucle = 10
i = 1
while i <= nbre_tours_boucle:
chaine_retour += str(a * i) + " "
i += 1
return chaine_retour
Ex 2 multiplication_multiple_trois
Idem, en signalant les multiples de 3 par un astérisque.
Voir la réponse
def multiplication_multiple_trois(a: int) -> str:
chaine_retour = ""
for i in range(1, 11):
resultat = a * i
chaine_retour += str(resultat)
if resultat % 3 == 0:
chaine_retour += "*"
chaine_retour += " "
return chaine_retour
Ex 3 multiplication_multiple_sept
50 premiers termes de la table de a, on ne garde que les multiples de 7.
Voir la réponse
def multiplication_multiple_sept(a: int) -> str:
chaine_retour = ""
for i in range(1, 51):
resultat = a * i
if resultat % 7 == 0:
chaine_retour += str(resultat) + " "
return chaine_retour
Ex 4 diviseurs
Liste des diviseurs de a, du plus grand au plus petit.
diviseurs(18) → '18 9 6 3 2 1 '
Voir la réponse
def diviseurs(a: int) -> str:
chaine_retour = ""
for i in range(a, 0, -1):
if a % i == 0:
chaine_retour += str(i) + " "
return chaine_retour
Bloc B — Boucles imbriquées
Ex 5 table_multiplication
Table de multiplication de 1 à 10, une ligne par table (séparateur \n). Deux boucles imbriquées.
Voir la réponse
def table_multiplication() -> str:
chaine_retour = ""
for i in range(1, 11):
for j in range(1, 11):
chaine_retour += str(i * j) + " "
chaine_retour += "\n"
return chaine_retour
# print(table_multiplication())
Ex 13 alphabet
Alphabet à l'endroit ("croissant") ou à l'envers, via ord/chr (codes ASCII [97 ; 122]).
Voir la réponse
def alphabet(sens: str) -> str:
if sens == "croissant":
debut, fin, inc, pas = 97, 122, 1, 1
else:
debut, fin, inc, pas = 122, 97, -1, -1
rep = ""
for i in range(debut, fin + inc, pas):
rep += chr(i)
return rep
Ex 14 fibo
n premiers termes de la suite de Fibonacci (u1=1, u2=1, un=u(n-1)+u(n-2)).
Voir la réponse
def fibo(n: int) -> str:
rep = "0 1 "
u, v = 0, 1
for i in range(2, n):
z = u + v
rep += str(z) + " "
u, v = v, z
return rep
Bloc C — Boucles et saisie utilisateur
Ex 6-7 plus_grand_plus_petit
Demander 10 valeurs (puis un nombre passé en argument) et retourner min et max.
Voir la réponse
def plus_grand_plus_petit(nbre_tours: int) -> str:
valeur_max = float('-inf')
valeur_min = float('inf')
for i in range(1, nbre_tours + 1):
valeur = float(input(f"Entrez la valeur {i} : "))
if valeur > valeur_max: valeur_max = valeur
if valeur < valeur_min: valeur_min = valeur
return f"Min : {valeur_min}, Max : {valeur_max}"
Ex 8-9 moyenne
Demander des notes (10, puis un nombre passé en argument) et retourner la moyenne.
Voir la réponse
def moyenne(nbre_notes: int) -> float:
total_notes = 0
for i in range(nbre_notes):
note = float(input(f"Entrez la note {i + 1} : "))
total_notes += note
return total_notes / nbre_notes
Ex 10 moyenne_auto
Sans nombre de notes fixé : une note négative arrête la saisie (valeur sentinelle).
Voir la réponse
def moyenne_auto() -> tuple[int, float]:
nbre_notes = 0
total_notes = 0
stop = False
while not stop:
note = float(input(f"Entrez la note {nbre_notes + 1} : "))
if note < 0:
stop = True
else:
total_notes += note
nbre_notes += 1
return (nbre_notes, total_notes / nbre_notes)
Bloc D — Boucles et hasard (module random)
Ex 11 loto_naif
6 entiers aléatoires entre 1 et 49 (répétitions possibles à ce stade).
Voir la réponse
from random import randint
def loto_naif() -> str:
rep = ""
for i in range(6):
rep += str(randint(1, 49)) + " "
return rep
Ex 12 devine
Jeu du nombre mystère entre 1 et 50, avec indices "trop grand"/"trop petit".
Voir la réponse
def devine() -> None:
nbre_a_deviner = randint(1, 50)
nbre_tentatives = 0
trouve = False
while not trouve:
proposition = int(input("Entrez votre proposition : "))
nbre_tentatives += 1
if proposition == nbre_a_deviner:
trouve = True
elif proposition > nbre_a_deviner:
print("Trop grand !")
else:
print("Trop petit !")
print(f"Nombre de tentatives : {nbre_tentatives}")
🎯 Défis bonus
Pour les élèves qui terminent en avance.
Bonus 1 — Pierre-feuille-ciseaux
Jeu contre l'ordinateur (random.choice), boucle tant que le joueur veut continuer.
Voir la réponse
from random import choice
def pierre_feuille_ciseaux() -> None:
choix = ["pierre", "feuille", "ciseaux"]
v = d = e = 0
continuer = True
while continuer:
joueur = input("pierre, feuille ou ciseaux ? ")
ordi = choice(choix)
if joueur == ordi:
e += 1
elif (joueur, ordi) in [("pierre","ciseaux"),("feuille","pierre"),("ciseaux","feuille")]:
v += 1
else:
d += 1
continuer = (input("Encore ? (o/n) ") == "o")
print(f"V:{v} D:{d} E:{e}")
Bonus 2 — Nombres premiers
Liste des nombres premiers inférieurs à n (boucles imbriquées).
Voir la réponse
def nombres_premiers(n: int) -> str:
rep = ""
for candidat in range(2, n):
est_premier = True
for diviseur in range(2, candidat):
if candidat % diviseur == 0:
est_premier = False
if est_premier:
rep += str(candidat) + " "
return rep
Séance 3 — Structure de liste
Révisions : parcours, construction et manipulation de listes
Ex 1 minmax
Retourne un tuple (min, max) d'une liste de nombres.
Voir la réponse
def minmax(liste: list[float]) -> tuple[float, float]:
val_min = liste[0]
val_max = liste[0]
for i in range(1, len(liste)):
if liste[i] > val_max: val_max = liste[i]
if liste[i] < val_min: val_min = liste[i]
return val_min, val_max
Ex 2 longueur
Nombre d'éléments d'une liste, sans utiliser len().
Voir la réponse
def longueur(liste: list) -> int:
longueur = 0
for element in liste:
longueur += 1
return longueur
Ex 3 loto
6 entiers distincts tirés entre 1 et 49 (utiliser l'opérateur in pour éviter les doublons).
Voir la réponse
from random import randint
def loto() -> list[int]:
tirages = []
while len(tirages) < 6:
tirage = randint(1, 49)
if tirage not in tirages:
tirages.append(tirage)
return tirages
Ex 4 statistiques
Moyenne d'une liste de notes + % de notes dans [0, moy-3[, [moy-3, moy+3[, [moy+3, 20], via deux fonctions auxiliaires.
Voir la réponse
def nombre_dans_intervalle(liste, valeur_min, valeur_max) -> int:
compteur = 0
for valeur in liste:
if valeur_min <= valeur < valeur_max:
compteur += 1
return compteur
def statistiques(notes: list[float]) -> tuple[float, float, float, float]:
moy = moyenne(notes)
n = longueur(notes)
nb_faibles = nombre_dans_intervalle(notes, 0, moy - 3)
nb_moyennes = nombre_dans_intervalle(notes, moy - 3, moy + 3)
nb_fortes = nombre_dans_intervalle(notes, moy + 3, 20.0001)
return (moy, nb_faibles/n*100, nb_moyennes/n*100, nb_fortes/n*100)
Ex 5-6 distance / distanceN
Distance euclidienne entre deux points (tuples), en dimension 3 puis en dimension N.
Voir la réponse
from math import sqrt
def distanceN(pt1: tuple, pt2: tuple) -> float:
if len(pt1) != len(pt2):
raise Exception("Les dimensions ne correspondent pas !")
carre_distance = 0
for i in range(len(pt1)):
carre_distance += (pt2[i] - pt1[i]) ** 2
return sqrt(carre_distance)
# distance (dim 3) est un cas particulier de distanceN
Ex 7 table_multiplication (liste de listes)
table_multiplication(4) → [[1,2,3,4],[2,4,6,8],[3,6,9,12],[4,8,12,16]]
Voir la réponse
def table_multiplication(n: int) -> list[list[int]]:
table = []
for i in range(1, n + 1):
ligne = []
for j in range(1, n + 1):
ligne.append(i * j)
table.append(ligne)
return table
🎯 Défis bonus
Pour les élèves qui terminent en avance.
Bonus 1 — Tri à bulles
Trier une liste de nombres croissants en comparant les voisins.
Voir la réponse
def tri_a_bulles(liste: list[float]) -> list[float]:
resultat = liste.copy()
n = longueur(resultat)
for i in range(n):
for j in range(0, n - i - 1):
if resultat[j] > resultat[j + 1]:
resultat[j], resultat[j + 1] = resultat[j + 1], resultat[j]
return resultat
Bonus 2 — Recherche séquentielle
Retrouver l'indice d'un élément sans utiliser .index().
Voir la réponse
def recherche(liste: list, element) -> int:
for i in range(longueur(liste)):
if liste[i] == element:
return i
return -1