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


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I think the trick today is to find a configuration in which no two robots are in the same cell. The author of AoC must have had a starting grid to which he applied velocities in reverse to get our puzzle input, and chances are after each time step there will be at least two robots in one cell by chance. At least that’s what worked for me: <a href="https://github.com/ibarakaiev/advent-of-code-2024/blob/main/lib/advent_of_code2024/day14.ex" class="inline-onebox" rel="noopener nofollow ugc">advent-of-code-2024/lib/advent_of_code2024/day14.ex at main · ibarakaiev/advent-of-code-2024 · GitHub</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="349844" 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-14/68091/22">Post #21</a>
	                </div>
	            </div>
              <div id="likers-container-349844" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="349844"
                     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 #21"></div>
  </section>
</div>
    <div class="postbit" id="349851" data-post-id="349851">
  <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 usually never feed chatgpt a full requirement. When im lazy and want to print a grid i give it an empty function with desired parameters and ask it to implement. Usually i know how to do it already, but im so dam lazy and chatgpt make it correct in at least 60% of the time .. which is better than my fooling around for 10mins … <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"> other times though, weak times, i just copy my complete solution and ask it to find the bug or fix a problem. That only works in 10% (or less) of the times i do it. I need to stop that **** …</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="349851" 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-14/68091/23">Post #22</a>
	                </div>
	            </div>
              <div id="likers-container-349851" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="349851"
                     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 #22"></div>
  </section>
</div>
    <div class="postbit" id="349875" data-post-id="349875">
  <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>visualization ftw</p>
<p>EDIT: recording with resource monitoring <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 used all 16 logical cores to produce the frames</p>
<p>link (<a href="https://www.dropbox.com/scl/fi/pj2zxgx2gtqtsjx8fwxe1/Screen-Recording-2024-12-15-135540.mp4?rlkey=by62zg75ioybkj8humcmrg4by&amp;st=y1q9yqd2&amp;dl=0" class="inline-onebox" rel="noopener nofollow ugc">Dropbox</a>)</p>
<p>Final screenshot</p>
<div class="spoiler">
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://forum.elixirforum.com/uploads/default/original/3X/8/a/8aa078f3bcd9e992d4305611c776d70746128b3f.jpeg" data-download-href="https://forum.elixirforum.com/uploads/default/8aa078f3bcd9e992d4305611c776d70746128b3f" title="IMG_0739" rel="nofollow"><img src="https://forum.elixirforum.com/uploads/default/optimized/3X/8/a/8aa078f3bcd9e992d4305611c776d70746128b3f_2_690x318.jpeg" alt="IMG_0739" data-base62-sha1="jMlHuXh2hVn5MGJZxbcUYQzOJH1" width="690" height="318" srcset="https://forum.elixirforum.com/uploads/default/optimized/3X/8/a/8aa078f3bcd9e992d4305611c776d70746128b3f_2_690x318.jpeg, https://forum.elixirforum.com/uploads/default/optimized/3X/8/a/8aa078f3bcd9e992d4305611c776d70746128b3f_2_1035x477.jpeg 1.5x, https://forum.elixirforum.com/uploads/default/optimized/3X/8/a/8aa078f3bcd9e992d4305611c776d70746128b3f_2_1380x636.jpeg 2x" data-dominant-color="1A1C1D"><div class="meta"><svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">IMG_0739</span><span class="informations">1792×828 95.5 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg></div></a></div><p></p>
</div>
<p>Basically just garbled mess before that last frame</p>
<p>actually im pretty happy with the code for part2 .. it uses infinite stream range and uses all of the machines logical cores</p>
<p><a href="https://github.com/jarlah/advent_of_code/blob/master/solutions/2024/day_14/lib/Part2.ex#L14" class="onebox" target="_blank" rel="noopener nofollow ugc">https://github.com/jarlah/advent_of_code/blob/master/solutions/2024/day_14/lib/Part2.ex#L14</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="349875" 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-14/68091/24">Post #23</a>
	                </div>
	            </div>
              <div id="likers-container-349875" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="349875"
                     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 #23"></div>
  </section>
</div>
    <div class="postbit" id="349906" data-post-id="349906">
  <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>I originally tried searching for clusters of half the bots, but that took waaay too long, even after memoizing.</p>
