[2018][ruby][16.1]
change ormqnsqnktsxtwywmpluuulmnznxwtzm
commit 3433b7a70bf78711d00b6ea9591bbe2236ea4d55
author Alpha Chen <alpha.chen@gmail.com>
date
parent rmskruws
diff --git a/2018/ruby/day_16.rb b/2018/ruby/day_16.rb
new file mode 100644
index 0000000..12974cb
--- /dev/null
+++ b/2018/ruby/day_16.rb
@@ -0,0 +1,74 @@
+require "minitest"
+require "minitest/pride"
+
+OPCODES = {
+  addr: ->(a, b, c) { ->(registers) { registers[c] = registers[a] + registers[b] } },
+  addi: ->(a, b, c) { ->(registers) { registers[c] = registers[a] + b } },
+  mulr: ->(a, b, c) { ->(registers) { registers[c] = registers[a] * registers[b] } },
+  muli: ->(a, b, c) { ->(registers) { registers[c] = registers[a] * b } },
+  banr: ->(a, b, c) { ->(registers) { registers[c] = registers[a] & registers[b] } },
+  bani: ->(a, b, c) { ->(registers) { registers[c] = registers[a] & b } },
+  borr: ->(a, b, c) { ->(registers) { registers[c] = registers[a] | registers[b] } },
+  bori: ->(a, b, c) { ->(registers) { registers[c] = registers[a] | b } },
+  setr: ->(a, b, c) { ->(registers) { registers[c] = registers[a] } },
+  seti: ->(a, b, c) { ->(registers) { registers[c] = a } },
+  gtir: ->(a, b, c) { ->(registers) { registers[c] = (a > registers[b]) ? 1 : 0 } },
+  gtri: ->(a, b, c) { ->(registers) { registers[c] = (a > b) ? 1 : 0 } },
+  gtrr: ->(a, b, c) { ->(registers) { registers[c] = (registers[a] > registers[b]) ? 1 : 0 } },
+  eqir: ->(a, b, c) { ->(registers) { registers[c] = (a == registers[b]) ? 1 : 0 } },
+  eqri: ->(a, b, c) { ->(registers) { registers[c] = (a == b) ? 1 : 0 } },
+  eqrr: ->(a, b, c) { ->(registers) { registers[c] = (registers[a] == registers[b]) ? 1 : 0 } },
+}
+
+class TestOpcodes < Minitest::Test
+  def test_mulr
+    registers = [3, 2, 1, 1]
+
+    OPCODES[:mulr].call(2, 1, 2).call(registers)
+
+    assert_equal [3, 2, 2, 1], registers
+  end
+
+  def test_addi
+    registers = [3, 2, 1, 1]
+
+    OPCODES[:addi].call(2, 1, 2).call(registers)
+
+    assert_equal [3, 2, 2, 1], registers
+  end
+
+  def test_seti
+    registers = [3, 2, 1, 1]
+
+    OPCODES[:seti].call(2, 1, 2).call(registers)
+
+    assert_equal [3, 2, 2, 1], registers
+  end
+end
+
+def solve(input)
+  samples = input.scan(/
+                       Before:\s*((?~\n))\n
+                       ((?~\n))\n
+                       After:\s*((?~\n))\n
+                       /mx)
+  samples.count {|sample|
+    before = sample[0].scan(/\d+/).map(&:to_i)
+    opcode = sample[1].scan(/\d+/).map(&:to_i)
+    after = sample[2].scan(/\d+/).map(&:to_i)
+    _, *args = opcode
+
+    opcode_count = OPCODES.count {|_, instruction|
+      registers = before.dup
+      instruction[*args][registers]
+      registers == after
+    }
+    opcode_count >= 3
+  }
+end
+
+if __FILE__ == $0
+  require "minitest/autorun" and exit if ENV["TEST"]
+
+  puts solve(ARGF.read)
+end