1
0
Fork 0
advent-of-code/2023/lib/2023/11.ex
2023-12-11 11:21:14 -05:00

68 lines
1.6 KiB
Elixir

import AOC
import AOCHelpers
aoc 2023, 11 do
def p1(input) do
input
|> read_input()
|> calculate_distances()
end
def p2(input) do
input
|> read_input()
|> calculate_distances(1_000_000)
end
def calculate_distances({galaxies, empty_columns, empty_rows}, expansion \\ 2) do
distance = make_distance_fn(empty_rows, empty_columns, expansion)
for [a, b] <- combinations(galaxies, 2), reduce: 0 do
acc -> acc + distance.(a, b)
end
end
def make_distance_fn(expanded_rows, expanded_columns, expansion) do
fn {x_a, y_a}, {x_b, y_b} ->
x_dist = abs(x_b - x_a)
y_dist = abs(y_b - y_a)
x_range = to_range(x_a, x_b)
y_range = to_range(y_a, y_b)
expanded_x = Enum.count(expanded_columns, &(&1 in x_range))
expanded_y = Enum.count(expanded_rows, &(&1 in y_range))
x_dist - expanded_x + expanded_x * expansion + (y_dist - expanded_y) +
expanded_y * expansion
end
end
def read_input(input) do
{grid, {x_bounds, y_bounds}} = to_grid(input)
empty_columns =
for x <- x_bounds, Enum.all?(column(grid, x, y_bounds), is?(".")), do: x
empty_rows =
for y <- y_bounds, Enum.all?(row(grid, y, x_bounds), is?(".")), do: y
galaxies =
grid
|> Enum.filter(&match?({_, "#"}, &1))
|> Enum.map(&elem(&1, 0))
{galaxies, empty_columns, empty_rows}
end
def row(grid, y, x_bounds) do
for x <- x_bounds, do: Map.get(grid, {x, y})
end
def column(grid, x, y_bounds) do
for y <- y_bounds, do: Map.get(grid, {x, y})
end
def to_range(l, r) when l < r, do: Range.new(l, r)
def to_range(l, r), do: Range.new(r, l)
end