Exercices pour s'entraîner☘
Prenez l'habitude de revenir vous entraîner régulièrement avec ces exercices tout au long de l'année. Ils sont généralement accompagnés de pistes et de leur solution pour vous permettre de progresser.
Rappels
- Chaque programme Python doit être sauvegardé sous forme de fichier texte
avec l'extension
.py
.
Enregistrez ce fichier dans le dossier[D02-Modularité]
avec le nom donné à l'exercice :ProgD02.51.py
,ProgD02.52.py
, etc... - Pour exécuter ce programme, il suffit de le sauvegarder puis d'appuyer
sur la touche
[F5]
.
Consignes communes
Dans chacun des exercices de cette partie, il vous est demandé :
- de programmer la structure de données signalée ;
- d'établir la documentation du module ;
- d'effectuer les tests nécessaires et de les placer dans le
«
main
» (programme principal) de ce module.
Exercice D02.51☘
Définir un classe Date
pour représenter une date avec trois attributs (entiers positifs ou nuls) : jour
, mois
et annee
.
Les méthodes de cette classe doivent permettrent :
- d'initialiser une date ;
- d'afficher cette date sous les formes suivantes : « 24 septembre 2020 » ou bien « 24/09/2020 » ;
- de comparer deux dates en surchargeant les opérateurs de test d'égalité «
==
» et d'inégalité «<
».
exemple de tests
>>> d1 = Date()
>>> print(d1)
1 janvier 0
>>> d1
01/01/0000
>>> d2 = Date(24, 9, 2020)
>>> print(d2)
24 septembre 2020
>>> d1 == d2
False
>>> d1 < d2
True
>>> d3 = Date(23, 9, 2020)
>>> d3
23/09/2020
>>> d2 < d3
False
Une piste - un code à compléter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
|
Une solution
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
|
Exercice D02.52☘
Définir un classe Ensemble
qui représente un ensemble d'entiers positifs ou
nuls, sans doublons. Cette classe a un unique attribut nommé valeurs
qui est
un tableau d'entiers tous distincts, triés par ordre croissant.
Les méthodes de cette classe doivent permettrent :
- d'initialiser un ensemble (vide, ou à partir d'une liste déjà donnée) ;
- de s'assurer que le tableau
valeurs
ne contient que des entiers distincts ; - d'ordonner le tableau
valeurs
par ordre croissant ; - d'afficher ce tableau ;
- de renvoyer le tableau
valeurs
; - d'indiquer si un entier
val
passé en paramètre est dans l'ensemble considéré ou pas (vous pouvez surcharger l'opérateurin
, mais il faudrait réussir à écrire un code qui n'utilise pasin
) ; - d'ajouter un entier
val
à cet ensemble (bien évidemment, directement à la bonne place...).
exemple de tests
>>> from random import randint
>>> e = Ensemble([randint(1, 100) for i in range(15)])
>>> print(e)
[17, 23, 29, 33, 35, 36, 46, 71, 77, 79, 83, 84, 86, 95]
>>> 50 in e
False
>>> 79 in e
True
>>> e.ajoute(50)
>>> e.ajoute(79)
>>> print(e)
[17, 23, 29, 33, 35, 36, 46, 50, 71, 77, 79, 83, 84, 86, 95]
Une piste
Dans l'initalisation, vous pouvez utiliser un algorithme éudié l'an dernier sur les tableaux pour le trier par ordre croissant.
Une piste - un code à compléter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
Une solution
class Ensemble:
"""
Une classe pour représenter un ensemble d'entiers positifs ou nuls, sans doublons
L'opérateur "in" renvoie vrai si l'entier saisit en paramètre appartient à l'ensemble
ajoute(val) : ajoute val à l'ensemble si cet entier n'est pas déjà dans l'ensemble
"""
def __init__(self, liste = None):
self.valeurs = []
if liste is not None:
for elt in liste:
if elt not in self.valeurs:
self.valeurs.append(elt)
self.valeurs.sort()
def __repr__(self):
return str(self.valeurs)
def __str__(self):
return self.__repr__()
def __contains__(self, val):
for elt in self.valeurs:
if elt == val:
return True
return False
def ajoute(self, val):
if not self.__contains__(val):
resultat = []
i = 0
while self.valeurs[i] < val:
resultat.append(self.valeurs[i])
i = i+1
resultat.append(val)
for k in range(i, len(self.valeurs)):
resultat.append(self.valeurs[k])
self.valeurs = resultat
if __name__ == "__main__":
from random import randint
print("Création d'un ensemble :")
e = Ensemble([randint(1, 100) for _ in range(40)])
print(e)
print("\nAppartenance :")
print("50 est-il dans l'ensemble ?", 50 in e)
print("67 est-il dans l'ensemble ?", 67 in e)
print("\nInsertion :")
print("On ajoute 50.")
e.ajoute(50)
print("On ajoute 67")
e.ajoute(67)
print(e)
Exercice D02.53☘
Un objet de la classe Carte
est muni de trois attributs :
couleur
(chaîne de caractères entre'PIQUE'
,'COEUR'
,'CARREAU'
et'TREFLE'
) ;nom
(chaîne de caractères entre'2'
,'3'
,'4'
,'5'
,'6'
,'7'
,'8'
,'9'
,'10'
,'Valet'
,'Dame'
,'Roi'
et'As'
) ;valeur
(entier compris entre2
et14
).
Pour définir un objet de cette classe, il faut deux arguments : le nom et la couleur de la carte. Il n'y a pas d'initialisation par défaut.
-
Programmez la classe
Carte
en respectant les spécifications données dans le docstring.1 2 3 4 5 6 7 8
class Carte: """ Une classe pour représenter une carte à jouer get_couleur() renvoie la couleur de la carte get_nom() renvoie le nom de la carte meme_nom(autreCarte) renvoie True si les cartes ont le même nom est_battue_par(autreCarte) renvoie True si la carte considérée a une valeur inférieure à celle de autreCarte """
Exemple de tests
>>> c1 = Carte('10', 'PIQUE') >>> print(c1) 10 de PIQUE >>> c1 10 de PIQUE >>> c2 = Carte('10', 'ROUGE') AssertionError: La couleur ne convient pas >>> c2 = Carte('12', 'PIQUE') AssertionError: Le nom ne convient pas >>> c1.get_couleur() 'PIQUE' >>> c1.get_nom() '10' >>> c2 = Carte('10', 'TREFLE') >>> c1.meme_nom(c2) True >>> c1.est_battue_par(c2) False
Une piste - un code à compléter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
class Carte: """ Une classe pour représenter une carte à jouer get_couleur() renvoie la couleur de la carte get_nom() renvoie le nom de la carte meme_nom(autreCarte) renvoie True si les cartes ont le même nom est_battue_par(autreCarte) renvoie True si la carte considérée a une valeur inférieure à celle de autreCarte """ def __init__(self, nom, couleur): pass def __repr__(self): pass def __str__(self): pass def get_couleur(self): pass def get_nom(self): pass def meme_nom(self, autreCarte): pass def est_battue_par(self, autreCarte): pass
Une autre piste
Pour faciliter votre travail, vous pouvez utiliser/copier/coller les variables globales suivantes en les plaçant au début de votre programme, en dehors de la définition de la classe
Carte
.1 2
couleurs = ['PIQUE', 'COEUR', 'CARREAU', 'TREFLE'] noms = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'Valet', 'Dame', 'Roi', 'As']
Une solution
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
couleurs = ['PIQUE', 'COEUR', 'CARREAU', 'TREFLE'] noms = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'Valet', 'Dame', 'Roi', 'As'] class Carte: """ Une classe pour représenter une carte à jouer get_couleur() renvoie la couleur de la carte get_nom() renvoie le nom de la carte meme_nom(autreCarte) renvoie True si les cartes ont le même nom est_battue_par(autreCarte) renvoie True si la carte considérée a une valeur inférieure à celle de autreCarte """ def __init__(self, nom, couleur): assert couleur in couleurs, 'La couleur ne convient pas' assert nom in noms, 'Le nom ne convient pas' self.couleur = couleur self.nom = nom self.valeur = noms.index(self.nom) def __repr__(self): return f"{self.nom} de {self.couleur}" def __str__(self): return self.__repr__() def get_couleur(self): return self.couleur def get_nom(self): return self.nom def meme_nom(self, autreCarte): return self.nom == autreCarte.nom def est_battue_par(self, autreCarte): return self.valeur < autreCarte.valeur
-
Programmez la classe
PaquetCartes
en respectant les spécifications données.
Cette classe a un seul attributpaquet
qui représente le tableau (la liste) des cartes contenues dans le paquet. Lors de l'initiatisation :- Si la liste fournie est vide, il faut vérifier que
nb
vaut soit32
, soit54
; - Sinon la liste devient le paquet de cartes (pour faciliter les choses, il
n'est pas utile de vérifier que chaque carte respecte les spécifications
de la classe
Carte
).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
class PaquetCartes: """ Une classe pour représenter un paquet de cartes à jouer PaquetCartes(nb, liste) : Lorsque liste vaut None, génère et mélange un paquet de nb cartes (nb doit valoir 32 ou 52). Lorsque liste est fourni et n'est pas vide, cette liste correspond au paquet. distribue_carte() renvoie la première Carte du jeu et met à jour le paquet de Cartes. distribue_jeu(nbJoueurs, nbCartes) renvoie un tableau de nbJoueurs paquets de cartes contenant nbCartes cartes s'il est possible de distribuer nbCartes à nbJoueurs. """ def __init__(self, nb, liste=None): pass def __repr__(self): pass def __str__(self): pass def melanger(self): pass def distribue_carte(self): pass def distribue_jeu(self, nbJoueurs, nbCartes): pass
Exemple de tests
>>> paquet1 = PaquetCartes(20) AssertionError: Le nombre de cartes du paquet est soit 32, soit 54 >>> paquet1 = PaquetCartes(32) >>> paquet1 [7 de COEUR, 7 de TREFLE, 9 de PIQUE, 9 de COEUR, 9 de TREFLE, 10 de COEUR, Valet de PIQUE, Valet de COEUR, Dame de COEUR, Roi de CARREAU, Valet de TREFLE, As de COEUR, 10 de CARREAU, Dame de CARREAU, Valet de CARREAU, 8 de PIQUE, 7 de CARREAU, As de PIQUE, 7 de PIQUE, Roi de COEUR, As de CARREAU, Dame de TREFLE, Dame de PIQUE, 9 de CARREAU, 10 de TREFLE, As de TREFLE, 8 de TREFLE, 8 de CARREAU, Roi de TREFLE, 10 de PIQUE, 8 de COEUR, Roi de PIQUE] >>> paquets = paquet1.distribue_jeu(4, 10) AssertionError: Distribution impossible, 4*10 est supérieur au nombre de cartes du paquet : 32. >>> paquets = paquet1.distribue_jeu(4, 8) >>> paquets [[7 de COEUR, Dame de TREFLE, 8 de PIQUE, As de TREFLE, 10 de PIQUE, Roi de TREFLE, 9 de TREFLE, Dame de PIQUE], [7 de TREFLE, 10 de COEUR, Dame de CARREAU, 7 de PIQUE, 9 de COEUR, 9 de PIQUE, Roi de PIQUE, Roi de CARREAU], [Dame de COEUR, 8 de CARREAU, Valet de CARREAU, 8 de COEUR, 10 de CARREAU, As de PIQUE, Valet de PIQUE, Roi de COEUR], [As de COEUR, As de CARREAU, 10 de TREFLE, 9 de CARREAU, 7 de CARREAU, Valet de TREFLE, 8 de TREFLE, Valet de COEUR]] >>> paquet2 = paquets[0] >>> print(paquet2) [7 de COEUR, Dame de TREFLE, 8 de PIQUE, As de TREFLE, 10 de PIQUE, Roi de TREFLE, 9 de TREFLE, Dame de PIQUE] >>> carte1 = paquet2.distribue_carte() >>> carte1 7 de COEUR >>> carte2 = paquet2.distribue_carte() >>> carte2 Dame de TREFLE >>> carte1.meme_nom(carte2) False >>> carte1.est_battue_par(carte2) True
Une solution - le code complet
from random import randint couleurs = ['PIQUE', 'COEUR', 'CARREAU', 'TREFLE'] noms = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'Valet', 'Dame', 'Roi', 'As'] class Carte: """ Une classe pour représenter une carte à jouer get_couleur() renvoie la couleur de la carte get_nom() renvoie le nom de la carte meme_nom(autreCarte) renvoie True si les cartes ont le même nom est_battue_par(autreCarte) renvoie True si la carte considérée a une valeur inférieure à celle de autreCarte """ def __init__(self, nom, couleur): assert couleur in couleurs, 'La couleur ne convient pas' assert nom in noms, 'Le nom ne convient pas' self.couleur = couleur self.nom = nom self.valeur = noms.index(self.nom) def __repr__(self): return f"{self.nom} de {self.couleur}" def __str__(self): return self.__repr__() def get_couleur(self): return self.couleur def get_nom(self): return self.nom def meme_nom(self, autreCarte): return self.nom == autreCarte.nom def est_battue_par(self, autreCarte): return self.valeur < autreCarte.valeur class PaquetCartes: """ Une classe pour représenter un paquet de cartes à jouer PaquetCartes(nb, liste) : Lorsque liste vaut None, génère et mélange un paquet de nb cartes (nb doit valoir 32 ou 52). Lorsque liste est fourni et n'est pas vide, cette liste correspond au paquet. distribue_carte() renvoie la première Carte du jeu et met à jour le paquet de Cartes. distribue_jeu(nbJoueurs, nbCartes) renvoie un tableau de nbJoueurs Paquets de cartes contenant nbCartes cartes s'il est possible de distribuer nbCartes à nbJoueurs. """ def __init__(self, nb, liste=None): if liste is None: assert nb == 32 or nb == 54, "Le nombre de cartes du paquet est soit 32, soit 54" if nb == 52: self.paquet = [Carte(nom, couleur) for nom in noms for couleur in couleurs] else: self.paquet = [Carte(noms[i], couleur) for i in range(5, len(noms)) for couleur in couleurs] else: self.paquet = liste self.melanger() def __repr__(self): return str(self.paquet) def __str__(self): return self.__repr__() def melanger(self): nb_cartes = len(self.paquet) dernier_indice = nb_cartes-1 for i in range(nb_cartes): # On retire un élément au hasard : elt = self.paquet.pop(randint(0, dernier_indice)) # On le place à la fin self.paquet.append(elt) def distribue_carte(self): carte = self.paquet.pop(0) return carte def distribue_jeu(self, nbJoueurs, nbCartes): assert nbJoueurs*nbCartes <= len(self.paquet), f"Distribution impossible, {nbJoueurs}*{nbCartes} est supérieur au nombre de cartes du paquet : {len(self.paquet)}." jeux = [] for i in range(nbJoueurs): jeux.append([]) for n in range(nbCartes): for j in range(nbJoueurs): jeux[j].append(self.distribue_carte()) paquets = [] for liste in jeux: paquets.append(PaquetCartes(nbCartes, liste)) return paquets if __name__ == "__main__": print("Création d'un paquet de 32 cartes :") paquet1 = PaquetCartes(32) print(paquet1) print("\nOn distribue pour 4 joueurs :") paquets = paquet1.distribue_jeu(4, 8) for paquet in paquets: print(paquet) print("\nOn récupère le premier paquet, on en fait un jeu :") paquet2 = paquets[0] print(paquet2) print("\nOn extrait les deux premières cartes, on teste si la première est battue par la deuxième :") carte1 = paquet2.distribue_carte() print(carte1) carte2 = paquet2.distribue_carte() print(carte2) print("Sont-elles de même valeur ?", carte1.meme_nom(carte2)) print("La première est-elle battue ?", carte1.est_battue_par(carte2))
- Si la liste fournie est vide, il faut vérifier que