<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="349021" data-post-id="349021">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="ken-kost" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/ken-kost/120/40209_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  ken-kost
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Here is mine:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Aoc2024.Solutions.Y24.Day08 do
  alias AoC.Input

  def parse(input, _part) do
    stream = Input.stream!(input, trim: true)

    antennas =
      stream
      |&gt; Stream.with_index()
      |&gt; Enum.reduce(%{}, fn {line, x}, antennas -&gt;
        line
        |&gt; String.to_charlist()
        |&gt; Stream.with_index()
        |&gt; Enum.reduce(antennas, fn
          {?., _}, antennas -&gt; antennas
          {symbol, y}, antennas -&gt; Map.update(antennas, symbol, [{x, y}], &amp;[{x, y} | &amp;1])
        end)
      end)
      |&gt; Map.values()

    row_end = Enum.count(stream) - 1
    col_end = length(String.to_charlist(Enum.at(stream, 0))) - 1

    {antennas, row_end, col_end}
  end

  def part_one({antennas, row_end, col_end}) do
    antennas
    |&gt; generate_combinations()
    |&gt; Enum.reduce(MapSet.new(), fn combinations, antinodes -&gt;
      Enum.reduce(combinations, antinodes, fn {{x1, y1}, {x2, y2}}, antinodes -&gt;
        antinodes
        |&gt; add_antinodes(x1, y1, x2 - x1, y2 - y1, row_end, col_end)
        |&gt; add_antinodes(x2, y2, x1 - x2, y1 - y2, row_end, col_end)
      end)
    end)
    |&gt; Enum.count()
  end

  def part_two({antennas, row_end, col_end}) do
    antennas
    |&gt; generate_combinations()
    |&gt; Enum.reduce(MapSet.new(List.flatten(antennas)), fn combinations, antinodes -&gt;
      Enum.reduce(combinations, antinodes, fn {{x1, y1}, {x2, y2}}, antinodes -&gt;
        antinodes
        |&gt; add_antinodes_recursive(x1, y1, x2 - x1, y2 - y1, row_end, col_end)
        |&gt; add_antinodes_recursive(x2, y2, x1 - x2, y1 - y2, row_end, col_end)
      end)
    end)
    |&gt; Enum.count()
  end

  defp generate_combinations(antennas) do
    for antenna &lt;- antennas do
      for {a, x} &lt;- Enum.with_index(antenna),
          {b, y} &lt;- Enum.with_index(antenna),
          x &lt; y,
          do: {a, b}
    end
  end

  defp add_antinodes(antinodes, x_original, y_original, dx, dy, row_end, col_end) do
    {x, y} = {x_original - dx, y_original - dy}

    if x &gt;= 0 and x &lt;= row_end and y &gt;= 0 and y &lt;= col_end do
      MapSet.put(antinodes, {x, y})
    else
      antinodes
    end
  end

  defp add_antinodes_recursive(antinodes, x_original, y_original, dx, dy, row_end, col_end) do
    {x, y} = {x_original - dx, y_original - dy}

    if x &gt;= 0 and x &lt;= row_end and y &gt;= 0 and y &lt;= col_end do
      antinodes = MapSet.put(antinodes, {x, y})
      add_antinodes_recursive(antinodes, x, y, dx, dy, row_end, col_end)
    else
      antinodes
    end
  end
end
</code></pre>
<p>Can somebody explain to me why is part 2 faster although it’s the same kind of function for calculation as in part 1 only recursive. <img src="https://forum.elixirforum.com/images/emoji/apple/confused.png?v=15" title=":confused:" class="emoji" alt=":confused:" loading="lazy" width="20" height="20"></p>
<pre data-code-wrap="elixir"><code class="lang-elixir">Solution for 2024 day 8
part_one: 376 in 8.85ms
part_two: 1352 in 1.22ms
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="349021" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/advent-of-code-2024-day-8/67956/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-349021" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="349021"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #11"></div>
  </section>
