#!/usr/bin/env ruby input = (ARGV.first.nil? ? DATA : ARGF) .readlines(chomp: true) split = input.index("") gates = input[split+1..] wires = input.join(" ").scan(/([a-z0-9]{3})/).flatten.uniq.map { [_1, nil] }.to_h input[...split] .map { _1.split(": ") } .each { wires[_1] = _2.to_i } i = 0 until gates.empty? if i >= gates.size i = 0 end gate = gates[i] in1, op, in2, out = gate.scan(/([a-z0-9]{3}) ([A-Z]+) ([a-z0-9]{3}) -> ([a-z0-9]{3})/).first if wires[in1].nil? || wires[in2].nil? i += 1 next end case op when "AND" wires[out] = wires[in1] & wires[in2] when "OR" wires[out] = wires[in1] | wires[in2] when "XOR" wires[out] = wires[in1] ^ wires[in2] end gates.delete(gate) end x = wires.select { _1.match?(/^x/) }.sort_by(&:first).map { _1.last.to_s }.reverse.join xi = x.to_i(2) y = wires.select { _1.match?(/^y/) }.sort_by(&:first).map { _1.last.to_s }.reverse.join yi = y.to_i(2) z = wires.select { _1.match?(/^z/) }.sort_by(&:first).map { _1.last.to_s }.reverse.join zi = z.to_i(2) p zi __END__ x00: 0 x01: 1 x02: 0 x03: 1 x04: 0 x05: 1 y00: 0 y01: 0 y02: 1 y03: 1 y04: 0 y05: 1 x00 AND y00 -> z05 x01 AND y01 -> z02 x02 AND y02 -> z01 x03 AND y03 -> z03 x04 AND y04 -> z04 x05 AND y05 -> z00