summaryrefslogtreecommitdiff
path: root/2015/day7.exs
diff options
context:
space:
mode:
Diffstat (limited to '2015/day7.exs')
-rw-r--r--2015/day7.exs81
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}")