AoC 2023 - Day 3
Mix.install([:kino])
Section
input = Kino.Input.textarea("enter input")
Common
defmodule AoC.Day3 do
end
Part 1
lines_with_index =
input
|> Kino.Input.read()
|> String.split("\n", trim: true)
|> Enum.with_index()
nums_with_positions =
lines_with_index
|> Enum.flat_map(fn {line, i} ->
Regex.scan(~r/\d+/, line, return: :index)
|> List.flatten()
|> Enum.map(fn {j, len} ->
{(i - 1)..(i + 1)//1, (j - 1)..(j + len)//1, String.to_integer(String.slice(line, j, len))}
end)
end)
symbol_positions =
lines_with_index
|> Stream.flat_map(fn {line, i} ->
Regex.scan(~r/[^a-zA-Z0-9\.]/, line, return: :index)
|> List.flatten()
|> Enum.map(fn {j, _} -> {i, j} end)
end)
|> MapSet.new()
nums_with_positions
|> Stream.filter(fn {row_span, col_span, _n} ->
for i <- row_span,
j <- col_span,
reduce: false,
do: (acc -> acc || {i, j} in symbol_positions)
end)
|> Stream.map(&elem(&1, 2))
|> Enum.sum()
Part 2
lines_with_index
|> Stream.flat_map(fn {line, i} ->
Regex.scan(~r/\*/, line, return: :index)
|> List.flatten()
|> Enum.map(fn {j, _} -> {i, j} end)
end)
|> Stream.map(fn {i, j} ->
case Enum.filter(nums_with_positions, fn {row_span, col_span, _n} ->
i in row_span and j in col_span
end) do
[a, b] -> elem(a, 2) * elem(b, 2)
_ -> 0
end
end)
|> Enum.sum()