From 82bb54622a47bb092094c8efab8200b12817c5b4 Mon Sep 17 00:00:00 2001 From: Sébastien Dailly 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