108 lines
2.4 KiB
Ruby
Executable file
108 lines
2.4 KiB
Ruby
Executable file
#!/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 }
|
|
|
|
flipped = Set.new
|
|
gates.select { _1.match?(/XOR/) }.each do |gate|
|
|
in1, op, in2, out = gate.scan(/([a-z0-9]{3}) ([A-Z]+) ([a-z0-9]{3}) -> ([a-z0-9]{3})/).first
|
|
|
|
if op == "XOR" && [in1, in2].map { _1[0] }.sort != %w[x y]
|
|
if !out.start_with?("z")
|
|
flipped << out
|
|
end
|
|
end
|
|
end
|
|
|
|
# 45 is a half adder
|
|
(0..44).each do |num|
|
|
z = "z#{'%02d' % num}"
|
|
gate = gates.find { _1.match?(/#{z}$/) }
|
|
in1, op, in2, out = gate.scan(/([a-z0-9]{3}) ([A-Z]+) ([a-z0-9]{3}) -> ([a-z0-9]{3})/).first
|
|
if op != "XOR"
|
|
flipped << z
|
|
end
|
|
end
|
|
|
|
gates.select { _1.match?(/AND/) }.each do |gate|
|
|
in1, op, in2, out = gate.scan(/([a-z0-9]{3}) ([A-Z]+) ([a-z0-9]{3}) -> ([a-z0-9]{3})/).first
|
|
|
|
if [in1, in2].map { _1[0] }.sort == %w[x y] && in1 != "x00"
|
|
if gates.find { _1.match?(/#{out}/) && _1.match?(/ OR /) }.nil?
|
|
flipped << out
|
|
end
|
|
end
|
|
end
|
|
|
|
gates.select { _1.match?(/XOR/) }.each do |gate|
|
|
in1, op, in2, out = gate.scan(/([a-z0-9]{3}) ([A-Z]+) ([a-z0-9]{3}) -> ([a-z0-9]{3})/).first
|
|
|
|
if [in1, in2].map { _1[0] }.sort == %w[x y] && in1 != "x00" && in1 != "y00"
|
|
if gates.count { _1.match?(/#{out}/) && _1.match?(/ XOR /) } != 2
|
|
flipped << out
|
|
end
|
|
end
|
|
end
|
|
|
|
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
|
|
|
|
p flipped.sort.join(",")
|
|
|
|
__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
|