|
|
@@ -1,58 +1,66 @@
|
|
|
open Stdio
|
|
|
open Str
|
|
|
|
|
|
-
|
|
|
-let rec construct_list l1=
|
|
|
- let line = In_channel.input_line In_channel.stdin in
|
|
|
- match line with
|
|
|
- | None -> l1
|
|
|
- | Some x -> let report = List.map int_of_string (Str.split (regexp {| |}) x) in
|
|
|
- construct_list (report::l1)
|
|
|
+let get_instructions_byregexp re line =
|
|
|
+ let rec aux pos list_positions =
|
|
|
+ try
|
|
|
+ let start_pos = search_forward re line pos in
|
|
|
+ aux (match_end ()) (list_positions@[start_pos])
|
|
|
+ with Not_found -> list_positions
|
|
|
+ in
|
|
|
+ aux 0 []
|
|
|
;;
|
|
|
|
|
|
-let monotony a b = if ((abs (a - b)) < 4) then
|
|
|
- (if (a < b) then "increasing" else
|
|
|
- (if (a > b) then "decreasing" else "ko"))
|
|
|
-else "ko"
|
|
|
+let active_regions x =
|
|
|
+ let list_dos_positions = get_instructions_byregexp (regexp {|do()|}) x in
|
|
|
+ let list_donts_positions = get_instructions_byregexp (regexp {|don't()|}) x in
|
|
|
+ let rec aux do_flag l_do l_dont pos res =
|
|
|
+ if do_flag then
|
|
|
+ (match l_do with
|
|
|
+ | hd::tl -> if (hd >= pos) then (aux false tl l_dont hd (res@[hd])) else (aux true tl l_dont pos res)
|
|
|
+ | [] -> res)
|
|
|
+ else
|
|
|
+ (match l_dont with
|
|
|
+ | hd::tl -> if (hd >= pos) then (aux true l_do tl hd (res@[hd])) else (aux false l_do tl pos res)
|
|
|
+ | [] -> res)
|
|
|
+ in
|
|
|
+ aux false list_dos_positions list_donts_positions 0 [0]
|
|
|
;;
|
|
|
|
|
|
+let rec is_active_mul mul_pos = function
|
|
|
+| a :: b :: tl -> (if (a<= mul_pos) then
|
|
|
+ (if (mul_pos <= b) then true
|
|
|
+ else is_active_mul mul_pos tl)
|
|
|
+ else false)
|
|
|
+| [a] -> mul_pos >= a
|
|
|
+| [] -> false
|
|
|
|
|
|
-let rec is_safe status tolerance prev_element l =
|
|
|
-if (tolerance < 0) then false else
|
|
|
-(match status with
|
|
|
-| "ko" -> (match l with
|
|
|
- | a :: b :: tl -> (is_safe (monotony prev_element a) (tolerance - 1) 0 (prev_element::b::tl)) ||
|
|
|
- (is_safe (monotony a b) (tolerance - 1) 0 (b::tl))
|
|
|
- | _ :: [] | [] -> true)
|
|
|
-| "increasing" -> (match l with
|
|
|
- | a :: b :: tl -> (if ((monotony a b) == "increasing") then (is_safe "increasing" tolerance a (b::tl))
|
|
|
- else ((is_safe "increasing" (tolerance-1) 0 (prev_element::b::tl)) ||
|
|
|
- (is_safe "increasing" (tolerance-1) 0 (a::tl))))
|
|
|
- | _ :: [] | [] -> true)
|
|
|
-| "decreasing" -> (match l with
|
|
|
- | a :: b :: tl -> (if ((monotony a b) == "decreasing") then (is_safe "decreasing" tolerance a (b::tl))
|
|
|
- else ((is_safe "decreasing" (tolerance-1) 0 (prev_element::b::tl)) ||
|
|
|
- (is_safe "decreasing" (tolerance-1) 0 (a::tl))))
|
|
|
- | _ :: [] | [] -> true)
|
|
|
-| "confirm_monotony" -> (match l with
|
|
|
- | a :: b :: tl -> let initial_monotonity = (monotony prev_element a) in
|
|
|
- let current_monotonity = (monotony a b) in
|
|
|
- let is_foul = (if initial_monotonity == current_monotonity then 0 else 1) in
|
|
|
- (is_safe current_monotonity (tolerance - is_foul) a (a::tl)) ||
|
|
|
- (is_safe initial_monotonity (tolerance - is_foul) a (prev_element::b::tl))
|
|
|
- | _ :: [] | [] -> true)
|
|
|
-| "init" -> (match l with
|
|
|
- | a :: b :: tl -> is_safe (if ((a == b) || (abs(a - b) >= 4)) then "ko" else "confirm_monotony") tolerance a (b::tl)
|
|
|
- | _ :: [] | [] -> true)
|
|
|
-| _ -> true )
|
|
|
-;;
|
|
|
|
|
|
+let parse_mult_instruction line=
|
|
|
+ let active_regions_list = active_regions line in
|
|
|
+ let r = regexp {|mul( *\([0-9][0-9]?[0-9]?\) *, *\([0-9][0-9]?[0-9]?\) *)|} in
|
|
|
+ let rec aux pos accum=
|
|
|
+ try
|
|
|
+ let mul_pos = search_forward r line pos in
|
|
|
+ if (is_active_mul mul_pos active_regions_list) then
|
|
|
+ (let x = float_of_string (matched_group 1 line) in
|
|
|
+ let y = float_of_string (matched_group 2 line) in
|
|
|
+ aux (match_end ()) (accum + int_of_float (x *. y)))
|
|
|
+ else
|
|
|
+ aux (match_end ()) accum
|
|
|
+ with Not_found -> accum
|
|
|
+ in
|
|
|
+ aux 0 0
|
|
|
+;;
|
|
|
|
|
|
-let rec solve accum = function
|
|
|
- | hd :: tl -> if (is_safe "init" 1 0 hd) then solve (accum + 1) tl else solve accum tl
|
|
|
- | [] -> accum
|
|
|
+let solve =
|
|
|
+ let rec one_string input =
|
|
|
+ let line = In_channel.input_line In_channel.stdin in
|
|
|
+ match line with
|
|
|
+ | None -> input
|
|
|
+ | Some x -> one_string (input ^ x)
|
|
|
+ in
|
|
|
+ parse_mult_instruction (one_string "")
|
|
|
;;
|
|
|
|
|
|
-let () =
|
|
|
- let li = construct_list [] in
|
|
|
- printf "Total: %d\n" (solve 0 li)
|
|
|
+let () = printf "Total: %d\n" (solve)
|