AbdoFizzy преди 6 месеца
родител
ревизия
e9dfb36cb0
променени са 3 файла, в които са добавени 56 реда и са изтрити 48 реда
  1. 1 1
      3/solve_1.ml
  2. 54 46
      3/solve_2.ml
  3. 1 1
      README.md

+ 1 - 1
3/solve_1.ml

@@ -12,7 +12,7 @@ let parse_mult_instruction line=
     with Not_found -> accum
   in
     aux 0 0
-  ;;
+;;
 let rec solve accum =
   let line = In_channel.input_line In_channel.stdin in
   match line with

+ 54 - 46
3/solve_2.ml

@@ -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)

+ 1 - 1
README.md

@@ -44,7 +44,7 @@ replace `<part_number>` with 1 for Part 1 or 2 for Part 2
 |-----|--------|--------|
 | 1   | ✅     | ✅     |
 | 2   | ✅     | ✅     |
-| 3   | ✅     |      |
+| 3   | ✅     |      |
 | 4   | ⬜     | ⬜     |
 | ... | ...    | ...    |
 | 25  | ⬜     | ⬜     |