</div>
    <div class="postbit" id="349029" data-post-id="349029">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="billylanchantin" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/billylanchantin/120/28428_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  billylanchantin
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p><a class="mention" href="/u/ken-kost" rel="nofollow">@ken-kost</a> your part 1 was faster for me. I’m not using <a href="https://github.com/lud/aoc/blob/main/lib/aoc/input.ex" rel="noopener nofollow ugc"><code>aoc</code></a> though so that might have something to do with it?</p>
<p>I ran:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">Benchee.run(%{
  "part1" =&gt; fn -&gt;
    "inputs/day08/input2.txt"
    |&gt; Aoc2024.Solutions.Y24.Day08.parse(1)
    |&gt; Aoc2024.Solutions.Y24.Day08.part_one()
  end,
  "part2" =&gt; fn -&gt;
    "inputs/day08/input2.txt"
    |&gt; Aoc2024.Solutions.Y24.Day08.parse(2)
    |&gt; Aoc2024.Solutions.Y24.Day08.part_two()
  end
})
</code></pre>
<p>After replacing the <code>Aoc.Input</code> part with:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir"># Before
stream = Input.stream!(input, trim: true)

# After
stream =
  input
  |&gt; File.stream!()
  |&gt; Stream.map(&amp;String.trim/1)
  |&gt; Stream.reject(&amp;(&amp;1 == ""))
</code></pre>
<p>and I got:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">Name            ips        average  deviation         median         99th %
part1        1.25 K        0.80 ms    ±39.13%        0.75 ms        1.43 ms
part2        0.99 K        1.01 ms    ±19.68%        0.95 ms        1.70 ms
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="349029" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/advent-of-code-2024-day-8/67956/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-349029" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="349029"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #12"></div>
  </section>
</div>
    <div class="postbit" id="349055" data-post-id="349055">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="Aetherus" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/Aetherus/120/17203_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  Aetherus
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Today’s problem is more like a reading comprehension problem than an algorithm problem, especially for a non English native speaker. Fortunately, I was a student of physics when I was at university, and this problem brings me back to those days.</p>
<p><a href="https://github.com/Aetherus/advent-of-code/blob/f78c7446e5a3777b4de6bd53a1a31255a75828ca/2024/day-08.livemd" class="onebox" target="_blank" rel="noopener nofollow ugc">https://github.com/Aetherus/advent-of-code/blob/f78c7446e5a3777b4de6bd53a1a31255a75828ca/2024/day-08.livemd</a></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="349055" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/advent-of-code-2024-day-8/67956/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-349055" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="349055"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #13"></div>
  </section>
</div>
    <div class="postbit" id="349080" data-post-id="349080">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="jarlah" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jarlah/120/24789_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  jarlah
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I really liked how this worked out in the end &lt;3</p>
<p><a href="https://github.com/jarlah/advent_of_code/blob/master/lib/2024/day_8/Part1.ex" class="onebox" target="_blank" rel="noopener nofollow ugc">https://github.com/jarlah/advent_of_code/blob/master/lib/2024/day_8/Part1.ex</a></p>
<p>and i like to use structs as you can see. It saves me from hidden issues like calling non existing keys on maps … and getting nil back …</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="349080" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/advent-of-code-2024-day-8/67956/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-349080" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="349080"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #14"></div>
  </section>
</div>
    <div class="postbit" id="349086" data-post-id="349086">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="jarlah" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jarlah/120/24789_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  jarlah
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>i just changed the existing part1 soluition for part2 as always</p>
<p><a href="https://github.com/jarlah/advent_of_code/blob/master/lib/2024/day_8/Part1.ex#L51" class="onebox" target="_blank" rel="noopener nofollow ugc">https://github.com/jarlah/advent_of_code/blob/master/lib/2024/day_8/Part1.ex#L51</a></p>
<p>this was a fun excercice <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="349086" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/advent-of-code-2024-day-8/67956/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-349086" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="349086"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #15"></div>
  </section>
</div>
    <div class="postbit" id="349088" data-post-id="349088">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="jarlah" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jarlah/120/24789_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  jarlah
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>btw i see most of you try to make it as few lines of possible and as fast as possible .. but i just sincerely enjoy doing the exercises <img src="https://forum.elixirforum.com/images/emoji/apple/wink.png?v=15" title=":wink:" class="emoji" alt=":wink:" loading="lazy" width="20" height="20"> I wonder what i will do rest of the year now, after december .. excercism ?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="349088" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/advent-of-code-2024-day-8/67956/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-349088" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="349088"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #16"></div>
  </section>
