solve_1.ml 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. open Stdio
  2. open Str
  3. module CharSet = Set.Make(Char)
  4. module IntSet = Set.Make(Int)
  5. let input_info =
  6. let rec one_string inp nb_rows nb_columns =
  7. let line = In_channel.input_line In_channel.stdin in
  8. match line with
  9. | None -> (inp, (nb_rows, nb_columns))
  10. | Some x -> one_string (inp ^ x) (nb_rows + 1) (String.length x)
  11. in one_string "" 0 0
  12. ;;
  13. let input = (fst input_info);;
  14. let nb_rows = (fst (snd input_info));;
  15. let nb_columns =(snd (snd input_info));;
  16. let encode_movement direction pos =
  17. match direction with
  18. | '^' -> let new_pos = pos - nb_columns in
  19. if (new_pos < 0) then -1 else new_pos
  20. | 'v' -> let new_pos = (pos + nb_columns) in
  21. if (new_pos >= (nb_rows*nb_columns)) then -1 else new_pos
  22. | '<' -> let new_pos = (pos - 1) in
  23. if (new_pos mod nb_columns == nb_columns -1) then -1 else
  24. (if (new_pos < 0) then -1 else new_pos)
  25. | '>' -> let new_pos = (pos + 1) in
  26. if (new_pos mod nb_columns == 0) then -1 else
  27. (if (new_pos >= (nb_rows*nb_columns)) then -1 else new_pos)
  28. | _ -> -1 (*Not supposed to happen*)
  29. ;;
  30. let rec move_n direction pos n =
  31. if (n <= 0 || pos == -1) then pos
  32. else (move_n direction (encode_movement direction pos) (n-1))
  33. let place_antinode_up delta_x delta_y pos =
  34. let pos_x = if (delta_x > 0) then (move_n '>' pos delta_x) else (move_n '<' pos (abs delta_x)) in
  35. let final_pos = if (pos_x == -1) then -1 else (move_n '^' pos_x delta_y) in
  36. final_pos
  37. ;;
  38. let place_antinode_down delta_x delta_y pos =
  39. let pos_x = if (delta_x > 0) then (move_n '<' pos delta_x) else (move_n '>' pos (abs delta_x)) in
  40. let final_pos = if (pos_x == -1) then -1 else (move_n 'v' pos_x delta_y) in
  41. final_pos
  42. ;;
  43. let get_antennas =
  44. let rec aux pos accum=
  45. try
  46. let pos_antenna = search_forward (regexp {|[^.]|}) input pos in
  47. aux (pos_antenna + 1) (CharSet.add input.[pos_antenna] accum)
  48. with Not_found -> accum
  49. in
  50. aux 0 CharSet.empty
  51. ;;
  52. (* Get distance between two antennas
  53. requires pos1 < pos2;
  54. *)
  55. let distance pos1 pos2 =
  56. let y_pos1, x_pos1 = (pos1/nb_columns, pos1 mod nb_columns) in
  57. let y_pos2, x_pos2 = (pos2/nb_columns, pos2 mod nb_columns) in
  58. let x_diff, y_diff = (x_pos1 - x_pos2), (y_pos2 - y_pos1) in
  59. (x_diff, y_diff)
  60. ;;
  61. let create_antinodes antenna fixed_antenna_pos =
  62. let rec aux pos accum =
  63. try
  64. let pos_antenna2 = search_forward (regexp (String.make 1 antenna)) input (pos + 1) in
  65. let x_diff, y_diff = (distance fixed_antenna_pos pos_antenna2) in
  66. let anti_node1 = (place_antinode_up x_diff y_diff fixed_antenna_pos) in
  67. let anti_node2 = (place_antinode_down x_diff y_diff pos_antenna2) in
  68. if (anti_node1 != -1) then
  69. (if (anti_node2 != -1) then
  70. (aux (pos_antenna2) (IntSet.add anti_node1 (IntSet.add anti_node2 accum)))
  71. else (aux (pos_antenna2) (IntSet.add anti_node1 accum)))
  72. else
  73. (if (anti_node2 != -1) then
  74. (aux (pos_antenna2) (IntSet.add anti_node2 accum))
  75. else
  76. (aux (pos_antenna2) accum))
  77. with Not_found -> accum
  78. in
  79. aux fixed_antenna_pos IntSet.empty
  80. ;;
  81. let create_all_antinodes antenna =
  82. let rec aux pos accum =
  83. try
  84. let pos = search_forward (regexp (String.make 1 antenna)) input pos in
  85. let set_positions = create_antinodes antenna pos in
  86. aux (pos+1) (IntSet.union accum set_positions)
  87. with Not_found -> accum
  88. in
  89. aux 0 IntSet.empty
  90. ;;
  91. let solve =
  92. let antinodes =
  93. CharSet.fold (fun c acc -> (IntSet.union (create_all_antinodes c) acc)) get_antennas IntSet.empty in
  94. IntSet.cardinal antinodes
  95. ;;
  96. let () =
  97. printf "Total: %d\n" solve;;