From 82bb54622a47bb092094c8efab8200b12817c5b4 Mon Sep 17 00:00:00 2001
From: Sébastien Dailly <sebastien@dailly.me>
Date: Fri, 11 Feb 2022 09:22:18 +0100
Subject: Hide structure in motus solver

---
 motus/lib/persistence.ml  | 46 +++++++++++++++++++++++++++++++++-------------
 motus/lib/persistence.mli | 24 ++++++++++++++++++++++++
 2 files changed, 57 insertions(+), 13 deletions(-)
 create mode 100644 motus/lib/persistence.mli

(limited to 'motus/lib')

diff --git a/motus/lib/persistence.ml b/motus/lib/persistence.ml
index 1bc20ad..6116653 100644
--- a/motus/lib/persistence.ml
+++ b/motus/lib/persistence.ml
@@ -1,3 +1,7 @@
+open StdLabels
+
+let () = Random.self_init ()
+
 type t =
   { number : int
   ; element : string list
@@ -12,7 +16,7 @@ let extract_freq : t -> (char * int) list =
   let number_2 = data.number / 2 in
   Hashtbl.fold (fun k v acc -> (k, abs (v - number_2)) :: acc) data.freq []
   (* Sort the list for a pretty printing *)
-  |> List.sort (fun v1 v2 -> snd v1 - snd v2)
+  |> List.sort ~cmp:(fun v1 v2 -> snd v1 - snd v2)
 
 
 let update_freq : (char, int) Hashtbl.t -> char -> unit =
@@ -24,15 +28,15 @@ let update_freq : (char, int) Hashtbl.t -> char -> unit =
 
 let add_word : Criteria.t list -> t -> string -> t =
  fun filters data word ->
-  match List.for_all (Criteria.check_filter word) filters with
+  match List.for_all ~f:(Criteria.check_filter word) filters with
   | true ->
       let len = String.length word in
       let chars =
-        List.init len (fun n -> String.get word n)
-        |> List.sort_uniq Char.compare
+        List.init ~len ~f:(fun n -> String.get word n)
+        |> List.sort_uniq ~cmp:Char.compare
       in
 
-      List.iter (update_freq data.freq) chars;
+      List.iter ~f:(update_freq data.freq) chars;
       { data with number = data.number + 1; element = word :: data.element }
   | false -> data
 
@@ -45,12 +49,12 @@ present many times, we consider that succeding letters does not give any more
 informations (do not consider the position here) *)
 let pick_next_word : t -> (char * int) list -> string * int =
  fun data scores ->
-  let p' : (string * int) option -> string -> (string * int) option =
+  let p' : (string list * int) option -> string -> (string list * int) option =
    fun prec word ->
     (* evaluate the score for this word *)
     let _, eval =
       String.fold_left
-        (fun (scores, score) c ->
+        ~f:(fun (scores, score) c ->
           match List.assoc_opt c scores with
           | None ->
               (* if the character has no score associated, we consider that it
@@ -59,17 +63,33 @@ let pick_next_word : t -> (char * int) list -> string * int =
               (scores, score + (data.number / 2))
           | Some v ->
               let new_scores =
-                List.filter (fun (c', _) -> not (Char.equal c c')) scores
+                List.filter ~f:(fun (c', _) -> not (Char.equal c c')) scores
               in
               (new_scores, score + v) )
-        (scores, 0)
+        ~init:(scores, 0)
         word
     in
     match prec with
-    | None -> Some (word, eval)
-    | Some (_, prec_score) when eval < prec_score -> Some (word, eval)
+    | None -> Some ([ word ], eval)
+    | Some (_, prec_score) when eval < prec_score -> Some ([ word ], eval)
+    | Some (w, prec_score) when eval = prec_score -> Some (word :: w, eval)
     | _ -> prec
   in
-  match List.fold_left p' None data.element with
+  match List.fold_left ~f:p' ~init:None data.element with
   | None -> ("", 0)
-  | Some r -> r
+  | Some (words, score) ->
+      (* Pick a reandom word from the list *)
+      let elements = List.length words in
+      let number = Random.int elements in
+      (List.nth words number, score)
+
+
+let remove_word : t -> string -> t =
+ fun t word ->
+  let element = List.filter ~f:(fun w -> not (String.equal w word)) t.element in
+  { t with element; number = t.number - 1 }
+
+
+let words : t -> string list = fun { element; _ } -> element
+
+let list_size : t -> int = fun { number; _ } -> number
diff --git a/motus/lib/persistence.mli b/motus/lib/persistence.mli
new file mode 100644
index 0000000..f5625e4
--- /dev/null
+++ b/motus/lib/persistence.mli
@@ -0,0 +1,24 @@
+type t
+
+val words : t -> string list
+
+val list_size : t -> int
+(** Number of words in the list *)
+
+val empty_data : unit -> t
+
+val extract_freq : t -> (char * int) list
+(** Evaluate the score for each char (lower is better) *)
+
+val add_word : Criteria.t list -> t -> string -> t
+(** Add a new word in the list. Check are made against the differents criteria in order to ensure that the word is valid *)
+
+val pick_next_word : t -> (char * int) list -> string * int
+(** Get the word which with the most information in it.
+
+The information is the score given to each character, representing each
+frequency in the whole word list (lower is better). If the same letter is
+present many times, we consider that succeding letters does not give any more
+informations (do not consider the position here) *)
+
+val remove_word : t -> string -> t
-- 
cgit v1.2.3