Advent 2024 - Day 8
Mix.install([
{:kino, "~> 0.14.2"}
])
Setup
input = Kino.Input.textarea("Please paste your input file")
input = input
|> Kino.Input.read()
|> String.split("\n")
|> Enum.map(&String.graphemes/1)
max_value = length(input)
antennas = for {col, y} <- input |> Enum.with_index() do
for {val, x} <- col |> Enum.with_index() do
if val != "." do
{val, {x, y}}
end
end
end
|> List.flatten()
|> Enum.filter(&(&1))
|> Enum.group_by(fn {val, _} -> val end)
|> Enum.map(fn {k, v} -> {k, v |> Enum.map(fn {^k, pos} -> pos end)} end)
|> Map.new()
Part 1
freq_positions = for {_, positions} <- antennas do
for {a_x, a_y} = a <- positions, {b_x, b_y} = b <- positions, a != b do
{x, y} = {b_x - a_x, b_y - a_y}
{b_x + x, b_y + y}
end
end
|> List.flatten()
|> Enum.filter(fn {x, y} ->
not (x < 0 or y < 0 or x >= max_value or y >= max_value)
end)
|> MapSet.new()
|> MapSet.size()
Part 2
defmodule Griddy do
def calc(max_value, {p_x, p_y} = pos, {m_x, m_y} = movement) do
{x, y} = new_pos = {p_x + m_x, p_y + m_y}
if x < 0 or y < 0 or x >= max_value or y >= max_value do
[pos]
else
[{x, y}] ++ calc(max_value, new_pos, movement)
end
end
end
freq_positions = for {_, positions} <- antennas do
for {a_x, a_y} = a <- positions, {b_x, b_y} = b <- positions, a != b do
movement = {b_x - a_x, b_y - a_y}
[{b_x, b_y}] ++ Griddy.calc(max_value, {b_x, b_y}, movement)
end
end
|> List.flatten()
|> Enum.filter(fn {x, y} ->
not (x < 0 or y < 0 or x >= max_value or y >= max_value)
end)
|> MapSet.new()
|> MapSet.size()