1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
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}")
|