Powered by AppSignal & Oban Pro

AoC 2015 Day 7

2015/day7.livemd

AoC 2015 Day 7

Mix.install([:kino])

defmodule Utils do
  def split(line, sep \\ "") do
    String.split(line, sep, trim: true)
  end

  def split_all_lines(text, sep \\ "") do
    text
    |> String.split("\n", trim: true)
    |> Enum.map(&split(&1, sep))
  end

  def to_numbers(number) when is_binary(number) do
    String.to_integer(number)
  end

  def to_numbers(numbers) when is_list(numbers) do
    Enum.map(numbers, &to_numbers/1)
  end

  def to_matrix(text, sep \\ "") do
    text
    |> split_all_lines(sep)
    |> then(fn data ->
      for {row, r} <- Enum.with_index(data), {col, c} <- Enum.with_index(row) do
        {{r, c}, col}
      end
    end)
    |> Map.new()
  end
end

Setup

import Utils
input = Kino.Input.textarea("Input:")
text = Kino.Input.read(input)
data =
  split_all_lines(text, " -> ")
  |> Enum.map(fn [l, r] -> {r, l |> String.split() |> List.to_tuple()} end)
  |> Enum.into(%{})
defmodule Gates do
  def eval({left, "AND", right}, lookup) do
    Bitwise.band(get(left, lookup), get(right, lookup))
  end

  def eval({left, "OR", right}, lookup) do
    Bitwise.bor(get(left, lookup), get(right, lookup))
  end

  def eval({left, "LSHIFT", right}, lookup) do
    Bitwise.bsl(get(left, lookup), get(right, lookup))
  end

  def eval({left, "RSHIFT", right}, lookup) do
    Bitwise.bsr(get(left, lookup), get(right, lookup))
  end

  def eval({"NOT", right}, lookup) do
    65536 + Bitwise.bnot(get(right, lookup))
  end

  def eval({v}, lookup) do
    get(v, lookup)
  end

  def get(target, lookup) do
    v =
      case Agent.get(lookup, & &1[target]) do
        v when is_tuple(v) ->
          eval(v, lookup)

        nil ->
          case target do
            v when is_binary(v) -> String.to_integer(v)
            v when is_integer(v) -> v
          end

        v ->
          v
      end

    Agent.update(lookup, &Map.put(&1, target, v))
    v
  end
end
{:ok, pid} = Agent.start_link(fn -> data end)

P1

a = Gates.get("a", pid)

P2

Agent.update(pid, fn _ -> Map.put(data, "b", a) end)
Gates.get("a", pid)