| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566 |
- open Stdio
- open Str
- 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 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 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 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 () = printf "Total: %d\n" (solve)
|