[2018][ruby][16.2]
change looutppsuynwmwsypzumvpqpnrmqsomp
commit 759cc48bf19c5162c2139f861cf0b6c71774c9b7
author Alpha Chen <alpha.chen@gmail.com>
date
parent vtkwxoxz
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