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

Advent of Code 2024 - Day 08

2024/day-08.livemd

Advent of Code 2024 - Day 08

Mix.install([{:kino, github: "livebook-dev/kino"}])

kino_input = Kino.Input.textarea("Please paste your input file: ")

Part 1

input = Kino.Input.read(kino_input)

input
|> String.split("\n", trim: true)
|> Enum.map(&String.graphemes/1)
|> then(fn grid ->
  Enum.flat_map(0..(length(grid) - 1), fn y ->
    Enum.reduce(0..(length(hd(grid)) - 1), [], fn x, acc ->
      case Enum.at(Enum.at(grid, y), x) do
        "." -> acc
        freq -> [{freq, x, y} | acc]
      end
    end)
  end)
  |> then(fn antennas ->
    in_bounds? = fn {x, y}, grid ->
      y >= 0 &amp;&amp; y < length(grid) &amp;&amp; x >= 0 &amp;&amp; x < length(hd(grid))
    end
    
    for {freq1, x1, y1} <- antennas,
        {freq2, x2, y2} <- antennas,
        freq1 == freq2 &amp;&amp; {x1, y1} != {x2, y2} do
      dx = x2 - x1
      dy = y2 - y1

        
      antinode1 = {x1 - dx, y1 - dy}
      antinode2 = {x2 + dx, y2 + dy}

      [antinode1, antinode2] |> Enum.filter(&amp;in_bounds?.(&amp;1, grid))
    end
    |> List.flatten()
    |> Enum.uniq()
  end)
end)
|> Enum.count()

Part 2

input = Kino.Input.read(kino_input)

input
|> String.split("\n", trim: true)
|> Enum.map(&amp;String.graphemes/1)
|> then(fn grid ->
  Enum.flat_map(0..(length(grid) - 1), fn y ->
    Enum.reduce(0..(length(hd(grid)) - 1), [], fn x, acc ->
      case Enum.at(Enum.at(grid, y), x) do
        "." -> acc
        freq -> [{freq, x, y} | acc]
      end
    end)
  end)
  |> then(fn antennas ->
    in_bounds? = fn {x, y}, grid ->
      y >= 0 &amp;&amp; y < length(grid) &amp;&amp; x >= 0 &amp;&amp; x < length(hd(grid))
    end
    
    for {freq1, x1, y1} <- antennas,
        {freq2, x2, y2} <- antennas,
        freq1 == freq2 &amp;&amp; {x1, y1} != {x2, y2} do
      dx = x2 - x1
      dy = y2 - y1

        
      antinode1 = 
        {x1, y1}
        |> Stream.iterate(fn {x, y} -> {x + dx, y + dy} end)
        |> Enum.take_while(&amp;in_bounds?.(&amp;1, grid))

      antinode2 = 
        {x2, y2}
        |> Stream.iterate(fn {x, y} -> {x - dx, y - dy} end)
        |> Enum.take_while(&amp;in_bounds?.(&amp;1, grid))

      [antinode1, antinode2]
    end
    |> List.flatten()
    |> Enum.uniq()
  end)
end)
|> Enum.count()