56 lines
1.7 KiB
Elixir
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()
|