<p>Checking for a number of bots surrounded by 8 other bots gets something, but not the right answer.</p>
<p>Finally I broke down and implemented the popular solution of looking for a contiguous row of 10 robots:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Day14.Part2 do
  @width 101
  @height 103

  defp parse(str) do
    str
    |&gt; String.split("\n", trim: true)
    |&gt; Enum.map(&amp;parse_bot/1)
  end

  defp parse_bot(line) do
    Regex.scan(~r/-?\d+,-?\d+/, line)
    |&gt; Enum.flat_map(fn [pair] -&gt;
      [
        String.split(pair, ",")
        |&gt; Enum.map(&amp;String.to_integer/1)
        |&gt; List.to_tuple()
      ]
    end)
  end

  defp tick([{p_x, p_y}, {v_x, v_y} = velocity] = _bot) do
    [{Integer.mod(p_x + v_x, @width), Integer.mod(p_y + v_y, @height)}, velocity]
  end

  defp tick([bot | _bots] = bots) when is_list(bot) do
    bots
    |&gt; Enum.map(&amp;tick/1)
  end

  defp contiguous?([]), do: true

  defp contiguous?([_bot]), do: true

  defp contiguous?([[{x, _y}, _v] = _bot, [{n_x, _n_y}, _n_v] = neighbor | bots]) do
    x == n_x - 1 and contiguous?([neighbor | bots])
  end

  defp contains_contiguous_row?(bots, count) when length(bots) &lt; count, do: false

  defp contains_contiguous_row?([_bot | bots_t] = bots, count) when length(bots) &gt;= count do
    bots
    |&gt; Enum.slice(0..(count - 1))
    |&gt; contiguous?() or contains_contiguous_row?(bots_t, count)
  end

  defp tree?(bots) do
    {[{_x, min_y}, _v], [{_n_x, max_y}, _n_v]} =
      bots
      |&gt; Enum.min_max_by(fn [{_x, y}, _vector] -&gt; y end)

    Stream.iterate(min_y, &amp;(&amp;1 + 1))
    |&gt; Enum.reduce_while(
      false,
      fn y, false -&gt;
        ten_in_a_row? =
          bots
          |&gt; Stream.filter(fn [{_b_x, b_y}, _v] -&gt; y == b_y end)
          |&gt; Enum.sort_by(fn [{x, _y}, _v] -&gt; x end)
          |&gt; contains_contiguous_row?(10)

        cond do
          ten_in_a_row? -&gt; {:halt, true}
          y &gt;= max_y -&gt; {:halt, false}
          true -&gt; {:cont, false}
        end
      end
    )
  end

  defp find_tree(bots) do
    Stream.iterate(bots, &amp;tick/1)
    |&gt; Enum.reduce_while(
      0,
      fn bots, ticks -&gt;
        if tree?(bots) do
          {:halt, ticks}
        else
          {:cont, ticks + 1}
        end
      end
    )
  end

  def solve() do
    File.read!("lib/advent_of_code/year/2024/day/14/input.txt")
    |&gt; parse()
    |&gt; find_tree()
    |&gt; IO.puts()
  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="349906" 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-14/68091/25">Post #24</a>
	                </div>
	            </div>
              <div id="likers-container-349906" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="349906"
                     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 #24"></div>
  </section>
</div>
    <div class="postbit" id="349910" data-post-id="349910">
  <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>I didn’t love this one. I think I prefer when the final condition is unambiguous from the text.</p>
