Refactor code for API #3
@ -1,10 +1,12 @@
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
line = sys.stdin.read().strip()
|
||||
|
||||
floor = 0
|
||||
floors = [(floor := floor + (1 if c == "(" else -1)) for c in line]
|
||||
from ..base import BaseSolver
|
||||
|
||||
|
||||
print(f"answer 1 is {floors[-1]}")
|
||||
print(f"answer 2 is {floors.index(-1)}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
floor = 0
|
||||
floors = [(floor := floor + (1 if c == "(" else -1)) for c in input]
|
||||
|
||||
yield floors[-1]
|
||||
yield floors.index(-1)
|
||||
|
@ -1,7 +1,7 @@
|
||||
import itertools
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
line = sys.stdin.read().strip()
|
||||
from ..base import BaseSolver
|
||||
|
||||
# see http://www.se16.info/js/lands2.htm for the explanation of 'atoms' (or elements)
|
||||
#
|
||||
@ -9,7 +9,7 @@ line = sys.stdin.read().strip()
|
||||
# CodeGolf answer https://codegolf.stackexchange.com/a/8479/42148
|
||||
|
||||
# fmt: off
|
||||
atoms = [
|
||||
ATOMS: list[tuple[str, tuple[int, ...]]] = [
|
||||
("22", (0, )), # 0
|
||||
("13112221133211322112211213322112", (71, 90, 0, 19, 2, )), # 1
|
||||
("312211322212221121123222112", (1, )), # 2
|
||||
@ -105,7 +105,7 @@ atoms = [
|
||||
]
|
||||
# fmt: on
|
||||
|
||||
starters = [
|
||||
STARTERS = [
|
||||
"1",
|
||||
"11",
|
||||
"21",
|
||||
@ -122,27 +122,26 @@ def look_and_say_length(s: str, n: int) -> int:
|
||||
if n == 0:
|
||||
return len(s)
|
||||
|
||||
if s in starters:
|
||||
if s in STARTERS:
|
||||
return look_and_say_length(
|
||||
"".join(f"{len(list(g))}{k}" for k, g in itertools.groupby(s)), n - 1
|
||||
)
|
||||
|
||||
counts = {i: 0 for i in range(len(atoms))}
|
||||
idx = next(i for i, (a, _) in enumerate(atoms) if s == a)
|
||||
counts = {i: 0 for i in range(len(ATOMS))}
|
||||
idx = next(i for i, (a, _) in enumerate(ATOMS) if s == a)
|
||||
counts[idx] = 1
|
||||
|
||||
for _ in range(n):
|
||||
c2 = {i: 0 for i in range(len(atoms))}
|
||||
c2 = {i: 0 for i in range(len(ATOMS))}
|
||||
for i in counts:
|
||||
for j in atoms[i][1]:
|
||||
for j in ATOMS[i][1]:
|
||||
c2[j] += counts[i]
|
||||
counts = c2
|
||||
|
||||
return sum(counts[i] * len(a[0]) for i, a in enumerate(atoms))
|
||||
return sum(counts[i] * len(a[0]) for i, a in enumerate(ATOMS))
|
||||
|
||||
|
||||
answer_1 = look_and_say_length(line, 40)
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
answer_2 = look_and_say_length(line, 50)
|
||||
print(f"answer 2 is {answer_2}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any] | None:
|
||||
yield look_and_say_length(input, 40)
|
||||
yield look_and_say_length(input, 50)
|
||||
|
@ -1,5 +1,7 @@
|
||||
import itertools
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
from ..base import BaseSolver
|
||||
|
||||
|
||||
def is_valid(p: str) -> bool:
|
||||
@ -40,10 +42,8 @@ def find_next_password(p: str) -> str:
|
||||
return p
|
||||
|
||||
|
||||
line = sys.stdin.read().strip()
|
||||
|
||||
answer_1 = find_next_password(line)
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
answer_2 = find_next_password(increment(answer_1))
|
||||
print(f"answer 2 is {answer_2}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
answer_1 = find_next_password(input)
|
||||
yield answer_1
|
||||
yield find_next_password(increment(answer_1))
|
||||
|
@ -1,6 +1,7 @@
|
||||
import json
|
||||
import sys
|
||||
from typing import TypeAlias
|
||||
from typing import Any, Iterator, TypeAlias
|
||||
|
||||
from ..base import BaseSolver
|
||||
|
||||
JsonObject: TypeAlias = dict[str, "JsonObject"] | list["JsonObject"] | int | str
|
||||
|
||||
@ -18,10 +19,9 @@ def json_sum(value: JsonObject, ignore: str | None = None) -> int:
|
||||
return 0
|
||||
|
||||
|
||||
data: JsonObject = json.load(sys.stdin)
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
data: JsonObject = json.loads(input)
|
||||
|
||||
answer_1 = json_sum(data)
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
answer_2 = json_sum(data, "red")
|
||||
print(f"answer 2 is {answer_2}")
|
||||
yield json_sum(data)
|
||||
yield json_sum(data, "red")
|
||||
|
@ -1,10 +1,11 @@
|
||||
import itertools
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from typing import Literal, cast
|
||||
from typing import Any, Iterator, Literal, cast
|
||||
|
||||
import parse # type: ignore
|
||||
|
||||
from ..base import BaseSolver
|
||||
|
||||
|
||||
def max_change_in_happiness(happiness: dict[str, dict[str, int]]) -> int:
|
||||
guests = list(happiness)
|
||||
@ -17,10 +18,12 @@ def max_change_in_happiness(happiness: dict[str, dict[str, int]]) -> int:
|
||||
)
|
||||
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = input.splitlines()
|
||||
|
||||
happiness: dict[str, dict[str, int]] = defaultdict(dict)
|
||||
for line in lines:
|
||||
happiness: dict[str, dict[str, int]] = defaultdict(dict)
|
||||
for line in lines:
|
||||
u1, gain_or_loose, hap, u2 = cast(
|
||||
tuple[str, Literal["gain", "lose"], int, str],
|
||||
parse.parse( # type: ignore
|
||||
@ -29,13 +32,9 @@ for line in lines:
|
||||
)
|
||||
happiness[u1][u2] = hap if gain_or_loose == "gain" else -hap
|
||||
|
||||
|
||||
answer_1 = max_change_in_happiness(happiness)
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
for guest in list(happiness):
|
||||
yield max_change_in_happiness(happiness)
|
||||
for guest in list(happiness):
|
||||
happiness["me"][guest] = 0
|
||||
happiness[guest]["me"] = 0
|
||||
|
||||
answer_2 = max_change_in_happiness(happiness)
|
||||
print(f"answer 2 is {answer_2}")
|
||||
yield max_change_in_happiness(happiness)
|
||||
|
@ -1,9 +1,10 @@
|
||||
import sys
|
||||
from dataclasses import dataclass
|
||||
from typing import Literal, cast
|
||||
from typing import Any, Iterator, Literal, cast
|
||||
|
||||
import parse # type: ignore
|
||||
|
||||
from ..base import BaseSolver
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Reindeer:
|
||||
@ -13,10 +14,12 @@ class Reindeer:
|
||||
rest_time: int
|
||||
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = input.splitlines()
|
||||
|
||||
reindeers: list[Reindeer] = []
|
||||
for line in lines:
|
||||
reindeers: list[Reindeer] = []
|
||||
for line in lines:
|
||||
reindeer, speed, speed_time, rest_time = cast(
|
||||
tuple[str, int, int, int],
|
||||
parse.parse( # type: ignore
|
||||
@ -26,18 +29,20 @@ for line in lines:
|
||||
),
|
||||
)
|
||||
reindeers.append(
|
||||
Reindeer(name=reindeer, speed=speed, fly_time=speed_time, rest_time=rest_time)
|
||||
Reindeer(
|
||||
name=reindeer, speed=speed, fly_time=speed_time, rest_time=rest_time
|
||||
)
|
||||
)
|
||||
|
||||
target = 1000 if len(reindeers) <= 2 else 2503
|
||||
target = 1000 if len(reindeers) <= 2 else 2503
|
||||
|
||||
states: dict[Reindeer, tuple[Literal["resting", "flying"], int]] = {
|
||||
states: dict[Reindeer, tuple[Literal["resting", "flying"], int]] = {
|
||||
reindeer: ("resting", 0) for reindeer in reindeers
|
||||
}
|
||||
distances: dict[Reindeer, int] = {reindeer: 0 for reindeer in reindeers}
|
||||
points: dict[Reindeer, int] = {reindeer: 0 for reindeer in reindeers}
|
||||
}
|
||||
distances: dict[Reindeer, int] = {reindeer: 0 for reindeer in reindeers}
|
||||
points: dict[Reindeer, int] = {reindeer: 0 for reindeer in reindeers}
|
||||
|
||||
for time in range(target):
|
||||
for time in self.progress.wrap(range(target)):
|
||||
for reindeer in reindeers:
|
||||
if states[reindeer][0] == "flying":
|
||||
distances[reindeer] += reindeer.speed
|
||||
@ -54,9 +59,5 @@ for time in range(target):
|
||||
else:
|
||||
states[reindeer] = ("resting", time + reindeer.rest_time)
|
||||
|
||||
|
||||
answer_1 = max(distances.values())
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
answer_2 = max(points.values()) - 1
|
||||
print(f"answer 2 is {answer_2}")
|
||||
yield max(distances.values())
|
||||
yield max(points.values()) - 1
|
||||
|
@ -1,9 +1,10 @@
|
||||
import math
|
||||
import sys
|
||||
from typing import Sequence, cast
|
||||
from typing import Any, Iterator, Sequence, cast
|
||||
|
||||
import parse # type: ignore
|
||||
|
||||
from ..base import BaseSolver
|
||||
|
||||
|
||||
def score(ingredients: list[list[int]], teaspoons: Sequence[int]) -> int:
|
||||
return math.prod(
|
||||
@ -18,10 +19,12 @@ def score(ingredients: list[list[int]], teaspoons: Sequence[int]) -> int:
|
||||
)
|
||||
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = input.splitlines()
|
||||
|
||||
ingredients: list[list[int]] = []
|
||||
for line in lines:
|
||||
ingredients: list[list[int]] = []
|
||||
for line in lines:
|
||||
_, *scores = cast(
|
||||
tuple[str, int, int, int, int, int],
|
||||
parse.parse( # type: ignore
|
||||
@ -32,11 +35,11 @@ for line in lines:
|
||||
)
|
||||
ingredients.append(scores)
|
||||
|
||||
total_teaspoons = 100
|
||||
calories: list[int] = []
|
||||
scores: list[int] = []
|
||||
total_teaspoons = 100
|
||||
calories: list[int] = []
|
||||
scores: list[int] = []
|
||||
|
||||
for a in range(total_teaspoons + 1):
|
||||
for a in range(total_teaspoons + 1):
|
||||
for b in range(total_teaspoons + 1 - a):
|
||||
for c in range(total_teaspoons + 1 - a - b):
|
||||
teaspoons = (a, b, c, total_teaspoons - a - b - c)
|
||||
@ -49,9 +52,5 @@ for a in range(total_teaspoons + 1):
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
answer_1 = max(scores)
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
answer_2 = max(score for score, calory in zip(scores, calories) if calory == 500)
|
||||
print(f"answer 2 is {answer_2}")
|
||||
yield max(scores)
|
||||
yield max(score for score, calory in zip(scores, calories) if calory == 500)
|
||||
|
@ -1,8 +1,9 @@
|
||||
import operator as op
|
||||
import re
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from typing import Callable
|
||||
from typing import Any, Callable, Iterator
|
||||
|
||||
from ..base import BaseSolver
|
||||
|
||||
MFCSAM: dict[str, int] = {
|
||||
"children": 3,
|
||||
@ -17,18 +18,10 @@ MFCSAM: dict[str, int] = {
|
||||
"perfumes": 1,
|
||||
}
|
||||
|
||||
lines = sys.stdin.readlines()
|
||||
|
||||
aunts: list[dict[str, int]] = [
|
||||
{
|
||||
match[1]: int(match[2])
|
||||
for match in re.findall(R"((?P<compound>[^:, ]+): (?P<quantity>\d+))", line)
|
||||
}
|
||||
for line in lines
|
||||
]
|
||||
|
||||
|
||||
def match(operators: dict[str, Callable[[int, int], bool]]) -> int:
|
||||
def match(
|
||||
aunts: list[dict[str, int]], operators: dict[str, Callable[[int, int], bool]]
|
||||
) -> int:
|
||||
return next(
|
||||
i
|
||||
for i, aunt in enumerate(aunts, start=1)
|
||||
@ -36,16 +29,29 @@ def match(operators: dict[str, Callable[[int, int], bool]]) -> int:
|
||||
)
|
||||
|
||||
|
||||
answer_1 = match(defaultdict(lambda: op.eq))
|
||||
print(f"answer 1 is {answer_1}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = input.splitlines()
|
||||
|
||||
answer_2 = match(
|
||||
aunts: list[dict[str, int]] = [
|
||||
{
|
||||
match[1]: int(match[2])
|
||||
for match in re.findall(
|
||||
R"((?P<compound>[^:, ]+): (?P<quantity>\d+))", line
|
||||
)
|
||||
}
|
||||
for line in lines
|
||||
]
|
||||
|
||||
yield match(aunts, defaultdict(lambda: op.eq))
|
||||
|
||||
yield match(
|
||||
aunts,
|
||||
defaultdict(
|
||||
lambda: op.eq,
|
||||
trees=op.gt,
|
||||
cats=op.gt,
|
||||
pomeranians=op.lt,
|
||||
goldfish=op.lt,
|
||||
),
|
||||
)
|
||||
)
|
||||
print(f"answer 2 is {answer_2}")
|
||||
|
@ -1,5 +1,6 @@
|
||||
import sys
|
||||
from typing import Iterator
|
||||
from typing import Any, Iterator
|
||||
|
||||
from ..base import BaseSolver
|
||||
|
||||
|
||||
def iter_combinations(value: int, containers: list[int]) -> Iterator[tuple[int, ...]]:
|
||||
@ -16,15 +17,18 @@ def iter_combinations(value: int, containers: list[int]) -> Iterator[tuple[int,
|
||||
yield (containers[i],) + combination
|
||||
|
||||
|
||||
containers = [int(c) for c in sys.stdin.read().split()]
|
||||
total = 25 if len(containers) <= 5 else 150
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
containers = [int(c) for c in input.split()]
|
||||
total = 25 if len(containers) <= 5 else 150
|
||||
|
||||
combinations = [combination for combination in iter_combinations(total, containers)]
|
||||
combinations = [
|
||||
combination for combination in iter_combinations(total, containers)
|
||||
]
|
||||
|
||||
answer_1 = len(combinations)
|
||||
print(f"answer 1 is {answer_1}")
|
||||
yield len(combinations)
|
||||
|
||||
min_containers = min(len(combination) for combination in combinations)
|
||||
|
||||
answer_2 = sum(1 for combination in combinations if len(combination) == min_containers)
|
||||
print(f"answer 2 is {answer_2}")
|
||||
min_containers = min(len(combination) for combination in combinations)
|
||||
yield sum(
|
||||
1 for combination in combinations if len(combination) == min_containers
|
||||
)
|
||||
|
@ -1,13 +1,18 @@
|
||||
import itertools
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
import numpy as np
|
||||
from numpy.typing import NDArray
|
||||
|
||||
grid0 = np.array([[c == "#" for c in line] for line in sys.stdin.read().splitlines()])
|
||||
from ..base import BaseSolver
|
||||
|
||||
# add an always off circle around
|
||||
grid0 = np.concatenate(
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
grid0 = np.array([[c == "#" for c in line] for line in input.splitlines()])
|
||||
|
||||
# add an always off circle around
|
||||
grid0 = np.concatenate(
|
||||
[
|
||||
np.zeros((grid0.shape[0] + 2, 1), dtype=bool),
|
||||
np.concatenate(
|
||||
@ -20,22 +25,21 @@ grid0 = np.concatenate(
|
||||
np.zeros((grid0.shape[0] + 2, 1), dtype=bool),
|
||||
],
|
||||
axis=1,
|
||||
)
|
||||
)
|
||||
|
||||
moves = list(itertools.product([-1, 0, 1], repeat=2))
|
||||
moves.remove((0, 0))
|
||||
moves = list(itertools.product([-1, 0, 1], repeat=2))
|
||||
moves.remove((0, 0))
|
||||
|
||||
jjs, iis = np.meshgrid(
|
||||
jjs, iis = np.meshgrid(
|
||||
np.arange(1, grid0.shape[0] - 1, dtype=int),
|
||||
np.arange(1, grid0.shape[1] - 1, dtype=int),
|
||||
)
|
||||
iis, jjs = iis.flatten(), jjs.flatten()
|
||||
)
|
||||
iis, jjs = iis.flatten(), jjs.flatten()
|
||||
|
||||
ins = iis[:, None] + np.array(moves)[:, 0]
|
||||
jns = jjs[:, None] + np.array(moves)[:, 1]
|
||||
ins = iis[:, None] + np.array(moves)[:, 0]
|
||||
jns = jjs[:, None] + np.array(moves)[:, 1]
|
||||
|
||||
|
||||
def game_of_life(grid: NDArray[np.bool_]) -> NDArray[np.bool_]:
|
||||
def game_of_life(grid: NDArray[np.bool_]) -> NDArray[np.bool_]:
|
||||
neighbors_on = grid[ins, jns].sum(axis=1)
|
||||
cells_on = grid[iis, jjs]
|
||||
|
||||
@ -44,23 +48,19 @@ def game_of_life(grid: NDArray[np.bool_]) -> NDArray[np.bool_]:
|
||||
|
||||
return grid
|
||||
|
||||
|
||||
grid = grid0
|
||||
n_steps = 4 if len(grid) < 10 else 100
|
||||
for _ in range(n_steps):
|
||||
grid = grid0
|
||||
n_steps = 4 if len(grid) < 10 else 100
|
||||
for _ in range(n_steps):
|
||||
grid = game_of_life(grid)
|
||||
|
||||
answer_1 = grid.sum()
|
||||
print(f"answer 1 is {answer_1}")
|
||||
yield grid.sum()
|
||||
|
||||
|
||||
n_steps = 5 if len(grid) < 10 else 100
|
||||
grid = grid0
|
||||
for _ in range(n_steps):
|
||||
n_steps = 5 if len(grid) < 10 else 100
|
||||
grid = grid0
|
||||
for _ in range(n_steps):
|
||||
grid[[1, 1, -2, -2], [1, -2, 1, -2]] = True
|
||||
grid = game_of_life(grid)
|
||||
|
||||
grid[[1, 1, -2, -2], [1, -2, 1, -2]] = True
|
||||
grid[[1, 1, -2, -2], [1, -2, 1, -2]] = True
|
||||
|
||||
answer_2 = sum(cell for line in grid for cell in line)
|
||||
print(f"answer 2 is {answer_2}")
|
||||
yield sum(cell for line in grid for cell in line)
|
||||
|
@ -1,37 +1,41 @@
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from typing import Any, Iterator
|
||||
|
||||
replacements_s, molecule = sys.stdin.read().split("\n\n")
|
||||
from ..base import BaseSolver
|
||||
|
||||
REPLACEMENTS: dict[str, list[str]] = defaultdict(list)
|
||||
for replacement_s in replacements_s.splitlines():
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
replacements_s, molecule = input.split("\n\n")
|
||||
|
||||
REPLACEMENTS: dict[str, list[str]] = defaultdict(list)
|
||||
for replacement_s in replacements_s.splitlines():
|
||||
p = replacement_s.split(" => ")
|
||||
REPLACEMENTS[p[0]].append(p[1])
|
||||
molecule = molecule.strip()
|
||||
molecule = molecule.strip()
|
||||
|
||||
generated = [
|
||||
generated = [
|
||||
molecule[:i] + replacement + molecule[i + len(symbol) :]
|
||||
for symbol, replacements in REPLACEMENTS.items()
|
||||
for replacement in replacements
|
||||
for i in range(len(molecule))
|
||||
if molecule[i:].startswith(symbol)
|
||||
]
|
||||
]
|
||||
|
||||
answer_1 = len(set(generated))
|
||||
print(f"answer 1 is {answer_1}")
|
||||
yield len(set(generated))
|
||||
|
||||
inversion: dict[str, str] = {
|
||||
inversion: dict[str, str] = {
|
||||
replacement: symbol
|
||||
for symbol, replacements in REPLACEMENTS.items()
|
||||
for replacement in replacements
|
||||
}
|
||||
}
|
||||
|
||||
# there is actually only one way to create the molecule, and we can greedily replace
|
||||
# tokens with their replacements, e.g., if H => OH then we can replace OH by H directly
|
||||
# without thinking
|
||||
# there is actually only one way to create the molecule, and we can greedily replace
|
||||
# tokens with their replacements, e.g., if H => OH then we can replace OH by H directly
|
||||
# without thinking
|
||||
|
||||
count = 0
|
||||
while molecule != "e":
|
||||
count = 0
|
||||
while molecule != "e":
|
||||
i = 0
|
||||
m2 = ""
|
||||
while i < len(molecule):
|
||||
@ -51,6 +55,4 @@ while molecule != "e":
|
||||
# print(m2)
|
||||
molecule = m2
|
||||
|
||||
|
||||
answer_2 = count
|
||||
print(f"answer 2 is {count}")
|
||||
yield count
|
||||
|
@ -1,20 +1,24 @@
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
import numpy as np
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
from ..base import BaseSolver
|
||||
|
||||
length, width, height = np.array(
|
||||
[[int(c) for c in line.split("x")] for line in lines]
|
||||
).T
|
||||
|
||||
lw, wh, hl = (length * width, width * height, height * length)
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
length, width, height = np.array(
|
||||
[[int(c) for c in line.split("x")] for line in input.splitlines()]
|
||||
).T
|
||||
|
||||
answer_1 = np.sum(2 * (lw + wh + hl) + np.min(np.stack([lw, wh, hl]), axis=0))
|
||||
print(f"answer 1 is {answer_1}")
|
||||
lw, wh, hl = (length * width, width * height, height * length)
|
||||
|
||||
answer_2 = np.sum(
|
||||
yield np.sum(2 * (lw + wh + hl) + np.min(np.stack([lw, wh, hl]), axis=0))
|
||||
|
||||
yield np.sum(
|
||||
length * width * height
|
||||
+ 2 * np.min(np.stack([length + width, length + height, height + width]), axis=0)
|
||||
)
|
||||
print(f"answer 2 is {answer_2}")
|
||||
+ 2
|
||||
* np.min(
|
||||
np.stack([length + width, length + height, height + width]), axis=0
|
||||
)
|
||||
)
|
||||
|
@ -1,10 +1,10 @@
|
||||
import itertools
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
target = int(sys.stdin.read())
|
||||
from ..base import BaseSolver
|
||||
|
||||
|
||||
def presents(n: int, elf: int, max: int = target) -> int:
|
||||
def presents(n: int, elf: int, max: int) -> int:
|
||||
count = 0
|
||||
k = 1
|
||||
while k * k < n:
|
||||
@ -21,8 +21,9 @@ def presents(n: int, elf: int, max: int = target) -> int:
|
||||
return count
|
||||
|
||||
|
||||
answer_1 = next(n for n in itertools.count(1) if presents(n, 10) >= target)
|
||||
print(f"answer 1 is {answer_1}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
target = int(input)
|
||||
|
||||
answer_2 = next(n for n in itertools.count(1) if presents(n, 11, 50) >= target)
|
||||
print(f"answer 2 is {answer_2}")
|
||||
yield next(n for n in itertools.count(1) if presents(n, 10, target) >= target)
|
||||
yield next(n for n in itertools.count(1) if presents(n, 11, 50) >= target)
|
||||
|
@ -1,7 +1,8 @@
|
||||
import itertools
|
||||
import sys
|
||||
from math import ceil
|
||||
from typing import TypeAlias
|
||||
from typing import Any, Iterator, TypeAlias
|
||||
|
||||
from ..base import BaseSolver
|
||||
|
||||
Modifier: TypeAlias = tuple[str, int, int, int]
|
||||
|
||||
@ -33,17 +34,18 @@ RINGS: list[Modifier] = [
|
||||
]
|
||||
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = input.splitlines()
|
||||
|
||||
player_hp = 100
|
||||
player_hp = 100
|
||||
|
||||
boss_attack = int(lines[1].split(":")[1].strip())
|
||||
boss_armor = int(lines[2].split(":")[1].strip())
|
||||
boss_hp = int(lines[0].split(":")[1].strip())
|
||||
boss_attack = int(lines[1].split(":")[1].strip())
|
||||
boss_armor = int(lines[2].split(":")[1].strip())
|
||||
boss_hp = int(lines[0].split(":")[1].strip())
|
||||
|
||||
|
||||
min_cost, max_cost = 1_000_000, 0
|
||||
for equipments in itertools.product(WEAPONS, ARMORS, RINGS, RINGS):
|
||||
min_cost, max_cost = 1_000_000, 0
|
||||
for equipments in itertools.product(WEAPONS, ARMORS, RINGS, RINGS):
|
||||
if equipments[-1][0] != "" and equipments[-2] == equipments[-1]:
|
||||
continue
|
||||
|
||||
@ -58,9 +60,5 @@ for equipments in itertools.product(WEAPONS, ARMORS, RINGS, RINGS):
|
||||
else:
|
||||
max_cost = max(cost, max_cost)
|
||||
|
||||
|
||||
answer_1 = min_cost
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
answer_2 = max_cost
|
||||
print(f"answer 2 is {answer_2}")
|
||||
yield min_cost
|
||||
yield max_cost
|
||||
|
@ -1,8 +1,9 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import heapq
|
||||
import sys
|
||||
from typing import Literal, TypeAlias, cast
|
||||
from typing import Any, Iterator, Literal, TypeAlias, cast
|
||||
|
||||
from ..base import BaseSolver
|
||||
|
||||
PlayerType: TypeAlias = Literal["player", "boss"]
|
||||
SpellType: TypeAlias = Literal["magic missile", "drain", "shield", "poison", "recharge"]
|
||||
@ -62,17 +63,6 @@ def play(
|
||||
continue
|
||||
|
||||
visited.add((player, player_hp, player_mana, player_armor, boss_hp, buffs))
|
||||
|
||||
if hard_mode and player == "player":
|
||||
player_hp = max(0, player_hp - 1)
|
||||
|
||||
if player_hp == 0:
|
||||
continue
|
||||
|
||||
if boss_hp == 0:
|
||||
winning_node = spells
|
||||
continue
|
||||
|
||||
new_buffs: list[tuple[BuffType, int]] = []
|
||||
for buff, length in buffs:
|
||||
length = length - 1
|
||||
@ -88,6 +78,16 @@ def play(
|
||||
if length > 0:
|
||||
new_buffs.append((buff, length))
|
||||
|
||||
if hard_mode and player == "player":
|
||||
player_hp = player_hp - 1
|
||||
|
||||
if player_hp <= 0:
|
||||
continue
|
||||
|
||||
if boss_hp <= 0:
|
||||
winning_node = spells
|
||||
continue
|
||||
|
||||
buffs = tuple(new_buffs)
|
||||
|
||||
if player == "boss":
|
||||
@ -155,23 +155,28 @@ def play(
|
||||
return winning_node
|
||||
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = input.splitlines()
|
||||
|
||||
player_hp = 50
|
||||
player_mana = 500
|
||||
player_armor = 0
|
||||
player_hp = 50
|
||||
player_mana = 500
|
||||
player_armor = 0
|
||||
|
||||
boss_hp = int(lines[0].split(":")[1].strip())
|
||||
boss_attack = int(lines[1].split(":")[1].strip())
|
||||
boss_hp = int(lines[0].split(":")[1].strip())
|
||||
boss_attack = int(lines[1].split(":")[1].strip())
|
||||
|
||||
answer_1 = sum(
|
||||
yield sum(
|
||||
c
|
||||
for _, c in play(player_hp, player_mana, player_armor, boss_hp, boss_attack, False)
|
||||
)
|
||||
print(f"answer 1 is {answer_1}")
|
||||
for _, c in play(
|
||||
player_hp, player_mana, player_armor, boss_hp, boss_attack, False
|
||||
)
|
||||
)
|
||||
|
||||
# 1242 (not working)
|
||||
answer_2 = sum(
|
||||
c for _, c in play(player_hp, player_mana, player_armor, boss_hp, boss_attack, True)
|
||||
)
|
||||
print(f"answer 2 is {answer_2}")
|
||||
# 1242 (not working)
|
||||
yield sum(
|
||||
c
|
||||
for _, c in play(
|
||||
player_hp, player_mana, player_armor, boss_hp, boss_attack, True
|
||||
)
|
||||
)
|
||||
|
@ -1,7 +1,7 @@
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from typing import Any, Iterator
|
||||
|
||||
line = sys.stdin.read().strip()
|
||||
from ..base import BaseSolver
|
||||
|
||||
|
||||
def process(directions: str) -> dict[tuple[int, int], int]:
|
||||
@ -27,8 +27,7 @@ def process(directions: str) -> dict[tuple[int, int], int]:
|
||||
return counts
|
||||
|
||||
|
||||
answer_1 = len(process(line))
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
answer_2 = len(process(line[::2]) | process(line[1::2]))
|
||||
print(f"answer 2 is {answer_2}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
yield len(process(input))
|
||||
yield len(process(input[::2]) | process(input[1::2]))
|
||||
|
@ -1,16 +1,20 @@
|
||||
import hashlib
|
||||
import itertools
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
line = sys.stdin.read().strip()
|
||||
from ..base import BaseSolver
|
||||
|
||||
it = iter(itertools.count(1))
|
||||
answer_1 = next(
|
||||
i for i in it if hashlib.md5(f"{line}{i}".encode()).hexdigest().startswith("00000")
|
||||
)
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
answer_2 = next(
|
||||
i for i in it if hashlib.md5(f"{line}{i}".encode()).hexdigest().startswith("000000")
|
||||
)
|
||||
print(f"answer 2 is {answer_2}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
it = iter(itertools.count(1))
|
||||
yield next(
|
||||
i
|
||||
for i in it
|
||||
if hashlib.md5(f"{input}{i}".encode()).hexdigest().startswith("00000")
|
||||
)
|
||||
yield next(
|
||||
i
|
||||
for i in it
|
||||
if hashlib.md5(f"{input}{i}".encode()).hexdigest().startswith("000000")
|
||||
)
|
||||
|
@ -1,4 +1,6 @@
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
from ..base import BaseSolver
|
||||
|
||||
VOWELS = "aeiou"
|
||||
FORBIDDEN = {"ab", "cd", "pq", "xy"}
|
||||
@ -27,10 +29,8 @@ def is_nice_2(s: str) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
answer_1 = sum(map(is_nice_1, lines))
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
answer_2 = sum(map(is_nice_2, lines))
|
||||
print(f"answer 2 is {answer_2}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = input.splitlines()
|
||||
yield sum(map(is_nice_1, lines))
|
||||
yield sum(map(is_nice_2, lines))
|
||||
|
@ -1,14 +1,16 @@
|
||||
import sys
|
||||
from typing import Literal, cast
|
||||
from typing import Any, Iterator, Literal, cast
|
||||
|
||||
import numpy as np
|
||||
import parse # type: ignore
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
from ..base import BaseSolver
|
||||
|
||||
lights_1 = np.zeros((1000, 1000), dtype=bool)
|
||||
lights_2 = np.zeros((1000, 1000), dtype=int)
|
||||
for line in lines:
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lights_1 = np.zeros((1000, 1000), dtype=bool)
|
||||
lights_2 = np.zeros((1000, 1000), dtype=int)
|
||||
for line in input.splitlines():
|
||||
action, sx, sy, ex, ey = cast(
|
||||
tuple[Literal["turn on", "turn off", "toggle"], int, int, int, int],
|
||||
parse.parse("{} {:d},{:d} through {:d},{:d}", line), # type: ignore
|
||||
@ -26,8 +28,5 @@ for line in lines:
|
||||
lights_1[sx:ex, sy:ey] = ~lights_1[sx:ex, sy:ey]
|
||||
lights_2[sx:ex, sy:ey] += 2
|
||||
|
||||
answer_1 = lights_1.sum()
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
answer_2 = lights_2.sum()
|
||||
print(f"answer 2 is {answer_2}")
|
||||
yield lights_1.sum()
|
||||
yield lights_2.sum()
|
||||
|
@ -1,11 +1,7 @@
|
||||
import logging
|
||||
import operator
|
||||
import os
|
||||
import sys
|
||||
from typing import Callable
|
||||
from typing import Any, Callable, Iterator
|
||||
|
||||
VERBOSE = os.getenv("AOC_VERBOSE") == "True"
|
||||
logging.basicConfig(level=logging.INFO if VERBOSE else logging.WARNING)
|
||||
from ..base import BaseSolver
|
||||
|
||||
OPERATORS = {
|
||||
"AND": operator.and_,
|
||||
@ -36,12 +32,27 @@ def value_of(key: str) -> tuple[str, Callable[[dict[str, int]], int]]:
|
||||
return key, lambda values: values[key]
|
||||
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
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]
|
||||
|
||||
signals: Signals = {}
|
||||
values: dict[str, int] = {"": 0}
|
||||
return values
|
||||
|
||||
for line in lines:
|
||||
|
||||
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"):
|
||||
@ -77,25 +88,9 @@ for line in lines:
|
||||
|
||||
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"]
|
||||
|
||||
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}")
|
||||
yield process(signals.copy(), values | {"b": values_1["a"]})["a"]
|
||||
|
@ -1,14 +1,13 @@
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
VERBOSE = os.getenv("AOC_VERBOSE") == "True"
|
||||
logging.basicConfig(level=logging.INFO if VERBOSE else logging.WARNING)
|
||||
from ..base import BaseSolver
|
||||
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = input.splitlines()
|
||||
|
||||
answer_1 = sum(
|
||||
yield sum(
|
||||
# left and right quotes (not in memory)
|
||||
2
|
||||
# each \\ adds one character in the literals (compared to memory)
|
||||
@ -20,10 +19,9 @@ answer_1 = sum(
|
||||
# avoid \\\\x, etc., but this does not occur in the examples and the actual input
|
||||
+ 3 * (line.count(R"\x") - line.count(R"\\x") + line.count(R"\\\x"))
|
||||
for line in lines
|
||||
)
|
||||
print(f"answer 1 is {answer_1}")
|
||||
)
|
||||
|
||||
answer_2 = sum(
|
||||
yield sum(
|
||||
# needs to wrap in quotes (2 characters)
|
||||
2
|
||||
# needs to escape every \ with an extra \
|
||||
@ -31,5 +29,4 @@ answer_2 = sum(
|
||||
# needs to escape every " with an extra \ (including the first and last ones)
|
||||
+ line.count('"')
|
||||
for line in lines
|
||||
)
|
||||
print(f"answer 2 is {answer_2}")
|
||||
)
|
||||
|
@ -1,27 +1,28 @@
|
||||
import itertools
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from typing import cast
|
||||
from typing import Any, Iterator, cast
|
||||
|
||||
import parse # type: ignore
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
from ..base import BaseSolver
|
||||
|
||||
distances: dict[str, dict[str, int]] = defaultdict(dict)
|
||||
for line in lines:
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = input.splitlines()
|
||||
|
||||
distances: dict[str, dict[str, int]] = defaultdict(dict)
|
||||
for line in lines:
|
||||
origin, destination, length = cast(
|
||||
tuple[str, str, int],
|
||||
parse.parse("{} to {} = {:d}", line), # type: ignore
|
||||
)
|
||||
distances[origin][destination] = distances[destination][origin] = length
|
||||
|
||||
distance_of_routes = {
|
||||
distance_of_routes = {
|
||||
route: sum(distances[o][d] for o, d in zip(route[:-1], route[1:]))
|
||||
for route in map(tuple, itertools.permutations(distances))
|
||||
}
|
||||
}
|
||||
|
||||
answer_1 = min(distance_of_routes.values())
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
answer_2 = max(distance_of_routes.values())
|
||||
print(f"answer 2 is {answer_2}")
|
||||
yield min(distance_of_routes.values())
|
||||
yield max(distance_of_routes.values())
|
||||
|
@ -178,7 +178,14 @@ def main():
|
||||
|
||||
start = datetime.now()
|
||||
last = start
|
||||
for i_answer, answer in enumerate(solver.solve(data.strip())):
|
||||
|
||||
it = solver.solve(data.strip())
|
||||
|
||||
if it is None:
|
||||
solver.logger.error(f"no implementation for {year} day {day}")
|
||||
exit()
|
||||
|
||||
for i_answer, answer in enumerate(it):
|
||||
current = datetime.now()
|
||||
|
||||
if api:
|
||||
|
@ -7,10 +7,12 @@ _T = TypeVar("_T")
|
||||
|
||||
class ProgressHandler(Protocol):
|
||||
@overload
|
||||
def wrap(self, values: Sequence[_T]) -> Iterator[_T]: ...
|
||||
def wrap(self, values: Sequence[_T]) -> Iterator[_T]:
|
||||
...
|
||||
|
||||
@overload
|
||||
def wrap(self, values: Iterable[_T], total: int) -> Iterator[_T]: ...
|
||||
def wrap(self, values: Iterable[_T], total: int) -> Iterator[_T]:
|
||||
...
|
||||
|
||||
|
||||
class BaseSolver:
|
||||
@ -31,4 +33,5 @@ class BaseSolver:
|
||||
self.outputs = outputs
|
||||
|
||||
@abstractmethod
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
def solve(self, input: str) -> Iterator[Any] | None:
|
||||
...
|
||||
|
Loading…
Reference in New Issue
Block a user