Compare commits
3 Commits
54f14c0492
...
6d551f5497
Author | SHA1 | Date | |
---|---|---|---|
6d551f5497
|
|||
b9af6249a3
|
|||
71c5b5e5a2
|
88
bin/day2408.ml
Normal file
88
bin/day2408.ml
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
type map = { map : string; width : int; height : int }
|
||||||
|
|
||||||
|
let map_of_file fname =
|
||||||
|
let strs = Aoc.strings_of_file fname in
|
||||||
|
let width = String.length (List.hd strs) in
|
||||||
|
let map = List.fold_left ( ^ ) "" strs in
|
||||||
|
let height = String.length map / width in
|
||||||
|
{ map; width; height }
|
||||||
|
|
||||||
|
let map_length map = String.length map.map
|
||||||
|
let map_get_by_idx map idx = map.map.[idx]
|
||||||
|
let map_pos_of_idx map idx = (idx mod map.width, idx / map.width)
|
||||||
|
|
||||||
|
let map_is_valid_pos map (x, y) =
|
||||||
|
x >= 0 && x < map.width && y >= 0 && y < map.height
|
||||||
|
|
||||||
|
module CharMap = Map.Make (Char)
|
||||||
|
|
||||||
|
(** [get_station_indices map] returns a list of pairs mapping station ID to the
|
||||||
|
indices in [map] where there is a station with that ID. *)
|
||||||
|
let get_station_indices map =
|
||||||
|
let rec impl acc idx =
|
||||||
|
if idx >= map_length map then acc
|
||||||
|
else if map_get_by_idx map idx = '.' then impl acc (idx + 1)
|
||||||
|
else
|
||||||
|
let station = map_get_by_idx map idx in
|
||||||
|
let update_fn lst =
|
||||||
|
match lst with None -> Some [ idx ] | Some t -> Some (idx :: t)
|
||||||
|
in
|
||||||
|
impl (CharMap.update station update_fn acc) (idx + 1)
|
||||||
|
in
|
||||||
|
impl CharMap.empty 0 |> CharMap.to_list
|
||||||
|
|
||||||
|
(** Generate antinodes for part 1. *)
|
||||||
|
let get_antinodes1 acc _ (px, py) (px', py') =
|
||||||
|
let dx = px' - px in
|
||||||
|
let dy = py' - py in
|
||||||
|
(px - dx, py - dy) :: (px' + dx, py' + dy) :: acc
|
||||||
|
|
||||||
|
(** [add_antinodes lst map pos vel] adds antinodes at [pos + n * vel] to [lst]
|
||||||
|
for all non-negative [n] that are valid positions in [map]. *)
|
||||||
|
let rec add_antinodes lst map (x, y) (dx, dy) =
|
||||||
|
if map_is_valid_pos map (x, y) then
|
||||||
|
add_antinodes ((x, y) :: lst) map (x + dx, y + dy) (dx, dy)
|
||||||
|
else lst
|
||||||
|
|
||||||
|
(** Generate antinodes for part 2. *)
|
||||||
|
let get_antinodes2 acc map (px, py) (px', py') =
|
||||||
|
let dx = px' - px in
|
||||||
|
let dy = py' - py in
|
||||||
|
let acc' = add_antinodes acc map (px, py) (dx, dy) in
|
||||||
|
let acc'' = add_antinodes acc' map (px, py) (-dx, -dy) in
|
||||||
|
acc''
|
||||||
|
|
||||||
|
(** [process_stations map fn stations] generates a list of all antinodes for the
|
||||||
|
stations in [stations] on the map [map]. [fn acc map p p'] is called to
|
||||||
|
generate the antinode list for each pair of stations [p] and [p']. It should
|
||||||
|
add the positions of antinodes to the list [acc]. *)
|
||||||
|
let process_stations map fn stations =
|
||||||
|
let rec impl2 acc p t =
|
||||||
|
match t with
|
||||||
|
| [] -> acc
|
||||||
|
| h :: t -> impl2 (fn acc map p (map_pos_of_idx map h)) p t
|
||||||
|
in
|
||||||
|
let rec impl acc = function
|
||||||
|
| [] -> acc
|
||||||
|
| h :: t -> impl (impl2 acc (map_pos_of_idx map h) t) t
|
||||||
|
in
|
||||||
|
List.map (impl []) stations
|
||||||
|
|
||||||
|
(** [part antifn map station_indices] process all the stations in
|
||||||
|
station_indices calling [antifn acc map p p'] on all stations. Here [acc] is
|
||||||
|
a list of antinodes which [antifn] should update and return, [p] and [p']
|
||||||
|
are positions of stations to generate antinodes for. *)
|
||||||
|
let part antifn map =
|
||||||
|
get_station_indices map
|
||||||
|
|> List.map snd (* we do not care about the station IDs *)
|
||||||
|
|> process_stations map antifn
|
||||||
|
|> List.concat
|
||||||
|
|> List.filter (map_is_valid_pos map)
|
||||||
|
|> List.sort_uniq Stdlib.compare
|
||||||
|
|> List.length
|
||||||
|
|
||||||
|
let _ =
|
||||||
|
Aoc.main map_of_file
|
||||||
|
[
|
||||||
|
(string_of_int, part get_antinodes1); (string_of_int, part get_antinodes2);
|
||||||
|
]
|
12
bin/dune
12
bin/dune
@@ -1,4 +1,12 @@
|
|||||||
(executables
|
(executables
|
||||||
(public_names day2401 day2402 day2403 day2404 day2405 day2406 day2407)
|
(public_names
|
||||||
(names day2401 day2402 day2403 day2404 day2405 day2406 day2407)
|
day2401
|
||||||
|
day2402
|
||||||
|
day2403
|
||||||
|
day2404
|
||||||
|
day2405
|
||||||
|
day2406
|
||||||
|
day2407
|
||||||
|
day2408)
|
||||||
|
(names day2401 day2402 day2403 day2404 day2405 day2406 day2407 day2408)
|
||||||
(libraries str aoc))
|
(libraries str aoc))
|
||||||
|
Reference in New Issue
Block a user