Advent of Code 2023 Day 3
Mix.install([
{:kino_aoc, "~> 0.1.5"}
])
Section
{:ok, puzzle_input} =
KinoAOC.download_puzzle("2023", "3", System.fetch_env!("LB_AOC_SESSION"))
lines = String.split(puzzle_input, "\n") |> Enum.with_index()
nums =
lines
|> 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)
Part 1
symbol_positions =
lines
|> 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
|> 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
|> 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, 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()