Parcourir la source

start solution day 9 part 1

AbderFaiz il y a 4 mois
Parent
commit
4ec7d449dd
5 fichiers modifiés avec 286 ajouts et 0 suppressions
  1. 3 0
      9/dune
  2. 40 0
      9/solve_1.ml
  3. 112 0
      9/solve_1.ml~
  4. 121 0
      9/solve_2.ml
  5. 10 0
      9/test~

+ 3 - 0
9/dune

@@ -0,0 +1,3 @@
+(executables
+ (names  solve_1 solve_2)
+ (libraries base stdio str))

+ 40 - 0
9/solve_1.ml

@@ -0,0 +1,40 @@
+open Stdio
+open Str
+
+
+let expand dm =
+  let rec aux i acc=
+    if (i >= String.length dm) then
+      acc
+    else (if (i == String.length dm -1)
+         then
+           let id = Char.chr (i/2 + int_of_char '0') in
+           let file_size = (int_of_char dm.[i] - int_of_char '0') in
+           let new_encoding = (String.make file_size id) in
+           (acc ^ new_encoding)
+         else
+           let id = Char.chr (i/2 + int_of_char '0') in
+           let file_size = (int_of_char dm.[i] - int_of_char '0') in
+           let empty_space = (int_of_char dm.[i+1] - int_of_char '0') in
+           let new_encoding = (String.make file_size id) ^ (String.make empty_space '.') in
+           aux (i+2) (acc ^ new_encoding))
+  in
+  aux 0 String.empty
+;;
+
+let calculate_checksum dm=
+  let rec aux id accum =
+    if (dm.[id] == '.') then accum
+    else
+      let block = (int_of_char dm.[id] - int_of_char '0') in
+      (aux (id+1) ((id * block) + accum))
+  in
+  aux 0 0;;
+  
+let solve = calculate_checksum "0099811188827773336446555566.............."
+;;
+
+let () =
+  printf "%s\n" (expand "2333133121414131402");
+  printf "Total: %d\n" solve;;
+

+ 112 - 0
9/solve_1.ml~

