diff options
Diffstat (limited to '2015/day7.exs')
-rw-r--r-- | 2015/day7.exs | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/2015/day7.exs b/2015/day7.exs new file mode 100644 index 0000000..c38a931 --- /dev/null +++ b/2015/day7.exs @@ -0,0 +1,81 @@ +gates = File.stream!("inputs/day7.txt") + +gateRegex = ~r/(([a-z]+|[0-9]+) )?(([A-Z]+) )?([a-z]+|[0-9]+) -> ([a-z]+)/ + +circuit = + Enum.reduce(gates, Map.new(), fn gate, acc -> + [_, _, input1, _, op, input2, output] = Regex.run(gateRegex, gate) + + inputs = + Enum.filter([input1, input2], fn input -> input != "" end) + |> Enum.map(fn input -> + case Integer.parse(input) do + {num, ""} -> num + :error -> input + end + end) + + Map.put(acc, output, {op, inputs}) + end) + +defmodule MemoizedCircuitSolver do + use Agent + + def start do + Agent.start_link(fn -> %{} end, name: __MODULE__) + end + + def evaluate(circuit, id) when is_integer(id) do + id + end + + def evaluate(circuit, id) do + cached_value = Agent.get(__MODULE__, &Map.get(&1, {circuit, id})) + + if cached_value do + cached_value + else + {op, inputs} = Map.get(circuit, id) + inputs = Enum.map(inputs, fn i -> evaluate(circuit, i) end) + + result = + case op do + "" -> + [result] = inputs + result + + "NOT" -> + [input] = inputs + Bitwise.bnot(input) + + "AND" -> + Enum.reduce(inputs, &Bitwise.band(&1, &2)) + + "OR" -> + Enum.reduce(inputs, &Bitwise.bor(&1, &2)) + + "LSHIFT" -> + [input, amount] = inputs + Bitwise.bsl(input, amount) + + "RSHIFT" -> + [input, amount] = inputs + Bitwise.bsr(input, amount) + end + + Agent.update(__MODULE__, &Map.put(&1, {circuit, id}, result)) + result + end + end +end + +{:ok, _} = MemoizedCircuitSolver.start() + +aValue = MemoizedCircuitSolver.evaluate(circuit, "a") + +IO.puts("Initial A value: #{aValue}") + +secondCircuit = Map.put(circuit, "b", {"", [aValue]}) + +aValue2 = MemoizedCircuitSolver.evaluate(secondCircuit, "a") +IO.puts("Final A value: #{aValue2}") |