<p>Part 1 was straightforward. Just a single mod calculation.</p>
<p>Part 2 was less straightforward. My approach is to use a sliding 7x7 window. I compute a total image score as the sum of the squares of the number of robots in each window. (This is related to an entropy or variance calculation but it’s not the same). Intuitively, when the robots are spread out randomly, most windows will have roughly the same score. Only when the robots are clustered together will we get higher window scores.</p>
<p>I searched for the image with the max score across all t = 100, 1,000, 10,000 until I found a Christmas tree.</p>
<p>This is not golfed.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Aoc2024.Day14 do
  def part1(file, x_max, y_max) do
    robots = file |&gt; File.read!() |&gt; String.split("\n", trim: true) |&gt; Enum.map(&amp;parse_line/1)

    x_mid = div(x_max, 2)
    y_mid = div(y_max, 2)
    t = 100

    robots
    |&gt; Enum.map(fn {px, py, vx, vy} -&gt;
      [Integer.mod(px + vx * t, x_max), Integer.mod(py + vy * t, y_max)]
    end)
    |&gt; Enum.frequencies_by(fn [x, y] -&gt; [compare(x, x_mid), compare(y, y_mid)] end)
    |&gt; Enum.reject(fn {xy, _} -&gt; :eq in xy end)
    |&gt; Enum.product_by(fn {_, v} -&gt; v end)
  end

  def part2(file, x_max, y_max) do
    robots = file |&gt; File.read!() |&gt; String.split("\n", trim: true) |&gt; Enum.map(&amp;parse_line/1)

    :ets.new(:cache, [:public, :set, :named_table])

    grid = for x &lt;- 0..(x_max - 1), y &lt;- 0..(y_max - 1), into: %{}, do: {{x, y}, 0}
    :ets.insert(:cache, {:grid, grid})

    {s_max, _, image} =
      Enum.reduce_while(
        Stream.iterate(1, &amp;(&amp;1 + 1)),
        {robots, {0, 0, nil}},
        fn t, {acc, {t_max, s_max, image}} -&gt;
          acc =
            Enum.map(acc, fn {px, py, vx, vy} -&gt;
              {Integer.mod(px + vx, x_max), Integer.mod(py + vy, y_max), vx, vy}
            end)

          if t &gt; 10_000 do
            {:halt, {t_max, s_max, image}}
          else
            s = score(acc, x_max, y_max)

            if s &gt; s_max do
              {t, s} |&gt; dbg
              {:cont, {acc, {t, s, acc}}}
            else
              {:cont, {acc, {t_max, s_max, image}}}
            end
          end
        end
      )

    print_image(image, x_max, y_max)
    s_max
  end

  @line ~r/p=(\d+),(\d+) v=(-?\d+),(-?\d+)/
  def parse_line(line) do
    Regex.scan(@line, line, capture: :all_but_first)
    |&gt; hd
    |&gt; Enum.map(&amp;String.to_integer/1)
    |&gt; List.to_tuple()
  end

  def compare(a, b) when is_integer(a) and is_integer(b) do
    cond do
      a &lt; b -&gt; :lt
      a == b -&gt; :eq
      a &gt; b -&gt; :gt
    end
  end

  def score(robots, x_max, y_max) do
    [grid: grid] = :ets.lookup(:cache, :grid)
    size = 7
    s = div(size, 2)

    grid =
      robots
      |&gt; Enum.reduce(grid, fn {x, y, _, _}, acc -&gt; Map.put(acc, {x, y}, 1) end)

    for x &lt;- s..(x_max - 1 - s)//size, y &lt;- s..(y_max - 1 - s)//size, reduce: 0 do
      sum -&gt;
        window_sum =
          for(dx &lt;- -s..s, dy &lt;- -s..s, reduce: 0, do: (sum -&gt; sum + grid[{x + dx, y + dy}]))

        sum + window_sum ** 2
    end
  end

  def print_image(robots, x_max, y_max) do
    [grid: grid] = :ets.lookup(:cache, :grid)

    grid =
      robots
      |&gt; Enum.reduce(grid, fn {x, y, _, _}, acc -&gt; Map.update!(acc, {x, y}, &amp;(&amp;1 + 1)) end)

    for y &lt;- 0..(y_max - 1) do
      for x &lt;- 0..(x_max - 1) do
        v = grid[{x, y}]

        if v == 0 do
          "."
        else
          Integer.to_string(v)
        end
      end
      |&gt; Enum.join("")
    end
    |&gt; Enum.join("\n")
    |&gt; IO.puts()
  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="349910" 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-14/68091/26">Post #25</a>
	                </div>
	            </div>
              <div id="likers-container-349910" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="349910"
                     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 #25"></div>
  </section>
</div>
    <div class="postbit" id="349997" data-post-id="349997">
  <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>I didn’t want to stumble in the dark for part 2 so I went here for help. <img src="https://forum.elixirforum.com/images/emoji/apple/dotted_line_face.png?v=15" title=":dotted_line_face:" class="emoji" alt=":dotted_line_face:" loading="lazy" width="20" height="20"><br>
