<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="349122" data-post-id="349122">
  <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>&lt;3 <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"> btw i just boils down to implicit requirements and to understand the problem. Thanks again</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="349122" 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-9/67977/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-349122" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="349122"
                     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="349128" data-post-id="349128">
  <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
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I’m glad to see it was not just me that was struggling / writing… less than pretty code for this one. <img src="https://forum.elixirforum.com/images/emoji/apple/grin.png?v=15" title=":grin:" class="emoji" alt=":grin:" loading="lazy" width="20" height="20"></p>
<p>I didn’t complete part 2, because although it worked on the sample, like <a class="mention" href="/u/aetherus" rel="nofollow">@Aetherus</a> I hadn’t accounted for the fact that moving a file that’s next to a space will leave a <em>bigger</em> space behind - and it’ll need a completely different approach to fix <img src="https://forum.elixirforum.com/images/emoji/apple/stopwatch.png?v=15" title=":stopwatch:" class="emoji" alt=":stopwatch:" 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="349128" 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-9/67977/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-349128" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="349128"
                     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="349159" data-post-id="349159">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>It should be easy to remember where to search:</p>
<p>If you move a file that starts at block 123, from now on you will not search free space after 123.</p>
<p>Even more, for a file that starts at block 100 and is of size 5, then you will only look for free space in the blocks <code>0..(100-5)</code></p>
<p>This is my new version using only lists, the version with maps was too much of a chore to my taste. This one was fun! (and best run was 33ms)</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule AdventOfCode.Solutions.Y24.Day09 do
  alias AoC.Input

  def parse(input, _part) do
    input
    |&gt; Input.read!()
    |&gt; String.trim()
    |&gt; String.graphemes()
    |&gt; Enum.map(&amp;String.to_integer/1)
  end

  def part_one(problem) do
    rev_blocks = build_disk(problem)
    blocks = :lists.reverse(rev_blocks)
    blocks = compress(blocks, Enum.filter(rev_blocks, fn {_, v} -&gt; v != :free end), [])
    hash(blocks)
  end

  defp build_disk(problem) do
    build_disk(problem, :file, 0, 0, [])
  end

  defp build_disk([0 | t], :file, block_id, file_id, acc) do
    build_disk(t, :free, block_id, file_id + 1, acc)
  end

  defp build_disk([0 | t], :free, block_id, file_id, acc) do
    build_disk(t, :file, block_id, file_id, acc)
  end

  defp build_disk([h | t], :file, block_id, file_id, acc) do
    build_disk([h - 1 | t], :file, block_id + 1, file_id, [{block_id, file_id} | acc])
  end

  defp build_disk([h | t], :free, block_id, file_id, acc) do
    build_disk([h - 1 | t], :free, block_id + 1, file_id, [{block_id, :free} | acc])
  end

  defp build_disk([], _, _, _, acc) do
    acc
  end

  defp compress([{bid, :free} | blocks], [{fbid, file_id} | movables], acc) when bid &lt;= fbid do
    compress(blocks, movables, [{bid, file_id} | acc])
  end

  defp compress([{bid, file_id} | blocks], [{fbid, _} | _] = movables, acc) when bid &lt;= fbid do
    compress(blocks, movables, [{bid, file_id} | acc])
  end

  defp compress(_blocks, _movables, acc) do
    acc
  end

  defp hash(blocks) do
    Enum.reduce(blocks, 0, fn
      {i, f}, acc when is_integer(f) -&gt; acc + i * f
      {_, :free}, acc -&gt; acc
    end)
  end

  def part_two(problem) do
    rev_blocks = build_disk(problem)

    {free_chunks, files_chunks} =
      rev_blocks
      |&gt; :lists.reverse()
      |&gt; Enum.chunk_by(fn {_, v} -&gt; v end)
      |&gt; Enum.map(fn [{_, fid_or_free} | _] = list -&gt;
        {Enum.map(list, &amp;elem(&amp;1, 0)), fid_or_free}
      end)
      |&gt; Enum.split_with(fn {_, id} -&gt; id == :free end)

    free_chunks = Enum.map(free_chunks, fn {bids, :free} -&gt; {bids, length(bids)} end)
    rev_files_chunks = :lists.reverse(files_chunks)
    blocks = defrag(rev_files_chunks, free_chunks, [])
    hash2(blocks)
  end

  defp defrag([{[low_bid | _] = bids, file_id} = h | rev_files_chunks], [{[high_free | _], _} | _] = free_chunks, acc)
       when high_free &lt; low_bid do
    space = take_space(free_chunks, bids)

    [bid | _] = bids

    case space do
      {[free_bid | _] = free_bids, free_chunks} when free_bid &lt; bid -&gt;
        defrag(rev_files_chunks, free_chunks, [{free_bids, file_id} | acc])

      _ -&gt;
        defrag(rev_files_chunks, free_chunks, [h | acc])
    end
  end

  defp defrag(rest, _, acc) do
    rest ++ acc
  end

  defp take_space(free_chunks, bids) do
    take_space(free_chunks, length(bids), [])
  end

  defp take_space([{vids, larger_len} | rest], len, skipped) when len &lt; larger_len do
    {vids_used, vids_rest} = Enum.split(vids, len)
    {vids_used, :lists.reverse(skipped, [{vids_rest, larger_len - len} | rest])}
  end

  defp take_space([{vids, same_len} | rest], same_len, skipped) do
    {vids, :lists.reverse(skipped, rest)}
  end

  defp take_space([skip | rest], len, skipped) do
    take_space(rest, len, [skip | skipped])
  end

  defp take_space([], _, _) do
    nil
  end

  defp hash2(blocks) do
    Enum.reduce(blocks, 0, fn
      {bids, f}, acc when is_integer(f) -&gt; Enum.reduce(bids, acc, fn b, acc -&gt; acc + b * f end)
    end)
  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="349159" 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-9/67977/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-349159" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="349159"
                     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="349161" data-post-id="349161">
  <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>Not a very impressive golf today. There’s a lot of essential complexity here I failed to circumvent.</p>
