2015 day 4, 5, 6, 7.
This commit is contained in:
101
src/holt59/aoc/2015/day7.py
Normal file
101
src/holt59/aoc/2015/day7.py
Normal file
@@ -0,0 +1,101 @@
|
||||
import logging
|
||||
import operator
|
||||
import os
|
||||
import sys
|
||||
from typing import Callable, Literal, TypeAlias, cast
|
||||
|
||||
VERBOSE = os.getenv("AOC_VERBOSE") == "True"
|
||||
logging.basicConfig(level=logging.INFO if VERBOSE else logging.WARNING)
|
||||
|
||||
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]
|
||||
|
||||
|
||||
lines = sys.stdin.read().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)
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
values_1 = process(signals.copy(), values.copy())
|
||||
logging.info("\n" + "\n".join(f"{k}: {values_1[k]}" for k in sorted(values_1)))
|
||||
answer_1 = values_1["a"]
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
values_2 = process(signals.copy(), values | {"b": values_1["a"]})
|
||||
answer_2 = values_2["a"]
|
||||
print(f"answer 2 is {answer_2}")
|
Reference in New Issue
Block a user