(** {1 Lemmas} *)
(** Alias for application operator. *)
let ($) f g = f g
(** Accessible to indexed_numbers only. *)
let current_index = ref (-1)
(** _ *)
(* NOTE: Fucking Ideone syntax highlighter does not understand
empty comments. *)
assert (index = !current_index + 1);
try
current_index := index;
result
with End_of_file ->
None
)
(** array which holds last n items only *)
class type ['item_type] last_n_items_type =
object
(** (array#set i x; array#get j) = error if i > j && i < j - n *)
method get
: int -> 'item_type
(** (array#set i x; array#get i) = x *)
method set
: int -> 'item_type
-> unit end
class ['item_type
] last_n_items
(n
: int) (initial_value
: 'item_type
) = object (self : 'item_type #last_n_items_type)
val mutable impl
= Array.make n initial_value
method get i = impl.(i mod n)
method set i (v : 'item_type) = impl.(i mod n) <- v
end
(** _ *)
fun n f ->
for i = 0 to n do
f ()
done
(** The same as {val:min} but considers -1 as +infinity. *)
fun a b ->
if a < b then b else a
(** {1 Proof} *)
let proof min_distance =
let last_n_numbers = new last_n_items min_distance 0
in
(* Ignore data length *)
ignore (next indexed_numbers
); (* Populate last_n_numbers *)
times min_distance (fun () ->
let (number, index) = next indexed_numbers in
last_n_numbers#set index number
);
(* Everybody do the flop! *)
let rec max_prod first_max_number previous_max_prod =
try
let (number, index) = next indexed_numbers in
let first_max_number =
unsigned_max first_max_number (last_n_numbers#get index)
in
let previous_max_prod =
unsigned_max previous_max_prod (first_max_number * number)
in
last_n_numbers#set index number;
max_prod first_max_number previous_max_prod
previous_max_prod
and none = (-1)
in
(* Print result *)
;;
proof 6;;