day 14
This commit is contained in:
117
14/main.ml
Normal file
117
14/main.ml
Normal file
@@ -0,0 +1,117 @@
|
||||
open Printf;;
|
||||
open Buffer;;
|
||||
open Str;;
|
||||
|
||||
let read_whole_file f =
|
||||
let s = really_input_string f (in_channel_length f) in
|
||||
close_in f;
|
||||
s
|
||||
|
||||
let rec find_all_numbers pos str =
|
||||
try
|
||||
let re = Str.regexp "-?[0-9]+" in
|
||||
let new_pos = Str.search_forward re str pos in
|
||||
let n_str = Str.matched_group 0 str in
|
||||
let n = int_of_string n_str in
|
||||
n :: find_all_numbers (new_pos + String.length n_str) str
|
||||
with Not_found -> []
|
||||
|
||||
let rec to_quadruples lst =
|
||||
match lst with
|
||||
| n1 :: n2 :: n3 :: n4 :: tail ->
|
||||
(n1, n2, n3, n4) :: to_quadruples tail
|
||||
| _ -> []
|
||||
|
||||
let true_modulo a b =
|
||||
((a mod b) + b) mod b
|
||||
|
||||
let find_state_after_steps (upper_x, upper_y) steps (x, y, vx, vy) =
|
||||
(true_modulo (x + vx * steps) upper_x, true_modulo (y + vy * steps) upper_y, vx, vy)
|
||||
|
||||
let transform_all_states (upper_x, upper_y) steps states_list =
|
||||
List.map (find_state_after_steps (upper_x, upper_y) steps) states_list
|
||||
|
||||
let count_in_area (lower_x, lower_y) (upper_x, upper_y) states_list =
|
||||
states_list
|
||||
|> List.filter (fun (x, y, _, _) -> lower_x <= x && x < upper_x && lower_y <= y && y < upper_y)
|
||||
|> List.length
|
||||
|
||||
let get_safety (upper_x, upper_y) states_list =
|
||||
count_in_area (0, 0) (upper_x / 2, upper_y / 2) states_list
|
||||
* count_in_area (upper_x / 2 + 1, 0) (upper_x, upper_y / 2) states_list
|
||||
* count_in_area (0, upper_y / 2 + 1) (upper_x / 2, upper_y) states_list
|
||||
* count_in_area (upper_x / 2 + 1, upper_y / 2 + 1) (upper_x, upper_y) states_list
|
||||
|
||||
module IntPairs =
|
||||
struct
|
||||
type t = int * int
|
||||
let compare (x0,y0) (x1,y1) =
|
||||
match Stdlib.compare x0 x1 with
|
||||
0 -> Stdlib.compare y0 y1
|
||||
| c -> c
|
||||
end
|
||||
module IntPairsSet = Set.Make(IntPairs)
|
||||
|
||||
let rec count_cluster occupied_set (x, y) =
|
||||
match IntPairsSet.find_opt (x, y) occupied_set with
|
||||
| Some _ ->
|
||||
[(x - 1, y); (x, y - 1); (x + 1, y); (x, y + 1)]
|
||||
|> List.fold_left (
|
||||
fun (acc_count, acc_set) pos ->
|
||||
let inner_count, new_set = count_cluster acc_set pos in
|
||||
(acc_count + inner_count, new_set)
|
||||
)
|
||||
(1, IntPairsSet.remove (x, y) occupied_set)
|
||||
| None -> (0, occupied_set)
|
||||
|
||||
let rec find_all_clusters_inner occupied_set =
|
||||
match IntPairsSet.min_elt_opt occupied_set with
|
||||
| Some root ->
|
||||
let count, new_set = count_cluster occupied_set root in
|
||||
count :: find_all_clusters_inner new_set
|
||||
| None -> []
|
||||
|
||||
let find_all_clusters (upper_x, upper_y) state_list =
|
||||
let occupied = List.fold_left (fun set (x, y, _, _) -> IntPairsSet.add (x, y) set) IntPairsSet.empty state_list in
|
||||
find_all_clusters_inner occupied
|
||||
|> List.sort (fun a b -> Stdlib.compare b a)
|
||||
|
||||
let print_field (upper_x, upper_y) state_list =
|
||||
let arr = Array.make_matrix upper_y upper_x '.' in
|
||||
List.iter (fun (x, y, _, _) -> arr.(y).(x) <- '#') state_list;
|
||||
arr
|
||||
|> Array.iter (fun row -> row
|
||||
|> Array.iter (fun x -> print_char x);
|
||||
print_endline "")
|
||||
|
||||
let is_probably_a_tree_with_border cluster_sizes =
|
||||
match cluster_sizes with
|
||||
| _ :: n2 :: tail -> begin
|
||||
match tail with
|
||||
| n3 :: _ -> n3 * 20 < n2
|
||||
| _ -> true
|
||||
end
|
||||
| _ -> false
|
||||
|
||||
let rec search_for_a_tree (upper_x, upper_y) state_list i =
|
||||
let cluster_sizes = find_all_clusters (upper_x, upper_y) state_list in
|
||||
if is_probably_a_tree_with_border cluster_sizes then
|
||||
i
|
||||
else if i > upper_x * upper_y then
|
||||
-1
|
||||
else
|
||||
search_for_a_tree (upper_x, upper_y) (transform_all_states (upper_x, upper_y) 1 state_list) (i + 1)
|
||||
|
||||
let () =
|
||||
let f = open_in_bin "input.txt" in
|
||||
let upper_x = 101 in
|
||||
let upper_y = 103 in
|
||||
let robots = f
|
||||
|> read_whole_file
|
||||
|> find_all_numbers 0
|
||||
|> to_quadruples in
|
||||
let final_states = transform_all_states (upper_x, upper_y) 100 robots in
|
||||
let result = get_safety (upper_x, upper_y) final_states in
|
||||
let result2 = search_for_a_tree (upper_x, upper_y) robots 0 in
|
||||
print_field (upper_x, upper_y) (transform_all_states (upper_x, upper_y) result2 robots);
|
||||
printf "%d\n%d\n" result result2
|
Reference in New Issue
Block a user