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
BINDING = Hash.new {|h,k| h[k] = Expr.new(nil, [k], k) }
MEMOIZED = {}
class Expr < Struct.new(*%i[ op inputs output ])
def reduced
return MEMOIZED[output] if MEMOIZED[output]
result = case op
when nil
input = inputs[0]
(input =~ /^\d+$/) ? input.to_i : BINDING[input].reduced
when "NOT"
~reduced_inputs[0] % 65536
when "OR"
reduced_inputs[0] | reduced_inputs[1]
when "AND"
reduced_inputs[0] & reduced_inputs[1]
when "RSHIFT"
reduced_inputs[0] >> reduced_inputs[1]
when "LSHIFT"
reduced_inputs[0] << reduced_inputs[1]
else
fail "WTF? #{op}"
end
MEMOIZED[output] = result
end
def reduced_inputs
inputs.map {|input| BINDING[input].reduced }
end
end
DATA.read.scan(/(.+) -> (.+)/) do |input, output|
inputs = input.split(" ")
op = inputs[-2]
inputs.delete(op)
BINDING[output] = Expr.new(op, inputs, output)
end
BINDING["b"] = Expr.new(nil, ["3176"], "b")
puts BINDING["a"].reduced
__END__