Advertisement
Guest User

YOM2 - Advent of Code 2024 Day 24

a guest
Dec 24th, 2024
257
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.73 KB | None | 0 0
  1. from collections import deque as queue
  2.  
  3. with open('input/Day24.txt', 'r') as file:
  4.     values, gates = file.read().split('\n\n')
  5. values = {nam: int(val)
  6.           for nam, val in (line.split(': ')
  7.                 for line in values.splitlines())}
  8. gates = queue((func, tuple(sorted([in1, in2])), out)
  9.          for in1, func, in2, _, out in (line.split()
  10.                 for line in gates.splitlines()))
  11.  
  12. # Copy of gates for part 2
  13. gates2 = queue(gates)
  14.  
  15. op = {
  16.     'AND' : lambda a,b : a&b,
  17.     'OR'  : lambda a,b : a|b,
  18.     'XOR' : lambda a,b : a^b
  19.     }
  20.  
  21. output = 0
  22.  
  23. while gates:
  24.     gate = gates.pop()
  25.     f, (in1, in2), out = gate
  26.     if in1 in values and in2 in values:
  27.         val = op[f](values[in1], values[in2])
  28.         if out[0] == 'z':
  29.             output |= (val << int(out[1:]))
  30.         values[out] = val
  31.     else:
  32.         gates.appendleft(gate)
  33.  
  34. print(output)
  35.  
  36. raw_input_xor = {}
  37. raw_input_and = {}
  38. output_xor = {}
  39. middle_and = {}
  40. carry_or = {}
  41. carry_or_in = {}
  42. swapped_gates = []
  43. swapped_wires = set()
  44.  
  45. while gates2:
  46.     gate = gates2.pop()
  47.     f, (in1, in2), out = gate
  48.     if in1[0] == 'x':
  49.         if out[0] == 'z' and out != 'z00':
  50.             swapped_gates.append(gate)
  51.             swapped_wires.add(out)
  52.         elif f == 'XOR':
  53.             raw_input_xor[in1[1:]] = gate
  54.             gates.append(gate)
  55.         else:
  56.             raw_input_and[in1[1:]] = gate
  57.             gates.append(gate)
  58.     elif f == 'XOR':
  59.         if out[0] != 'z':
  60.             swapped_gates.append(gate)
  61.             swapped_wires.add(out)
  62.         else:
  63.             output_xor[out] = gate
  64.             gates.append(gate)
  65.     else:
  66.         if out[0] == 'z' and out != 'z45':
  67.             swapped_gates.append(gate)
  68.             swapped_wires.add(out)
  69.         else:
  70.             if f == 'OR':
  71.                 carry_or[out] = gate
  72.                 gates.append(gate)
  73.             else:
  74.                 middle_and[out] = gate
  75.                 gates.append(gate)
  76.  
  77. # Handle the "easy" swaps
  78. for gate1 in swapped_gates:
  79.     f, ins, out = gate1
  80.     if out[0] == 'z':
  81.         if f == 'XOR':
  82.             # Have to navigate through all three carry gates
  83.             raise NotImplementedError()
  84.         elif f == 'OR':
  85.             sout = raw_input_xor[out[1:]][2]
  86.             for gate2 in swapped_gates:
  87.                 if gate2[0] == 'XOR' and sout in gate2[1]:
  88.                     sout = gate2[2]
  89.                     output_xor[out] = (gate2[0], gate2[1], out)
  90.                     carry_or[sout] = (f, ins, sout)
  91.                     gates.append(output_xor[out])
  92.                     gates.append(carry_or[sout])
  93.                     break
  94.         else:
  95.             sout = raw_input_xor[out[1:]][2]
  96.             for gate2 in swapped_gates:
  97.                 if gate2[0] == 'XOR' and sout in gate2[1]:
  98.                     sout = gate2[2]
  99.                     output_xor[out] = (gate2[0],gate2[1],out)
  100.                     gates.append(output_xor[out])
  101.                     if ins[0][0] == 'x':
  102.                         raw_input_and[sout] = (f, ins, sout)
  103.                         gates.append(raw_input_and[sout])
  104.                     else:
  105.                         middle_and[sout] = (f, ins, sout)
  106.                         gates.append(middle_and[sout])
  107.  
  108. sum1 = {}
  109. sum2 = {}
  110. c1 = {}
  111. c2 = {}
  112. cout = {}
  113.  
  114. handled = []
  115.  
  116. faulty_input = {}
  117. swapped_input = {}
  118. swapped_vals = {}
  119.  
  120. def isFaulty(x1,x2):
  121.     if x1 in swapped_input or x2 in swapped_input:
  122.         return True
  123.     return x1 in faulty_input or x2 in faulty_input
  124.  
  125. def inputMatch(x1,x2,s1,s2):
  126.     if x1 in s1 and x2 in s2 and s1[x1] == s2[x2]:
  127.         return s1[x1]
  128.     elif x1 in s2 and x2 in s1 and s1[x2] == s2[x1]:
  129.         return s1[x2]
  130.  
  131. while gates:
  132.     gate = gates.pop()
  133.     f, (in1, in2), out = gate
  134.     # Handles the first half-adder of each full adder
  135.     if in1[0] == 'x':
  136.         inp = {n[0] : int(n[1:]) for n in [in1,in2]}
  137.         val = int(in1[1:])
  138.         if f == 'XOR':
  139.             if in1 in ['x00', 'y00']:
  140.                 sum2[out] = inp['x']
  141.             else:
  142.                 sum1[out] = inp['x']
  143.         else:
  144.             if in1 in ['x00','y00']:
  145.                 # This half-adder is not part of a full adder
  146.                 cout[out] = 1
  147.             else:
  148.                 c1[out] = inp['y']
  149.         handled.append(out)
  150.     # Handles the carry out
  151.     elif f == 'OR':
  152.         if in1 in handled and in2 in handled:
  153.             if isFaulty(in1, in2):
  154.                 faulty_input[out] = gate
  155.             else:
  156.                 val = inputMatch(in1,in2,c1,c2)
  157.                 if val == None:
  158.                     swapped_input[out] = gate
  159.                 else:
  160.                     cout[out] = val + 1
  161.             handled.append(out)
  162.         else:
  163.             gates.appendleft(gate)
  164.     # Handles the second half-adder's sum
  165.     elif f == 'XOR':
  166.         if in1 in handled and in2 in handled:
  167.             if isFaulty(in1, in2):
  168.                 faulty_input[out] = gate
  169.             else:
  170.                 val = inputMatch(in1,in2,cout,sum1)
  171.                 if val == None:
  172.                     swapped_input[out] = gate
  173.                 else:
  174.                     sum2[out] = val
  175.             handled.append(out)
  176.         else:
  177.             gates.appendleft(gate)
  178.     # Handles the second half-adder's carry
  179.     else:
  180.         if in1 in handled and in2 in handled:
  181.             if isFaulty(in1, in2):
  182.                 faulty_input[out] = gate
  183.             else:
  184.                 val = inputMatch(in1,in2,sum1,cout)
  185.                        
  186.                     swapped_input[out] = gate
  187.                 else:
  188.                     c2[out] = val
  189.             handled.append(out)
  190.         else:
  191.             gates.appendleft(gate)
  192.  
  193. print(','.join(sorted(swapped_wires)))
  194.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement