diff --git a/2018/ruby/day_16.rb b/2018/ruby/day_16.rb
index 3472387..8977933 100644
--- a/2018/ruby/day_16.rb
+++ b/2018/ruby/day_16.rb
@@ -52,19 +52,44 @@ def solve(input)
((?~\n))\n
After:\s*((?~\n))\n
/mx)
- samples.count {|sample|
+
+ valid_opcodes = samples.map do |sample|
before = sample[0].scan(/\d+/).map(&:to_i)
- opcode = sample[1].scan(/\d+/).map(&:to_i)
+ instruction = sample[1].scan(/\d+/).map(&:to_i)
after = sample[2].scan(/\d+/).map(&:to_i)
- _, *args = opcode
+ opcode, *args = instruction
- opcode_count = OPCODES.count {|_, instruction|
+ opcodes = OPCODES.select {|_, instruction|
registers = before.dup
instruction[*args][registers]
registers == after
- }
- opcode_count >= 3
- }
+ }.map(&:first)
+ [opcode, opcodes]
+ end
+
+ # Part One
+ # return valid_opcodes.count {|_,opcodes| opcodes.length >= 3 }
+
+ opcode_map = {}
+ until opcode_map.length == OPCODES.length
+ number, opcodes = valid_opcodes.find {|_,opcodes| opcodes.length == 1 }
+ opcode = opcodes[0]
+ opcode_map[number] = opcode
+
+ valid_opcodes.delete_if {|n,_| n == number }
+ valid_opcodes.each do |_,opcodes|
+ opcodes.delete(opcode)
+ end
+ end
+
+ program = input[/[\d\s]+\Z/].lines.map {|line| line.scan(/\d+/).map(&:to_i) }.reject(&:empty?)
+ registers = [0, 0, 0, 0]
+ program.each do |instruction|
+ number, *args = instruction
+ opcode = opcode_map.fetch(number)
+ OPCODES.fetch(opcode)[*args][registers]
+ end
+ registers[0]
end
if __FILE__ == $0