<p>LOC: 39</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Aoc2024.Day09 do
  def part1(file) do
    {blocks, frees, _} = parse(file)
    n = Enum.reduce(blocks, 0, fn {_, range}, sum -&gt; sum + Range.size(range) end)
    blocks = Enum.flat_map(blocks, fn {id, range} -&gt; Enum.map(range, &amp;{id, &amp;1}) end)
    {left, right} = Enum.split_while(blocks, fn {_, index} -&gt; index &lt; n end)
    right = Enum.zip(Enum.map(right, &amp;elem(&amp;1, 0)) |&gt; Enum.reverse(), Enum.flat_map(frees, &amp; &amp;1))
    Enum.reduce(left ++ right, 0, fn {a, b}, sum -&gt; sum + a * b end)
  end

  def part2(file) do
    {blocks, frees, _} = parse(file)

    Enum.reduce(Enum.reverse(blocks), {frees, 0}, fn {id, br}, {fs, checksum} -&gt;
      s = Range.size(br)
      {l, r} = Enum.split_while(fs, fn fr -&gt; s &gt; Range.size(fr) or fr.first &gt; br.first end)

      case r do
        [fits | rest] -&gt;
          {o, p} = Range.split(fits, s)
          {l ++ if(p.step == 1, do: [p | rest], else: rest), checksum + id * Enum.sum(o)}

        [] -&gt;
          {fs, checksum + id * Enum.sum(br)}
      end
    end)
    |&gt; elem(1)
  end

  def parse(file) do
    s = file |&gt; File.stream!(1) |&gt; Stream.reject(&amp;(&amp;1 == "\n"))
    chunks = s |&gt; Enum.map(&amp;String.to_integer/1) |&gt; Enum.chunk_every(2, 2) |&gt; Enum.with_index()

    Enum.reduce(chunks, {[], [], 0}, fn {[nb | rest], id}, {blocks, frees, c} -&gt;
      new_free = if((nf = List.first(rest) || 0) &gt; 0, do: (c + nb)..(c + nb + nf - 1), else: ..)
      {blocks ++ [{id, c..(c + nb - 1)}], frees ++ [new_free], c + nb + nf}
    end)
  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="349161" 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-9/67977/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-349161" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="349161"
                     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="349172" data-post-id="349172">
  <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 liked it your solution. I failed part2 today and used your code as a basis to understand how you solved it. The gist of it which i really need to get it into my head is Enum.chunk_every. That was perfect for for this problem, coupled with with_index. I will see if i can refactor this another day, rewrite it with the core idea of blocks and ranges etc. probably with structs. To make it a) more readable and understandable and b) just because i like structs</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="349172" 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-9/67977/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-349172" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="349172"
                     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="349175" data-post-id="349175">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>One reason I’ve started doing more this year in Livebook is that I can easily copy and paste my part 1 soln into a new cell and start hacking away at it to solve part 2. That came in handy for this one.<br>
