| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051 |
- open Stdio
- open Str
- let input_info =
- let rec one_string inp nb_rows nb_columns =
- let line = In_channel.input_line In_channel.stdin in
- match line with
- | None -> (inp, (nb_rows, nb_columns))
- | Some x -> one_string (inp ^ x) (nb_rows + 1) (String.length x)
- in one_string "" 0 0
- ;;
- let input = fst input_info;;
- let nb_rows = (fst (snd input_info));;
- let nb_columns = (snd (snd input_info));;
- let initial_pos = search_forward (regexp {|\^\|<\|>\|v|}) input 0;;
- let guard_direction = input.[initial_pos];;
- (*TODO handle exit from the sides*)
- let rec is_run_a_loop new_map pos direction l_pos=
- if (pos < 0 || pos >= (nb_rows*nb_columns)) then false else
- (if (List.exists (fun x -> ((fst x) == pos) && ((snd x) == direction)) (List.tl l_pos)) then
- (List.iter (fun x -> printf "(%d,%c); " (fst x) (snd x)) l_pos;printf "%d %c\n" pos direction; true) else
- match direction with
- | '^' -> let new_pos = (pos - nb_columns) in
- if (new_pos >= 0 && new_map.[new_pos] == '#') then is_run_a_loop new_map pos '>' l_pos else is_run_a_loop new_map new_pos '^' ((new_pos,'^')::l_pos)
- | 'v' -> let new_pos = (pos + nb_columns) in
- if (new_pos < (nb_rows*nb_columns) && new_map.[new_pos] == '#') then is_run_a_loop new_map pos '<' l_pos else is_run_a_loop new_map new_pos 'v' ((new_pos,'v')::l_pos)
- | '<' -> let new_pos = (pos - 1) in
- if (new_pos >= 0 && new_map.[new_pos] == '#') then is_run_a_loop new_map pos '^' l_pos else is_run_a_loop new_map new_pos '<' ((new_pos,'<')::l_pos)
- | '>' -> let new_pos = (pos + 1) in
- if (new_pos < (nb_rows*nb_columns) && new_map.[new_pos] == '#') then is_run_a_loop new_map pos 'v' l_pos else is_run_a_loop new_map new_pos '>' ((new_pos,'>')::l_pos)
- | _ -> false) (*Not supposed to happen*)
- let rec eliminate_duplicates = function
- | a :: (b :: _ as t) -> if a = b then eliminate_duplicates t else a :: eliminate_duplicates t
- | smaller -> smaller;;
-
- let solve =
- let rec aux pos accum=
- printf " i(#) = %d\n" pos;
- if pos > (nb_columns*nb_rows) then accum else
- if (pos == initial_pos) then aux (pos+1) accum else
- let map_update = String.mapi (fun i c -> if i = pos then '#' else c) input in
- if (is_run_a_loop map_update initial_pos guard_direction [(initial_pos, guard_direction)]) then aux (pos + 1) (accum + 1)
- else aux (pos + 1) accum
- in
- aux 0 0;;
- let () = printf "Total: %d\n" solve;;
|