Files
aoc-2023/lib/day10.ex
bluepython508 5c04d2651e Day 10
2023-12-10 17:24:56 +00:00

94 lines
2.3 KiB
Elixir

defmodule Aoc2023.Day10 do
use Aoc2023
require Integer
@connections %{
?| => [{-1, 0}, {1, 0}],
?- => [{0, -1}, {0, 1}],
?L => [{-1, 0}, {0, 1}],
?J => [{-1, 0}, {0, -1}],
?7 => [{1, 0}, {0, -1}],
?F => [{1, 0}, {0, 1}],
?. => [],
?S => []
}
defp add_coords({y, x}, {y_, x_}), do: {y + y_, x + x_}
defp path(s_conns, conns) do
loop = fn recur, checked, checking ->
checked_ = MapSet.union(checked, checking)
checking_ =
checking
|> Enum.flat_map(&Map.get(conns, &1, []))
|> MapSet.new()
|> MapSet.difference(checked_)
if MapSet.size(checking_) > 0, do: recur.(recur, checked_, checking_), else: checked_
end
loop.(loop, MapSet.new(), MapSet.new(s_conns))
end
def parse(input) do
grid =
input
|> lines
|> Enum.map(&String.to_charlist/1)
|> Enum.with_index()
s =
grid
|> Enum.find_value(fn {line, y} ->
x = line |> Enum.find_index(&(&1 == ?S))
if x, do: {y, x}
end)
conns =
grid
|> Enum.flat_map(fn {row, y} ->
row
|> Enum.with_index()
|> Enum.map(fn {c, x} ->
{
{y, x},
Map.get(@connections, c) |> Enum.map(pipe(add_coords({y, x})))
}
end)
end)
|> Enum.into(%{})
s_conns = conns |> Enum.filter(&(s in elem(&1, 1))) |> Enum.map(pipe(elem(0)))
{s, s_conns, grid, path(s_conns, conns)}
end
def part1({_, _, _, path}) do
path
|> MapSet.size()
|> then(&(&1 / 2))
|> trunc()
end
def part2({{sy, sx}, s_conns, grid, path}) do
s_dirs = s_conns |> Enum.map(pipe(add_coords({-sy, -sx}))) |> Enum.sort()
s_char = @connections |> Enum.find(fn {_, conns} -> Enum.sort(conns) == s_dirs end) |> elem(0)
grid_ = grid |> list_map_at(sy, pipe(map_nth(0, pipe(List.replace_at(sx, s_char)))))
grid_
|> Stream.map(fn {line, y} ->
for x <- 0..length(line) - 1, reduce: {false, 0} do
{within, area} ->
cond do
{y, x} in path and Enum.at(line, x) in [?L, ?J, ?|] -> {not within, area}
{y, x} in path -> {within, area}
within -> {within, area + 1}
true -> {within, area}
end
end
|> elem(1)
end)
|> Enum.sum()
end
end