Part 1:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Fragmenter do
  def parse_disk_map(map) do
    map
      |&gt; String.to_charlist()
      |&gt; Stream.map(&amp;(&amp;1 - 48))
      |&gt; Stream.chunk_every(2)
      |&gt; Stream.with_index()
      |&gt; Enum.flat_map(fn {[used, free], id} -&gt;
        (for _ &lt;- Stream.cycle([0]) |&gt; Enum.take(used) do id end) ++ (for _ &lt;- Stream.cycle([0]) |&gt; Enum.take(free) do nil end)
        {[used], id} -&gt; 
        (for _ &lt;- Stream.cycle([0]) |&gt; Enum.take(used) do id end)
      end)
  end

  @doc """
  ## Examples
  iex&gt; "2333133121414131402" |&gt; Fragmenter.parse_disk_map() |&gt; Fragmenter.defrag() |&gt; Fragmenter.checksum()
  1928
  """
  def defrag(disk) do
    cl_disk = disk |&gt; Stream.with_index()
    bak = cl_disk |&gt; Enum.reverse() |&gt; Enum.reject(&amp;(elem(&amp;1,0) == nil))
    
    cl_disk
    |&gt; Enum.reduce(
      {[], bak },
      fn
        {c, i}, {fwd, [{_, j} | _] = bak} when c != nil and i &lt;= j -&gt;
          { [c | fwd], bak}
        {c, i}, {fwd, [{_, j} | _] = bak} when c != nil and i &gt; j -&gt;
          { [nil | fwd], bak}
        {nil, i}, {fwd, [{c, j} | rest]} when i &lt;= j -&gt;
          { [c | fwd], rest }
        {nil, i}, {fwd, [{_, j} | rest]} when i &gt; j -&gt;
          { [nil | fwd], rest }
      end
    ) |&gt; elem(0) |&gt; Enum.reverse()
  end

  def checksum(disk) do
    disk
    |&gt; Stream.with_index()
    |&gt; Stream.reject(&amp;(elem(&amp;1, 0) == nil))
    |&gt; Enum.reduce(
      0,
      fn {c, i}, acc -&gt; acc + c*i end
    )
  end
end
</code></pre>
<p>Part 2:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Fragmenter2 do
  def parse_disk_map(map) do
    map
      |&gt; String.to_charlist()
      |&gt; Stream.map(&amp;(&amp;1 - 48))
      |&gt; Stream.chunk_every(2)
      |&gt; Stream.with_index()
      |&gt; Stream.flat_map(fn {[used, free], id} -&gt;
          [Stream.cycle([id]) |&gt; Enum.take(used), Stream.cycle([nil]) |&gt; Enum.take(free)]
        {[used], id} -&gt; 
          [Stream.cycle([id]) |&gt; Enum.take(used)]
      end)
    |&gt; Stream.reject(&amp;(&amp;1 == []))
  end

  def defrag(disk) do
    files = disk |&gt; Enum.into([])
    x = Stream.flat_map(disk, &amp;(&amp;1)) |&gt; Stream.reject(&amp;(&amp;1 == nil)) |&gt; Enum.into(MapSet.new())
    defrag(files |&gt; :queue.from_list(), :queue.new(), x)
  end

  def merge_empty(file, empty) do
      [file, empty |&gt; Enum.take(Enum.count(empty) - Enum.count(file))]
  end
  
  def defrag(dq, fragged, x) do
    if :queue.is_empty(dq) do
      fragged |&gt; :queue.to_list()
    else
      case :queue.get(dq) do
        [] -&gt; defrag(:queue.drop(dq), fragged, x)
        [n | _] = file when n != nil -&gt; 
        n_available? = MapSet.member?(x, n)  
        defrag(
          :queue.drop(dq),
          :queue.in(
            if n_available? do
               file      
            else
              Stream.cycle([nil]) |&gt; Enum.take(file |&gt; Enum.count())
            end,
            fragged
          ),
          x
        )
        [nil | _] = empty -&gt;
          fit_q = :queue.filter(
            fn [n | _] = l -&gt; MapSet.member?(x, n) and (l |&gt; Enum.count()) &lt;= (empty |&gt; Enum.count()) 
              and (l |&gt; Enum.at(0) != nil) 
              end, dq)
          cond do
            fit_q |&gt; :queue.is_empty() -&gt; defrag(
              dq |&gt; :queue.drop(),
              :queue.in(empty, fragged),
              x
            )
            true -&gt;
              first_fit = fit_q |&gt; :queue.get_r()
              [first_fit, empty] = merge_empty(first_fit, empty)
              defrag(
                dq |&gt; :queue.drop() |&gt; then(&amp;:queue.in_r(empty, &amp;1)),
                :queue.in(first_fit, fragged),
                x |&gt; MapSet.delete(first_fit |&gt; Enum.at(0))
              )
          end
      end
    end
  end
  
  def checksum(disk) do
    disk
    |&gt; Stream.flat_map(&amp;(&amp;1))
    |&gt; Stream.with_index()
    |&gt; Stream.reject(&amp;(elem(&amp;1, 0) == nil))
    |&gt; Enum.reduce(
      0,
      fn {c, i}, acc -&gt; acc + c*i end
    )
  end
