Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from collections import deque as queue
- with open('input/Day24.txt', 'r') as file:
- values, gates = file.read().split('\n\n')
- values = {nam: int(val)
- for nam, val in (line.split(': ')
- for line in values.splitlines())}
- gates = queue((func, tuple(sorted([in1, in2])), out)
- for in1, func, in2, _, out in (line.split()
- for line in gates.splitlines()))
- # Copy of gates for part 2
- gates2 = queue(gates)
- op = {
- 'AND' : lambda a,b : a&b,
- 'OR' : lambda a,b : a|b,
- 'XOR' : lambda a,b : a^b
- }
- output = 0
- while gates:
- gate = gates.pop()
- f, (in1, in2), out = gate
- if in1 in values and in2 in values:
- val = op[f](values[in1], values[in2])
- if out[0] == 'z':
- output |= (val << int(out[1:]))
- values[out] = val
- else:
- gates.appendleft(gate)
- print(output)
- raw_input_xor = {}
- raw_input_and = {}
- output_xor = {}
- middle_and = {}
- carry_or = {}
- carry_or_in = {}
- swapped_gates = []
- swapped_wires = set()
- while gates2:
- gate = gates2.pop()
- f, (in1, in2), out = gate
- if in1[0] == 'x':
- if out[0] == 'z' and out != 'z00':
- swapped_gates.append(gate)
- swapped_wires.add(out)
- elif f == 'XOR':
- raw_input_xor[in1[1:]] = gate
- gates.append(gate)
- else:
- raw_input_and[in1[1:]] = gate
- gates.append(gate)
- elif f == 'XOR':
- if out[0] != 'z':
- swapped_gates.append(gate)
- swapped_wires.add(out)
- else:
- output_xor[out] = gate
- gates.append(gate)
- else:
- if out[0] == 'z' and out != 'z45':
- swapped_gates.append(gate)
- swapped_wires.add(out)
- else:
- if f == 'OR':
- carry_or[out] = gate
- gates.append(gate)
- else:
- middle_and[out] = gate
- gates.append(gate)
- # Handle the "easy" swaps
- for gate1 in swapped_gates:
- f, ins, out = gate1
- if out[0] == 'z':
- if f == 'XOR':
- # Have to navigate through all three carry gates
- raise NotImplementedError()
- elif f == 'OR':
- sout = raw_input_xor[out[1:]][2]
- for gate2 in swapped_gates:
- if gate2[0] == 'XOR' and sout in gate2[1]:
- sout = gate2[2]
- output_xor[out] = (gate2[0], gate2[1], out)
- carry_or[sout] = (f, ins, sout)
- gates.append(output_xor[out])
- gates.append(carry_or[sout])
- break
- else:
- sout = raw_input_xor[out[1:]][2]
- for gate2 in swapped_gates:
- if gate2[0] == 'XOR' and sout in gate2[1]:
- sout = gate2[2]
- output_xor[out] = (gate2[0],gate2[1],out)
- gates.append(output_xor[out])
- if ins[0][0] == 'x':
- raw_input_and[sout] = (f, ins, sout)
- gates.append(raw_input_and[sout])
- else:
- middle_and[sout] = (f, ins, sout)
- gates.append(middle_and[sout])
- sum1 = {}
- sum2 = {}
- c1 = {}
- c2 = {}
- cout = {}
- handled = []
- faulty_input = {}
- swapped_input = {}
- swapped_vals = {}
- def isFaulty(x1,x2):
- if x1 in swapped_input or x2 in swapped_input:
- return True
- return x1 in faulty_input or x2 in faulty_input
- def inputMatch(x1,x2,s1,s2):
- if x1 in s1 and x2 in s2 and s1[x1] == s2[x2]:
- return s1[x1]
- elif x1 in s2 and x2 in s1 and s1[x2] == s2[x1]:
- return s1[x2]
- while gates:
- gate = gates.pop()
- f, (in1, in2), out = gate
- # Handles the first half-adder of each full adder
- if in1[0] == 'x':
- inp = {n[0] : int(n[1:]) for n in [in1,in2]}
- val = int(in1[1:])
- if f == 'XOR':
- if in1 in ['x00', 'y00']:
- sum2[out] = inp['x']
- else:
- sum1[out] = inp['x']
- else:
- if in1 in ['x00','y00']:
- # This half-adder is not part of a full adder
- cout[out] = 1
- else:
- c1[out] = inp['y']
- handled.append(out)
- # Handles the carry out
- elif f == 'OR':
- if in1 in handled and in2 in handled:
- if isFaulty(in1, in2):
- faulty_input[out] = gate
- else:
- val = inputMatch(in1,in2,c1,c2)
- if val == None:
- swapped_input[out] = gate
- else:
- cout[out] = val + 1
- handled.append(out)
- else:
- gates.appendleft(gate)
- # Handles the second half-adder's sum
- elif f == 'XOR':
- if in1 in handled and in2 in handled:
- if isFaulty(in1, in2):
- faulty_input[out] = gate
- else:
- val = inputMatch(in1,in2,cout,sum1)
- if val == None:
- swapped_input[out] = gate
- else:
- sum2[out] = val
- handled.append(out)
- else:
- gates.appendleft(gate)
- # Handles the second half-adder's carry
- else:
- if in1 in handled and in2 in handled:
- if isFaulty(in1, in2):
- faulty_input[out] = gate
- else:
- val = inputMatch(in1,in2,sum1,cout)
- swapped_input[out] = gate
- else:
- c2[out] = val
- handled.append(out)
- else:
- gates.appendleft(gate)
- print(','.join(sorted(swapped_wires)))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement