fork download
  1. open Stream
  2. open Array
  3.  
  4. (** {1 Lemmas} *)
  5.  
  6. (** Alias for application operator. *)
  7. let ($) f g = f g
  8. (** Accessible to indexed_numbers only. *)
  9. let current_index = ref (-1)
  10. (** _ *)
  11. (* NOTE: Fucking Ideone syntax highlighter does not understand
  12.   empty comments. *)
  13. let indexed_numbers : (int * int) Stream.t =
  14. Stream.from (fun index ->
  15. assert (index = !current_index + 1);
  16. try
  17. let result = Some (int_of_string $ read_line (), index) in
  18. current_index := index;
  19. result
  20. with End_of_file ->
  21. None
  22. )
  23. (** array which holds last n items only *)
  24. class type ['item_type] last_n_items_type =
  25. object
  26. (** (array#set i x; array#get j) = error if i > j && i < j - n *)
  27. method get : int -> 'item_type
  28. (** (array#set i x; array#get i) = x *)
  29. method set : int -> 'item_type -> unit
  30. end
  31. class ['item_type] last_n_items (n : int) (initial_value : 'item_type) =
  32. object (self : 'item_type #last_n_items_type)
  33. val mutable impl = Array.make n initial_value
  34. method get i = impl.(i mod n)
  35. method set i (v : 'item_type) = impl.(i mod n) <- v
  36. end
  37. (** _ *)
  38. let times : int -> (unit -> unit) -> unit =
  39. fun n f ->
  40. for i = 0 to n do
  41. f ()
  42. done
  43. (** The same as {val:min} but considers -1 as +infinity. *)
  44. let unsigned_max : int -> int -> int =
  45. fun a b ->
  46. if a < b then b else a
  47.  
  48. (** {1 Proof} *)
  49. let proof min_distance =
  50. let last_n_numbers = new last_n_items min_distance 0
  51. in
  52. (* Ignore data length *)
  53. ignore (next indexed_numbers);
  54. (* Populate last_n_numbers *)
  55. times min_distance (fun () ->
  56. let (number, index) = next indexed_numbers in
  57. last_n_numbers#set index number
  58. );
  59. (* Everybody do the flop! *)
  60. let rec max_prod first_max_number previous_max_prod =
  61. try
  62. let (number, index) = next indexed_numbers in
  63. let first_max_number =
  64. unsigned_max first_max_number (last_n_numbers#get index)
  65. in
  66. let previous_max_prod =
  67. unsigned_max previous_max_prod (first_max_number * number)
  68. in
  69. last_n_numbers#set index number;
  70. max_prod first_max_number previous_max_prod
  71. with Failure ->
  72. previous_max_prod
  73. and none = (-1)
  74. in
  75. (* Print result *)
  76. print_endline (string_of_int $ max_prod none none)
  77. ;;
  78. proof 6;;
Success #stdin #stdout 0.01s 2780KB
stdin
9
12
22
21
5
4
9
45
10
12
stdout
264