I tried out your approach.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Aoc2024.Solutions.Y24.Day14 do
  alias AoC.Input

  @x_max if Mix.env() == :test, do: 11, else: 101
  @y_max if Mix.env() == :test, do: 7, else: 103

  @tree [{50, 51}, {49, 51}, {51, 51}, {48, 52}, {49, 52}, {50, 52}, {51, 52}, {52, 52}]

  def parse(input, _part) do
    input
    |&gt; Input.stream!(trim: true)
    |&gt; Enum.map(fn line -&gt;
      ~r/-?\d+(\.\d+)?/
      |&gt; Regex.scan(line)
      |&gt; Enum.reduce({}, fn [e], acc -&gt;
        Tuple.append(acc, String.to_integer(e))
      end)
    end)
  end

  def part_one(problem) do
    {q1, q2, q3, q4} =
      problem
      |&gt; Enum.map(&amp;move_robot(&amp;1, 100))
      |&gt; Enum.filter(fn {x, y, _xv, _yv} -&gt; x != div(@x_max, 2) and y != div(@y_max, 2) end)
      |&gt; Enum.reduce({0, 0, 0, 0}, fn {x, y, _xv, _yv}, {q1, q2, q3, q4} -&gt;
        cond do
          x &lt; div(@x_max, 2) and y &lt; div(@y_max, 2) -&gt;
            {q1 + 1, q2, q3, q4}

          x &lt; div(@x_max, 2) and y &gt; div(@y_max, 2) -&gt;
            {q1, q2 + 1, q3, q4}

          x &gt; div(@x_max, 2) and y &lt; div(@y_max, 2) -&gt;
            {q1, q2, q3 + 1, q4}

          x &gt; div(@x_max, 2) and y &gt; div(@y_max, 2) -&gt;
            {q1, q2, q3, q4 + 1}
        end
      end)

    q1 * q2 * q3 * q4
  end

  def part_two(problem) do
    iterate_until(problem, 0)
  end

  defp iterate_until(robot_positions, solution) do
    robot_positions = Enum.map(robot_positions, &amp;move_robot(&amp;1, 1))
    positions = Enum.map(robot_positions, fn {x, y, _xv, _yv} -&gt; {x, y} end)

    if Enum.all?(@tree, &amp;(&amp;1 in positions)),
      do: solution + 1,
      else: iterate_until(robot_positions, solution + 1)
  end

  defp move_robot(solution, 0), do: solution

  defp move_robot({x, y, xv, yv}, seconds) do
    x = rem(x + xv, @x_max)
    x = if x &lt; 0, do: @x_max + x, else: x
    y = rem(y + yv, @y_max)
    y = if y &lt; 0, do: @y_max + y, else: y
    move_robot({x, y, xv, yv}, seconds - 1)
  end
end

</code></pre>
<p>I got the correct solution with <code>[{50, 51}, {49, 51}, {51, 51}, {48, 52}, {49, 52}, {50, 52}, {51, 52}, {52, 52}]</code> i.e. the middle 3 and under it 5 is the condition and it worked! <img src="https://forum.elixirforum.com/images/emoji/apple/cowboy_hat_face.png?v=15" title=":cowboy_hat_face:" class="emoji" alt=":cowboy_hat_face:" 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="349997" 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-14/68091/27">Post #26</a>
	                </div>
	            </div>
              <div id="likers-container-349997" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="349997"
                     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 #26"></div>
  </section>
