1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
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
|