TP - Rendu de Monnaie☘
Le problème du rendu de monnaie a été étudié en 1ère. À l'époque,
vous l'aviez résolu grâce à un algorithme glouton non optimal.
Ce TP a pour but de vous faire programmer une version optimale utilisant le
paradigme de programmation dynamique.
Conseil
Il est conseillé de se munir des résultats du TD effectué en classe.
Téléchargez le fichier « à trous » : TPE03.20.py
(clic droit -> [Enregistrer sous]) et enregistrez-le dans le répertoire
[E03-Prog_Dynamique]
.
Présentation du problème☘
On dispose d'un tableau d'entiers distincts strictement positifs.
Ce tableau, nommé pieces
, est trié par ordre croissant et son premier
élément vaut 1.
Exemples
On peut avoir :
1 |
|
ou bien :
1 |
|
ou encore :
1 |
|
Ce tableau représente les différentes valeurs de pièces possibles, chacune est disponible en quantité illimité.
On dispose aussi du montant d'une somme d'argent à rendre, nommé montant
.
Comment déterminer le nombre minimal de pièces nécessaires à la
décomposition de ce montant
?
Vous avez vu en TD qu'une méthode dynamique pour répondre à cette question
consiste à créer et compléter le contenu d'un tableau 2D nb_pieces
de
dimensions len(pieces)
et montant + 1
.
Exemple
Si le montant
vaut 21
et le tableau pieces
est [1, 7, 18]
, alors
on peut construire le tableau :
D'après ce tableau, le montant 21
nécessite 3 pièces de notre
système monétaire : 3 pièces de valeur 7
.
La relation de récurrence permettant de construire le tableau nb_pieces
est :
Partie 1 - Programmation itérative « Bottom-Up »☘
-
Complétez la définition de la fonction
creer_tab_nb_pieces()
qui doit renvoyer le tableau 2D présenté dans la partie précédente.1 2 3 4 5 6 7 8 9 10 11 12 13 14
def creer_tab_nb_pieces(montant, pieces): """ montant - int, entier positif ou nul pieces - list, tableau d'entiers positifs distincts, triés par ordre croissant Le plus petit entier DOIT avoir pour valeur 1 Sortie: list - Tableau de len(pieces) tableaux ayant chacun montant+1 éléments La case de coordonnées [i][j] contient le nombre minimal de pièces nécessaires pour décomposer le montant j avec des valeurs de pièces prises dans le sous-tableau pieces[0..i] Version itérative "Bottom-Up" >>> pieces = [1, 7, 18] >>> creer_tab_nb_pieces(21, pieces) [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], [0, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 8, 3], [0, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 1, 2, 3, 3]] """
Des pistes
-
Commencez par initialiser un tableau dont toutes les cases contiennent la même valeur. Celle-ci ne doit pas être un nombre de pièces possible pour la décomposition de
montant
. -
Quelle pièce renvoie la décomposition la plus grande en nombre de pièces ? Quelle décomposition est alors la plus grande ?
Augmentez-la un peu et vous pourrez initialiser le tableau. -
Complétez la première ligne et la première colonne.
-
Utilisez la relation de récurrence pour compléter les autres cases du tableau.
-
-
Pour mieux visaliser le tableau obtenu, complétez la définition de la fonction
affiche_tab_2D()
.
Utilisez le test ci-dessous pour adapter cet affichage.Test d'affichage
>>> affiche_tab_2D([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) 1 2 3 4 5 6 7 8 9 10 11 12
-
Utilisez les deux fonctions précédentes pour tester votre travail.
Exemple de test
>>> tab = creer_tab_nb_pieces(21, [1, 2, 5, 10, 20, 50]) >>> affiche_tab_2D(tab) 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 0 1 1 2 2 1 2 2 3 3 2 3 3 4 4 3 4 4 5 5 4 5 0 1 1 2 2 1 2 2 3 3 1 2 2 3 3 2 3 3 4 4 2 3 0 1 1 2 2 1 2 2 3 3 1 2 2 3 3 2 3 3 4 4 1 2 0 1 1 2 2 1 2 2 3 3 1 2 2 3 3 2 3 3 4 4 1 2
-
Complétez la définition de la fonction
decomposition_mini()
qui doit renvoyer la plus petite décomposition demontant
obtenue à partir du système monétaire donné par le tableaupieces
.1 2 3 4 5 6 7 8 9 10 11 12
def decomposition_mini(montant, pieces): """ montant - int, entier positif ou nul pieces - list, tableau d'entiers positifs distincts, triés par ordre croissant Le plus petit entier DOIT avoir pour valeur 1 Sortie: list - Tableau des valeurs de la décomposition de montant utilisant le minimum de pièces >>> pieces = [1, 7, 18] >>> decomposition_mini(21, pieces) [7, 7, 7] """
Des pistes
-
Parcourez le tableau créé en question 1. à partir de la dernière case puis « remontez » dans ce tableau en suivant la décomposition minimale.
-
Distinguez une décomposition identique avec un montant de pièce plus petit.
-
Sinon, effectuez un « décalage » sur la même ligne de pièce.
Exemple de test
>>> pieces = [1, 2, 5, 10, 20, 50] >>> decomposition_mini(21, pieces) [20, 1]
-
Partie 2 - Programmation récursive « Top-Down »☘
-
Complétez la définition de la fonction
creer_tab_nb_pieces_rec()
qui doit renvoyer le tableau 2D présenté dans la partie précédente, avec un tableau complété récursivement.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
def creer_tab_nb_pieces_rec(montant, pieces): """ montant - int, entier positif ou nul pieces - list, tableau d'entiers positifs distincts, triés par ordre croissant Le plus petit entier DOIT avoir pour valeur 1 Sortie: list - Tableau de len(pieces) tableaux ayant chacun montant+1 éléments La case de coordonnées [i][j] contient le nombre minimal de pièces nécessaires pour décomposer le montant j avec des valeurs de pièces prises dans le sous-tableau pieces[0..i] Version récursive "Top-Down" >>> pieces = [1, 7, 18] >>> creer_tab_nb_pieces_rec(21, pieces) [[0, 22, 22, 3, 22, 22, 22, 7, 22, 22, 22, 22, 22, 22, 14, 22, 22, 22, 22, 22, 22, 21], [0, 22, 22, 3, 22, 22, 22, 1, 22, 22, 22, 22, 22, 22, 2, 22, 22, 22, 22, 22, 22, 3], [22, 22, 22, 3, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 3]] """
Exemple de test
>>> pieces = [1, 2, 5, 10, 20, 50] >>> tab = creer_tab_nb_pieces_rec(21, pieces) >>> affiche_tab_2D(tab) 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 22 19 22 21 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 22 10 22 11 22 1 22 22 22 22 2 22 22 22 22 3 22 22 22 22 4 22 22 22 22 5 22 1 22 22 22 22 22 22 22 22 22 2 22 22 22 22 22 22 22 22 22 3 22 1 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 2 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 2
-
Expliquez à l'enseignant pourquoi autant de cases contiennent la valeur
22
. - Est-ce gênant pour la recherche de la décomposition ?
Testez-le en adaptant la fonctiondecomposition_mini()
pour qu'elle fasse appel au tableau renvoyé par la fonctioncreer_tab_nb_pieces_rec()
.