On se donne deux représentations différentes des complexes:
cartesien
polaire
type cartesien = {re: float; im: float}
type polaire = {modulus: float; arg: float}
polaire_to_cartesien
qui convertit un complexe sous forme polaire vers sa représentation cartésienne.cartesien_to_polaire
qui convertit un complexe sous forme cartésienne vers sa représentation polaire. On rappelle l'existence de la fonction atan2
telle que atan2 y x
renvoie une mesure de l'angle entre le vecteur directeur de l'axe des abscisses et le vecteur de coordonnées (x, y).complexe
qui permet de travailler simultanément sur les deux représentations possibles.conj
qui renvoie le conjugué d'un complexe. Le type de la fonction doit donc être complexe -> complexe
.add: complexe -> complexe -> complexe
qui calcule la somme de deux nombres complexes.mul: complexe -> complexe -> complexe
qui calcule le produit de deux nombres complexes.Un tas, aussi appellé file de priorité est une structure de données qui dispose des opérations suivantes:
get_min
: renvoie le plus petit élément du tasremove_min
: enlève le plus petit élément du tasinsert x
: ajoute l'élément x
au tas Un tas d'appariement (en anglais pairing heap) est un tas qui admet facilement une implémentation "purement fonctionnelle" (on dira plutôt persistante, au sens où on ne modifie pas de manière visible la structure de données, on en obtient toujours une copie avec la mise à jour effectuée). On supposera dans la suite pour simplifier que les éléments d'un tas sont des entiers (on verra plus tard comment on pourrait généraliser de manière propre à un ensemble ordonné quelconque).
pairing_tree
permettant de représenter un arbre d'appariement.pairing_heap
.get_min
.merge2 : pairing_heap -> pairing_heap -> pairing_heap
qui fusionne deux tas.
insert: int -> pairing_heap -> pairing_heap
. Pour cela on crée un nouveau tas avec l'élément à insérer et on le fusionne avec le tas passé en paramètre.remove_min: pairing_tree -> pairing_heap
n'est définie que sur un tas non vide (donc un arbre). Il suffit de fusionner tous les fils de la racine. On doit donc définir une fonction auxiliaire merge: pairing_tree list -> pairing_heap
qui fusionne un nombre arbitraire d'arbres. On procède par récurrence sur le nombre d'arbres en utilisant la fonction merge2
définie précédemment:t1
et t2
et encore une liste tl
d'autres arbres, on fusionne d'une part t1
et t2
, d'autre part on fusionne tl
par récurrence, puis on fusionne ces deux tas fusionnés.from_list
qui crée un tas d'appariement à partir d'une listeto_list
qui crée la liste (ordonnée) des éléments d'un tas d'appariementheap_sort
qui trie une liste par l'algorithme du tri par tas.On représente un monôme par son coefficient (non nul) et son degré. Un polynôme "creux" (avec beaucoup de coefficients à zéro) est représenté succinctement par la liste de ses monômes non nuls triée par degrés décroissants.
type monome = {coeff: float; deg: int}
type polynome = monome list
Remarquez que le type polynome
est un alias du type monome list
. On verra plus tard comment abstraire et rendre opaque un type tel que polynome
pour mieux mettre en avant le fait qu'un polynôme est une liste de monômes qui vérifie certains invariants, et non une liste quelconque de monômes. Mais comme c'était déjà le cas dans l'exercice précédent, toutes les opérations que nous allons définir sur ce type concret devront préserver ces invariants.
degree
qui renvoie le degré d'un polynôme.degree
? Pouvons-nous y faire quelque chose?++
qui réalise la somme de deux polynômes.~~
qui renvoie l'opposé d'un polynôme. En déduire l'opérateur --
qui réalise la différence de deux polynômes.mult_monome
qui réalise le produit d'un monôme et d'un polynôme. En déduire l'opérateur **
qui réalise le produit de deux polynômes.//
qui réalise la division euclidienne de deux polynômes.monomes_to_polynome
qui prend en argument une liste de monômes sans aucune contrainte et qui renvoie le polynôme qui correspond à leur somme.