De nombreuses applications des notions Python que vous avec vues : variables, chaînes de caractères, conditions, boucles, fonctions.
Certaines applications sont à compléter, d'autres à écrire de A à Z !
Mais auparavant, lisez ce premier paragraphe qui met l'accent sur une notion fondamentale en programmation, à savoir documenter son code.
Vous venez d'écrire vos premières fonctions...pas de problème, vous savez parfaitement comment elles "fonctionnent", c'est à dire quel(s) paramètre(s) elles ont, et le type de résultat qu'elles renvoient...
Mais qu'en sera-t-il dans un mois ? voire même une semaine ?? Vous aurez ( sûrement ! ) oublié tout ça, et si vous devez réutiliser ou modifier une de ces fonctions, quelle perte de temps à se "remettre dedans" !
C'est pourquoi il est indispensable lorsqu'on écrit une fonction de la documenter, c'est à dire de fournir à l’utilisateur de cette fonction toutes les informations dont il a besoin pour l'utiliser.
Les annotations de type sont des informations sur le type des paramètres et du résultat renvoyé par une fonction.
Considérons l'exemple ci-dessous :
def volume_sphere(r):
volume = (4/3)*pi*r**3
return volume
→ on sait que cette fonction prend un paramètre r de type flottant, et renvoie un résultat volume de type également flottant.
On peut alors préciser ces types dans l'en-tête de la fonction sous la forme :
def volume_sphere(r: float) -> float:
volume = (4/3)*pi*r**3
return volume
L'ensemble du nom d'une fonction, du nom et du type du (ou des) paramètre(s) qu'elle prend, ainsi que le type du ( ou des ) résultat(s) qu'elle renvoie est appelé la signature de la fonction.
Il est souvent très utile de disposer ainsi de la signature complète d'une fonction directement dans son en-tête de définition.
Voici les annotations de type que l'on peut utiliser ( certains types seront vus plus tard dans l'année ) :
int
: nombre entierfloat
: nombre flottanrstr
: chaîne de caractèresbool
: booléenlist
: tableaudict
: dictionnaireAttention cependant, les annotations ne sont là qu’à titre indicatif. Rien n’empêche d'appeler la fonction volume_sphere()
avec des chaînes de caractères, aucune erreur ne sera
alors signalée du fait que le type du paramètre n'est pas le bon, mais le script a toutes les chances de ne pas fonctionner correctement ! 😎
Les annotations sont optionnelles; elles ne sont utiles que dans un but de documentation de la fonction ( c'est déjà bien ), pas pour vérifier son bon fonctionnement.
Les annotations de type sont une fonctionnalité relativement récente de Python ( version de Python >= 3.5 ) ; si vous rencontrez une erreur à leur sujet lors de l'écriture d'un script, ne les utilisez pas : votre version de Python est peut-être trop ancienne et ne les supporte pas.
Il est d'usage de préciser toutes les informations nécessaires à l'utilisation de la fonction dans la docstring ( = "documentation string" ) de la fonction : il s'agit de commentaires placés au début de la définition de la fonction et qui constituent sa documentation.
Voici un exemple pour une fonction vue dans le cours :
def division(n1: int, n2: int ) -> int, int : # deux résultats sont renvoyés, on annote donc leurs types à tous les deux
"""
Fonction pour calculer le quotient et le reste de la division de deux nombres.
Entrée :
deux nombres n1, n2
Sortie :
deux entiers dans l'ordre : quotient, reste de la division de n1 par n2
"""
quotient = n1 // n2
reste = n1 % n2
return quotient, reste
Ces commentaires sont placés entre deux groupes de triples guillemets ( """ ).
On précise ainsi quelles sont les spécifications en entrée et en sortie de la fonction, mais de plus, cette docstring est alors accessible depuis l'interpréteur Python grâce à la fonction help()
( ceci est d'ailleurs valable pour toute fonction ! ) :
>>> help(division)
Help on function division in module __main__:
division(n1 : int, n2 : int) -> int, int:
Fonction pour calculer le quotient et le reste de la division de deux nombres.
Entrée :
deux nombres n1, n2
Sortie :
deux entiers dans l'ordre : quotient, reste de la division de n1 par n2
>>>
On remarque que la fonction help()
affiche également les éventuelles annotations de type.
Dorénavant, à chaque fonction que vous écrirez, vous penserez impérativement à écrire une docstring succincte de votre fonction, et éventuellement, à indiquer les annotations de type dans son en-tête.
minutes()
suivante pour qu'elle renvoie le nombre de minutes correspondant au nombre d'heures h et de minutes m passées en paramètres.On décide de ranger des œufs dans des boîtes de six.
nb_boites()
qui prend en paramètre un entier n correspondant à un nombre d’œufs et renvoie le nombre de boîtes nécessaires pour ranger les œufs.nb_boites(8) == 2
nb_boites(3) == 1
nb_boites(6) == 1
nb_boites(38) == 7
nb_boites(600) == 100
nb_boites(601) == 101
nb_boites(0) == 0
return
dans une même fonction )On dit qu'un nombre entier positif est premier s'il admet exactement deux diviseurs (1 et lui même). Ainsi :
Mis à part pour 0 et 1 qui sont particuliers (et ne sont pas premiers), pour tester si un nombre n
est premier il suffit de tester un par un tous les nombres compris entre
2 et n-1 : si l'un d'eux divise n, alors n n'est pas premier.
Par exemple pour tester si 323 est premier, il suffit de tester tous les nombres entre 2 et 322 : si l'un d'eux divise 323 alors 323 n'est pas premier ( en l'occurrence, on trouve que 17 divise 323, donc 323 n'est pas premier).
Remarque : Pour tester si n est divisible par k, on peut utiliser l'opérateur modulo %
qui donne le reste dans la division euclidienne de n
par k.
est_premier()
ci-dessous qui prend en paramètre un nombre n entier positif ou nul et renvoie un booléen indiquant si le nombre est premier
(True
) ou pas (False
).est_premier(0) == False
est_premier(1) == False
est_premier(4) == False
est_premier(6) == False
est_premier(48) == False
est_premier(57) == False
est_premier(77) == False
est_premier(2) == True
est_premier(3) == True
est_premier(5) == True
est_premier(7) == True
est_premier(11) == True
est_premier(13) == True
est_premier(89) == True
est_premier(241) == True
mot_double()
ci-dessous pour qu'elle double chaque caractère de la chaîne ch passée
en argument, quelle que soit sa longueur.mot_double('MAC') == 'MMAACC'
mot_double('Z') == 'ZZ'
mot_double('Lovelace') == 'LLoovveellaaccee
'mot_double('Turing') == 'TTuurriinngg'
On dit qu'un texte est «enrhumé» lorsque certains caractères ont été remplacés par d'autres caractères correspondant à une prononciation «enrhumée».
Voici un exemple :
Quelle poisse d’être enrhume, une tisane s'il te plaît !
Guelle boizze d'êdre enrhube, une dizane z'il de plaid !
On utilise donc la table de correspondance ci-dessous :
enrhuber_chaine()
suivante pour qu'elle renvoie la version "enrhumée" de la chaîne passée en argument.enrhuber_chaine("place") == 'blage'
enrhuber_chaine("chant") == 'ghant'
enrhuber_chaine("arret") == 'arred'
enrhuber_chaine("ourse") == 'ourze'
enrhuber_chaine("stylo") == 'zdylo'
Le javanais ou langue de feu, apparu en France dans la dernière moitié du XIXe siècle, est un procédé de codage argotique [basé sur] l'insertion d'une syllabe supplémentaire entre voyelles
et consonnes, dans le but de rendre ce texte moins compréhensible aux non initiés.
Cette syllabe comporte un son lié au nom de la variante : « ja » ou « av » dans la variante « javanaise » et une syllabe comportant « f » dans la variante « langue de feu ».( Source : Wikipedia )
Exemples :
Règles :
javanais()
qui prend en paramètre une chaîne de caractères, et renvoie la chaîne "traduite" en javanaisDans tout ce qui suit les notes sont sur 20 points.
Voici un exemple de calcul de moyenne avec des coefficients :
Un examen comporte 6 épreuves :
Un·e étudiant·e peut être admis·e de deux façons :
reussir_examen()
qui prend les six notes des épreuves comme paramètres (fra, ang, phi, mat, phy et inf) et qui renvoie True
ou False
selon que l'étudiant·e est admis·e ou pas.reussir_examen(10, 13, 11, 15, 6, 12) == True
reussir_examen(8, 13, 11, 15, 6, 12) == False
reussir_examen(10, 13, 11, 11, 6, 12) == False
reussir_examen(6, 3, 11, 15, 16, 20) == True
Dans un casino, les machines à sous comportent trois roues ou trois cylindres mécaniques portant chacun les chiffres de 1 à 9.
En faisant tourner ces roues ou cylindres, on peut tirer au hasard un nombre entre 111 et 999 (ne comportant pas de chiffre zéro).
Le joueur mise un euro et récupère un gain qui dépend du résultat :
gain_tirage()
qui prend en paramètre trois chiffres c, d et u correspondant aux chiffres des centaines, des dizaines et des unités
et qui renvoie la somme récupérée correspondant à ce tirage.gain_tirage(1, 7, 4) == 0
gain_tirage(4, 5, 6) == 15
gain_tirage(5, 7, 5) == 1
gain_tirage(4, 4, 4) == 33
gain_tirage(7, 7, 7) == 333
gain_tirage()
, compléter la fonction machine_a_sous()
afin qu'elle renvoie trois chiffres tirés au hasard ainsi que la somme récupérée correspondante.
On considère les tarifs proposés par deux entreprises de location de véhicules pour la location d’un même modèle automobile :
meilleur_tarif()
qui :
meilleur_tarif(45, 1) == ('A', 27.15)
meilleur_tarif(75, 1) == ('A', 35.25)
meilleur_tarif(150, 1) == ('B', 54.5)
meilleur_tarif(150, 2) == ('A', 70.5)
meilleur_tarif(350, 2) == ('B', 118.5)
Depuis ses huit ans, Super-avare économise des klipoks (monnaie locale).
calculer_tirelire()
qui prend en paramètre un entier n supérieur ou égal à 8 et renvoie le nombre entier correspondant au nombre de klipocks que Super-avare
a dans sa tirelire le jour de son n-ième anniversaire.calculer_tirelire(8) == 512
calculer_tirelire(9) == 1241
calculer_tirelire(10) == 2241
calculer_tirelire(11) == 3572
age_millionnaire()
qui utilise la fonction précédente pour renvoyer l'âge à partir duquel Super-avare devient millionnaire
on regarde successivement chaque bit du nombre binaire ( en commençant par le premier ou le dernier ) :
si le bit courant est égal à 1 :
alors on ajoute à la somme totale la puissance de 2 correspondant à la position du bit courant
si le bit courant est égal à 0:
on n'ajoute rien
Écrire une fonction bin_vers_dec()
qui :
Il faut coder l'algorithme que vous avez utilisé pour passer du binaire à la base 10.
Indication
Contrairement à ce que vous aviez ( peut-être ) fait lors des conversions "à la main", il est plus facile de coder cet algorithme en commençant par le bit de poids le plus grand ( le MSB ) : Python dispose en effet d'une fonction pour parcourir une chaîne de caractères depuis la gauche, cela peut servir ici...
Faites par contre bien attention au fait que, dans ce cas, on commence par la puissance de 2 la plus grande (27 pour un nombre à 8 bits par exemple ).
Cependant, les nombres binaires à convertir n'auront pas forcément 8 bits : il faut donc que la fonction s'adapte à un nombre quelconque n de bits.
Ce n'est pas très compliqué :
Attention un peu plus délicat...
Contentez-vous pour ce script d'une conversion sur 8 bits ( donc des valeurs en base 10 comprises entre 0 et 255 ).
tant que le nombre en base 10 n'est pas nul:
on compare le nombre en base 10 à la plus grande puissance de 2 (2^7 pour un nombre sur 8 bits )
si le nombre est supérieur ou égal à la puissance :
alors on ajoute un bit '1' à la chaîne représentant le nombre binaire
on soustrait la puissance au nombre en base 10
sinon on ajoute un bit à '0' à la chaîne
on passe à la puissance de 2 inférieure
Écrire une fonction dec_vers_bin()
qui:
Il existe un autre algorithme pour la conversion décimal → binaire :
tant que quotient n'est pas nul :
quotient ← division entière du nombre en base 10 par 2
reste ← reste de la division entière du nombre en base 10 par 2
binaire ← "reste" + binaire
nombre en base 10 ← quotient
Réarranger les instructions de la fonction dec_vers_bin_v2()
ci-dessous qui utilise l'algorithme précédent; ne pas oublier l'indentation !
Vous pourrez vérifier le bon fonctionnement de votre solution dans l'éditeur ci-dessous :