#!/usr/bin/env ruby require_relative '../common' class Integer def bitwise_complement self ^ 65535 end end class Day07 < Day def part1 wires = input.each_with_object({}) do |row, hash| instruction, wire = row.split(' -> ') hash[wire] = Instruction.new(instruction) end wires.map { |wire, instruction| [wire, instruction.signal(wires)] }.sort.to_h.fetch('a') end def part2 wires = input.each_with_object({}) do |row, hash| instruction, wire = row.split(' -> ') hash[wire] = Instruction.new(instruction) end a_signal = wires.map { |wire, instruction| [wire, instruction.signal(wires)] }.sort.to_h.fetch('a') wires = input.each_with_object({}) do |row, hash| instruction, wire = row.split(' -> ') hash[wire] = Instruction.new(instruction) end wires['b'] = Instruction.new(a_signal.to_s) wires.map { |wire, instruction| [wire, instruction.signal(wires)] }.sort.to_h.fetch('a') end class Instruction def initialize(text) @text = text @not, @first, @operation, @second = text.match( /\A((?NOT) )?(?[a-z0-9]+)( (?AND|OR|LSHIFT|RSHIFT) (?[a-z0-9]+))?\z/ ).captures @signal = nil end def signal(wires) @signal ||= process(wires) end private def process(wires) return process_wire(@first, wires).bitwise_complement if @not return process_wire(@first, wires) if @operation.nil? case @operation when "AND" process_wire(@first, wires) & process_wire(@second, wires) when "OR" process_wire(@first, wires) | process_wire(@second, wires) when "LSHIFT" process_wire(@first, wires) << process_wire(@second, wires) when "RSHIFT" process_wire(@first, wires) >> process_wire(@second, wires) end end def process_wire(value, wires) return value.to_i if value.match?(/\A[0-9]+\z/) wires[value].signal(wires) end end end Day07.run