</div>
    <div class="postbit" id="349099" data-post-id="349099">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="sevenseacat" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sevenseacat/120/23153_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  sevenseacat
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Author of Ash Framework</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>There’s always previous year puzzles to do, if you haven’t done those!</p>
<p><a href="https://everybody.codes/" rel="noopener nofollow ugc">https://everybody.codes/</a> is anothe one that popped up last month for more puzzley goodness</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="349099" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/advent-of-code-2024-day-8/67956/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-349099" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="349099"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #17"></div>
  </section>
</div>
    <div class="postbit" id="349160" data-post-id="349160">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="mwilsoncoding" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mwilsoncoding/120/36815_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  mwilsoncoding
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Catching back up.</p>
<p>Here’s my pt 1:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">#!/usr/bin/env elixir

defmodule Day8.Part1 do
  @open_space ~c"." |&gt; List.first()

  defp parse(str) do
    [row | _rows] =
      rows =
      str
      |&gt; String.split("\n")
      |&gt; Enum.map(&amp;to_charlist/1)

    height = Enum.count(rows)
    length = Enum.count(row)

    antennae =
      for y &lt;- 0..(height - 1), x &lt;- 0..(length - 1) do
        {x, y}
      end
      |&gt; Enum.reduce(
        %{},
        fn {x, y} = pos, acc -&gt;
          c = rows |&gt; Enum.at(y) |&gt; Enum.at(x)

          if c == @open_space,
            do: acc,
            else: acc |&gt; Map.update("#{c}", [pos], fn coordinates -&gt; [pos | coordinates] end)
        end
      )

    %{
      antennae: antennae,
      height: height,
      length: length
    }
  end

  defp on_board?(height, length, {x, y}) when x &lt; 0 or x &gt;= length or y &lt; 0 or y &gt;= height,
    do: false

  defp on_board?(_height, _length, _pair), do: true

  # Produce a List of coordinate pairs representing antinodes
  defp pairwise_antinodes_on_board(height, length, antennae) do
    Stream.unfold(
      antennae,
      fn
        [] -&gt; nil
        [_h | t] = antennae -&gt; {antennae, t}
      end
    )
    |&gt; Enum.map(fn antennae -&gt; pairwise_antinodes_on_board_for_antenna(antennae, height, length) end)
    |&gt; List.flatten()
  end

  defp pairwise_antinodes_on_board_for_antenna(
         [_antenna],
         _height,
         _length
       ),
       do: []

  defp pairwise_antinodes_on_board_for_antenna(
         [{x_1, y_1} = antenna_1, {x_2, y_2} = _antenna_2 | antennae],
         height,
         length
       )
       when abs(x_1 - x_2) &gt; length / 2 or abs(y_1 - y_2) &gt; height / 2,
       do: pairwise_antinodes_on_board_for_antenna([antenna_1 | antennae], height, length)

  defp pairwise_antinodes_on_board_for_antenna(
         [{x_1, y_1} = antenna_1, {x_2, y_2} = _antenna_2 | antennae],
         height,
         length
       ) do
    south_ish? = y_2 - y_1 &lt; 0
    west_ish? = x_2 - x_1 &lt; 0
    {x_min, x_max} = Enum.min_max([x_1, x_2])
    delta_x = abs(x_1 - x_2)
    {y_min, y_max} = Enum.min_max([y_1, y_2])
    delta_y = abs(y_1 - y_2)

    {antinode_1_x, antinode_2_x} =
      if west_ish? do
        {x_max + delta_x, x_min - delta_x}
      else
        {x_min - delta_x, x_max + delta_x}
      end

    {antinode_1_y, antinode_2_y} =
      if south_ish? do
        {y_max + delta_y, y_min - delta_y}
      else
        {y_min - delta_y, y_max + delta_y}
      end

    [
      [{antinode_1_x, antinode_1_y}, {antinode_2_x, antinode_2_y}]
      |&gt; Enum.filter(&amp;on_board?(height, length, &amp;1))
      | pairwise_antinodes_on_board_for_antenna([antenna_1 | antennae], height, length)
    ]
    |&gt; List.flatten()
  end

  defp count_antinodes(%{
         antennae: antennae,
         height: height,
         length: length
       }) do
    antennae
    |&gt; Map.keys()
    |&gt; Enum.reduce(
      MapSet.new(),
      fn frequency, antinodes -&gt;
        pairwise_antinodes_on_board(height, length, antennae[frequency])
        |&gt; Enum.reduce(antinodes, &amp;MapSet.put(&amp;2, &amp;1))
      end
    )
    |&gt; Enum.count()
  end

  def solve() do
    File.read!("08/input.txt")
    |&gt; parse()
    |&gt; count_antinodes()
    |&gt; IO.puts()
  end
