aboutsummaryrefslogtreecommitdiff
path: root/motus/lib/validity.ml
diff options
context:
space:
mode:
Diffstat (limited to 'motus/lib/validity.ml')
-rw-r--r--motus/lib/validity.ml98
1 files changed, 98 insertions, 0 deletions
diff --git a/motus/lib/validity.ml b/motus/lib/validity.ml
new file mode 100644
index 0000000..ae85f04
--- /dev/null
+++ b/motus/lib/validity.ml
@@ -0,0 +1,98 @@
+open StdLabels
+
+(* Enclose the type definition into a warning removval in order to hide some
+ auto-generated values *)
+[@@@warning "-32"]
+
+type t =
+ | Wellplaced
+ | Misplaced
+ | Missing
+[@@deriving enum]
+
+[@@@warning "+32"]
+
+let m = Float.of_int (1 + max)
+
+(** Get the index of a validity result *)
+let index_of_result : t array -> int =
+ fun elems ->
+ let _, value =
+ Array.fold_left elems ~init:(0., 0.) ~f:(fun (pos, acc) content ->
+ let v = Float.of_int (to_enum content) in
+ let acc' = acc +. (v *. (m ** pos)) in
+ (pos +. Float.one, acc') )
+ in
+ Float.to_int value
+
+
+let index_to_result : base:int -> int -> t array =
+ fun ~base n ->
+ let rec _f acc n i =
+ let next = Float.round (n /. m)
+ and rem = Float.(to_int @@ rem n m) in
+
+ match (rem, i) with
+ | _, 0 -> Array.of_list acc
+ | n, _ ->
+ ( match of_enum n with
+ | None -> Array.of_list acc
+ | Some v -> _f (v :: acc) next (i - 1) )
+ in
+ _f [] (Float.of_int n) base
+
+
+(** Build a sequence of all the possible status for a given number of letters *)
+let sequence : int -> t array Seq.t =
+ fun base ->
+ let max_element = Float.to_int @@ (m ** Float.of_int base) in
+
+ Seq.unfold
+ (fun n ->
+ if n < max_element then Some (index_to_result ~base n, n + 1) else None )
+ 0
+
+
+let compare_words : string -> ref:string -> t array option =
+ fun w1 ~ref ->
+ let l1 = String.length w1 in
+ if l1 <> String.length ref
+ then None
+ else
+ let result =
+ Array.init l1 ~f:(fun i ->
+ let c1 = String.get w1 i
+ and c2 = String.get ref i in
+
+ let state =
+ if Char.equal c1 c2
+ then Wellplaced
+ else if String.contains ref c1
+ then Misplaced
+ else Missing
+ in
+ state )
+ in
+ Some result
+
+
+let to_criteria : char -> int -> t -> Criteria.t list -> Criteria.t list =
+ fun c i t acc ->
+ match t with
+ | Wellplaced -> Criteria.add (Criteria.Contain (c, Some i)) acc
+ | Missing -> Criteria.add (Criteria.NotContain (c, None)) acc
+ | Misplaced ->
+ Criteria.add
+ (Criteria.NotContain (c, Some i))
+ (Criteria.add (Criteria.Contain (c, None)) acc)
+
+
+let to_criterias : string -> t array -> Criteria.t list =
+ fun word t ->
+ let l, _ =
+ Array.fold_left t ~init:([], 0) ~f:(fun (acc, i) t ->
+ let acc = to_criteria (String.get word i) i t acc in
+ (acc, i + 1) )
+ in
+
+ List.rev l