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


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="cblavier" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/cblavier/120/29763_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  cblavier
                    <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="Hallski" data-post="11" data-topic="36143">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hallski/48/7398_2.png" class="avatar"> Hallski:</div>
<blockquote>
<p>Also learnt the lesson of making sure to copy the entire test data instead of all but the last ten lines…</p>
</blockquote>
</aside>
<p>I ended up writing a generator to create my adventofcode files for each challenge and to download the puzzle as well. You can use <a href="https://github.com/cblavier/advent/blob/master/lib/mix/tasks/advent_gen.ex" rel="noopener nofollow ugc">the code</a> if you want to</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="197143" 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-2020-day-11/36143/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-197143" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="197143"
                     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="197199" data-post-id="197199">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I ended up with something nice for finding neighbours on part 2, but wow, this is veeeerryyyy slooooow (~4 seconds)</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  def neighbours(current, {x, y}) do
    Enum.reduce(@dirs, 0, fn {dx, dy}, acc -&gt;
      [v] =
        Stream.iterate(1, &amp;(&amp;1 + 1))
        |&gt; Stream.map(fn mul -&gt; {x + dx * mul, y + dy * mul} end)
        |&gt; Stream.map(fn {xx, yy} -&gt; Map.get(current, {xx, yy}) end)
        |&gt; Stream.drop_while(&amp;(&amp;1 == @floor))
        |&gt; Enum.take(1)

      if v == @occupied, do: acc + 1, else: acc
    end)
  end