end
</code></pre>
<p>This is probably some of the ugliest Elixir I’ve ever written, but this one took me like 2.5hrs between part 1 and 2 to get right and I kept hitting stupid bugs. No clue if the use of <code>:queue</code> was necessary or even helpful here and I have yet to go back and try to optimize it (pt 2 takes about 3.5s on my machine, pt 1 is about 35ms).</p>
<p>Edit: I think <a class="mention" href="/u/sevenseacat" rel="nofollow">@sevenseacat</a> says it best:</p>
<blockquote>
<p>I am not proud of the code I wrote today.</p>
</blockquote> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="349175" 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-9/67977/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-349175" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="349175"
                     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="349176" data-post-id="349176">
  <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>Glad it helped! I’ll also recommend <a class="mention" href="/u/bjorng" rel="nofollow">@bjorng</a>’s solution (or anyone else who used a map instead of a list to track state). Map-based solutions often end up being more performant. I’m trying to write really terse solutions this year so I end up sacrificing speed for LOC.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="349176" 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-9/67977/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-349176" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="349176"
                     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="349180" data-post-id="349180">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I started with maps but in the end it’s the list version that is the faster for me. Around 40ms.</p>
<p>(but yeah my map version was probably just bad <img src="https://forum.elixirforum.com/images/emoji/apple/smiley.png?v=15" title=":smiley:" class="emoji" alt=":smiley:" 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="349180" 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-9/67977/19">Post #18</a>
	                </div>
	            </div>
              <div id="likers-container-349180" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="349180"
                     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="349183" data-post-id="349183">
  <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 stand corrected! I think 40ms may be the thread leader.</p>
<p>I generally expect maps to perform better when the lists are sparse, but when the lists are dense it’s a toss-up. I’d just assumed that because mine was so slow (~4s) it was one of those cases but I didn’t check.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="349183" 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-9/67977/20">Post #19</a>
	                </div>
	            </div>
              <div id="likers-container-349183" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="349183"
                     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="349187" data-post-id="349187">
  <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>Almost caught up. Posting part 1 for posterity:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">#!/usr/bin/env elixir

defmodule Day9.Part1 do
  @ascii_adjustment 48

  defp parse(str) do
    [{_size, _id} | _diskmap] =
      diskmap =
      str
      |&gt; String.trim()
      |&gt; to_charlist()
      |&gt; Enum.map(&amp;(&amp;1 - @ascii_adjustment))
      |&gt; Enum.with_index()

    %{
      empty_space: empty_space,
      files: [{first_file_size, _ffid} = _file | _files] = files,
      optimal_size: optimal_size
    } =
      diskmap
      |&gt; Enum.reduce(
        %{},
        fn {size, id} = item, acc -&gt;
          if rem(id, 2) == 0 do
            acc
            |&gt; Map.update(:files, [item], fn files -&gt; [item | files] end)
            |&gt; Map.update(:optimal_size, size, &amp;(&amp;1 + size))
          else
            acc
            |&gt; Map.update(:empty_space, [item], fn empty_space -&gt; [item | empty_space] end)
          end
        end
      )
      |&gt; Map.new(fn
        {:empty_space = k, v} -&gt; {k, v |&gt; Enum.map(&amp;elem(&amp;1, 0)) |&gt; Enum.reverse()}
        {:files = k, v} -&gt; {k, v |&gt; Enum.reverse() |&gt; Enum.map(&amp;elem(&amp;1, 0)) |&gt; Enum.with_index()}
        optimal_size -&gt; optimal_size
      end)

    optimal_size = optimal_size - first_file_size

    empty_space_count = empty_space |&gt; Enum.count()

    file_count = files |&gt; Enum.count()

    ends_with_space? = empty_space_count == file_count

    empty_space =
      if ends_with_space?,
        do: empty_space |&gt; List.delete_at(empty_space_count - 1),
        else: empty_space

    initial_insertion_index = 1

    %{
      files: files,
      empty_space: empty_space,
      optimal_size: optimal_size,
      insertion_index: initial_insertion_index
    }
  end

  defp pull([] = _files, _blocks), do: {[], []}
  defp pull(files, 0 = _blocks), do: {[], files}

  defp pull([{block_size, id} = file | files], blocks) do
    block_diff = block_size - blocks

    case block_diff do
      x when x &lt; 0 -&gt;
        {pulled_files, remaining_files} = pull(files, abs(block_diff))
        {[file | pulled_files], remaining_files}

      x when x &gt; 0 -&gt;
        {[{blocks, id}], [{block_diff, id} | files]}

      0 -&gt;
        {[{blocks, id}], files}
    end
  end

  defp pull_from_end(files, blocks) do
    {pulled, remaining} = pull(Enum.reverse(files), blocks)
    {pulled, remaining |&gt; Enum.reverse()}
  end

  defp optimize(%{
         files: files,
         empty_space: _empty_space,
         optimal_size: nil,
         insertion_index: _index
       }),
       do: files

  defp optimize(%{
         files: files,
         empty_space: _empty_space,
         optimal_size: optimal_size,
         insertion_index: _index
       })
       when optimal_size &lt;= 0,
       do: files

  defp optimize(%{
         files: files,
         empty_space: [],
         optimal_size: _optimal_size,
         insertion_index: _index
       }),
       do: files

  defp optimize(%{
         files: files,
         empty_space: [empty_size | empty_spaces],
         optimal_size: optimal_size,
         insertion_index: index
       }) do
    next_optimal_size = optimal_size - empty_size

    {files_to_insert, remaining_files} =
      if next_optimal_size &lt; 0,
        do: pull_from_end(files, optimal_size),
        else: pull_from_end(files, empty_size)

    next_file_index = index + 1

    next_optimal_size =
      if next_file_index &gt; remaining_files |&gt; Enum.count() do
        nil
      else
        next_optimal_size - (remaining_files |&gt; Enum.at(index) |&gt; elem(0))
      end

    file_count = files_to_insert |&gt; Enum.count()

    modified_files =
      (remaining_files
       |&gt; Enum.take(index)) ++ files_to_insert ++ (remaining_files |&gt; Enum.drop(index))

    insertion_index = next_file_index + file_count

    optimize(%{
      files: modified_files,
      empty_space: empty_spaces,
      optimal_size: next_optimal_size,
      insertion_index: insertion_index
    })
  end

  def checksum(files) do
    files
    |&gt; Enum.reduce(
      {0, 0},
      fn {block_size, id} = _chunk, {index, acc} -&gt;
        ids = for _ &lt;- 0..(block_size - 1), do: id

        acc =
          acc +
            (ids
             |&gt; Enum.with_index()
             |&gt; Enum.map(fn {id, i} -&gt;
               id * (i + index)
             end)
             |&gt; Enum.sum())

        {index + block_size, acc}
      end
    )
  end

  def solve() do
    File.read!("09/input.txt")
    |&gt; parse()
    |&gt; optimize()
    |&gt; checksum()
    |&gt; elem(1)
    |&gt; IO.puts()
  end
end

Day9.Part1.solve()
</code></pre>
<p>Still working on part 2</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="349187" 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-9/67977/21">Post #20</a>
	                </div>
	            </div>
              <div id="likers-container-349187" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="349187"
                     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 #20"></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/67977/load_more?page=3">Load more posts (10 remaining)</a>
</div></template></turbo-stream>