Fonctions - Correction des applications
Minutes
def minutes(heures, minutes):
"""Renvoie le nombre de minutes total correspondant à un nombre d'heures et de minutes.
Entréés :
heures = le nombre d'heures (int)
minutes = le nombre de minutes (int)
Sorties :
le nombre de minutes total (int)
"""
return heures * 60 + minutes # oui, on peut tout faire en une seule ligne !
print(minutes(5, 27))
print(minutes(13, 4))
print(minutes(0, 59))
Œufs en boîte
Le nombre de boîtes de 6 œufs est le quotient du nombre d’œufs par 6.
Il faut une boîte "additionnelle" dans le cas où il reste ensuite moins de 6 œufs à ranger, ce qui se produit si le nombre d'œufs n'est pas un multiple de 6 : on le détermine en calculant le reste de la division du nombre d’œufs par 6, et en testant si il est nul ( multiple de 6 ) ou pas ( pas multiple ).
def nb_boites(oeufs):
"""Renvoie le nombre de boîte(s) de 6 oeufs nécessaire pour ranger un certain nombre d'oeufs
Entrée :
oeufs = le nombre d'oeufs (int)
Sortie :
le nombre de boîte de 6 oeufs (int)
"""
boites = oeufs // 6 # nmbre "brut" de boîtes nécessaire
if oeufs % 6 != 0: # si le nombre d'oeufs n'est pas un multiple de 6,
boites = boites + 1 # alors il faut une boîte en plus pour ranger les oeufs restants.
return boites
print(nb_boites(8))
print(nb_boites(3))
print(nb_boites(6))
print(nb_boites(38))
print(nb_boites(600))
print(nb_boites(601))
print(nb_boites(0))
Nombre premier
def est_premier(n):
"""Fonction qui détermine si un nombre entier est premier ou pas.
Entrée :
n = le nombre à tester (int)
Sortie :
True si le nombre est premier, False sinon (bool)
"""
if n == 0 or n == 1 : # deux cas particuliers
return False
for i in (2, n) : # pour tous les nombres entre 2 et n - 1,
if n % i == 0 : # si n est divisible par i ( <=> le reste de la division de n par i est nul )
return False # alors on renvoie prématurément 'False'
return True # une fois la boucle terminée, n n'est jamais été divisible par i, il est donc premier, on renvoie 'True'
print(est_premier(0))
print(est_premier(1))
print(est_premier(4))
print(est_premier(6))
print(est_premier(48))
print(est_premier(57))
print(est_premier(77))
print(est_premier(2))
print(est_premier(3))
print(est_premier(5))
print(est_premier(7))
print(est_premier(11))
print(est_premier(13))
print(est_premier(89))
print(est_premier(241))
Mot double
def mot_double(ch):
"""Renvoie une nouvelle chaîne avec chaque caractère doublé.
Entrée :
ch = la chaîne à doubler (str)
Sortie :
une nouvelle chaîne avec les caractères doublés (str)
"""
ch2 = "" # initialisation de la nouvelle chaîne
for car in ch: # pour chaque caractère de la chaîne d'origine,
ch2 = ch2 + car*2 # on concatène deux fois le caractère à la nouvelle chaîne
return ch2
print(mot_double('MAC'))
print(mot_double('Z'))
print(mot_double('Lovelace'))
print(mot_double('Turing'))
Ligne 13 : car*2 ne fait bien entendu pas une multiplication, mais crée une chaîne de 2 fois le caractère car ( cf. chapitre sur les chaînes )
Texte enrhumé
Version basique
On parcourt la chaîne, et on teste si le caractère courant est égal à un de ceux à remplacer; si c'est le cas, on fait la substitution.
On concatène ensuite le caractère, remplacé ou non, à une nouvelle chaîne :
def enrhuber_chaine(chaine):
"""Renvoie une chaîne dans laquelle certains caractères ont été remplacés par d'autres.
Entréé :
chaine = la chaîne à transformer (str)
Sortie :
une nouvelle chaîne dans laquelle certains caractères de la chaîne d'origine ont été remplacés (str)
"""
chaine2 = "" # initialisation de la nouvelle chaîne
for car in chaine: # pour chaque caractère de la chaîne d'origine,
if car == "c" or car == "q": # on teste si le caractère courant
chaine2 = chaine2 + "g" # est un de ceux qu'ils faut remplacer;
elif car == "m" or car == "p" or car == "v":# on regroupe les tests pour que ceux-ci soient les plus simples.
chaine2 = chaine2 + "b" # Si un des test est positif,
elif car == "s": # alors on concatène à la nouvelle chaîne le
chaine2 = chaine2 + "z" # caractère de remplacement.
elif car == "t":
chaine2 = chaine2 + "d"
else: # sinon, on concatène
chaine2 = chaine2 + car # simplement le caractère courant.
return chaine2
print(enrhuber_chaine("place"))
print(enrhuber_chaine("chant"))
print(enrhuber_chaine("arret"))
print(enrhuber_chaine("ourse"))
print(enrhuber_chaine("stylo"))
Bien entendu, on a pensé à regrouper les tests qui menaient à la substitution du même caractère !
Version améliorée
Ça en fait, des if...et si on veut gérer aussi les majuscules, cela rajoute encore des conditions...
Pour optimiser le code, on peut se souvenir de l'existence de deux choses en Python :
- l'opérateur
in, qui permet de tester si un caractère donné se trouve dans une chaîne donnée - la fonction
chaîne.index(caratère), qui renvoie l'indice d'un caractère dans une chaîne
D'où l'idée :
- on crée une chaîne original contenant tous les caractères susceptibles d'être remplacés ( on peut y inclure les majuscules )
- on crée une deuxième chaîne remplacement contenant les caractères de remplacement, dans le même ordre que les caractères à remplacer dans la chaîne original : les caractères à remplacer et ceux de remplacement ont donc le même indice dans les deux chaînes.
- en parcourant la chaîne en entrée, on teste si le caractère courant se trouve dans la chaîne original, ce qui signifie qu'il faut le remplacer;
- on détermine alors son indice dans la chaîne original, et on le remplace par le caractère de même indice dans la chaîne remplacement
def enrhuber_chaine(chaine):
"""Renvoie une chaîne dans laquelle certains caractères ont été remplacés par d'autres.
Entrée :
chaine = la chaîne à transformer (str)
Sortie :
une nouvelle chaîne dans laquelle certains caractères de la chaîne d'origine ont été remplacés (str)
"""
original = "cCqQmMpPvVsStT" # chaîne contenant tous les caractères à remplacer
remplacement = "gGgGbBbBbBzZdD" # chaîne contenant tous les caractères de remplacement, DANS LE MÊME ORDRE
chaine2 = "" # initialisation de la nouvelle chaîne
for car in chaine: # pour chaque caractère de la chaîne d'origine,
if car in original: # on teste si le caractère courant est un de ceux qu'ils faut remplacer;
indice = original.index(car) # dans ce cas, on détermine son indice dans la chaîne 'original',
car = remplacement[indice] # et on le remplace par le caractère DE MÊME INDICE dans la chaîne 'remplacement'.
chaine2+= car # On concatène le caractère, remplacé ou non, à la nouvelle chaîne.
return chaine2
Le javanais
Première idée
L'idée qui vient tout de suite à l'esprit est de parcourir la chaîne à transformer caractère par caractère, et si le caractère courant est une voyelle, alors on concatène "av" + le caractère à une nouvelle chaîne :
def javanais(chaine):
""" 'Traduit' une chaîne de caractères en javanais, c'est à dire rajoute 'av' devant les voyelles.
Entréee :
chaine = la chaîne d'origine (str)
Sortie :
la chaîne en javanais (str)
"""
chaine2 = "" # initialisation d'une nouvelle chaîne
for car in chaine: # pour chaque caractère de la chaîne d'origine,
if car == "a" or car == "e" or car == "i" or car == "o" or car == "u" or car == "y": # si le caractère courant est une voyelle,
chaine2 = chaine2 + "av" + car # alors on concatène "av" + le caractère courant à la nouvelle chaîne,
else:
chaine2 = chaine2 + car # sinon, on concatène simplement le caractère courant.
return chaine2
print(javanais('gros')) # 'gravos' => ça marche
print(javanais('bonjour')) # 'bavonjavoavur' => ça ne marche pas !
Problème : cela ne fonctionne pas dans le cas où le mot contient deux voyelles successives.
On parcourt différemment la chaîne...
Pour résoudre ce problème, il faudrait pouvoir tester si le caractère précédent le caractère courant est aussi une voyelle, et dans ce cas, ne pas concaténer "av".
Mais il est impossible de faire ça avec le type de parcours de chaîne que l'on utilise ici, qui est un parcours par valeur; il va donc falloir utiliser l'autre façon de "s'adresser" à un
caractère dans une chaîne, qui est de le désigner par son index ( cf. cours sur les chaînes si ce n'est plus clair ), et adopter alors un parcours par index de la chaîne grâce à une boucle
for ... in range() :
def javanais(chaine):
""" 'Traduit' une chaîne de caractères en javanais, c'est à dire rajoute 'av' devant les voyelles.
Entréee :
chaine = la chaîne d'origine (str)
Sortie :
la chaîne en javanais (str)
"""
chaine2 = "" # initialisation d'une nouvelle chaîne
for i in range(len(chaine)): # pour chaque caractère de la chaîne d'origine,
if (chaine[i] == "a" or chaine[i] == "e" or chaine[i] == "i" or chaine[i] == "o" or chaine[i] == "u" or chaine[i] == "y") and (chaine[i-1] != "a" and chaine[i-1] != "e" and chaine[i-1] != "i" and chaine[i-1] != "o" and chaine[i-1] != "u" and chaine[i-1] != "y"): # si le caractère courant est une voyelle, et que le caractère précédent N'EST PAS une voyelle,
chaine2 = chaine2 + "av" + chaine[i] # alors on concatène "av" + le caractère courant à la nouvelle chaîne,
else:
chaine2 = chaine2 + chaine[i] # sinon, on concatène simplement le caractère courant.
return chaine2
print(javanais('gros')) # ça marche,
print(javanais('bonjour')) # et là, ça marche aussi !
Version un peu plus lisible
Le test à la ligne 6 du script précédent est un peu compliqué...
On peut l'écrire plus judicieusement en utilisant, comme à l'exercice précédent, les opérateurs in ( est dans ) et not in ( n'est pas dans ).
Ici, la chaîne en question sera formée de l'ensemble des voyelles ( 'aeiouy', avec éventuellement les majuscules ), et il suffira de tester l'appartenance d'un caractère
à cette chaîne pour déterminer si ce caractère est une voyelle ou pas.
D'où le script final :
def javanais(chaine):
"""Traduit un texte en javanais.
Entrée :
chaine = la chaine à traduire (str)
Sortie :
une nouvelle chaine, traduction en javanais de celle d'origine (str)
"""
chaine2 = "" # initialisation d'une nouvelle chaîne
voyelles = 'aeiouyé' # chaîne contenant les voyelles ( on peut aussi y rajouter les caractères accentués, les majuscules,...)
for i in range(len(chaine)): # pour chaque caractère de la chaîne d'origine,
if (chaine[i] in voyelles and chaine[i-1] not in voyelles): # si le caractère courant est une voyelle, et que le caractère précédent N'EST PAS une voyelle,
chaine2 = chaine2 + "av" + chaine[i] # alors on concatène "av" + le caractère courant à la nouvelle chaîne,
else:
chaine2 = chaine2 + chaine[i] # sinon, on concatène simplement le caractère courant.
return chaine2
print(javanais('train'))
print(javanais('gros'))
print(javanais('bonjour'))
print(javanais('bon'))
print(javanais('champion'))
print(javanais('plans'))
print(javanais('supermarché'))
print(javanais('poirier'))
Réussir à l'examen
def reussir_examen(fra, ang, phi, mat, phy, inf):
"""Détermine si un étudiant a réussi à un examens selon les notes qu'il a reçu.
Entrées :
fra = la moyenne en français (float)
ang = la moyenne en anglais (float)
phi = la moyenne en philo (float)
mat = la moyenne en maths (float)
phy = la moyenne en physique (float)
info = la moyenne en info (float)
Sortie :
un booléen indiquant si l'étudiant a réussi ou non l'examen (bool)
"""
m_litt = (4*fra + 3*ang + phi)/(4+3+1)
m_sci = (4*mat + 2*phy + 6*inf)/(4+2+6)
if (m_litt >= 11 and m_sci >= 11) or m_sci >= 16:
return True
else:
return False
print(reussir_examen(10, 13, 11, 15, 6, 12))
print(reussir_examen(8, 13, 11, 15, 6, 12))
print(reussir_examen(10, 13, 11, 11, 6, 12))
print(reussir_examen(6, 3, 11, 15, 16, 20))
print(reussir_examen(8, 11, 14, 13, 9, 11)) # cet étudiant n'a pas réussi l'examen...
Il est à signaler, comme cela a déjà été dit ( par exemple ici ), que, à la place des tests aux lignes 13 à 16, on peut très bien simplement renvoyer le résultat de la condition évaluée :
def reussir_examen(fra, ang, phi, mat, phy, inf):
...
return (m_litt >= 11 and m_sci >= 11) or m_sci >= 16
Une expression booléenne est en effet évaluée à ( True ou False ).
Casino
Gain tirage
def gain_tirage(c, d, u):
"""Calcule le gain à un tirage d'une machine à sous.
Entrées :
c = le nombre des centaines (int)
d = le nombre des dizaines (int)
u = le nombre des unités (int)
Sortie :
le gain au tirage (int)
"""
if c == 7 and d == 7 and u == 7 :
somme = 333
elif c == d and d == u :
somme = 33
elif c == u :
somme = 1
elif c < d and d < u :
somme = 15
else :
somme = 0
return somme
print(gain_tirage(1, 7, 4))
print(gain_tirage(4, 5, 6))
print(gain_tirage(5, 7, 5))
print(gain_tirage(4, 4, 4))
print(gain_tirage(7, 7, 7))
print(gain_tirage(5, 6, 5)) # gain de 1
Remarque : le test à la ligne 3 peut effectivement être écrit ainsi en Python :
if c == d == u == 7 :
...
Et de même, celui à la ligne 9 :
elif c < d < u :
...
Ce qui se rapproche plus de la notation mathématique des égalités/inégalités.
Mais cette écriture est uniquement "pythonesque" et n'existe pas dans les autres langages : on évitera donc de l'utiliser.
Machine à sous
from random import randint
def gain_tirage(c: int, d: int, u: int)->int:
if c == 7 and d == 7 and u == 7 :
somme = 333
elif c == d and d == u :
somme = 33
elif c == u :
somme = 1
elif c < d and d < u :
somme = 15
else :
somme = 0
return somme
def machine_a_sous()->int:
c = randint(1, 9)
d = randint(1, 9)
u = randint(1, 9)
somme = gain_tirage(c, d, u)
return (c, d, u, somme)
print(machine_a_sous())
En lançant le script plusieurs fois de suite, on s'aperçoit qu'on ne gagne pas beaucoup, et pas très souvent 😭...
Meilleur tarif
def meilleur_tarif(km, j):
"""Détermine l'entreprise proposant le meilleur tarif pour un nombre de km et de jour de location donnés.
Entrées :
km = le nombre de km parcourus (int)
jr = le nombre de jours de location (int)
Sortie :
le nom de l'entreprise proposant le meilleur tarif (str)
la valeur de ce tarif (float)
"""
tarif_A = 15*j + 0.27*km
tarif_B = 26*j + 0.19*km
if tarif_A < tarif_B:
return 'A', tarif_A
else:
return 'B', tarif_B
print(meilleur_tarif(45, 1))
print(meilleur_tarif(75, 1))
print(meilleur_tarif(150, 1))
print(meilleur_tarif(150, 2))
print(meilleur_tarif(350, 2))
print(meilleur_tarif(1250, 7)) # choix de l'entreprise 'B' avec un tarif de 419.5€
Super-Avare
Calculer tirelire
def calculer_tirelire(n):
"""Renvoie le contenu de la tirelire au n-ième anniversaire de Super-Avare
Entrée :
n = l'age de Super-Avare (int)
Sortie :
le contenu de la tirelire (int)
"""
tirelire = 0 # initialisation de la tirelire, ne contient rien initialement
for annee in range(8, n+1): # pour chaque année de 8 jusqu'à n
tirelire = tirelire + annee**3 # on rajoute annee**3 au contenu précédent de la tirelire
return tirelire
print(calculer_tirelire(8))
print(calculer_tirelire(9))
print(calculer_tirelire(10))
print(calculer_tirelire(11))
Age millionnaire
def calculer_tirelire(n):
# Code ci-dessus
return tirelire
def age_millionnaire():
"""Renvoie l'age auquel Super-Avare devient millionnaire
Entrée :
aucune
Sortie :
l'age auquel Super-Avare devient millionnaire (int)
"""
age = 8 # à l'age de 8 ans,
tirelire = 0 # Super-Avare n'a rien dans sa tirelire.
while tirelire < 10**6: # tant que sa tirelire ne contient pas 10**6 = 1 millions,
tirelire = calculer_tirelire(age) # on calcule le contenu de sa tirelire,
age = age + 1 # et on incrémente son age.
return age
print(age_millionnaire()) # millionnaire à 46 ans !
Conversion binaire → base 10
def bin_vers_dec(binaire):
"""Convertit un nombre binaire en son équivalent décimal.
Entrée :
binaire = le nombre binaire (str)
Sortie :
la conversion du nombre binaire en décimal (int)
"""
n = len(binaire) # n = nombre de bits = nombre de caractères dans la chaîne 'binaire'
dec = 0 # variable qui contiendra le nombre en base 10
for bit in binaire: # pour chaque caractère/chaque bit de la chaîne 'binaire',
if bit == '1': # si le bit est à 1/le caractère est '1',
dec = dec + 2**(n-1)# alors on ajoute à 'dec' la puissance correspondant à ce bit ( sinon, on n'ajoute rien ! )
n = n - 1 # on décrémente 'n' pour passer à la puissance de 2 inférieure
return dec
print(bin_vers_dec('1001110101110'))
Conversion base 10 → binaire
def dec_vers_binaire(dec):
"""Fonction de conversion d'un nombre en base 10 vers le binaire.
Entrée :
dec = le nombre en base 10 (int)
Sortie :
la conversion du nombre en base 10 vers le binaire (str)
"""
binaire = ""
puissance = 7 # conversion sur 8 bits ( peut être modifié )
while puissance >= 0 : # tant que le nombre en base 10 n'est pas nul
if dec >= 2**puissance : # si 'dec' est supérieur ou égal à la puissance de 2 courante,
binaire = binaire + '1' # alors on concatène un bit à '1' à 'binaire'
dec = dec - 2**puissance # et on soustrait la puissance de 2 au nombre en base 10.
else: # sinon ( donc si dec < 2**puissance ),
binaire = binaire + '0' # on concatène un bit '0' à 'binaire'
puissance = puissance - 1 # dans les deux cas, on n'oublie pas de diminuer la valeur de la puissance
return binaire
print(dec_vers_binaire(212))
Conversion base 10 → binaire ( bis )
def dec_vers_bin_v2(dec):
"""Fonction de conversion d'un nombre en base 10 vers le binaire.
Entrée :
dec = le nombre en base 10 (int)
Sortie :
la conversion du nombre en base 10 vers le binaire (str)
"""
quotient = 1
binaire = ''
while quotient != 0:
quotient = dec // 2
reste = dec % 2
binaire = str(reste) + binaire
dec = quotient
return binaire
print(dec_vers_bin_v2(217))
- Ligne 10 : il est indispensable d'initialiser la variable quotient, sinon une erreur serait générée par la suite à la ligne 13.
- Lignes 14 et 15 : rappelez-vous de l'existence des opérateurs de division entière et de reste ( modulo ).
- Ligne 16 : on concatène le bit calculé au début de la chaîne, sans oublier de le transtyper en type chaîne : on ne pourrait en effet pas "ajouter" directement un entier à une chaîne !...
- Ligne 19 : il ne faut bien entendu pas oublier de renvoyer un résultat ! ( L'affichage lors de l'appel de la fonction ( ligne 21 ) affiche sinon
None, qui signifie 'Rien' ! )
Somme des chiffres d'un nombre
def somme_chiffres(nombre):
"""Renvoie la somme des chiffres d'un nombre.
Entrée :
le nombre dont on cherche la somme des chiffres (int)
Sortie :
la somme des chiffres du nombre (int)
"""
somme = 0
while nombre != 0: # tant que 'nombre' n'est pas égal à 0,
somme += nombre % 10 # on ajoute le chiffre le plus à droite à la somme,
nombre = nombre//10 # et on remplace 'nombre' par le chiffres restants.
return somme
Rendre fiable une pièce truquée
from random import randint
def piece_truquee():
""" Simule le lancer d'une pièce truquée, qui donne "Pile" dans 60% des lancers, et "Face" dans 40%.
Entrée :
aucune
Sortie :
le résultat du lancer ( str )
"""
l = randint(1, 100)
if l <= 60:
return "Pile"
else:
return "Face"
def piece_fiable():
l1 = piece_truquee()
l2 = piece_truquee()
pile = 0
face = 0
while (l1 == "Pile" and l2 == "Pile") or (l1 == "Face" and l2 == "Face"): # tant que l'on n'a pas obtenu deux lancers DIFFÉRENTS,
l1 = piece_truquee() # on refait deux lancers.
l2 = piece_truquee()
if (l1 == "Pile") and (l2 == "Face"): # dans ce cas,
return "Pile" # on renvoie "Pile",
else: # sinon ( donc, dans le cas inverse, il n'y a plus d'autre possibilité ! ),
return "Face" # on renvoie "Face".
def test(n):
pile = 0
face = 0
for i in range(n):
lancer = piece_truquee() # ou lancer = piece_fiable()
if lancer == "Pile":
pile += 1
else:
face += 1
return "Pile = " + str(pile), "Face = " + str(face)
print(test(10000))