</div>
    <div class="postbit" id="351861" data-post-id="351861">
  <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>Haven’t tried part 2 yet, but I’m very pleased that I got part 1 without any false starts and refactors. I do have a suspicion that were I to try and parallelize some of the logic I’d have problems b/c there are some steps where a function takes a value from an ETS table, then either replaces it or leaves it off the table depending on that value. If another process were to attempt to take the value for the same key before that first process finished I think I’d be in trouble. For this problem it was not an issue.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Day14 do
  alias Day14.{Robot, Board}

  @real File.read!(__DIR__ &lt;&gt; "/input.txt") |&gt; String.trim()

  @re ~r/p=(\d+),(\d+) v=(-*\d+),(-*\d+)/

  def parse(input) do
    Regex.scan(@re, input, capture: :all_but_first)
    |&gt; Enum.map(fn robot -&gt; Enum.map(robot, &amp;String.to_integer/1) end)
  end

  def run(input \\ :real, board_x \\ 101, board_y \\ 103)
  def run(:real, board_x, board_y), do: run(@real, board_x, board_y)

  def run(input, board_x, board_y) do
    Robot.init_roster()
    Board.new(board_x, board_y)

    input
    |&gt; parse()
    |&gt; Robot.init_bots()

    Robot.move_all(100)

    Board.search_quadrants() |&gt; safety_factor() |&gt; IO.inspect(label: :part_1)
  end

  def quit() do
    Board.close()
    Robot.shut_down_all()
  end

  defp safety_factor(groups) do
    groups
    |&gt; Enum.map(fn {k, grp} -&gt; {k, List.flatten(grp)} end)
    |&gt; Enum.map(fn {k, grp} -&gt; {k, grp |&gt; Enum.flat_map(fn {_coord, bots} -&gt; bots end)} end)
    |&gt; Enum.reduce(1, fn {_, bots}, acc -&gt; acc * length(bots) end)
  end

  defmodule Robot do
    def init_roster() do
      :ets.new(:robot_list, [:named_table, :ordered_set])
    end

    def init_bot(name, [px, py, vx, vy]) do
      :ets.insert(:robot_list, {name, %{px: px, py: py, vx: vx, vy: vy}})

      if :board not in :ets.all() do
        Board.new()
      end

      Board.add_to_spot(name, px, py)
    end

    def init_bots(robots) do
      robots
      |&gt; Stream.with_index()
      |&gt; Stream.each(fn {robot, ndx} -&gt;
        name = "R2D#{ndx}"
        init_bot(name, robot)
      end)
      |&gt; Stream.run()
    end

    def shut_down_all() do
      :ets.delete(:robot_list)
    end

    def shut_down_bot(robot) do
      :ets.take(:robot_list, robot)
    end

    def move_all(seconds) do
      Stream.iterate(0, &amp;(&amp;1 + 1))
      |&gt; Stream.map(fn i -&gt; :ets.slot(:robot_list, i) end)
      |&gt; Stream.take_while(fn n -&gt; n != :"$end_of_table" end)
      |&gt; Stream.map(fn [{robot, state}] -&gt; move_bot(robot, state, seconds) end)
      |&gt; Stream.run()
    end

    defp move_bot(robot, state, seconds) do
      board_x = :ets.lookup_element(:board, :width, 2)
      board_y = :ets.lookup_element(:board, :height, 2)

      px =
        case rem(state.px + state.vx * seconds, board_x) do
          n when n &gt;= 0 -&gt; n
          n -&gt; board_x + n
        end

      py =
        case rem(state.py + state.vy * seconds, board_y) do
          n when n &gt;= 0 -&gt; n
          n -&gt; board_y + n
        end

      Board.remove_from_spot(robot, state.px, state.py)
      :ets.update_element(:robot_list, robot, {2, %{state | px: px, py: py}})
      Board.add_to_spot(robot, px, py)
    end
  end

  defmodule Board do
    def new(x \\ 101, y \\ 103) do
      :ets.new(:board, [:named_table, :ordered_set])

      :ets.insert(:board, [{:width, x}, {:height, y}])

      define_quadrants(x, y)
    end

    defp define_quadrants(x, y) do
      mid_x = div(x, 2)
      mid_y = div(y, 2)

      quadrants = [
        {:nw, {0..(mid_x - 1), 0..(mid_y - 1)}},
        {:ne, {(mid_x + 1)..x, 0..(mid_y - 1)}},
        {:sw, {0..(mid_x - 1), (mid_y + 1)..y}},
        {:se, {(mid_x + 1)..x, (mid_y + 1)..y}}
      ]

      :ets.insert(:board, quadrants)
    end

    def remove_from_spot(occupant, x, y) do
      case :ets.take(:board, {x, y}) do
        [{{_x, _y}, [^occupant]}] -&gt; true
        [{{^x, ^y}, occupants}] -&gt; :ets.insert(:board, {{x, y}, occupants -- [occupant]})
        [] -&gt; true
      end
    end

    def add_to_spot(occupant, x, y) do
      case :ets.take(:board, {x, y}) do
        [{{x, y}, occupants}] -&gt; :ets.insert(:board, {{x, y}, [occupant | occupants]})
        [] -&gt; :ets.insert(:board, {{x, y}, [occupant]})
      end
    end

    def search_quadrants() do
      Stream.iterate(0, &amp;(&amp;1 + 1))
      |&gt; Stream.map(fn i -&gt; :ets.slot(:board, i) end)
      |&gt; Stream.take_while(fn res -&gt; res != :"$end_of_table" end)
      |&gt; Stream.filter(fn [{k, _v}] -&gt; k not in [:width, :height, :nw, :sw, :ne, :se] end)
      |&gt; Enum.group_by(fn [{{x, y}, _robots}] -&gt; quadrant(x, y) end)
      |&gt; Enum.reject(fn {k, _grp} -&gt; k == nil end)
    end

    defp quadrant(x, y) do
      [:nw, :ne, :sw, :se]
      |&gt; Enum.find(fn q -&gt;
        case :ets.lookup_element(:board, q, 2) do
          {x1..x2//_, y1..y2//_} when x1 &lt;= x and x2 &gt;= x and (y1 &lt;= y and y2 &gt;= y) -&gt; true
          _ -&gt; false
        end
      end)
    end

    def close() do
      :ets.delete(:board)
    end
  end
end
</code></pre>
<p>PS Sorry to everyone who moved on two weeks ago. I finally have some time and enjoy the puzzles more than the competition aspect. Hope no one minds the necro bumps of these threads.</p>
<p>PPS I haven’t checked the thread but did people actually implement edge detection and pattern recognition for finding the undefined christmas tree for part 2? I really think I’m just going to make it print the board every second and watch it until I see a tree. <img src="https://forum.elixirforum.com/uploads/default/original/2X/7/776053aa22968f83c10e90c98b23aa0ddd5c9d47.gif?v=15" title=":lol:" class="emoji emoji-custom" alt=":lol:" 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="351861" 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-14/68091/28">Post #27</a>
	                </div>
	            </div>
              <div id="likers-container-351861" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="351861"
                     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 #27"></div>
  </section>
</div>
    <div class="postbit" id="351863" data-post-id="351863">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="adamu" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/adamu/120/31482_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  adamu
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="stevensonmt" data-post="28" data-topic="68091">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/stevensonmt/48/20503_2.png" class="avatar"> stevensonmt:</div>
<blockquote>
<p>Hope no one minds the necro bumps of these threads.</p>
</blockquote>
</aside>
<aside class="quote no-group" data-username="stevensonmt" data-post="28" data-topic="68091">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/stevensonmt/48/20503_2.png" class="avatar"> stevensonmt:</div>
<blockquote>
<p>I haven’t checked the thread</p>
</blockquote>
</aside>
<p>I think you should read the thread before posting, as you are mostly repeating what has already been said… Maybe that’s the nature of AoC though, everyone wants to share their code/experience, which is likely similar since we’re all doing the same puzzle.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="351863" 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-14/68091/29">Post #28</a>
	                </div>
	            </div>
              <div id="likers-container-351863" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="351863"
                     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 #28"></div>
  </section>
</div>
    <div class="postbit" id="351904" data-post-id="351904">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="stevensonmt" data-post="28" data-topic="68091">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/stevensonmt/48/20503_2.png" class="avatar"> stevensonmt:</div>
<blockquote>
<p>did people actually implement edge detection and pattern recognition for finding the undefined christmas tree for part 2</p>
</blockquote>
</aside>
<p>The “safety factor” from part 1 was sufficient for my case - it had a significantly lower value for the “Christmas tree” pattern than for the random messes on either side.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="351904" 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-14/68091/30">Post #29</a>
	                </div>
	            </div>
              <div id="likers-container-351904" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="351904"
                     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 #29"></div>
  </section>
</div>
    <div class="postbit" id="351911" data-post-id="351911">
  <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">
								<aside class="quote no-group" data-username="adamu" data-post="29" data-topic="68091">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/adamu/48/31482_2.png" class="avatar"> adamu:</div>
<blockquote>
<p>I think you should read the thread before posting, as you are mostly repeating what has already been said… Maybe that’s the nature of AoC though, everyone wants to share their code/experience, which is likely similar since we’re all doing the same puzzle.</p>
</blockquote>
</aside>
<p>Do you mean my comment about part 2 is repeating what has been said or do you mean generally my solutions across the threads are not unique or interesting because of how similar they are to other solutions? If the latter I think that’s a bit uncharitable. As you said most of the time the puzzles have a fairly clear method of solving and the individual implementations will tend to coalesce around that method. That said, I think the slight differences are potentially helpful for historical reference as people consulting these threads from Google searches in the future may learn different tools Elixir provides that they were not aware of. For instance, at least for this day’s puzzle my solution to part 1 is logically identical to almost every other solution because it is a very straight forward math problem. I think my solution has value, however, as I chose to (unnecessarily) set up the problem in what I think of as a more BEAM-ish approach to managing state. I hope that future readers find that helpful.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="351911" 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-14/68091/31">Post #30</a>
	                </div>
	            </div>
              <div id="likers-container-351911" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="351911"
                     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 #30"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/68091/load_more?page=4">Load more posts (3 remaining)</a>
</div></template></turbo-stream>