Co-authored-by: Mikael CAPELLE <mikael.capelle@thalesaleniaspace.com> Co-authored-by: Mikaël Capelle <capelle.mikael@gmail.com> Reviewed-on: #3
97 lines
2.7 KiB
Python
97 lines
2.7 KiB
Python
import operator
|
|
from typing import Any, Callable, Iterator
|
|
|
|
from ..base import BaseSolver
|
|
|
|
OPERATORS = {
|
|
"AND": operator.and_,
|
|
"OR": operator.or_,
|
|
"LSHIFT": operator.lshift,
|
|
"RSHIFT": operator.rshift,
|
|
}
|
|
|
|
ValueGetter = Callable[[dict[str, int]], int]
|
|
Signals = dict[
|
|
str,
|
|
tuple[
|
|
tuple[str, str],
|
|
tuple[ValueGetter, ValueGetter],
|
|
Callable[[int, int], int],
|
|
],
|
|
]
|
|
|
|
|
|
def zero_op(_a: int, _b: int) -> int:
|
|
return 0
|
|
|
|
|
|
def value_of(key: str) -> tuple[str, Callable[[dict[str, int]], int]]:
|
|
try:
|
|
return "", lambda _p, _v=int(key): _v
|
|
except ValueError:
|
|
return key, lambda values: values[key]
|
|
|
|
|
|
def process(
|
|
signals: Signals,
|
|
values: dict[str, int],
|
|
) -> dict[str, int]:
|
|
while signals:
|
|
signal = next(s for s in signals if all(p in values for p in signals[s][0]))
|
|
_, deps, command = signals[signal]
|
|
values[signal] = command(deps[0](values), deps[1](values)) % 65536
|
|
del signals[signal]
|
|
|
|
return values
|
|
|
|
|
|
class Solver(BaseSolver):
|
|
def solve(self, input: str) -> Iterator[Any] | None:
|
|
lines = input.splitlines()
|
|
|
|
signals: Signals = {}
|
|
values: dict[str, int] = {"": 0}
|
|
|
|
for line in lines:
|
|
command, signal = line.split(" -> ")
|
|
|
|
if command.startswith("NOT"):
|
|
name = command.split(" ")[1]
|
|
signals[signal] = (
|
|
(name, ""),
|
|
(lambda values, _n=name: values[_n], lambda _v: 0),
|
|
lambda a, _b: ~a,
|
|
)
|
|
|
|
elif not any(command.find(name) >= 0 for name in OPERATORS):
|
|
try:
|
|
values[signal] = int(command)
|
|
except ValueError:
|
|
signals[signal] = (
|
|
(command, ""),
|
|
(lambda values, _c=command: values[_c], lambda _v: 0),
|
|
lambda a, _b: a,
|
|
)
|
|
|
|
else:
|
|
op: Callable[[int, int], int] = zero_op
|
|
lhs_s, rhs_s = "", ""
|
|
|
|
for name in OPERATORS:
|
|
if command.find(name) >= 0:
|
|
op = OPERATORS[name]
|
|
lhs_s, rhs_s = command.split(f" {name} ")
|
|
break
|
|
|
|
lhs_s, lhs_fn = value_of(lhs_s)
|
|
rhs_s, rhs_fn = value_of(rhs_s)
|
|
|
|
signals[signal] = ((lhs_s, rhs_s), (lhs_fn, rhs_fn), op)
|
|
|
|
values_1 = process(signals.copy(), values.copy())
|
|
for k in sorted(values_1):
|
|
self.logger.info(f"{k}: {values_1[k]}")
|
|
yield values_1["a"]
|
|
|
|
yield process(signals.copy(), values | {"b": values_1["a"]})["a"]
|