</code></pre>
<p>I was thinking about the fact that the current map is RO, did someone try to add some concurrency into the mix ?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="197199" 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-2020-day-11/36143/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-197199" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="197199"
                     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="197209" data-post-id="197209">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p><strong>ugly and not optimized brute force but it works</strong></p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Advent.Day11 do

  def start(part \\ :part1, file \\ "/tmp/input.txt"), do:
    File.read!(file) |&gt; String.split() |&gt; normalize_input() |&gt; execute(part)

  defp execute({seats, rows, cols}, part), do:
    1..(rows * cols) |&gt; Enum.reduce({false, %{}}, fn idx, {changed, acc} -&gt;
      state = seats[idx]
      new_state = verify_seat(state, seats, idx, rows, part)
      {changed || new_state != state, Map.put(acc, idx, new_state)}
    end)
    |&gt; execute(rows, cols, part)

  defp execute({true, seats}, rows, cols, part), do: execute({seats, rows, cols}, part)
  defp execute({false, seats}, _rows, _cols, _part), do: seats |&gt; Map.to_list() |&gt; Enum.count(fn {_, v} -&gt; v == ?# end)

  def get_adjacent_state(seats, idx, rows, :part1) do
    r = rem(idx, rows)
    [ (r == 1) &amp;&amp; ?. || (seats[idx - rows - 1]),
      seats[idx - rows],
      (r == 0) &amp;&amp; ?. || (seats[idx - rows + 1]),
      (r == 1) &amp;&amp; ?. || (seats[idx - 1]),
      (r == 0) &amp;&amp; ?. || (seats[idx + 1]),
      (r == 1) &amp;&amp; ?. || (seats[idx + rows - 1]),
      seats[idx + rows],
      (r == 0) &amp;&amp; ?. || (seats[idx + rows + 1])]
  end

  def get_adjacent_state(seats, idx, rows, :part2), do:
  [ get_vertical(seats, idx, rows, - 1 - rows, 1),
    get_vertical(seats,idx, rows, -rows, - 1),
    get_vertical(seats, idx, rows, -rows + 1, 0),
    get_horizontal(seats, idx, rows, 1),
    get_horizontal(seats, idx, rows, 0),
    get_vertical(seats, idx, rows, rows - 1, 1),
    get_vertical(seats, idx, rows, rows, -1),
    get_vertical(seats, idx, rows, rows + 1, 0)
]

  def verify_seat(?., _seats, _idx, _rows, _part), do: ?.
  def verify_seat(?L, seats, idx, rows, part), do:
    (get_adjacent_state(seats, idx, rows, part) |&gt; Enum.any?(fn o -&gt; o == ?# end)) &amp;&amp; ?L || ?#

  def verify_seat(?#, seats, idx, rows, part), do:
    (get_adjacent_state(seats, idx, rows, part) |&gt; Enum.count(fn o -&gt; o == ?# end) &gt; (part == :part1 &amp;&amp; 3 || 4)) &amp;&amp; ?L || ?#

  defp normalize_input(lst), do:
    Enum.reduce(lst, {1, %{}}, fn lst, {idx, acc} -&gt;
      lst |&gt; String.to_charlist() |&gt; Enum.reduce({idx, acc}, fn el, {idx, acc} -&gt;
        {idx + 1, Map.put(acc, idx, el)}
      end)
    end) |&gt; (fn x -&gt; {elem(x, 1), List.first(lst) |&gt; String.length(), length(lst)} end).()

  def get_vertical(seats, idx, rows, delta_rows, rr), do:
    (rem(idx, rows) == rr) &amp;&amp; ?. || (
            case seats[idx + delta_rows] do
              nil -&gt; ?.
              ?. -&gt; get_vertical(seats, idx + delta_rows, rows, delta_rows, rr)
              v -&gt; v
            end
    )

  def get_horizontal(seats, idx, rows, rr) do
    delta = rr == 1 &amp;&amp; -1 || 1
    (rem(idx, rows) == rr) &amp;&amp; ?. || (
      case seats[idx + delta] do
        nil -&gt; ?.
        ?. -&gt; get_horizontal(seats, idx + delta, rows, rr)
        v -&gt; v
      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="197209" 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-2020-day-11/36143/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-197209" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="197209"
                     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="197214" data-post-id="197214">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>No, the first optimization that comes to mind is precomputing/caching the first visible seat location for each seat, because they will never change. Haven’t seen anyone do it yet, and I didn’t bother because I’m happy as long as I get the right answer. <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="197214" 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-2020-day-11/36143/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-197214" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="197214"
                     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="197217" data-post-id="197217">
  <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>Yeah, I also just use recursion for that, same as <a class="mention" href="/u/lostkobrakai" rel="nofollow">@LostKobrakai</a>.</p>
<p>Stopping when stable:<br>
<a href="https://github.com/adamu/AdventOfCode2020/blob/main/day11/day11part2.exs#L12-L20" class="onebox" target="_blank" rel="noopener nofollow ugc">https://github.com/adamu/AdventOfCode2020/blob/main/day11/day11part2.exs#L12-L20</a></p>
<p>Stopping as soon as we find the first occupied seat (<code>nil</code> = coordinate not in grid AKA no occupied seat in that direction):<br>
<a href="https://github.com/adamu/AdventOfCode2020/blob/main/day11/day11part2.exs#L69-L78" class="onebox" target="_blank" rel="noopener nofollow ugc">https://github.com/adamu/AdventOfCode2020/blob/main/day11/day11part2.exs#L69-L78</a></p>
<p>Actually thinking about it, I’m currently counting the number of occupied seats in all directions, but could stop when it hits 4/5 instead of continuing to count all 8. Anyway, day 12 in an hour <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="197217" 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-2020-day-11/36143/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-197217" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="197217"
                     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="197219" data-post-id="197219">
  <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 swear my code is almost identical to yours but I’m timing out on part 2 and can’t figure out why. Can anyone tell me where the bottleneck is?</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Day11 do
  @input File.stream!("lib/input")
         |&gt; Stream.with_index()
         |&gt; Stream.map(fn {line, row} -&gt; {row, String.graphemes(String.trim(line))} end)
         |&gt; Stream.flat_map(fn {row, line} -&gt;
           line
           |&gt; Stream.with_index()
           |&gt; Stream.map(fn {spot, col} -&gt; {{col, row}, spot} end)
         end)
         |&gt; Enum.into(%{})

  @adjacent [{1, 0}, {-1, 0}, {0, 1}, {0, -1}, {1, 1}, {-1, -1}, {1, -1}, {-1, 1}]

  def apply_rules(map, part) do
    map
    |&gt; Stream.filter(fn {_k, v} -&gt; v != "." end)
    |&gt; Stream.map(fn {coord, seat} -&gt;
      case seat do
        "L" -&gt;
          if make_occupied?(coord, map, part) do
            {coord, "#"}
          else
            {coord, seat}
          end

        "#" -&gt;
          if make_empty?(coord, map, part) do
            {coord, "L"}
          else
            {coord, seat}
          end
      end
    end)
    |&gt; Enum.into(map)
  end

  def make_occupied?({col, row}, map, _) do
    @adjacent
    |&gt; Stream.map(fn {a, b} -&gt; {col + a, row + b} end)
    |&gt; Stream.map(fn k -&gt;
      Map.get(map, k)
    end)
    |&gt; Enum.all?(fn v -&gt; v != "#" end)
  end

  def make_empty?({col, row}, map, 1) do
    @adjacent
    |&gt; Stream.map(fn {a, b} -&gt; {col + a, row + b} end)
    |&gt; Stream.map(fn k -&gt; Map.get(map, k) end)
    |&gt; Stream.filter(fn v -&gt; v == "#" end)
    |&gt; Enum.count()
    |&gt; Kernel.&gt;=(4)
  end

  def make_empty?({col, row}, map, 2) do
    find_first_visible({col, row}, map)
    |&gt; Stream.filter(fn v -&gt; v end)
    |&gt; Enum.count()
    |&gt; Kernel.&gt;=(5)
  end

  def part_1() do
    run(@input, 1)
  end

  def run(map, part) do
    run(map, apply_rules(map, part), part)
  end

  def run(map, new_map, part) do
    if Map.equal?(map, new_map) do
      count_occupied(new_map)
    else
      run(new_map, apply_rules(new_map, part), part)
    end
  end

  def count_occupied(map) do
    map
    |&gt; Stream.filter(fn {_, v} -&gt; v == "#" end)
    |&gt; Enum.count()
  end

  def find_first_visible({col, row}, map) do
    @adjacent
    |&gt; Enum.map(fn dir -&gt; find_first_visible({col, row}, map, dir) end)
  end

  def find_first_visible({col, row}, map, {a, b}) do
    case Map.get(map, {col + a, row + b}) do
      nil -&gt;
        false

      "." -&gt;
        find_first_visible({col + a, row + b}, map, {a, b})

      "L" -&gt;
        false

      "#" -&gt;
        true
    end
  end

  def part_2() do
    run(@input, 2)
  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="197219" 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-2020-day-11/36143/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-197219" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="197219"
                     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="197220" data-post-id="197220">
  <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>You need to consider the full line of sight for an empty seat too. An empty seat becomes occupied if there are 0 occupied seats visible in all directions, but you are only checking the immediately adjacent seats.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  def make_occupied?({col, row}, map, 1) do
    @adjacent
    |&gt; Stream.map(fn {a, b} -&gt; {col + a, row + b} end)
    |&gt; Stream.map(fn k -&gt;
      Map.get(map, k)
    end)
    |&gt; Enum.all?(fn v -&gt; v != "#" end)
  end

  def make_occupied?({col, row}, map, 2) do
    find_first_visible({col, row}, map)
    |&gt; Stream.filter(fn v -&gt; v end)
    |&gt; Enum.count()
    |&gt; Kernel.==(0)
  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="197220" 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-2020-day-11/36143/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-197220" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="197220"
                     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="197221" data-post-id="197221">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I think I had a similar experience today. Worked out okay, but a bit slower than I would like (~1s/~3s).</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Day11 do

  defguard in_bounds(x, list) when 0 &lt;= x and x &lt; length(list)

  def part_1, do: solve(&amp;by_adjacency/4)
  def part_2, do: solve(&amp;by_visibility/4)

  def solve(method) do
    load()
    |&gt; find_stable(method)
    |&gt; count_occupied()
  end

  def count_occupied(seats) do
    seats
    |&gt; Enum.map(fn row -&gt; Enum.count(row, &amp;(&amp;1 == ?#)) end)
    |&gt; Enum.sum()
  end

  def find_stable(seats, transform) do
    case next_gen(seats, transform) do
      next when next == seats -&gt; next
      next -&gt; find_stable(next, transform)
    end
  end

  def next_gen(seats, transform) do
    for {row, r_idx} &lt;- Enum.with_index(seats) do
      for {seat, c_idx} &lt;- Enum.with_index(row) do
        transform.(seats, seat, r_idx, c_idx)
      end
    end
  end

  def by_visibility(_, ?., _, _), do: ?.
  def by_visibility(seats, ?L, row, col) do
    if visible(seats, row, col) == 0, do: ?#, else: ?L
  end
  def by_visibility(seats, ?#, row, col) do
      if visible(seats, row, col) &gt;= 5, do: ?L, else: ?#
  end

  def visible(seats, r_idx, c_idx) do
    directions()
    |&gt; Enum.count(fn {x, y} -&gt; next(seats, r_idx + x, c_idx + y, x, y) end)
  end

  def next(_, row, col, _, _) when row &lt; 0 or col &lt; 0, do: false
  def next(seats, row, col, drow, dcol) do
    case get_seat(seats, row, col) do
      ?. -&gt; next(seats, row + drow, col + dcol, drow, dcol)
      x -&gt; x == ?#
    end
  end

  def by_adjacency(_, ?., _, _), do: ?.
  def by_adjacency(seats, ?L, row, col) do
    if adjacent(seats, row, col) == 0, do: ?#, else: ?L
  end
  def by_adjacency(seats, ?#, row, col) do
      if adjacent(seats, row, col) &gt;= 4, do: ?L, else: ?#
  end

  def adjacent(seats, row, col) do
    directions()
    |&gt; Enum.count(fn {x, y} -&gt; get_seat(seats, row + x, col + y) == ?#  end)
  end

  def directions do
    for x &lt;- -1..1, y &lt;- -1..1, not_origin(x, y), do: {x, y}
  end

  def not_origin(x, y), do: not(x == 0 and y == 0)

  def get_seat(seats=[fst|_], row, col)
    when in_bounds(row, seats) and in_bounds(col, fst),
    do: seats |&gt; Enum.at(row) |&gt; Enum.at(col) 
  def get_seat(_, _, _), do: nil

  def load do
    File.read!("day-11.input")
    |&gt; String.split("\n", trim: true)
    |&gt; Enum.map(&amp;String.to_charlist/1)
  end
end
</code></pre>
<p><a href="https://github.com/felix-alonso/advent-of-code/blob/master/2020/day-11.ex" rel="noopener nofollow ugc">Code on 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="197221" 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-2020-day-11/36143/19">Post #18</a>
	                </div>
	            </div>
              <div id="likers-container-197221" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="197221"
                     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="197223" data-post-id="197223">
  <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>ah, I misread the problem. Thanks.<br>
After fixing that issue I went ahead and implemented the optimization <a class="mention" href="/u/aaronnamba" rel="nofollow">@aaronnamba</a> suggested. I’m not sure that was the bottleneck for me b/c it’s still slow. Anyway, got the right answer so moving on.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Day11Helper do
  def find_first_visible({col, row}, map, {a, b}) do
    case Map.get(map, {col + a, row + b}) do
      nil -&gt;
        false

      "." -&gt;
        find_first_visible({col + a, row + b}, map, {a, b})

      "L" -&gt;
        {col + a, row + b}

      "#" -&gt;
        {col + a, row + b}
    end
  end

  def cache_first_visible(input, adjacent) do
    input
    |&gt; Enum.map(fn {{col, row} = coord, _seat} -&gt;
      {coord,
       adjacent
       |&gt; Enum.map(fn dir -&gt; find_first_visible({col, row}, input, dir) end)}
    end)
    |&gt; Enum.into(%{})
  end
end

defmodule Day11 do
...
 @cache_first_visible Day11Helper.cache_first_visible(@input, @adjacent)
</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="197223" 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-2020-day-11/36143/20">Post #19</a>
	                </div>
	            </div>
              <div id="likers-container-197223" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="197223"
                     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="197256" data-post-id="197256">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Had some time yesterday to try this one. It takes <code>~0.31s</code> for the part-1 and <code>~0.72s</code> for part-2.<br>
This might be a different approach compared to the solutions here, not using map for the grid since we only need to know about surrounding seats. Code can be made more readable I guess <img src="https://forum.elixirforum.com/images/emoji/apple/slightly_smiling_face.png?v=15" title=":slightly_smiling_face:" class="emoji" alt=":slightly_smiling_face:" loading="lazy" width="20" height="20"></p>
<p><a href="https://gist.github.com/akash-akya/1a7e0e30a6beda1c34e0beeffd45001f" rel="noopener nofollow ugc">Gist</a></p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule AOC2020.Day11 do
  def parse(input) do
    String.split(input, "\n", trim: true)
    |&gt; Enum.map(&amp;String.codepoints(&amp;1))
  end

  def show(room) do
    Enum.map(room, &amp;IO.puts(Enum.join(&amp;1)))
    room
  end

  def count_occupied(room) do
    Enum.map(room, fn row -&gt; Enum.count(row, &amp;(&amp;1 == "#")) end)
    |&gt; Enum.sum()
  end

  def sample_input do
    """
    L.LL.LL.LL
    LLLLLLL.LL
    L.L.L..L..
    LLLL.LL.LL
    L.LL.LL.LL
    L.LLLLL.LL
    ..L.L.....
    LLLLLLLLLL
    L.LLLLLL.L
    L.LLLLL.LL
    """
  end

  defmodule PartOne do
    alias AOC2020.Day11

    defp new_seat_state(adj_seats, cur) do
      count = Enum.count(adj_seats, fn v -&gt; v == "#" end)

      cond do
        count == 0 &amp;&amp; cur == "L" -&gt; "#"
        count &gt;= 4 &amp;&amp; cur == "#" -&gt; "L"
        true -&gt; cur
      end
    end

    defp do_traverse_row(
           [t_left, t],
           [c_left, c],
           [b_left, b]
         ) do
      [new_seat_state([t_left, t, c_left, b_left, b], c)]
    end

    defp do_traverse_row(
           [t_left | [t, t_right | _] = top],
           [c_left | [c, c_right | _] = cur],
           [b_left | [b, b_right | _] = bottom]
         ) do
      seat = new_seat_state([t_left, t, t_right, c_left, c_right, b_left, b, b_right], c)
      [seat | do_traverse_row(top, cur, bottom)]
    end

    defp traverse_row(
           [t, t_right | _] = top,
           [c, c_right | _] = cur,
           [b, b_right | _] = bottom
         ) do
      seat = new_seat_state([t, t_right, c_right, b, b_right], c)
      [seat | do_traverse_row(top, cur, bottom)]
    end

    defp do_traverse_room([top, cur]) do
      bottom = Enum.map(cur, fn _ -&gt; "." end)
      row = traverse_row(top, cur, bottom)
      [row]
    end

    defp do_traverse_room([top, cur, bottom | rest]) do
      row = traverse_row(top, cur, bottom)
      [row | do_traverse_room([cur, bottom | rest])]
    end

    defp traverse_room([cur, bottom | _] = room) do
      top = Enum.map(cur, fn _ -&gt; "." end)
      row = traverse_row(top, cur, bottom)
      [row | do_traverse_room(room)]
    end

    defp do_run(room) do
      new_room = traverse_room(room)

      if new_room == room do
        new_room
      else
        do_run(new_room)
      end
    end

    def run(input) do
      Day11.parse(input)
      |&gt; do_run()
      |&gt; Day11.count_occupied()
    end
  end

  # part 2

  defmodule PartTwo do
    alias AOC2020.Day11

    defp invert(m), do: Enum.reduce(m, [], &amp;[Enum.reverse(&amp;1) | &amp;2])

    defp merge_row([], []), do: []

    defp merge_row([a | adj_rest], [b | i_adj_rest]) do
      [
        Map.merge(a, %{
          right: b[:left],
          bottom_right: b[:top_left],
          bottom: b[:top],
          bottom_left: b[:top_right]
        })
        | merge_row(adj_rest, i_adj_rest)
      ]
    end

    defp merge([], []), do: []

    defp merge([adj_row | adj], [i_adj_row | i_adj]) do
      [merge_row(adj_row, i_adj_row) | merge(adj, i_adj)]
    end

    defp do_row_cache([t_left, t], [c_left, c]) do
      seat_cache =
        case c do
          "." -&gt; %{top_left: t_left.top_left, top: t.top, top_right: ".", left: c_left.left}
          "#" -&gt; %{top_left: "#", top: "#", top_right: "#", left: "#"}
          "L" -&gt; %{top_left: "L", top: "L", top_right: "L", left: "L"}
        end

      [seat_cache]
    end

    defp do_row_cache(
           [t_left | [t, t_right | _] = top],
           [c_left | [c | rest]]
         ) do
      seat_cache =
        case c do
          "." -&gt;
            %{
              top_left: t_left.top_left,
              top: t.top,
              top_right: t_right.top_right,
              left: c_left.left
            }

          "#" -&gt;
            %{top_left: "#", top: "#", top_right: "#", left: "#"}

          "L" -&gt;
            %{top_left: "L", top: "L", top_right: "L", left: "L"}
        end

      [seat_cache | do_row_cache(top, [seat_cache | rest])]
    end

    defp row_cache([t, t_right | _] = top, [c | cur]) do
      seat_cache =
        case c do
          "." -&gt; %{top_left: ".", top: t.top, top_right: t_right.top_right, left: "."}
          "#" -&gt; %{top_left: "#", top: "#", top_right: "#", left: "#"}
          "L" -&gt; %{top_left: "L", top: "L", top_right: "L", left: "L"}
        end

      [seat_cache | do_row_cache(top, [seat_cache | cur])]
    end

    defp adj_cache(top, [cur]), do: [row_cache(top, cur)]

    defp adj_cache(top, [cur, bottom | rest]) do
      new_cur = row_cache(top, cur)
      [new_cur | adj_cache(new_cur, [bottom | rest])]
    end

    defp create_adj_cache([cur, bottom | rest]) do
      top = Enum.map(cur, fn _ -&gt; %{top_left: ".", top: ".", top_right: "."} end)
      new_cur = row_cache(top, cur)
      [new_cur | adj_cache(new_cur, [bottom | rest])]
    end

    defp new_seat_state(adj_seats, cur) do
      count = Enum.count(adj_seats, fn v -&gt; v == "#" end)

      cond do
        count == 0 &amp;&amp; cur == "L" -&gt; "#"
        count &gt;= 5 &amp;&amp; cur == "#" -&gt; "L"
        true -&gt; cur
      end
    end

    defp do_traverse_row(
           [c],
           [t_left | [t | _]],
           [c_left | [_ | _]],
           [b_left | [b | _]]
         ) do
      seat =
        new_seat_state(
          [
            t_left[:top_left],
            t[:top],
            b[:bottom],
            b_left[:bottom_left],
            c_left[:left]
          ],
          c
        )

      [seat]
    end

    defp do_traverse_row(
           [c | row],
           [t_left | [t, t_right | _] = top],
           [c_left | [_, c_right | _] = cur],
           [b_left | [b, b_right | _] = bottom]
         ) do
      seat =
        new_seat_state(
          [
            t_left[:top_left],
            t[:top],
            t_right[:top_right],
            c_right[:right],
            b_right[:bottom_right],
            b[:bottom],
            b_left[:bottom_left],
            c_left[:left]
          ],
          c
        )

      [seat | do_traverse_row(row, top, cur, bottom)]
    end

    defp traverse_row(
           [c | row],
           [t, t_right | _] = top,
           [_, c_right | _] = cur,
           [b, b_right | _] = bottom
         ) do
      seat =
        new_seat_state(
          [
            t[:top],
            t_right[:top_right],
            c_right[:right],
            b[:bottom],
            b_right[:bottom_right]
          ],
          c
        )

      [seat | do_traverse_row(row, top, cur, bottom)]
    end

    defp do_traverse_room([cur], [near_prev, near_cur]) do
      near_next = Enum.map(cur, fn _ -&gt; %{bottom_right: ".", bottom: ".", bottom_left: "."} end)
      [traverse_row(cur, near_prev, near_cur, near_next)]
    end

    defp do_traverse_room([cur | room], [near_prev, near_cur, near_next | rest]) do
      new_row = traverse_row(cur, near_prev, near_cur, near_next)
      [new_row | do_traverse_room(room, [near_cur, near_next | rest])]
    end

    defp traverse_room([cur | room], [near_cur, near_next | _] = near) do
      near_prev = Enum.map(cur, fn _ -&gt; %{top_left: ".", top: ".", top_right: "."} end)
      new_row = traverse_row(cur, near_prev, near_cur, near_next)
      [new_row | do_traverse_room(room, near)]
    end

    defp compute_new_room_state(room) do
      adj = create_adj_cache(room)
      i_adj = create_adj_cache(invert(room))
      adj = merge(adj, invert(i_adj))

      traverse_room(room, adj)
    end

    defp do_run(room) do
      new_room = compute_new_room_state(room)

      if new_room == room do
        new_room
      else
        do_run(new_room)
      end
    end

    def run(input) do
      Day11.parse(input)
      |&gt; do_run()
      |&gt; Day11.count_occupied()
    end
  end
end
</code></pre>
<p>This vaguely reminded me of <a href="https://en.wikipedia.org/wiki/Kernel_(image_processing)" rel="noopener nofollow ugc">convolution matrix.</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="197256" 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-2020-day-11/36143/21">Post #20</a>
	                </div>
	            </div>
              <div id="likers-container-197256" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="197256"
                     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>