POO et récursivité
Modélisation d'appartements¶
Un appartement est constitué (en général) de plusieurs pièces. Dans ces pièces se trouvent un ou plusieurs meubles, qui occupent une surface au sol, diminuant ainsi la surface disponible dans la pièce. L'objectif de cet exercice est de représenter cette situation à l'aide de classes en python. Les questions de cet exercice forment un ensemble, mais il n'est pas nécessaire d'avoir répondu à une question pour aborder la suivante. En particulier, on pourra utiliser les méthodes des questions précédentes même quand elles n'ont pas été codées.
-
On donne le code de la classe
Meuble. L'attributnomindique de quel meuble il s'agit (une armoire, un lit, etc.) ; l'attributsurface_solrepresente la surface qu'occupe le meuble au sol, en mètre carrés.1 2 3 4 5
class Meuble: def __init__(self, n, t): """ Meuble, str, float -> NoneType """ self.nom = n self.surface_sol = tDonner une instruction qui créé une variable
litde typeMeuble, qui représente un lit nommé "Lit Queen Size" (longueur : 2m, largeur 1,6m).1lit = Meuble("Lit Queen Size", 3.2) -
On représente une pièce d'un appartement à l'aide de la classe
Piece. Ses attributs sont les suivants :nomde typestr("chambre 1", "cuisine", par exemple).superficiede typefloat. Il s'agit de la taille de la pièce en mètre carrés.superficie_occupee, de typefloat. Vaut 0 initialement, augmente lorsque l'on ajoute des meubles.-
liste_meubles, une liste deMeuble. Initialement vide, contient la liste des meubles présents dans la pièce. -
Écrire le code python qui permet de définir une classe
Piecepossédant les attributs décrits dans l'énoncé. On écrira de plus la signature de la fonction__init__.1 2 3 4 5 6 7
class Piece: def __init__(self, nom, superficie): """ Piece, str, float -> NoneType """ self.nom = nom self.superficie = superficie self.superficie_occupee = 0 self.liste_meubles = [] -
Écrire une méthode
possede_placede la classePiecequi renvoieTruesi et seulement si la pièceselfpossède au moinssurfacemètre carrés disponibles.1 2 3 4
def possede_place(self, surface): """ Piece, float -> bool Détermine si la pièce possède surface m2 disponibles """ return self.superficie_occupee + surface < self.superficie -
Écrire une méthode
ajoutede la classePiece, qui ajoute lemeubleà la pièceself, en modifiant l'attributliste_meubles. Cette méthode mettra également à jour l'attributsuperficie_occupeeen l'incrémentant de la surface au sol occupée par le meuble. Il est cependant possible qu'il n'y ait pas suffisamment d'espace dans la pièce pour accueillir le meuble. Dans ce cas l'attributliste_meublene sera pas modifié. La méthode renverraTruesi le meuble a effectivement été ajouté à la pièce,Falsesinon.1 2 3 4 5 6 7 8
def ajoute(self, meuble): """ Pièce, Meuble -> bool """ # if meuble.surface_sol + self.superficie_occupee < self.superficie: if self.possede_place(meuble.surface_sol): self.superficie_occupee += meuble.surface_sol self.liste_meubles.append(meuble) return True return False
-
Un appartement contient une ou plusieurs pièces. On donne ci-dessous la définition de la classe
Appartement:1 2 3 4
class Appartement: def __init__(self, c): """ Appartement, [Piece] -> NoneType """ self.contenu = c-
On suppose que les variables de type
Meublesuivants ont été correctement définies.1 2 3 4 5
bain = Meuble("Baignoire", 1.2) wc = Meuble("Toilettes", 0.4) lav = Meuble("Lavabo (toilettes)", 0.1) gaz = Meuble("Gazinière", 0.25) ev = Meuble("Évier (cuisine)", 0.15)Variable litbainwclavgazevNom Lit Queen Size Baignoire Toilettes Lavabo (toilettes) Gazinière Évier (cuisine) Surface au sol 3.2 1.2 0.4 0.1 0.25 0.15 Par exemple, la variable
litest de typeMeuble,lit.nomest"Lit Queen Size"etlit.surface_solvaut3.2. À l'aide des variables décrites dans le tableau de l'énoncé, écrire le code python qui permet d'instancier une variable de typeAppartementqui représente l'appartement dont on donne le plan ci-dessous.
1 2 3 4 5 6 7 8 9 10
sdb = Piece("Salle de bain", 4.5) sdb.ajoute(wc) sdb.ajoute(bain) sdb.ajoute(lav) sal = Piece("Salon", 27) coul = Piece("Couloir", 4) cuis = Piece("Cuisine", 3) cuis.ajoute(gaz) cuis.ajoute(ev) apt = Appartement([sdb, sal, coul, cuis]) -
Écrire une méthode
prixde la classeAppartement, qui étant donné un prix de vente au mètre carré, renvoie le prix de vente total de l'appartement. Celui-ci sera obtenu en calculant la superficie totale (disponible et occupée) de l'ensemble des pièces de l'appartement, que l'on multipliera par le prix au mètre carré passé en paramètre.1 2 3 4 5 6 7
def prix(self, prix_m2): """ Appartement, float -> float Calcule le prix de vente de l'appartement. """ s = 0 for piece in self.contenu: s += piece.superficie return s*prix_m2 -
Écrire une méthode
recherche_placede la classeAppartement, qui étant donné unesuperficie(donnée en mètre carrés) renvoie la liste des pièces où on peut trouversuperficiemètre carrés disponibles.1 2 3 4 5 6 7 8
def recherche_place(self, superficie): """ Appartement, float -> [Piece] Renvoie la listes des pièces de l'appartement avec plus de superficie mètre carrés disponibles. """ l = [] for piece in self.contenu: if piece.possede_place(superficie): l.append(piece) return l
-
-
Écrire une fonction
recherche_appartqui étant donné une listecollectiond'appartements dont le prix de vente au mètre carré est de 10 000€, renvoie l'appartement dont le prix de vente est le minimum parmi ceux qui possèdent au moins 4 pièces et dont l'une des pièces possède au moins 20 mètre carrés disponibles. Si aucun appartement de la listecollectionne satisfait les conditions demandées, alors la fonction renverraNone. Toute trace de recherche, même incomplète, sera valorisée dans cette question.1 2 3 4 5 6 7 8 9
def recherche_appart(collection): """ [Appartement] -> Appartement | NoneType """ appart_mini = None prix_mini = float("inf") for appart in collection: if appart.prix(10000) < prix_mini and len(appart.contenu) >= 4 and len(appart.recherche_place(20)) > 0: appart_mini = appart prix_mini = appart.prix(10000) return appart
Des étoiles¶
-
Écrire une fonction python
etoilesqui étant donné un entiernrenvoie la chaine de caractères constituée du caractère*, répéténfois. Toute syntaxe python est acceptée.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
def etoiles(n): """ int -> NoneType Affiche n fois le caractère *. Version récursive """ if n == 0: return "" else: avant = etoiles(n - 1) return "*" + avant def etoiles(n): """ int -> NoneType Affiche n fois le caractère *. Version itérative """ s = "" for _ in range(n): s += "*" return s def etoiles(n): """ int -> NoneType Affiche n fois le caractère *. Une ligne """ return "".join(["*" for _ in range(n)])1 2
print(etoiles(2)) print(etoiles(5))** *****Rappel. Si
s1ets2sont deux chaînes de caractères, alorss1 + s2renvoie la concaténation des1avecs2. Ainsi,"bonjour" + " ! "renvoie la chaîne"bonjour ! ". -
On donne le code des fonctions
f,g,hetksuivantes.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
def f(n): """ int -> None """ if n == 1: print(etoiles(1)) else: print(etoiles(n)) f(n - 1) def g(n): """ int -> None """ if n == 1: print(etoiles(1)) else: g(n - 1) print(etoiles(n))1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
def h(n): """ int -> None """ if n == 1: print(etoiles(1)) else: h(n - 1) print(etoiles(n)) h(n - 1) def k(n): """ int -> None """ if n == 1: print(etoiles(1)) else: print(etoiles(n)) k(n - 1) print(etoiles(n))On donne également, dans le désordre les affichages réalisés par les instructions
f(3),g(3),h(3), etk(3).1h(3)* ** * *** * ** *1f(3)*** ** *1g(3)* ** ***1k(3)*** ** * ** ***Sans justifier votre réponse, déterminer quelle instruction a provoqué quel affichage.
-
On se propose d'étudier l'affichage réalisé par la fonction
usuivante.1 2 3 4 5 6 7 8 9
def u(n, i): """ int, int -> NoneType On suppose que i <= n. """ if i == n: print(etoiles(n)) else: print(etoiles(i)) u(n, i + 1) print(etoiles(i))-
Dresser l'arbre d'appel de l'instruction
u(5, 2). On représentera les appels successifs les uns en dessous des autres, et on indiquera au bon endroit le long de l'arbre les différents événements d'affichage à l'aide de la ligne de code correspondante.
-
En déduire l'affichage réalisé par
u(5, 2).1u(5, 2)** *** **** ***** **** *** ** -
Quelle erreur soulève l'instruction
u(2, 5)? Expliquer votre réponse.u(2, 5)soulève l'erreurRecursionError, car le cas de base n'est jamais atteint :u(2, 5), appelleu(2, 6)qui appelleu(2, 7)etc. Ainsi, plus de 1000 appels seront réalisés ce qui déclenchera l'erreur.
-