Bonjour,
Je cherche à programmer une fonction qui prenne en argument 2 ensembles, l'un étant des nombres (réels), l'autre des opérations (supposées binaires pour l'instant, par exemple +.,-.,*.), et qui rende l'ensemble des résultats différents qui peuvent être construits en utilisant une et une seule fois chaque nombre (dans l'ordre que l'on veut), et les opérations autant de fois que l'on veut. (Exemple : pour {1,3,4,6} et {+.,*.,/.,-.}, 24 est une solution ;-) ).
Pour ce faire, je me suis dit qu'un algorithme de base était de lister toutes les possibilités, pour ensuite les évaluer, enlever tous les doublons, bref, travailler sur l'ensemble trouvé. Appelons liste_des_formules la fonction qui prend en argument l'ensemble E des scalaires et F l'ensemble des lois de composition interne, et qui rend la liste de toutes les formules qu'il est possible de faire, avec les contraintes énoncées plus haut.
La représentation que j'ai choisi pour les formules est celle d'arbre binaire (les noeuds seront les lois de composition, et les feuilles seront les scalaires).
Considérons dans un premier temps qu'il n'existe qu'une seule loi de composition lc.
De manière récursive, lorsqu'on a n scalaires, on obtient "liste_des formules E n" (avec E de cardinal n) en étudiant toutes les partitions de E.
Considérons que la fonction partition : 'a list -> ('a list * 'a list) list = <fun> qui permet de donner l'ensemble des partitions en 2 éléments d'un ensemble existe déjà.
Pour bien comprendre ce que fait la fonction partition, voici un exemple :
Par ailleurs, pour ceux qui voudraient faire des tests sur leur machine, je vous propose la fonction partition suivante :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 #partition [1;2;3];; - : (int list * int list) list = [[], [1; 2; 3]; [3], [1; 2]; [2], [1; 3]; [2; 3], [1]; [1], [2; 3]; [1; 3], [2]; [1; 2], [3]; [1; 2; 3], []]
Par ailleurs, j'ai également fait ces petites fonctions dont je ne suis pas sûr :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 let partition l= let rec parties l = (*fonction qui donne l'ensemble des parties d'un ensemble*) let rec ajout a = function | [] -> [] | (liste1 :: tl) -> (a :: liste1) :: (ajout a tl) in match l with |[]->[[]] |t::q->let mem=(parties q) in mem @ (ajout t mem) in let rec appartient a=function (*fonction de base, qui dit si un élément est dans une liste*) |[]->false |b::q->if a=b then true else appartient a q in let construire_complementaire l1 l2 = (*fonction qui donne le complémentaire d'un ensemble l1 dans un ensemble l2*) let rec complementaire l1 l2= match l2 with |[]->[] |a::q->if (appartient a l1) then complementaire l1 q else a::(complementaire l1 q) in (l1,complementaire l1 l2) in let rec f=function (*fonction partition définie à partir des fonctions précédentes*) |[]->[] |a::q->(construire_complementaire a l)::(f q) in f (parties l);; partition [1;2;3];;
- Une fonction qui évalue une formule, et qui servira plus tard (je n'ai volontairement pas utilisé la division, car la division par zéro pose problème, alors que les autres sont définies partout).
- Une fonction qui définit le type loi de composition :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 let rec eval formule = match formule with |x->x |(a, lc, b) -> match lc with |add -> (eval a) +.(eval b) |mult -> (eval a) *.(eval b) |sous -> (eval a) -.(eval b) |div -> (eval a) /.(eval b);;
Enfin, la fonction qui est censée donner toutes les formules possibles :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 type 'a lc = |add of 'a * 'a |mult of 'a * 'a |sous of 'a * 'a |div of 'a * 'a ;;
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 let rec formule f lc = match F with |[x] ->[x] |_-> let rec f (partie_fixe, lc, partie_variant) = match partie_variant with |[x] ->[x] | triplet1 ::q->(partie_fixe, lc, triplet1) :: (f (partie_fixe, lc, q)) in let rec pour_chaque_partition=function |[ ]->[ ] |couple1 :: q-> let couple1 = (partie1,partie2) in (f partie1 (f partie2 partie1)) @ (pour_chaque_partition q) in pour_chaque_partition (partition f);;
Après cette petite introduction sur ce que je veux faire, ma question est alors la suivante : Pouvez-vous m'aider à continuer mon programme (pour l'instant, la fonction "formule" ne marche pas), me dire éventuellement ce qui ne va pas ou ce qui peut être amélioré, et ensuite dans un deuxième temps m'aider à généraliser (on a fait pas mal de cas particuliers : une seule loi pour l'instant, toujours pas d'écriture du programme qui donne l'ensemble des solutions recherchées, mais simplement l'ensemble des formules possibles, que des opérations binaires, etc...).
Merci d'avance pour votre aide.
Partager