77 lines
2.0 KiB
Ruby
77 lines
2.0 KiB
Ruby
|
#!/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>NOT) )?(?<first>[a-z0-9]+)( (?<operation>AND|OR|LSHIFT|RSHIFT) (?<second>[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
|