Vous devrez soumettre votre travail (un unique fichier Caml valide) en utilisant l'interface TPLab.
Le seul fait que votre programme fonctionne ne suffit pas pour avoir une bonne note. Les points suivants seront pris en compte :
Attention : les points suivants ne rapportent rien, mais ne pas les respecter pourra retrancher jusqu'à 10 points sur la note finale :
Le but de cet exercice est d'écrire un petit ensemble de fonctions pour manipuler les expressions arithmétiques telles que 3+(4 * (2+3)) ou (a+b)*(a+b) - 2*a*b.
Donnez un type de données expr
pour les expressions arithmétiques. Une expression arithmétique est :
X1
, Y
, ...)
La fonction print_int : int -> unit
permet d'afficher un entier à l'écran. En utilisant cette fonction ainsi que les fonctions print_char
et print_string
ainsi que l'opérateur ;
pour séquentialiser les commandes, écrivez une fonction print_expr : expr -> unit
.
Par exemple, votre fonction pourra afficher la chaîne (7 * X1) + (0 * X2)
pour l'expression correspondant à (7*X1) + (0*X2).
Écrivez une fonction calcule : expr -> int
qui calcule la valeur entière d'une expression arithmétique sans variables.
Modifiez cette fonction pour qu'elle prenne un argument supplémentaire env
censé contenir les valeurs des variables dans un dictionnaire (liste de couples). Vous pouvez utiliser la fonction List.assoc
pour rechercher une valeur dans un dictionnaire.
Pouvez-vous facilement transformer votre fonction en fonction récursive terminale ?
Écrivez une fonction transforme : string -> expr
qui transformera une chaîne de caractère utilisant la notation polonaise préfixée en expression arithmétique.
La notation polonaise préfixée fonctionne de la manière suivante : le symbole arithmétique (binaire) vient avant ses deux arguments. Par exemple, pour l'expression
3 + ((12 - X) * 2)
on notera
+ 3 * - 12 X 2
.
Les fonctions suivantes peuvent vous être utiles :
int_of_string : string -> int
qui transforme une chaîne de caractères en entier.
Str.split : Str.regexp -> string -> string list
qui permet de séparer une chaîne en morceaux, en utilisant une expression régulière.
Pour utiliser Str.split
, il faut soit lancer Caml avec ocaml str.cma
, soit ajouter
#load "str.cma";;
# let split s = Str.split (Str.regexp_string " ") s;; val split : string -> string list = <fun> # split "Salut, je m'appelle Bob !";; - : string list = ["Salut,"; "je"; "m'appelle"; "Bob"; "!"]
Écrivez une fonction auxiliaire de type string list -> expr * string list
qui renverra la première expression lue dans la liste, ainsi que la partie de la liste qui n'a pas servie pour créer l'expression :
aux ["+"; "*"; "12"; "X"; "Y"; "-"; "0"; "X"; ...] --> (Add(Mult(Val(12),Var("X")),Var("Y")) , ["-"; "0"; "X"; ...])
Pour tester, la fonction read_line
qui lit une chaîne de caractères sur l'entrée standard pourra vous servir...
Comment pouvez tester l'équivalence de deux expressions arithmétiques sans variable ? Écrivez la fonction correspondante equiv_sans_var : expr -> expr -> bool
.
À votre avis, comment peut-on tester l'équivalence de deux expressions arithmétiques avec des variables. (Pas la peine de le faire, donnez simplement des idées.)
Un polynôme à coefficients entiers et à plusieurs variables peut être représenté par
type monome = int * (string list) type polynome = monome list
Par exemple, le polynôme X1 2 + 2X1 X2 + X2 2 est représenté par
[(1, ["X1"; "X1"]); (2, ["X1"; "X2"]); (1, ["X2"; "X2"])]
Écrivez une fonction normalize : expr -> polynome
qui développe une expression arithmétique pour la transformer en polynôme correspondant.
Pour ceci, il sera intéressant d'écrire les fonctions
addition : polynome -> polynome -> polynome
,
multiplication_monome : monome -> polynome -> polynome
,
multiplication : polynome -> polynome -> polynome
Essayez de faire en sorte que deux expressions arithmétiques équivalentes (comme (X1+X2)*(X1+X2) et X1*X1 + 2*X1*X2 + X2*X2) soient normalisées en polynômes égaux.