@@ -0,0 +1,112 @@
+open Stdio
+open Str
+module CharSet = Set.Make(Char)
+module IntSet = Set.Make(Int)
+
+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 encode_movement direction pos =
+  match direction with
+  | '^' -> let new_pos = pos - nb_columns in
+           if (new_pos < 0) then -1 else new_pos
+  | 'v' -> let new_pos = (pos + nb_columns) in
+           if (new_pos >= (nb_rows*nb_columns)) then -1  else new_pos
+  | '<' -> let new_pos = (pos - 1) in
+           if (new_pos mod nb_columns == nb_columns -1) then -1 else
+             (if (new_pos < 0) then -1 else new_pos)
+  | '>' -> let new_pos = (pos + 1) in
+           if (new_pos mod nb_columns == 0) then -1 else
+             (if (new_pos >= (nb_rows*nb_columns)) then -1 else new_pos)
+  | _ -> -1 (*Not supposed to happen*)
+;;
+
+let rec move_n direction pos n =
+  if (n <= 0 || pos == -1) then pos
+  else (move_n direction (encode_movement direction pos) (n-1))
+  
+
+let place_antinode_up delta_x delta_y pos =
+  let pos_x = if (delta_x > 0) then (move_n '>' pos delta_x) else (move_n '<' pos (abs delta_x))  in
+  let final_pos = if (pos_x == -1) then -1 else (move_n '^' pos_x delta_y) in
+  final_pos
+;;
+  
+let place_antinode_down delta_x delta_y pos =
+  let pos_x = if (delta_x > 0) then (move_n '<' pos delta_x) else (move_n '>' pos (abs delta_x)) in
+  let final_pos = if (pos_x == -1) then -1 else (move_n 'v' pos_x delta_y) in
+  final_pos
+;;    
+
+let get_antennas =
+    let rec aux pos accum=
+    try
+      let pos_antenna = search_forward (regexp {|[^.]|}) input pos in
+      aux (pos_antenna + 1) (CharSet.add input.[pos_antenna] accum) 
+    with Not_found -> accum
+  in
+  aux 0 CharSet.empty
+;;
+
+(* Get distance between two antennas
+   requires pos1 < pos2;
+*)
+let distance pos1 pos2 =
+  let y_pos1, x_pos1 = (pos1/nb_columns, pos1 mod nb_columns) in
+  let y_pos2, x_pos2 = (pos2/nb_columns, pos2 mod nb_columns) in
+  let x_diff, y_diff = (x_pos1 - x_pos2), (y_pos2 - y_pos1) in
+  (x_diff, y_diff)
+;;
+
+
+let create_antinodes antenna fixed_antenna_pos =
+  let rec aux pos accum =
+    try
+      let pos_antenna2 = search_forward (regexp (String.make 1 antenna)) input (pos + 1) in
+      let x_diff, y_diff = (distance fixed_antenna_pos pos_antenna2) in
+      let anti_node1 = (place_antinode_up x_diff y_diff fixed_antenna_pos) in
+      let anti_node2 = (place_antinode_down x_diff y_diff pos_antenna2) in
+      if (anti_node1 != -1) then
+        (if (anti_node2 != -1) then
+          (aux (pos_antenna2) (IntSet.add anti_node1 (IntSet.add anti_node2 accum)))
+        else (aux (pos_antenna2) (IntSet.add anti_node1 accum)))
+      else
+        (if (anti_node2 != -1) then
+          (aux (pos_antenna2) (IntSet.add anti_node2 accum))
+        else
+          (aux (pos_antenna2) accum))
+    with Not_found -> accum
+  in
+  aux fixed_antenna_pos IntSet.empty
+;;
+
+let create_all_antinodes antenna =
+  let rec aux pos accum =
+  try
+    let pos = search_forward (regexp (String.make 1 antenna)) input pos in
+    let set_positions = create_antinodes antenna pos in
+    aux (pos+1) (IntSet.union accum set_positions)
+  with Not_found -> accum
+  in
+  aux 0 IntSet.empty
+;;
+
+let solve =
+  let antinodes =
+    CharSet.fold (fun c acc -> (IntSet.union (create_all_antinodes c) acc)) get_antennas IntSet.empty in
+  IntSet.cardinal antinodes
+;;
+
+let () =
+  printf "Total: %d\n" solve;;
+

+ 121 - 0
9/solve_2.ml