end

Day8.Part1.solve()
</code></pre>
<p>And part 2:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">#!/usr/bin/env elixir

defmodule Day8.Part1 do
  @open_space ~c"." |&gt; List.first()

  defp parse(str) do
    [row | _rows] =
      rows =
      str
      |&gt; String.split("\n")
      |&gt; Enum.map(&amp;to_charlist/1)

    height = Enum.count(rows)
    length = Enum.count(row)

    antennae =
      for y &lt;- 0..(height - 1), x &lt;- 0..(length - 1) do
        {x, y}
      end
      |&gt; Enum.reduce(
        %{},
        fn {x, y} = pos, acc -&gt;
          c = rows |&gt; Enum.at(y) |&gt; Enum.at(x)

          if c == @open_space,
            do: acc,
            else: acc |&gt; Map.update("#{c}", [pos], fn coordinates -&gt; [pos | coordinates] end)
        end
      )

    %{
      antennae: antennae,
      height: height,
      length: length
    }
  end

  defp pairwise_antinodes_on_board(height, length, antennae) do
    Stream.unfold(
      antennae,
      fn
        [] -&gt; nil
        [_h | t] = antennae -&gt; {antennae, t}
      end
    )
    |&gt; Enum.map(fn antennae -&gt; pairwise_antinodes_on_board_for_antenna(antennae, height, length) end)
    |&gt; List.flatten()
  end

  defp pairwise_antinodes_on_board_for_antenna(
         [_antenna],
         _height,
         _length
       ),
       do: []

  defp pairwise_antinodes_on_board_for_antenna(
         [{x_1, y_1} = antenna_1, {x_2, y_2} = _antenna_2 | antennae],
         height,
         length
       ) do
    south_ish? = y_2 - y_1 &lt; 0
    west_ish? = x_2 - x_1 &lt; 0
    {x_min, x_max} = Enum.min_max([x_1, x_2])
    delta_x = x_max - x_min
    {y_min, y_max} = Enum.min_max([y_1, y_2])
    delta_y = y_max - y_min

    north_eastern = [x_max..(length - 1)//delta_x, y_max..(height - 1)//delta_y]
    south_western = [x_min..0//-delta_x, y_min..0//-delta_y]
    south_eastern = [x_max..(length - 1)//delta_x, y_min..0//-delta_y]
    north_western = [x_min..0//-delta_x, y_max..(height - 1)//delta_y]

    [antinodes_1, antinodes_2] =
      if west_ish? and south_ish? or (not west_ish? and not south_ish?) do
        [south_western, north_eastern]
      else
        [south_eastern, north_western]
      end
      |&gt; Enum.map(
        fn ranges -&gt;
          ranges
          |&gt; Enum.map(&amp;Enum.to_list(&amp;1))
          |&gt; Enum.zip()
        end
      )

    [
      antinodes_1 | [antinodes_2 | pairwise_antinodes_on_board_for_antenna([antenna_1 | antennae], height, length)]
    ]
    |&gt; List.flatten()
  end

  defp count_antinodes(%{
         antennae: antennae,
         height: height,
         length: length
       }) do
    antennae
    |&gt; Map.keys()
    |&gt; Enum.reduce(
      MapSet.new(),
      fn frequency, antinodes -&gt;
        pairwise_antinodes_on_board(height, length, antennae[frequency])
        |&gt; Enum.reduce(antinodes, &amp;MapSet.put(&amp;2, &amp;1))
      end
    )
    |&gt; Enum.count()
  end

  def solve() do
    File.read!("08/input.txt")
    |&gt; parse()
    |&gt; count_antinodes()
    |&gt; IO.puts()
  end
end

Day8.Part1.solve()
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="349160" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/advent-of-code-2024-day-8/67956/19">Post #18</a>
	                </div>
	            </div>
              <div id="likers-container-349160" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="349160"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #18"></div>
  </section>
</div>
    <div class="postbit" id="349319" data-post-id="349319">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="MikeLindner" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  MikeLindner
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>A bit of a crude solution, particularly when it came to part2. Copy/paste/modify got the job done without bothering to refactor anything. Trying to get caught up.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Aoc2024.Day8 do
  @moduledoc false

  defp coord(i, width) do
    {Integer.mod(i, width), Integer.floor_div(i, width)}
  end

  defp get_bounds(data) do
    map =
      data
      |&gt; String.split("\n", trim: true)
      |&gt; Enum.map(&amp;String.split(&amp;1, "", trim: true))

    {length(List.first(map)) - 1, length(map) - 1}
  end

  defp get_input(data) do
    map =
      data
      |&gt; String.split("\n", trim: true)
      |&gt; Enum.map(&amp;String.split(&amp;1, "", trim: true))

    width = length(List.first(map))

    data
    |&gt; String.replace("\n", "")
    |&gt; String.split("", trim: true)
    |&gt; Enum.with_index()
    |&gt; Enum.filter(fn {c, _} -&gt; c != "." end)
    |&gt; Enum.reduce(Map.new(), fn {v, i}, antennas -&gt;
      Map.update(antennas, v, [coord(i, width)], fn s -&gt;
        [coord(i, width) | s]
      end)
    end)
  end

  # Generate the pair of antinodes for a given pair of nodes.
  defp antinode(a = {ax, ay}, b = {bx, by}) do
    dx = bx - ax
    dy = by - ay
    if a != b, do: [{ax - dx, ay - dy}, {bx + dx, by + dy}], else: []
  end

  # Generate all antinodes including those out of bounds and duplicates.
  defp find_antinodes(antennas) do
    for locations &lt;- Map.values(antennas) do
      for a &lt;- locations, b &lt;- locations do
        antinode(a, b)
      end
    end
  end

  defp in_bounds?({x, y}, {last_x, last_y}) do
    x &gt;= 0 and x &lt;= last_x and y &gt;= 0 and y &lt;= last_y
  end

  def part1(file) do
    data = File.read!(file)

    get_input(data)
    |&gt; find_antinodes()
    |&gt; List.flatten()
    |&gt; Enum.uniq()
    |&gt; Enum.filter(&amp;in_bounds?(&amp;1, get_bounds(data)))
    |&gt; Enum.count()
  end

  # Generate all antinodes for a pair of antennas radiating outward.
  defp antinode2(a = {ax, ay}, b = {bx, by}, mult \\ 1) do
    # Cheating a bit here instead of passing in the maximum position indexes.
    size = 49
    dx = (bx - ax) * mult
    dy = (by - ay) * mult

    if a == b do
      [a]
    else
      n = {ax - dx, ay - dy}
      m = {bx + dx, by + dy}
      if not in_bounds?(n, {size, size}) and not in_bounds?(m, {size, size}) do
        []
      else
        [n | [m | antinode2(a, b, mult + 1)]]
      end
    end
  end

  defp find_antinodes2(antennas) do
    for locations &lt;- Map.values(antennas) do
      for a &lt;- locations, b &lt;- locations do
        antinode2(a, b)
      end
    end
  end

  def part2(file) do
    data = File.read!(file)

    get_input(data)
    |&gt; find_antinodes2()
    |&gt; List.flatten()
    |&gt; Enum.uniq()
    |&gt; Enum.filter(&amp;in_bounds?(&amp;1, get_bounds(data)))
    |&gt; Enum.sort()
    |&gt; Enum.count()
  end
end
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="349319" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/advent-of-code-2024-day-8/67956/20">Post #19</a>
	                </div>
	            </div>
              <div id="likers-container-349319" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="349319"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #19"></div>
  </section>
</div>
    <div class="postbit" id="351358" data-post-id="351358">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="stevensonmt" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/stevensonmt/120/20503_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  stevensonmt
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I feel like there were probably some really clever ways to approach this problem but my solution is just kind of basic. Still nice for it to feel easy after all my false starts with day 7.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Day8 do
  @test """
  ............
  ........0...
  .....0......
  .......0....
  ....0.......
  ......A.....
  ............
  ............
  ........A...
  .........A..
  ............
  ............
  """
  @real File.read!(__DIR__ &lt;&gt; "/input.txt")

  def run(mode) do
    {antennae, max_row, max_col} =
      mode
      |&gt; input()
      |&gt; parse()

    part_1(antennae, max_row, max_col) |&gt; IO.inspect(label: :part1)
    part_2(antennae, max_row, max_col) |&gt; IO.inspect(label: :part2)
  end

  defp input(:test), do: @test
  defp input(:real), do: @real
  defp input(_), do: raise("Please use :test or :real as the mode to run.")

  defp parse(data) do
    data
    |&gt; grid()
  end

  defp grid(data) do
    data
    |&gt; lines()
    |&gt; Enum.with_index()
    |&gt; Enum.reduce({%{}, 0, 0}, fn {row, r}, {map, max_r, max_c} -&gt;
      row
      |&gt; String.graphemes()
      |&gt; Enum.with_index()
      |&gt; Enum.reduce({map, max_r, max_c}, fn
        {".", c}, {m, m_r, m_c} -&gt;
          {m, max(m_r, r), max(m_c, c)}

        {ant, c}, {m, m_r, m_c} -&gt;
          {Map.update(m, ant, [{r, c}], fn curr -&gt; [{r, c} | curr] end), max(m_r, r), max(m_c, c)}
      end)
    end)
  end

  defp lines(data) do
    data
    |&gt; String.split("\n", trim: true)
  end

  defp part_1(antennae, max_row, max_col) do
    antennae
    |&gt; Task.async_stream(fn {_freq, ants} -&gt;
      antinodes(ants, [], max_row, max_col)
    end)
    |&gt; Enum.map(&amp;elem(&amp;1, 1))
    |&gt; Enum.reduce(MapSet.new(), fn nodes, ms -&gt;
      nodes |&gt; Enum.reduce(ms, fn n, m -&gt; MapSet.put(m, n) end)
    end)
    |&gt; MapSet.size()
  end

  defp antinodes([_], antinodes, _, _), do: antinodes

  defp antinodes([a, b | rest], antinodes, max_row, max_col) do
    antinodes([a | rest], antinodes, max_row, max_col) ++
      antinodes([b | rest], antinodes, max_row, max_col) ++ find_antinodes(a, b, max_row, max_col)
  end

  defp find_antinodes({a, b}, {c, d}, max_r, max_c) do
    d_r = a - c
    d_c = b - d

    {i, j} = {a + d_r, b + d_c}
    {k, l} = {c - d_r, d - d_c}

    [{i, j}, {k, l}]
    |&gt; Enum.filter(fn {x, y} -&gt; x &lt;= max_r and y &lt;= max_c and x &gt;= 0 and y &gt;= 0 end)
  end

  defp part_2(antennae, max_row, max_col) do
    antennae
    |&gt; Task.async_stream(fn {_freq, ants} -&gt; harmonic_antinodes(ants, max_row, max_col) end)
    |&gt; Enum.map(&amp;elem(&amp;1, 1))
    |&gt; Enum.reduce(MapSet.new(), fn nodes, ms -&gt;
      nodes |&gt; Enum.reduce(ms, fn n, m -&gt; MapSet.put(m, n) end)
    end)
    |&gt; MapSet.size()
  end

  defp harmonic_antinodes(ants, max_r, max_c) do
    for ant1 &lt;- ants,
        ant2 &lt;- ants -- [ant1],
        reduce: [] do
      acc -&gt;
        acc ++ find_harmonics(ant1, ant2, max_r, max_c)
    end
  end

  defp find_harmonics({a, b}, {c, d}, max_r, max_c) do
    for i &lt;- 0..max_r,
        j &lt;- 0..max_c,
        slope({a, b}, {c, d}) == slope({a, b}, {i, j}),
        reduce: [{a, b}, {c, d}] do
      acc -&gt;
        [{i, j} | acc]
    end
  end

  defp slope({_a, b}, {_c, b}), do: :infinity

  defp slope({a, b}, {c, d}) do
    (a - c) / (b - d)
  end
end
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="351358" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/advent-of-code-2024-day-8/67956/21">Post #20</a>
	                </div>
	            </div>
              <div id="likers-container-351358" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="351358"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-last-post cat-last-post" title="Last post!"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <span class="all-loaded">— All posts loaded —</span>
</div></template></turbo-stream>