advent_of_code/elixir/lib/Y2023/2023_day3.exs
2024-11-15 21:03:49 -05:00

56 lines
1.7 KiB
Elixir

contains_symbol = fn s ->
match = Regex.match?(~r/[^\d.]/, s)
match
end
grab_numbers = fn line ->
Regex.scan(~r/\d+/, line, return: :index)
|> Enum.map(fn [{index, len}] ->
{index, len, line |> String.slice(index, len) |> Integer.parse() |> elem(0)}
end)
end
part1 = fn s ->
for [pre, curr, post] <-
s
|> Enum.reject(&(String.length(&1) == 0))
|> then(fn x -> Enum.concat([""], x) end)
|> Enum.chunk(3, 1)
|> Enum.map(fn u -> Enum.map(u, &String.trim/1) end),
[{index, length}] <- Regex.scan(~r/\d+/, curr, return: :index),
contains_symbol.(String.slice(curr, max(index - 1, 0), length + 2)) ||
contains_symbol.(String.slice(pre, max(index - 1, 0), length + 2)) ||
contains_symbol.(String.slice(post, max(index - 1, 0), length + 2)),
{number, _} = String.slice(curr, index, length) |> Integer.parse() do
number
end
|> Enum.sum()
end
r_digits = ~r/\d+/
part2 = fn s ->
for [pre, curr, post] <-
s
|> Enum.reject(&(String.length(&1) == 0))
|> Enum.chunk(3, 1)
|> Enum.map(fn u -> Enum.map(u, &String.trim/1) end),
curr |> String.contains?("*"),
[{gear_idx, _}] <- Regex.scan(~r/\*/, curr, return: :index),
matches =
grab_numbers.(pre)
|> Enum.concat(grab_numbers.(post))
|> Enum.concat(grab_numbers.(curr)),
valid_matches =
matches
|> Enum.filter(fn {m_idx, m_len, _} ->
gear_idx in max(0, m_idx - 1)..(m_idx + m_len)
end),
valid_matches |> Enum.count() == 2,
[{_, _, a}, {_, _, b}] = valid_matches do
a * b
end
|> Enum.sum()
end
part1.(IO.stream()) |> IO.puts()