Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Day 21

day21.livemd

Day 21

Mix.install([{:kino, "~> 0.5.0"}])

Section

input = """
root: pppw + sjmn
dbpl: 5
cczh: sllz + lgvd
zczc: 2
ptdq: humn - dvpt
dvpt: 3
lfqf: 4
humn: 5
ljgn: 2
sjmn: drzm * dbpl
sllz: 4
pppw: cczh / lfqf
lgvd: ljgn * ptdq
drzm: hmdt - zczc
hmdt: 32
"""
input = Kino.Input.textarea("paste input here:")
input = Kino.Input.read(input)
defmodule Monkeys do
  def calculate(monkeys, current) do
    case Integer.parse(monkeys[current]) do
      {n, _} ->
        n

      :error ->
        <> = monkeys[current]
        left = calculate(monkeys, left)
        right = calculate(monkeys, right)

        case op do
          ?+ -> left + right
          ?* -> left * right
          ?- -> left - right
          ?/ -> left / right
        end
    end
  end

  def calculate2(monkeys, current, need \\ :unknown)
  def calculate2(_, "humn", :unknown), do: :humn
  def calculate2(_, "humn", need), do: need

  def calculate2(monkeys, current, need) do
    case Integer.parse(monkeys[current]) do
      {n, _} ->
        n

      :error ->
        <> =
          monkeys[current]

        op = if current == "root", do: ?=, else: op

        left = calculate2(monkeys, left_label)
        right = calculate2(monkeys, right_label)
        # IO.inspect({current, left, [op], right, need})

        if (left == :humn or right == :humn) and (need == :unknown and op != ?=) do
          :humn
        else
          case {left, right, op} do
            {:humn, right, ?+} -> calculate2(monkeys, left_label, need - right)
            {left, :humn, ?+} -> calculate2(monkeys, right_label, need - left)
            {:humn, right, ?*} -> calculate2(monkeys, left_label, need / right)
            {left, :humn, ?*} -> calculate2(monkeys, right_label, need / left)
            {:humn, right, ?-} -> calculate2(monkeys, left_label, need + right)
            {left, :humn, ?-} -> calculate2(monkeys, right_label, left - need)
            {:humn, right, ?/} -> calculate2(monkeys, left_label, need * right)
            {left, :humn, ?/} -> calculate2(monkeys, right_label, left / need)
            {:humn, right, ?=} -> calculate2(monkeys, left_label, right)
            {left, :humn, ?=} -> calculate2(monkeys, right_label, left)
            {_, _, ?+} -> left + right
            {_, _, ?*} -> left * right
            {_, _, ?-} -> left - right
            {_, _, ?/} -> left / right
          end
        end
    end
  end
end
input
|> String.split("\n", trim: true)
|> Enum.map(&amp;(String.split(&amp;1, ": ") |> List.to_tuple()))
|> Map.new()
|> Monkeys.calculate2("root")