Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Advent 2024 - Day 8

day8.livemd

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(&amp;(&amp;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()