Duc de Toscane avec CAML

Le problème du Duc de Toscane simulé avec CAML. On fabrique nos outils...

OCaml
(* vecteur aléatoire de n entiers entre min et max *)
let vec_alea (min: int) (max: int) (taille: int): int list =
  let rec aux_alea (size: int) (acc: int list): int list =
    if size = 0 then acc
    else aux_alea (size - 1) ((min + Random.int (max - min + 1)) :: acc)
  in aux_alea taille [];;
 
(* sommes des éléments d'une liste d'entiers *)
let somme (liste : int list): int =
  List.fold_left (+) 0 liste;;
 
(* une liste d'expériences aléatoires *)
let simul_exp (exp: unit -> 'issue) (occ: int): 'issue list =
  let rec aux_exp = fun n acc ->
    if n = occ then acc
    else aux_exp (n + 1) ((exp ()) :: acc)
  in aux_exp 0 [];;
 
(* simulations du lancer de trois dés : X = somme des faces  *)
let toscane ((): unit): int = 
  somme (vec_alea 1 6 3);; 
 
(* pour clarifier : on définit un type polymorphe pour les
   dictionnaire avec un constructeur d'arité 1  *)
type ('cle,'valeur) dictionnaire = Dict of ('cle * 'valeur) list;;
 
let list_of_dic (d: ('cle,'valeur) dictionnaire): ('cle * 'valeur) list =
  match d with Dict(li) -> li;;
 
(* renvoie la liste des couples (élément, fréquence en pourcentage) *)
let compte (liste: 'issue list) : ('issue,float) dictionnaire =
  let effectif_total = float_of_int (List.length liste) in
  let rec count (l: 'issue list) (accu: ('issue * float) list) : ('issue,float) dictionnaire =
    match l with
    | []    -> Dict(accu)
    |t :: q ->
      let c = List.partition (fun x -> x = t) l in
      count (snd c) ((t,100. *. (float_of_int (List.length (fst c))) /. effectif_total)::accu)
  in count liste [];;
 
(* on entre l'expérience et le nb de simulations et on obtient le dictionnaire des
   fréquences en pourcentage *)
let simul_dic (exp_alea: unit -> 'issue) (nb_exp: int): ('issue,float) dictionnaire =
  let li = list_of_dic (compte (simul_exp exp_alea nb_exp)) in 
  Dict(List.sort compare li);;
 
(* idem avec un joli affichage sous forme de chaîne de caractères *)
let pretty_dic (ft: ('i -> 's, unit, string) format) (dic: ('a,float) dictionnaire): ('a , string) dictionnaire =
  Dict(List.map (fun cpl -> (fst cpl, Printf.sprintf ft (snd cpl) ^ " %")) (list_of_dic dic));;
 
 
(* simule 100_000 expériences du Duc de Toscane *)
simul_dic toscane 100_000;;
 
pretty_dic "%.2f" (simul_dic toscane 100_000);;

courtesy of webmatter.de