solve_2.ml 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. open Stdio
  2. open Str
  3. let input_info =
  4. let rec one_string inp nb_rows nb_columns =
  5. let line = In_channel.input_line In_channel.stdin in
  6. match line with
  7. | None -> (inp, (nb_rows, nb_columns))
  8. | Some x -> one_string (inp ^ x) (nb_rows + 1) (String.length x)
  9. in one_string "" 0 0
  10. ;;
  11. let input = fst input_info;;
  12. let nb_rows = (fst (snd input_info));;
  13. let nb_columns = (snd (snd input_info));;
  14. let initial_pos = search_forward (regexp {|\^\|<\|>\|v|}) input 0;;
  15. let guard_direction = input.[initial_pos];;
  16. (*TODO handle exit from the sides*)
  17. let rec is_run_a_loop new_map pos direction l_pos=
  18. if (pos < 0 || pos >= (nb_rows*nb_columns)) then false else
  19. (if (List.exists (fun x -> ((fst x) == pos) && ((snd x) == direction)) (List.tl l_pos)) then
  20. (List.iter (fun x -> printf "(%d,%c); " (fst x) (snd x)) l_pos;printf "%d %c\n" pos direction; true) else
  21. match direction with
  22. | '^' -> let new_pos = (pos - nb_columns) in
  23. 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)
  24. | 'v' -> let new_pos = (pos + nb_columns) in
  25. 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)
  26. | '<' -> let new_pos = (pos - 1) in
  27. 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)
  28. | '>' -> let new_pos = (pos + 1) in
  29. 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)
  30. | _ -> false) (*Not supposed to happen*)
  31. let rec eliminate_duplicates = function
  32. | a :: (b :: _ as t) -> if a = b then eliminate_duplicates t else a :: eliminate_duplicates t
  33. | smaller -> smaller;;
  34. let solve =
  35. let rec aux pos accum=
  36. printf " i(#) = %d\n" pos;
  37. if pos > (nb_columns*nb_rows) then accum else
  38. if (pos == initial_pos) then aux (pos+1) accum else
  39. let map_update = String.mapi (fun i c -> if i = pos then '#' else c) input in
  40. if (is_run_a_loop map_update initial_pos guard_direction [(initial_pos, guard_direction)]) then aux (pos + 1) (accum + 1)
  41. else aux (pos + 1) accum
  42. in
  43. aux 0 0;;
  44. let () = printf "Total: %d\n" solve;;