Refactoring
This commit is contained in:
@@ -55,58 +55,59 @@
|
||||
# what signal is ultimately provided to wire a?
|
||||
|
||||
import functools
|
||||
import operator
|
||||
|
||||
with open("files/P7.txt") as f:
|
||||
instructions = [line for line in f.read().strip().split("\n")]
|
||||
|
||||
|
||||
def and_gate(x: int, y: int) -> int:
|
||||
return x & y
|
||||
OPS = {
|
||||
"ASSIGN": lambda x: x,
|
||||
"NOT": operator.invert,
|
||||
"AND": operator.and_,
|
||||
"OR": operator.or_,
|
||||
"LSHIFT": operator.lshift,
|
||||
"RSHIFT": operator.rshift,
|
||||
}
|
||||
|
||||
|
||||
def or_gate(x: int, y: int) -> int:
|
||||
return x | y
|
||||
def parse_instruction(lhs):
|
||||
tokens: list[str] = lhs.split()
|
||||
|
||||
if len(tokens) == 1:
|
||||
return ("ASSIGN", tokens[0], None)
|
||||
|
||||
if len(tokens) == 2 and tokens[0] == "NOT":
|
||||
return ("NOT", tokens[1], None)
|
||||
|
||||
if len(tokens) == 3:
|
||||
left, op, right = tokens
|
||||
if op in OPS:
|
||||
return (op, left, right)
|
||||
|
||||
|
||||
def not_gate(x: int) -> int:
|
||||
return ~x
|
||||
|
||||
|
||||
def lshift_gate(x: int, y: int) -> int:
|
||||
return x << y
|
||||
|
||||
|
||||
def rshift_gate(x: int, y: int) -> int:
|
||||
return x >> y
|
||||
def resolve_token(token: str) -> int:
|
||||
if token.isdigit():
|
||||
return int(token) # & MASK_16BIT
|
||||
return rec_solve(token)
|
||||
|
||||
|
||||
@functools.lru_cache()
|
||||
def rec_solve(node: str) -> int:
|
||||
if node.isdigit():
|
||||
return int(node)
|
||||
instruction = gates[node]
|
||||
if "NOT" in instruction:
|
||||
return not_gate(rec_solve(instruction[1]))
|
||||
elif "AND" in instruction:
|
||||
return and_gate(rec_solve(instruction[0]), rec_solve(instruction[2]))
|
||||
elif "OR" in instruction:
|
||||
return or_gate(rec_solve(instruction[0]), rec_solve(instruction[2]))
|
||||
elif "LSHIFT" in instruction:
|
||||
return lshift_gate(
|
||||
rec_solve(instruction[0]), rec_solve(instruction[2])
|
||||
)
|
||||
elif "RSHIFT" in instruction:
|
||||
return rshift_gate(
|
||||
rec_solve(instruction[0]), rec_solve(instruction[2])
|
||||
)
|
||||
op, left, right = gates[node]
|
||||
|
||||
if op in ["ASSIGN", "NOT"]:
|
||||
result = OPS[op](resolve_token(left))
|
||||
else:
|
||||
return rec_solve(instruction[0])
|
||||
result = OPS[op](resolve_token(left), resolve_token(right))
|
||||
|
||||
return result
|
||||
|
||||
|
||||
gates = {}
|
||||
for instr in instructions:
|
||||
lhs, rhs = instr.split(" -> ")
|
||||
gates[rhs.strip()] = lhs.strip().split()
|
||||
gates[rhs.strip()] = parse_instruction(lhs.strip())
|
||||
|
||||
|
||||
def part_1() -> None:
|
||||
@@ -124,7 +125,7 @@ def part_1() -> None:
|
||||
def part_2() -> None:
|
||||
signal_a = rec_solve("a")
|
||||
rec_solve.cache_clear()
|
||||
gates["b"] = [str(signal_a)]
|
||||
gates["b"] = parse_instruction(str(signal_a))
|
||||
signal_b = rec_solve("a")
|
||||
print(f"Signal B will be ultimately {signal_b}")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user