@@ -0,0 +1,121 @@
+open Stdio
+open Str
+module CharSet = Set.Make(Char)
+module IntSet = Set.Make(Int)
+
+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 encode_movement direction pos =
+  match direction with
+  | '^' -> let new_pos = pos - nb_columns in
+           if (new_pos < 0) then -1 else new_pos
+  | 'v' -> let new_pos = (pos + nb_columns) in
+           if (new_pos >= (nb_rows*nb_columns)) then -1  else new_pos
+  | '<' -> let new_pos = (pos - 1) in
+           if (new_pos mod nb_columns == nb_columns -1) then -1 else
+             (if (new_pos < 0) then -1 else new_pos)
+  | '>' -> let new_pos = (pos + 1) in
+           if (new_pos mod nb_columns == 0) then -1 else
+             (if (new_pos >= (nb_rows*nb_columns)) then -1 else new_pos)
+  | _ -> -1 (*Not supposed to happen*)
+;;
+
+let rec move_n direction pos n =
+  if (n <= 0 || pos == -1) then pos
+  else (move_n direction (encode_movement direction pos) (n-1))
+  
+
+let place_antinode_up delta_x delta_y pos =
+  let rec aux accum p =
+    let pos_x = if (delta_x > 0) then (move_n '>' p delta_x) else (move_n '<' p (abs delta_x))  in
+    if (pos_x == -1) then accum
+    else
+    (let final_pos = (move_n '^' pos_x delta_y) in
+    if (final_pos == -1) then accum else (aux (final_pos::accum) final_pos))
+  in
+  aux [] pos
+;;
+
+let place_antinode_down delta_x delta_y pos =
+  let rec aux accum p =
+    let pos_x = if (delta_x > 0) then (move_n '<' p delta_x) else (move_n '>' p (abs delta_x))  in
+    if (pos_x == -1) then accum
+    else
+    (let final_pos = (move_n 'v' pos_x delta_y) in
+    if (final_pos == -1) then accum else (aux (final_pos::accum) final_pos))
+  in
+  aux [] pos
+;;
+
+let get_antennas =
+  let rec aux pos accum =
+    try
+      let pos_antenna = search_forward (regexp {|[^.]|}) input pos in
+      aux (pos_antenna + 1) (CharSet.add input.[pos_antenna] accum) 
+    with Not_found -> accum
+  in
+  aux 0 CharSet.empty
+;;
+
+(* Get distance between two antennas
+   requires pos1 < pos2;
+*)
+let distance pos1 pos2 =
+  let y_pos1, x_pos1 = (pos1/nb_columns, pos1 mod nb_columns) in
+  let y_pos2, x_pos2 = (pos2/nb_columns, pos2 mod nb_columns) in
+  let x_diff, y_diff = (x_pos1 - x_pos2), (y_pos2 - y_pos1) in
+  (x_diff, y_diff)
+;;
+
+
+let create_antinodes antenna fixed_antenna_pos =
+  let rec aux pos accum =
+    try
+      let pos_antenna2 = search_forward (regexp (String.make 1 antenna)) input (pos + 1) in
+      let x_diff, y_diff = (distance fixed_antenna_pos pos_antenna2) in
+      let anti_node1 = (place_antinode_up x_diff y_diff fixed_antenna_pos) in
+      let anti_node2 = (place_antinode_down x_diff y_diff pos_antenna2) in
+      let antenna_as_antinode_set = (IntSet.add pos_antenna2 accum) in
+      let set_antinode1 = List.fold_left (fun acc p -> IntSet.add p acc) IntSet.empty anti_node1 in
+      let set_antinode2 = List.fold_left (fun acc p -> IntSet.add p acc) set_antinode1 anti_node2 in
+      aux (pos_antenna2) (IntSet.union (IntSet.union set_antinode1 set_antinode2) antenna_as_antinode_set)
+    with Not_found -> if ((IntSet.cardinal accum) == 1) then (IntSet.remove fixed_antenna_pos accum) else accum
+  in
+  aux fixed_antenna_pos (IntSet.add fixed_antenna_pos IntSet.empty)
+;;
+
+let create_all_antinodes antenna =
+  let rec aux pos accum =
+  try
+    let pos = search_forward (regexp (String.make 1 antenna)) input pos in
+    let set_positions = create_antinodes antenna pos in
+    aux (pos+1) (IntSet.union accum set_positions)
+  with Not_found -> accum
+  in
+  aux 0 IntSet.empty
+;;
+
+let solve =
+  let antinodes =
+    CharSet.fold (fun c acc -> (IntSet.union (create_all_antinodes c) acc)) get_antennas IntSet.empty in
+  (* printf "\n\nAntinodes : \n"; *)
+  (* IntSet.iter (fun d -> printf "%d " d) antinodes; *)
+  IntSet.cardinal antinodes
+;;
+
+let () =
+  (* printf "anitnodes for A\n"; *)
+  (* IntSet.iter (fun p -> printf "%d " p) (create_antinodes 'A' 104); *)
+  printf "Total: %d\n" solve;;
+

+ 10 - 0
9/test~

@@ -0,0 +1,10 @@
+T.........
+...T......
+.T........
+..........
+..........
+..........
+..........
+..........
+..........
+..........