0% ont trouvé ce document utile (0 vote)
120 vues3 pages

TP 5

Ce document décrit plusieurs algorithmes pour résoudre le problème du rendu de monnaie de manière optimale. Il présente une approche gloutonne, une approche récursive, et une approche mémoisée avec un module de dictionnaire. Le document contient plusieurs questions visant à implémenter et comparer l'efficacité de ces différentes approches.

Transféré par

Diams Badji
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
120 vues3 pages

TP 5

Ce document décrit plusieurs algorithmes pour résoudre le problème du rendu de monnaie de manière optimale. Il présente une approche gloutonne, une approche récursive, et une approche mémoisée avec un module de dictionnaire. Le document contient plusieurs questions visant à implémenter et comparer l'efficacité de ces différentes approches.

Transféré par

Diams Badji
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

info401 : Programmation fonctionnelle

TP 5 : rendre de la monnaie, références et modules

Pierre Hyvernat
Laboratoire de mathématiques de l’université de Savoie
bâtiment Chablais, bureau 22, poste : 94 22
email : [email protected]
www : http://www.lama.univ-savoie.fr/~hyvernat/
wiki : http://www.lama.univ-savoie.fr/wiki

Ce TP, comme les suivants, sera noté. Je ne demande aucun compte rendu à part,
mais seulement un unique fichier Caml, commenté.
- Votre fichier doit contenir du code valide et ne doit pas provoquer d’erreur
lorsqu’on l’évalue avec l’interprète Caml. (Testez avant de me l’envoyer : si
votre fichier ne s’évalue pas correctement, vous perdez automatiquement 5
points sur votre note finale.)
- Votre fichier devra contenir un commentaire contenant votre nom, prénom et
filière. (Idem, si ce n’est pas le cas, vous perdez 5 points sur votre note finale.)
- Pour m’envoyer votre TP, utilisez uniquement le formulaire dont l’adresse est :
(lien disponible sur le wiki)
http://www.lama.univ-savoie.fr/~hyvernat/envoi-TP.php

Partie 1 : comment faire de la monnaie

La boulangère dispose d’une quantité illimitée de pièces de 1, 2, 5 et 10 centimes. Elle peut


obtenir n’importe quelle somme à partir de ces pièces, mais comment faire pour minimiser le
nombre total de pièces utilisées ?

Question 1. (Préliminaire) Proposez un algorithme simple pour trouver une solution optimale.
Programmez une fonction correspondante :
monnaie glouton : int -> (int*int) list
devra prendre en argument la somme S voulue et devra renvoyer une solution qui minimise le
nombre total de pièces utilisées.
Par exemple : monnaie glouton 9 donnera [ (5,1) ; (2,2) ] car il suffit d’une pièce de
5 centimes et de 2 pièces de 2 centimes pour faire 9 centimes.

Question 2. Adaptez votre algorithme pour qu’on puisse lui donner en argument la liste des
pièces de monnaies existantes :
monnaie glouton : int list -> int -> (int*int) list
L’évaluation de l’expression monnaie glouton [1 ; 5 ; 25 ; 125] 142 devra donc donner le
résultat [ (1,125) ; (3,5) ; (2,1) ]...

Question 3. Sur la planète kcahteN, les habitants utilisent des pièces de 1, 4 et 6 dimkroz.
Que pensez-vous de l’algorithme précédent sur la planète kcahteN pour les valeurs entre 1 et
10 dimkroz ?

Question 4. Pour corriger le problème de la question précédente, nous allons utiliser un


algorithme récursif plus complexe :

1
monnaie_rec 0 _ = 0
monnaie_rec _ [] = IMPOSSIBLE (* ou bien : "+infini" *)
monnaie_rec n (p::l) = min (monnaie_rec n l)
(1 + (monnaie|rec (n-p) (p::l)))
Le premier cas correspond au cas où on n’utilise pas la pièce p, et le second au cas où on utilise
la pièce p.
Écrivez la fonction monnaie rec correspondante.
Question 5. Généralisez ce principe pour obtenir le nombre de chacune des pièces, et écrivez
la fonction correspondante :
monnaie rec : int list -> int -> (int*int) list
Question 6. Pour mémoizer la fonction, nous allons utiliser un petit module de type
module type TypeDict = sig
type key = int*(int list)
type (+’a) t (* type des dictionnaires *)
val empty : ’a t
val find : key -> ’a t -> ’a (* pour trouver une valeur *)
val add : key -> ’a -> ’a t -> ’a t (* pour ajouter une valeur *)
end
La fonction find devra lever l’exception Not found quand l’élément n’existe pas dans le
dictionnaire.
Créez un module Dict de ce type qui utilise les listes d’associations comme type des diction-
naires :
module Dict : TypeDict = struct
type key = int*int
type ’a t = (key*’a) list
let empty = ...
...
end

Question 7. En utilisant une référence vers une valeur de type “... Dict.t” (dictionnaire
avec des valeurs bien choisies), programmez une version mémoizée monnaie memoizee : int
list -> int -> (int*int) list* de la fonction précédente.
Consignes :
- réfléchissez avant de programmer,
- justifiez vos choix,
- pour garantir la transparence référentielle à l’extérieur de votre programme, utiliser une
référence locale à votre fonction.
Question 8. Comparez l’efficacité des fonctions monnaie glouton, monnaie rec et mon-
naie memoizee.
En plus du temps d’exécution, vous pourrez utiliser des compteurs pour compter le nombre
d’appels à chacune des fonctions (pour des arguments identiques).
Quelles sont, à votre avis, leur complexités théoriques. (Essayez de justifier votre réponse.)
Question 9. Pour augmenter l’efficacité de la fonction, remplacer le module Dict par une
instance du module Map de Caml en utilisant le foncteur Map.Make :
module M = struct type t=int*(int list) let compare = compare end
module Dict : TypeDict = Map.Make(M)

Expérimentez pour constater l’efficacité de la fonction monnaie memoizee obtenue avec ce


module.
* ou bien monnaie memoizee : int list -> int -> int si vous n’avez pas fait la question 5.

2
Question 10. Pour finir, écrivez une fonction test : int list -> int -> unit qui fait la
chose suivante :
- elle prend en argument en ensemble de pièces et une somme,
- elle calcule une solution en utilisant les fonctions monnaie glouton, monnaie rec et
monnaie memoizee,
- elle affiche un résumé de ce qui c’est passé. En particulier :
. elle affiche les 3 solutions trouvées,
. est-ce que l’algorithme monnaie glouton donne une solution optimale,
. elle affiche le nombre d’appels récursifs pour chacune des fonctions,
. elle lève une exception si la solution proposée par monnaie glouton est strictement
meilleure qu’une des solutions proposée par monnaie rec ou monnaie memoizee.

Pour les affichages, vous pouvez utiliser les fonctions suivantes :


- print int : int -> unit
- print string : string -> unit
- print newline : string -> unit (rajoute un saut de ligne à la fin)
- Printf.printf (très puissante, mais plus compliquée à utiliser)

Vous aimerez peut-être aussi