On s'entraîne à coder de petits projets
Quelques exercices pour se mettre le code dans les pattes. Pour chacun des projets vous ferez 2 fichiers :
- le programme principal de nom
main.pyqui sera exécuté - le fichier contenant les différentes fonctions appelées dans le programme principal. Son nom doit être en relation avec son contenu.
Chaque sujet contient son corrigé, mais faites dans l'ordre :
Pour chaque sujet
- faites tous les exercices
- regardez les erreurs courantes et corriger si besoin votre projet
- comparez votre code au corrigé
Syracuse
On essaye d'écrire un programme qui teste la conjecture de Syracuse pour des entiers.
Questions
Écrivez une fonction syracuse telle que :
- entrée : un entier $x$
- sortie :
- $x/2$ si $x$ est pair
- $3x + 1$ si $x$ est impair
En utilisant le fait que le modulo s'écrit % en python.
corrigé
corrigé
def syracuse(x):
if x % 2 == 0:
return x / 2
else:
return 3 * x + 1
Écrivez une fonction qui rend tous les éléments de la suite de Syracuse associée à un nombre
- entrée : un entier $x$
- sortie : les élément de la suite de Syracuse associée à $x$
La suite de Syracuse est définie telle que :
- $u_0 =x$
- $u_{n+1} = \mbox{syracuse}(u_n)$
- on s'arrête lorsque $u_n =1$
corrigé
corrigé
def suite(u_0):
sortie = [u_0]
u_n = u_0
while u_n != 1:
u_n = syracuse(u_n)
sortie.append(u_n)
return sortie
Écrivez le programme principale qui demande à l'utilisateur de taper un nombre et rend la suite de Syracuse de ce nombre.
- vous supposerez que l'utilisateur ne se trompe pas (pas besoin de gérer ses erreurs potentielles)
- vous utiliserez la fonction
input()qui rend une chaîne de caractères tapée par l'utilisateur int(x)est l'entier représenté par la chaîne de caractèrex.
corrigé
corrigé
from syracuse import suite
sortie_utilisateur = input("Donnez un entier : ")
u_0 = int(sortie_utilisateur)
print("suite de Syracuse associée : ", suite(u_0))
Corrigé détaillé
Jeu du pendu
On essaye d'écrire un programme qui joue au jeu du pendu.
Questions
Écrire la fonction est_une_lettre(lettre, mot) telle que :
- paramètres d'entrée :
lettreun caractèremotune chaîne de caractères
- sortie :
- si au moins une des lettres de
motetlettre, la fonction rendTrue - sinon, la fonction rend
False
- si au moins une des lettres de
- exemples :
est_une_lettre("i", "victoire")doit rendreTrueest_une_lettre("e", "la disparition")doit rendreFalse
corrigé
corrigé
Plusieurs possibilités. Commençons par la plus simple, que tout le monde devrait arriver à faire, c'est une retranscription directe d'un algorithme du cours :
def est_une_lettre(lettre, mot):
for c in mot:
if lettre == c:
return True
return False
On pouvait aussi utiliser le mot clé in de python (supposé connu de tous), pour une solution écrite en 30 secondes chrono :
def est_une_lettre(lettre, mot):
if lettre in mot:
return True
else:
return False
Notez que la version précédente est identique à la version ci-dessous, bien plus élégante :
def est_une_lettre(lettre, mot):
return lettre in mot
Écrire la fonction caractères(lettre, mot) telle que :
- paramètres d'entrée :
lettreun caractèremotune chaîne de caractères
- sortie :
- une liste $L$ contenant tous les indices des caractères de
motqui valentlettre. Cette liste doit être triée par ordre croissant.
- une liste $L$ contenant tous les indices des caractères de
- exemples :
caractères("i", "victoire")doit rendre[1, 5]caractères("e", "la disparition")doit rendre[]
corrigé
corrigé
def caractères(lettre, mot):
position = []
for i in range(len(mot)):
if mot[i] == lettre:
position.append(i)
return position
On utilise ici la fonction range pour itérer sur les indices du tableau plutôt que sur ses valeurs.
Encore une fois, tout le monde devrait arriver à faire cette fonction d'une seule traite, sans réfléchir.
Écrire la fonction découvre(mot_caché, lettre, positions) telle que :
- paramètres d'entrée :
mot_cachéune chaîne de caractèreslettreun caractèrepositionsune liste d'entiers rangés par ordre croissant
- sortie :
- la chaîne de caractères
mot_cachéoù les indices correspondants aux entiers depositionssont remplacés parlettre
- la chaîne de caractères
- exemples :
découvre("......", "r", [1, 2, 5])doit rendre".rr..r"découvre("erre.r", "u", [4])doit rendre"erreur"découvre("erre.r", "u", [])doit rendre"erre.r"
corrigé
corrigé
La fonction que j'attends est :
def découvre(mot_caché, lettre, positions):
mot = ""
for i in range(len(mot_caché)):
if i in positions:
mot += lettre
else:
mot += mot_caché[i]
return mot
En utilisant les caractéristiques de la liste positions trié par ordre croissant, on aurait pu forger la fonction ci-dessous de complexité $\mathcal{O}(n)$ (pourquoi est-ce que ça marche ?):
def découvre(mot_caché, lettre, positions):
mot = ""
if len(positions) == 0:
return mot_caché
pos = 0
for i in range(len(mot_caché)):
if i == positions[pos]:
mot += lettre
pos = min(pos + 1, len(positions) - 1)
else:
mot += mot_caché[i]
return mot
Écrire la fonction caché(mot) telle que :
- paramètres d'entrée :
motune chaîne de caractères
- sortie :
- une chaîne de caractères composée uniquement de
"."et de longueur égale à celle demot
- une chaîne de caractères composée uniquement de
- exemples :
caché("anticonstitutionnellement")doit rendre"........................."caché("")doit rendre""
corrigé
corrigé
En utilisant la multiplications des chaînes de caractères, la fonction est triviale :
def caché(mot):
return "." * len(mot)
Créez un programme principal permettant de jouer au pendu jusqu'à ce que le mot à trouver ne contienne plus de "."
corrigé
corrigé
Une proposition de programme principal :
mot_à_trouver = "table"
mot_caché = caché(mot_à_trouver)
print("mot à trouver :", mot_caché)
nombre_essai = 0
while est_une_lettre(".", mot_caché):
lettre = input("Donnez une lettre : ")
mot_caché = découvre(mot_caché, lettre, caractères(lettre, mot_à_trouver))
print("mot à trouver :", mot_caché)
nombre_essai += 1
print("Victoire !, vous avez gagné en", nombre_essai, "essais.")
Corrigé détaillé
Le compte est bon
Le programme consiste à demander à l'utilisateur une chaîne de caractères et un caractère. On cherchera à savoir combien de fois apparaît le caractère dans la chaîne. On va créer le programme en ajoutant petit à petit des fonctionnalités au programme.
Questions
Créer un fichier main.py permettant d'exécuter les 4 étapes de l'algorithme suivant :
- Demander à l'utilisateur une chaîne de caractères que l'on nommera
chaîne_entrée(en utilisant la fonctioninput([prompt: str]) -> str) - Demander à l'utilisateur un caractère que l'on nommera
caractère_entrée(vous ne ferez aucune vérification de type) - Afficher à l'écran le plus petit indice (ou -1) de
chaîne_entréevalantcaractère_entrée(vous pourrez utiliser la méthodefinddes chaînes de caractères) - Retournez à l'étape 1. de cet algorithme à part si
chaîne_entréevalait"sortie"
corrigé
corrigé
Fichier main.py :
chaîne_entrée = ""
while chaîne_entrée != "sortie":
chaîne_entrée = input("Entre une chaîne de caractères : ")
caractère_entrée = input("Entre un caractère : ")
index_caractère = chaîne_entrée.find(caractère_entrée)
print("Premier index du caractère :", index_caractère)
On veut savoir si le caractère caractère_entrée apparaît plusieurs fois dans la chaîne chaîne_entrée. Comme on connaît déjà le premier indice où il apparaît, on cherche s'il apparaît aussi plus tard.
Créer la fonction donne_prochain_indice(chaîne:str, indice:int) -> int qui rend :
- Le plus petit indice $j$ strictement plus grand que le paramètre
indicetel quechaîne[j] == chaîne[indice], Nonesi cet indice n'existe pas.
corrigé
corrigé
def donne_prochain_indice(chaîne, indice):
possible_suivant = chaîne.find(chaîne[indice], indice + 1)
if possible_suivant > -1:
return possible_suivant
return None
Dans l'étape 3. de l'algorithme du programme principal, utilisez la fonction que vous venez de coder pour ajouter un affichage qui indique si caractère_entrée apparaît plusieurs fois dans chaîne_entrée ou pas.
L'étape 3. du programme principal sera alors constitué de deux actions :
- Afficher à l'écran le plus petit indice (ou -1) de
chaîne_entréevalantcaractère_entrée(vous pourrez utiliser la méthodefinddes chaînes de caractères) (question 1) - Afficher si
caractère_entréeest présent plus d'une fois danschaîne_entrée(question 2)
corrigé
corrigé
On ajoute à la fin du fichier main.py les lignes suivantes, dans le bloc while :
if index_caractère == -1:
print("Il n'apparaît pas")
elif donne_prochain_indice(chaîne_entrée, index_caractère) != None:
print("Il apparaît plusieurs fois")
else:
print("Il apparaît une fois")
On veut finalement savoir combien de fois apparaît caractère_entrée dans la chaîne chaîne_entrée. Comme on connaît sa première position grace à la question 1 et qu'on peut connaître la suivante grace à la question 2, on va terminer le boulot et compter combien de fois apparaît caractère_entrée dans chaîne_entrée.
Créer la fonction compte_caractère(chaîne: str, indice: int) -> int qui rend le nombre de fois où le caractère chaîne[indice] est présent dans le paramètre chaîne
corrigé
corrigé
def compte_caractère(chaîne, indice):
compte = 0
while indice != None:
compte += 1
indice = donne_prochain_indice(chaîne, indice)
return compte
Dans l'étape 3. de l'algorithme du programme principal, utilisez la fonction que vous venez de coder pour ajouter un affichage qui indique le nombre de fois où caractère_entrée apparaît dans chaîne_entrée.
L'étape 3. du programme principal sera alors constitué de trois actions :
- Afficher à l'écran le plus petit indice (ou -1) de
chaîne_entréevalantcaractère_entrée(vous pourrez utiliser la méthodefinddes chaînes de caractères) (question 1) - Afficher à l'écran si
caractère_entréeest présent plus d'une fois danschaîne_entrée(question 2) - Afficher à l'écran le nombre de fois où
caractère_entréeapparaît danschaîne_entrée(question 3)
corrigé
corrigé
On ajoute à la fin du fichier main.py les lignes suivantes, dans le bloc while :
if index_caractère > -1:
nombre = compte_caractère(chaîne_entrée, index_caractère)
print("Le caractère apparaît", nombre , "fois.")
Cerise sur le gateau, on cherche à savoir si caractère_entrée est le caractère qui apparaît le plus de fois dans chaîne_entrée.
Créer la fonction donne_max_doublon(chaîne: str) -> int qui rend le nombre maximum de fois où apparaît un même caractère dans chaîne.
corrigé
corrigé
def donne_max_doublon(chaîne):
nombre_max = 0
for i in range(len(chaîne)):
nombre_max = max(nombre_max, compte_caractère(chaîne, i))
return nombre_max
Dans l'étape 3. de l'algorithme du programme principal, utilisez la fonction que vous venez de coder pour ajouter un affichage qui le nombre maximum de répétition d'un caractère, et affichez un message de victoire si caractère_entrée réalise ce maximum.
L'étape 3. du programme principal sera alors constitué de quatre actions :
- Afficher à l'écran le plus petit indice (ou -1) de
chaîne_entréevalantcaractère_entrée(vous pourrez utiliser la méthodefinddes chaînes de caractères) (question 1) - Afficher à l'écran si
caractère_entréeest présent plus d'une fois danschaîne_entrée(question 2) - Afficher à l'écran le nombre de fois où
caractère_entréeapparaît danschaîne_entrée(question 3) - Afficher à l'écran le nombre maximum de répétition d'un caractère, et affichez un message de victoire si
caractère_entréeréalise ce maximum. (question 4)
corrigé
corrigé
On ajoute à la fin du fichier main.py les lignes suivantes, dans le bloc while :
if index_caractère > -1:
nombre = compte_caractère(chaîne_entrée, index_caractère)
print("Le caractère apparaît", nombre, "fois.")
if nombre == donne_max_doublon(chaîne_entrée):
print("c'est le max !")