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