2024: d24: ex1: add solution
This commit is contained in:
parent
b2765e5d31
commit
ecc39bdde8
83
2024/d24/ex1/ex1.py
Executable file
83
2024/d24/ex1/ex1.py
Executable file
|
@ -0,0 +1,83 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import copy
|
||||
import enum
|
||||
import sys
|
||||
from typing import NamedTuple
|
||||
|
||||
|
||||
class Op(enum.StrEnum):
|
||||
AND = "AND"
|
||||
OR = "OR"
|
||||
XOR = "XOR"
|
||||
|
||||
def apply(self, lhs: bool, rhs: bool) -> bool:
|
||||
match self:
|
||||
case Op.AND:
|
||||
return lhs & rhs
|
||||
case Op.OR:
|
||||
return lhs | rhs
|
||||
case Op.XOR:
|
||||
return lhs ^ rhs
|
||||
|
||||
|
||||
class Gate(NamedTuple):
|
||||
lhs: str
|
||||
op: Op
|
||||
rhs: str
|
||||
|
||||
|
||||
def solve(input: str) -> int:
|
||||
def parse_values(input: list[str]) -> dict[str, bool]:
|
||||
return {
|
||||
name: bool(int(val)) for name, val in map(lambda s: s.split(": "), input)
|
||||
}
|
||||
|
||||
def parse_operation(input: str) -> tuple[str, Gate]:
|
||||
lhs, op, rhs, _, name = input.split()
|
||||
return name, Gate(lhs, Op(op), rhs)
|
||||
|
||||
def parse_circuit(input: list[str]) -> dict[str, Gate]:
|
||||
return {name: gate for name, gate in map(parse_operation, input)}
|
||||
|
||||
def parse(input: str) -> tuple[dict[str, bool], dict[str, Gate]]:
|
||||
values, circuit = input.split("\n\n")
|
||||
return parse_values(values.splitlines()), parse_circuit(circuit.splitlines())
|
||||
|
||||
def run_circuit(
|
||||
values: dict[str, bool], circuit: dict[str, Gate]
|
||||
) -> dict[str, bool]:
|
||||
def helper(values: dict[str, bool], wire: str) -> bool:
|
||||
if (res := values.get(wire)) is not None:
|
||||
return res
|
||||
gate = circuit[wire]
|
||||
val = gate.op.apply(helper(values, gate.lhs), helper(values, gate.rhs))
|
||||
values[wire] = val
|
||||
return val
|
||||
|
||||
res = copy.copy(values)
|
||||
for key in circuit:
|
||||
helper(res, key)
|
||||
return res
|
||||
|
||||
def read_zs(values: dict[str, bool]) -> int:
|
||||
zs = sorted(
|
||||
(wire for wire in values.keys() if wire.startswith("z")), reverse=True
|
||||
)
|
||||
res = 0
|
||||
for z in zs:
|
||||
res = res << 1 | values[z]
|
||||
return res
|
||||
|
||||
values, circuit = parse(input)
|
||||
values = run_circuit(values, circuit)
|
||||
return read_zs(values)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
input = sys.stdin.read()
|
||||
print(solve(input))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in a new issue