open Battery module BatteryBank = struct type t = Battery.t list let rec highest_joltage bb = assert (List.length bb > 0) ; match highest_joltage_aux (None, None) bb with | None, None -> 0 | Some x, Some y -> int_of_string (Battery.to_string x ^ Battery.to_string y) | _ -> failwith "highest_joltage must be two digits" and highest_joltage_aux acc = function | [] -> acc | [elt] -> ( match acc with | None, None -> (Some (Battery.of_int 0), Some elt) | Some first, None -> (Some first, Some elt) | None, Some second -> (Some second, Some elt) | Some first, Some second -> if elt > second then (Some first, Some elt) else (Some first, Some second) ) | h :: t -> highest_joltage_aux ( match acc with | None, None -> (Some h, None) | Some first, None -> let second = Battery.of_int 0 in swap_if_higher first second h | Some first, Some second -> swap_if_higher first second h | _ -> failwith "this branch should be impossible" ) t and swap_if_higher first second considering = assert (first >= second) ; let c_gt_f = Battery.compare considering first = 1 in let c_gt_s = Battery.compare considering second = 1 in match (c_gt_f, c_gt_s) with | true, true -> (Some considering, None) | false, true -> (Some first, Some considering) | true, false -> failwith "[second] should never be greater than [first]" | false, false -> (Some first, Some second) let of_string s = s |> String.to_seq |> Seq.map (fun c -> Char.escaped c |> int_of_string |> Battery.of_int) |> List.of_seq let of_list lst = lst let to_list bb = bb let pp bb = "[ " ^ ( bb |> List.map Battery.pp |> List.fold_left (fun acc b -> if acc = "" then b ^ ";" else Printf.sprintf "%s %s;" acc b ) "" ) ^ " ]" end