• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mbarbin / super-master-mind / 262

15 May 2026 02:30PM UTC coverage: 81.112% (-10.1%) from 91.171%
262

push

github

mbarbin
Upgrade dune CI to 3.23.1

1211 of 1493 relevant lines covered (81.11%)

1638737.34 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.33
/src/code.ml
1
(*********************************************************************************)
2
(*  super-master-mind: A solver for the super master mind game                   *)
3
(*  SPDX-FileCopyrightText: 2021-2025 Mathieu Barbin <mathieu.barbin@gmail.com>  *)
4
(*  SPDX-License-Identifier: MIT                                                 *)
5
(*********************************************************************************)
6

7
type t = int
8

9
let equal = Int.equal
10
let compare = Int.compare
11
let size = Cue.code_size
12

13
let cardinality =
14
  lazy
15
    (let cardinality = Lazy.force Color.cardinality in
6✔
16
     let size = Lazy.force size in
6✔
17
     let res = ref cardinality in
6✔
18
     for _ = 2 to size do
19
       res := !res * cardinality
24✔
20
     done;
21
     !res)
22
;;
23

24
module Hum = struct
25
  type t = Color.Hum.t array
26

27
  let to_dyn t = Dyn.array Color.Hum.to_dyn t
39✔
28
  let to_json t : Json.t = `List (Array.to_list t |> List.map ~f:Color.Hum.to_json)
×
29

30
  let of_json (json : Json.t) : t =
31
    match json with
×
32
    | `List l -> Array.of_list l |> Array.map ~f:Color.Hum.of_json
×
33
    | _ -> raise (Json.Invalid_json ("Expected list for [Code.Hum.t].", json))
×
34
  ;;
35

36
  let to_string t = to_json t |> Json.to_string
×
37
end
38

39
module Computing = struct
40
  type t = Color.t array
41

42
  let check_size_exn hum =
43
    let expected_size = Lazy.force size in
32,858✔
44
    let code_size = Array.length hum in
32,858✔
45
    if code_size <> expected_size
32,858✔
46
    then
47
      Code_error.raise
3✔
48
        "Invalid code size."
49
        [ "code", Hum.to_dyn hum
3✔
50
        ; "code_size", Dyn.int code_size
3✔
51
        ; "expected_size", Dyn.int expected_size
3✔
52
        ]
53
  ;;
54

55
  let create_exn hum =
56
    check_size_exn hum;
32,858✔
57
    Array.map hum ~f:Color.of_hum
32,855✔
58
  ;;
59

60
  let to_hum t = t |> Array.map ~f:Color.to_hum
32,804✔
61

62
  let of_code (i : int) : t =
63
    let size = Lazy.force size in
32,154,778✔
64
    let color_cardinality = Lazy.force Color.cardinality in
32,137,845✔
65
    let colors = Array.create ~len:size (Color.of_index_exn 0) in
31,898,455✔
66
    let remainder = ref i in
32,367,745✔
67
    for i = 0 to size - 1 do
68
      let rem = !remainder mod color_cardinality in
155,644,585✔
69
      remainder := !remainder / color_cardinality;
70
      colors.(i) <- Color.of_index_exn rem
154,483,465✔
71
    done;
72
    colors
73
  ;;
74

75
  let to_code (t : t) : int =
76
    let color_cardinality = Lazy.force Color.cardinality in
34,668✔
77
    Array.fold_right t ~init:0 ~f:(fun color acc ->
34,668✔
78
      (acc * color_cardinality) + Color.to_index color)
173,340✔
79
  ;;
80

81
  let analyze ~(solution : t) ~(candidate : t) =
82
    let solution = Array.map solution ~f:(fun i -> Some i) in
15,996,494✔
83
    let accounted = Array.map candidate ~f:(fun _ -> false) in
15,949,423✔
84
    let black = ref 0 in
15,933,056✔
85
    let white = ref 0 in
86
    Array.iteri candidate ~f:(fun i color ->
87
      match solution.(i) with
79,152,130✔
88
      | None -> assert false
89
      | Some color' ->
79,224,388✔
90
        if Color.equal color color'
91
        then (
10,664,549✔
92
          Int.incr black;
93
          accounted.(i) <- true;
10,662,949✔
94
          solution.(i) <- None));
10,661,423✔
95
    Array.iteri candidate ~f:(fun i color ->
16,092,464✔
96
      if not accounted.(i)
79,718,208✔
97
      then (
69,323,208✔
98
        accounted.(i) <- true;
99
        match
69,275,999✔
100
          Array.find_mapi solution ~f:(fun j solution ->
101
            Option.bind solution ~f:(fun solution ->
279,261,511✔
102
              if Color.equal color solution then Some j else None))
24,619,366✔
103
        with
104
        | None -> ()
44,755,305✔
105
        | Some j ->
24,629,471✔
106
          Int.incr white;
107
          solution.(j) <- None));
24,620,268✔
108
    Cue.create_exn { white = !white; black = !black }
16,134,770✔
109
  ;;
110

111
  let map_color t ~color_permutation =
112
    Array.map t ~f:(fun color -> Color_permutation.map_color color_permutation color)
1,813✔
113
  ;;
114
end
115

116
let create_exn hum = hum |> Computing.create_exn |> Computing.to_code
32,855✔
117
let to_hum t = t |> Computing.of_code |> Computing.to_hum
32,804✔
118
let to_dyn t = t |> to_hum |> Hum.to_dyn
36✔
119
let to_index t = t
32,768✔
120
let of_json_hum json = Hum.of_json json |> create_exn
×
121

122
let param =
123
  Command.Param.create'
11✔
124
    ~docv:"CODE"
125
    ~of_string:(fun s ->
126
      match Json.of_string s |> of_json_hum with
×
127
      | e -> Ok e
×
128
      | exception e -> Error (`Msg (Printexc.to_string e)))
×
129
    ~to_string:(fun t -> Hum.to_string (to_hum t))
×
130
    ()
131
;;
132

133
let check_index_exn index =
134
  let cardinality = Lazy.force cardinality in
4,293,372✔
135
  if not (0 <= index && index < cardinality)
4,293,039✔
136
  then
137
    Code_error.raise
1✔
138
      "Index out of bounds."
139
      [ "index", Dyn.int index; "cardinality", Dyn.int cardinality ]
1✔
140
;;
141

142
let of_index_exn index =
143
  check_index_exn index;
4,293,371✔
144
  index
4,293,073✔
145
;;
146

147
let analyze ~solution ~candidate =
148
  Computing.analyze
16,172,621✔
149
    ~solution:(Computing.of_code solution)
16,101,371✔
150
    ~candidate:(Computing.of_code candidate)
16,027,966✔
151
;;
152

153
let map_color t ~color_permutation =
154
  t |> Computing.of_code |> Computing.map_color ~color_permutation |> Computing.to_code
1,813✔
155
;;
156

157
let to_json t : Json.t = `Int (to_index t)
×
158

159
let of_json (json : Json.t) : t =
160
  match json with
777✔
161
  | `Int i -> of_index_exn i
777✔
162
  | _ -> raise (Json.Invalid_json ("Expected int for [Code.t].", json))
×
163
;;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc