Powered by AppSignal & Oban Pro

Day 20

2021/day20.livemd

Day 20

Section

[algo, board] =
  File.read!("day20.txt")
  |> String.split("\n\n")

board =
  board
  |> String.split("\n", trim: true)
  |> Enum.with_index()
  |> Enum.flat_map(fn {row, y} ->
    :binary.bin_to_list(row)
    |> Enum.with_index()
    |> Enum.map(fn {c, x} -> {{x, y}, if(c == ?#, do: 1, else: 0)} end)
  end)
  |> Map.new()

defmodule Day20 do
  defmodule Image do
    defstruct [:board, :background]

    @behaviour Access

    def new(board, background \\ 0),
      do: %__MODULE__{board: board, background: background}

    def dims(%__MODULE__{board: board}) do
      {{min_x, min_y}, {max_x, max_y}} = board |> Map.keys() |> Enum.min_max()

      {min_x..max_x, min_y..max_y}
    end

    def lighted(%__MODULE__{background: 1}), do: :inf
    def lighted(%__MODULE__{board: board}), do: board |> Map.values() |> Enum.sum()

    @impl Access
    def fetch(%__MODULE__{} = img, {_, _} = key) do
      case Map.fetch(img.board, key) do
        {:ok, value} -> {:ok, value}
        :error -> {:ok, img.background}
      end
    end

    def fetch(_data, _key), do: :error

    @impl Access
    def get_and_update(_data, _key, _func), do: :error

    @impl Access
    def pop(_data, _key), do: :error

    defimpl Inspect do
      import Inspect.Algebra

      def inspect(%@for{} = img, _opts) do
        {min_x..max_x, min_y..max_y} = @for.dims(img)

        display =
          for y <- (min_y - 1)..(max_y + 1) do
            row =
              for x <- (min_x - 1)..(max_x + 1) do
                if img[{x, y}] == 1, do: "█", else: " "
              end

            concat([concat(row), line()])
          end

        concat([
          "#Image<{#{max_x - min_x + 1}x#{max_y - min_y + 1}}",
          line(),
          concat(display),
          ">"
        ])
      end
    end
  end

  defmodule Algo do
    defstruct [:desc]

    @behaviour Access

    def new(desc), do: %__MODULE__{desc: desc}

    @impl Access
    def fetch(%__MODULE__{desc: desc}, pos) do
      loc = rem(pos, 512)
      {:ok, if(binary_part(desc, loc, 1) == "#", do: 1, else: 0)}
    end

    @impl Access
    def get_and_update(_data, _key, _func), do: :error

    @impl Access
    def pop(_data, _key), do: :error
  end

  def get_bits(img, {x, y}) do
    digits =
      for dy <- -1..1,
          dx <- -1..1,
          do: img[{x + dx, y + dy}]

    Integer.undigits(digits, 2)
  end

  def enchance(img, algo) do
    {min_x..max_x, min_y..max_y} = Image.dims(img)

    board =
      for y <- (min_y - 1)..(max_y + 1),
          x <- (min_x - 1)..(max_x + 1),
          into: %{},
          do: {{x, y}, algo[get_bits(img, {x, y})]}

    Image.new(board, algo[512 - img.background])
  end
end

alg = Day20.Algo.new(algo)
img = Day20.Image.new(board)
#Image<{100x100}
                                                                                                      
 █ █   █  ██  ████████   ██    █ █ ███ █ ██ ██   █  ███ █ ██ █ █  █  ██  ███    █  ██ ██    █   ██ █  
  ███ █  █ █ █  ██ ██ █ ████  ██ █   █ ███   █ █    █ █ ███  █ █  ███   ██  ██████  █  █  █████       
 ██ █ ███ █ █  ███   ██  ███ █ █  █    █   █  █     ██  ███ ███ ██████ ████ █ █   ██ █ ██ ████  █ ██  
    █  ██   ████████ ██  █  █   █   █   ██ █  █ █  █ ██  ██ █  █   █ ██        █ █ █ ██████  █  █ █   
      ███    █ ██    ████  █ █ █ ███ ███ ██ █ █ ███  █  ██ █   ██ ███  █ ██  ██ ██  █ █    ████  █ █  
   ████  ███ █  ███ █     █  █  █    █████████ ████ █  █ ██ ██  █    █     █ █ █  █ █  █  ███ ██   ██ 
 ███ █  █████   ████ ██   ████   █ █████ ██   ██ ████ ███   ███   ██   █  █ █ ██████ ██    █    ██  █ 
    █   █ █ ███  █ █  █ █ ████  ████ █  █   █   █ █   █   █     ██  █     █ █ █    █████ ██  █ █  ███ 
 ██   ██  ███  █  █   █  █  █ ████   █ ██ ███ █ █    █  ██    █     █ ██ ███ ███ █     █████ █   █    
  ██ █  █  █  █ ██ █ ██ ███ ███    ██ █ █   █████ █  ██  █    ███  █ █   ██ ███ █  █ ████  ██  ██████ 
 █ █  ████ ███ █████ ███ ██    ██  ████ ██ ██ █████████         █ █     ████ ██     █ █   ██ █    ██  
  █  █ █ █  █ █ █ █ █  ███    ██ █ ██ █    █ ██ █    █████ █  ███   ██      █  █ █ ██  ██  ██████  ██ 
   ██ ████ ██     █ ███████  ██ ██   ██ ████ ████ ██   ████  █ ███    █  ███  ██  █ ████    ███  ██   
 █ █    █   █ █ █  █ █  █   █████  █ █  ███ █ ██   █████     ██ █    █ █ ██ █  █ █  ███   █ █ █  █  █ 
 ██ █ █  █ ███ ███ ██ ████    ███ █ ██ █ █ ██   ███ ██ █ █   ██ █ ██  █ ██ ██ █ █    █     █ █ ███    
  █ ██ █    █ █ █ ███ ██  ███████ ███  █   █   █████ ███ █ █ ███  ███   ███ ██████ █ █    █   █████ █ 
 ████  █  ████ █      ████  ██   ████   ██ █ ██████ ███ ███ █ █ █ █    ██ ███████    ██ █  ████  ██ █ 
   ██ █  ███   ██    ██ ███ █ █ █    █  ██  ███  ██  ██  █ ████  █    █ █ ████  █  ██ █  █    █  ██ █ 
  █  █ █  ██ ███    █   ████   ██ ██  █ █  ██ ██ ██ ███    ██   ██     █ ███      ███  █ █  ███    █  
 ███ █   █ ██   ████ █ ██ ███  █     ██ █ █   █ █  ███ ██  ███ █  █ █ █ █ █████ █ ████ ██  ████  ██   
      █ █  █ ██   █  █     █ ███ ██████████ ██     █  ████ ██ ██ ███ ██  █ ██  █    █ █  ██   ███ █   
 █  █ ██ █ █ █  █    ██████████ ███  █ █   █ ██   █████  █  ██  █  ████       ███  █  █ ███  ███ ██ █ 
 ███ █  ██  ██  ████   █ ████  ██ ██████    █  █   █  ██   █████ ████ ██ ████   ██████  █  ██   ██  █ 
   ██ █████   █ ██  ███   ███ █      █ █ ██████ █   ████ ████ ██ ██    ██  ██ █ █  ████ █████ ██████  
   ██  █ █  ███  █     ████  █ ████ ██ █ ████ ██     ████  ██  █   ███ █   ███   █ █ █        ██   █  
  █ ███ ██ ██ █ ██ ██  █ █ ███   ██  █  █  █ ██ █ █  ██ █ █ █ ██    ██    █ █      █    █  █    ██ █  
 █████ █ ███   ███ █  █ ██ ███   ███ ██ ██        █ ███ █   ██ ███ █   ███ ██ ██  █ ██ ███  ████ ███  
 █    ████ █  █ ███    ██ █ ██  ██     █  █   █   ██ █  █ █   █  ██ █  ██  ██████ ██  ████ ██   █ █   
   █ █  █  ██ ██   ██ ███   █   ███  █ ██  █ █████  █ █ ██ ███████ ██ █ █  ██  ████     █████  █ █ ██ 
 █ █     █ █ ██ ██ ██ ██      █   ██ ██ ███  █   █ █        ██    █ █     █ ██ ███    █  ███  █  █ ██ 
   █ █ ████  █ ██   █ ███ ██    █ ██ █████████ ███   ██   ██ █ █    █   █   ██     ███ ██         █   
 ███ ██ █ █   █   ██   ██   ██ ██ █  █ █    ██ █ ██  █  ██ █ ██ ██  █ █ ████ ███ █ ██ ██    █ ███ ██  
 ███  █ ██████ █ ███ ██ ███  ██ █  ██████  ███     ███      █ ██  ██  █     ██  ██ ██  █ █    ██ ██ █ 
   ██ █    █         ██ ██ █ █  ████  ██ █      █    █   ██ █████  ██        ██    █ ███   ███ ███  █ 
 ██   ███ █ █  █ █  ██ █ ██ ████    ███    ██ █████ ██    █ ██   ██  █     █    █   ██████  █ █   ███ 
  ██ ██ █  ███ █ ███ █ █ ███   ████ ██ █ █ █ ████ █   ████ ██  ███ █   ██  ██ ████  ███ █ █  ██  ██   
 █  █   █████ ██   █   ██  ███ █ █    █ █   █████████  ██     ██ █ █   ███      █ ██ ████████  █ ██   
 ██  ██ ██       ██  ██        ███ █    █ ████ █  █ █ ███    █ █ █ █ ███ █ █  ██  ██   ██ █     █     
     █  ██   █████   ██  █ ███    ██ ██  ██ █    █    █  █ █   █ █████   █  ██ █ ██   █ █   ████   ██ 
   ██  ████ ██    █ ███ ████   ███ █ ██ ██   █  ██  █ ███ ███ █ █ ██████ █  █████      ██  █ ███ █ █  
 █  █ █    █   ███ █ █    ██ ███  █    ██  ████ █  █ █████ █ ███ ██████   █  ███ ██  ████ █   ██ █  █ 
   █ ██ ██ █ ██        █  ██     █ █ █ █ ██ ██  █  ██   █ ██   █   █ ██ ███  ███     ██  █    █ █  ██ 
 ███ ██   ██ █ █   ██   ████ ███ █   ████  ███   █ ██ █  █ █ ███      █ █   ███  █ ████ ██ █ █ ████   
 █ █ ██ ██   █  ██  █    █ ██  ██      ███  ███   ████  ██   ███ █ ██ ██  ██   ████ █     █ ██ ██   █ 
      █   █ ██ █  █ ██ █ ████ ███████      ██ █  █   ██  █   █ ███ ███ █ ██ █ ██  █ ██ ██ █  █ ███  █ 
 ████   █████  ██    ██ █████   █   █   ██     ██  ███  █   ███  █   █   ██ ███  ███ █████   ██ █     
 █  ███   ███    █ █ █ ██████ ███  ████  █████   ███  ███  ███    ██ █ ██  █ ██  ██  █ ███ █████      
 █ █ ██ █ ████  █████ ███ █  █████ █  █ █ █  █ ██    ██ █ █ █ █ ███ ███  ███   █████ █ ██ █ █ █  █    
  █ █   █  █ ██ █  ████  ███ █  █ ████████ ████      █   ██  █████  █   █ █  ███  █ █    ████    █  █ 
 ██ ███ ███  █  ██ █  █   █  ████  █ ███  ██    █ █   ██████ ██    ██   █    █         ████ █ ███ █   
  ██  ████ ██ █ █  ████   █ ██  ██ ██  ███   █     ██   █      █    ██   █████  █████ █ █ █   █  ██   
  █   ██ █ ███ █ █ ██    ███  ███ ██ █ ██     ███ ████       █ █ █ █    ██ █  █  █  █████  █    █ █ █ 
   █ ██ ███ ███                 ███ █   █   █ ██ █ ███  ███  █  ██  █ █  ███  ██ █ ██ █ ██ ██ ██ █    
 ███ █   █  █   ███       ███ █ █  █████ ████ █  █   ██   █████  █        ███ █  █ ███████  ████ █ ██ 
    █ ██ █████ █   ██ ███   ██ █  █  ██ ██ ██  █ █ █ █ ███   █ ██  █ ██ ██ █ █ ██   ██ ███    █  █ ██ 
 ██ █ ████ ██ █  █████ █ █   ██████ ███ █ █ ██ ██   ██ █ ██ █  █   ██ ██ █  █   █  █  █  █  █ ██ █    
 █ ███████ █  █ ██  █  █ █  █  ████    █ █  █  █   █     ████   █  █       █  █   ██  ██ ██ ██  █ █   
   ██ █ ████ █ █ █      ████████  █  █     ███ █ ████ █  █████ ██  ████ █ ███    ██ █ █  █ ██  █████  
  ██ █ ██ █ █  █ █ █ █   █████████   █████  █   ███ █ ██  ██ █  ██   ███ ██ █ █ █ █   ████ █ █ ████ █ 
  █████ ████  ██ ██    █ █ █   ██████ █ █  █ █ █    █ █    ██ █  █ ███  █  █ ████   ███  ██ █ █ █ █   
  ██  █  ███ ██████ █ █ █  ██████ ██  █  █ ██████    ███ ██  █████     ████ █ █ █   ██ ███ █   ██ ██  
  █ ████  ██ █  █ █  █ ███ ██ █    ██  █ █  █████ ██ ██   █  ████  ███  █        █ ██  ██ ████   ███  
   ██  ███ █ ███ █   ██ █ ██ ██ ███████  ██ █    █ ████ █   ████   ████ ███ ██ ██   ██ █  █ █    █  █ 
  ██  █ ██████  █ █ ██     ██████ █████      ███ █    ███ ██ █ ███ █  █ █ ███ █ ████   ████ ██     ██ 
  ████    █ ██ ██ █ █    █ ██ █  █   ██     █  ██      █  ███████  █ ██ ███ █  █ ███ ████  ███ █ █  █ 
   █ ██ █ █  ██  ████    ███████ ██   █ ██     █ █ ██    █ ███ █ █  █ ███ █     █ ████ █     ██ █   █ 
 ██   █ ██  ██ █         █  █  ███████ ██ █  ███ █ ███  █ ██ █  █   █  █  █ ██ ██ █  ███ ███   ██ ██  
    █ █  ███  █ ██ █████ █ ██   █ ██  ███ █   █   █ ██    █████  █████    ███  █ ████ █   █ ███     █ 
   █ ████  █  █ █  █ ██████   ██ ██   ██   █ █ █     █  █   ██  █ ████████████ ███ ████    ███  ███   
 █ █   █ █ ██  ██  █ █  █   ████ ██ ██ █ █ █ ██  ██ █ █     █    █   █   █ ███ █ █████  ██ ███   █  █ 
  █    █ ██  ███ █  █ ███ █  █ █  ██  ██       ████████ █   █   █████ █   █  █  ██     █ ██     ████  
 █ █████ █ ██ ███ █ █    █ █ ███   ██ █     ██  ██  █ █████  █ █ ██ █  ███  ██   █ █ ██ █ █     █ █   
   ███   █ █       █ █      ██ █  █ █ █ █ █   █ ███ ██   ████    ██████      █   █████  ███ ██   █  █ 
 █  █   █  ██  █   █   ████ █   █    █████ █   █   █ █     ██   ██  █   █    █  █████   █     ██   █  
 █ ████ █   █   █  ██   ██    █   █ █ ██ ██ ██   ██  ██ █  █  █ ██ ██ ██ █ ██      █ █   ██     █   █ 
  █  ████  ███        █████   █    █ ████  ██  █████ ██ ███  █  ███   ██  ██   ██     █  █ █ ███ █    
  █    █ ████    █    ██  █ █ ██████ ███████ █ ██ ███ ███   █ █    ██  █  ████ ███ █    ███   █ █     
    ███  ██ █ ██  █ █ █████ ██████ █  ██████ ██   █ ██ █  ██ ███ █       █  █   █ ███   ██  ████ ██ █ 
 █    ███    █  █████ █  █   ███  ██ ██   ██ ███   █   █    █  █   █  ████ █ ████   █  ██    █   █ ██ 
 █ ████ ███   █  █ ████   █  █ ██ ███ █ ██ █    █  ██ █ █   ██ █  █ ██ ██  █████  █  █   ███   █ ████ 
 █ ██ ██  ██ ██      █ █ ██   ███ ████ ███ ████ █   ██   █ █   ███  ███ ██████ █████    ███ ████ █    
 ██  █ ███    █ █  ███ █  ██  ███ █  ██  █████ █ ███  █ █   ██ █ █ █ ████    ██   ██    ███ █ █ █  ██ 
    █ ███ ███  ███ ██   █ ███ █ ████ ██  █ █  ███   █  ██ ██████ █ █  ███  █ ██   ██ ███    ██ █   █  
 █  █ █  █ █  █ █ █ █ █  ██  █    █  ███ ███ █   █ █████ █  █  █ █    █ █ █ █    ██ ██  █   ██      █ 
    █   ██    █    █ ██ ██████ █   █     █ ██  █    █  ██ █         ███  █  █  █ ██ ██   █ █  ███████ 
 ██ ██  █  █ █  █ █ ██████ ██   ████   █   █  █  ██ █      █ █    █ ███  █ ███   █   █   █ ██   ███   
 █ ████ █ ██    ██  ███    █ ██ █ ██    ████ █ █ ██ █    █  █  ███   █     ██ ██    ████  ███         
   █  ██   ██ █   █  █ █  ███    ██   █   ████     ████    ███  ██  ██  ██ ███  █     ██████          
  ███ ███ ██ █   █ ██  ██ █ ██ █ █  █ █  ███ █    ███ █  ██ ███    █   █████ ███  ███ ████  █ █   ██  
   ██ █ █ ████ █  █  ███ ██ █████ █ █    ██  █ █ ██  ██  █   ███ █   █   █   █   █  █  ██ █   ██   ██ 
       ███  █████   ██  ██ █     ███ █   █  ███  ████  ██  █  █████  ██  █  ██  ████ █  █         █   
 ███            █ █       ███  █  ██  █ █████ █ ██ ████████ ██  ████ █ ████████  █ ███     █ ████ █ █ 
  █     █    ██  █ ██  █   █ █ ██ ██  █ ██   █ ██ █  █      ██     ██  ██ █  ██ ███   ███    █ ██ ███ 
   █   ███    ██    █ █   ███ ███  ██ ██   █ █ █ █  █    ███ █ ██     ██ █  █ ███████ █ ███   ███     
 ██ █ █ █ █   ████ ██  █ █████  ██████  █ █   █ █         █    ██     █    █ ███    █ █ █  █   ██     
        █ █ █  █    ████ ██ ██ █       █ █ ███  █  █  █  ██ █ █ ██ █ ██ █ █ █  ██ █  ███  █ ███   ██  
   ██ █ █  ██ ██   █  █  █  █  ███  █ ██  █ ██  █  █    █    █ ██ ██ ███ ██ ███  ██       ██████ ███  
 ██ █ █ █ █ █  ███   ███  ████   ██  ██ ███ █  █  ████ █   ███  █ ██ ██ █ █ ███  ███ █ █ █   ███  █   
   ██   ████      ██  █  █  █   █   █  ██   ██████ ██      █ █ █    █ █ █ █  █  ██ █   █ ████████   █ 
 ████ ██ █ █ ████  █ █ ██ █  █   █ █ ██ █    █  █ ████ █ █████ ███  ██ █ ████   ██ ███ █ █    █ █████ 
                                                                                                      
>

Task 1

img
|> Day20.enchance(alg)
|> Day20.enchance(alg)
|> Day20.Image.lighted()
5179

Task 2

1..50
|> Enum.reduce(img, fn _, acc -> Day20.enchance(acc, alg) end)
|> Day20.Image.lighted()
16112