Refactor code for API #3
@ -1,27 +1,9 @@
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
lookups_1 = {str(d): d for d in range(1, 10)}
|
||||
lookups_2 = lookups_1 | {
|
||||
d: i + 1
|
||||
for i, d in enumerate(
|
||||
(
|
||||
"one",
|
||||
"two",
|
||||
"three",
|
||||
"four",
|
||||
"five",
|
||||
"six",
|
||||
"seven",
|
||||
"eight",
|
||||
"nine",
|
||||
)
|
||||
)
|
||||
}
|
||||
from ..base import BaseSolver
|
||||
|
||||
|
||||
def find_values(lookups: dict[str, int]) -> list[int]:
|
||||
def find_values(lines: list[str], lookups: dict[str, int]) -> list[int]:
|
||||
values: list[int] = []
|
||||
|
||||
for line in filter(bool, lines):
|
||||
@ -41,5 +23,27 @@ def find_values(lookups: dict[str, int]) -> list[int]:
|
||||
return values
|
||||
|
||||
|
||||
print(f"answer 1 is {sum(find_values(lookups_1))}")
|
||||
print(f"answer 2 is {sum(find_values(lookups_2))}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lookups_1 = {str(d): d for d in range(1, 10)}
|
||||
lookups_2 = lookups_1 | {
|
||||
d: i + 1
|
||||
for i, d in enumerate(
|
||||
(
|
||||
"one",
|
||||
"two",
|
||||
"three",
|
||||
"four",
|
||||
"five",
|
||||
"six",
|
||||
"seven",
|
||||
"eight",
|
||||
"nine",
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
lines = input.splitlines()
|
||||
|
||||
yield sum(find_values(lines, lookups_1))
|
||||
yield sum(find_values(lines, lookups_2))
|
||||
|
@ -1,13 +1,16 @@
|
||||
import math
|
||||
import sys
|
||||
from typing import Literal, TypeAlias, cast
|
||||
from typing import Any, Iterator, Literal, TypeAlias, cast
|
||||
|
||||
from ..base import BaseSolver
|
||||
|
||||
CubeType: TypeAlias = Literal["red", "blue", "green"]
|
||||
|
||||
MAX_CUBES: dict[CubeType, int] = {"red": 12, "green": 13, "blue": 14}
|
||||
|
||||
# parse games
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = input.splitlines()
|
||||
games: dict[int, list[dict[CubeType, int]]] = {}
|
||||
for line in filter(bool, lines):
|
||||
id_part, sets_part = line.split(":")
|
||||
@ -21,8 +24,7 @@ for line in filter(bool, lines):
|
||||
for cube_set_s in sets_part.strip().split(";")
|
||||
]
|
||||
|
||||
# part 1
|
||||
answer_1 = sum(
|
||||
yield sum(
|
||||
id
|
||||
for id, set_of_cubes in games.items()
|
||||
if all(
|
||||
@ -31,13 +33,11 @@ answer_1 = sum(
|
||||
for cube, n_cubes in cube_set.items()
|
||||
)
|
||||
)
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
# part 2
|
||||
answer_2 = sum(
|
||||
yield sum(
|
||||
math.prod(
|
||||
max(cube_set.get(cube, 0) for cube_set in set_of_cubes) for cube in MAX_CUBES
|
||||
max(cube_set.get(cube, 0) for cube_set in set_of_cubes)
|
||||
for cube in MAX_CUBES
|
||||
)
|
||||
for set_of_cubes in games.values()
|
||||
)
|
||||
print(f"answer 2 is {answer_2}")
|
||||
|
@ -1,10 +1,15 @@
|
||||
import string
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from typing import Any, Iterator
|
||||
|
||||
from ..base import BaseSolver
|
||||
|
||||
NOT_A_SYMBOL = "." + string.digits
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = input.splitlines()
|
||||
|
||||
values: list[int] = []
|
||||
gears: dict[tuple[int, int], list[int]] = defaultdict(list)
|
||||
@ -44,10 +49,5 @@ for i, line in enumerate(lines):
|
||||
# continue starting from the end of the number
|
||||
j = k
|
||||
|
||||
# part 1
|
||||
answer_1 = sum(values)
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
# part 2
|
||||
answer_2 = sum(v1 * v2 for v1, v2 in filter(lambda vs: len(vs) == 2, gears.values()))
|
||||
print(f"answer 2 is {answer_2}")
|
||||
yield sum(values)
|
||||
yield sum(v1 * v2 for v1, v2 in filter(lambda vs: len(vs) == 2, gears.values()))
|
||||
|
@ -1,5 +1,7 @@
|
||||
import sys
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Iterator
|
||||
|
||||
from ..base import BaseSolver
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@ -9,7 +11,9 @@ class Card:
|
||||
values: list[int]
|
||||
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = input.splitlines()
|
||||
|
||||
cards: list[Card] = []
|
||||
for line in lines:
|
||||
@ -26,8 +30,7 @@ for line in lines:
|
||||
winnings = [sum(1 for n in card.values if n in card.numbers) for card in cards]
|
||||
|
||||
# part 1
|
||||
answer_1 = sum(2 ** (winning - 1) for winning in winnings if winning > 0)
|
||||
print(f"answer 1 is {answer_1}")
|
||||
yield sum(2 ** (winning - 1) for winning in winnings if winning > 0)
|
||||
|
||||
# part 2
|
||||
card2cards = {i: list(range(i + 1, i + w + 1)) for i, w in enumerate(winnings)}
|
||||
@ -38,4 +41,4 @@ for i in range(len(cards)):
|
||||
for j in card2cards[i]:
|
||||
card2values[j] += card2values[i]
|
||||
|
||||
print(f"answer 2 is {sum(card2values.values())}")
|
||||
yield sum(card2values.values())
|
||||
|
@ -1,5 +1,6 @@
|
||||
import sys
|
||||
from typing import Sequence
|
||||
from typing import Any, Iterator, Sequence
|
||||
|
||||
from ..base import BaseSolver
|
||||
|
||||
MAP_ORDER = [
|
||||
"seed",
|
||||
@ -12,55 +13,6 @@ MAP_ORDER = [
|
||||
"location",
|
||||
]
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
# mappings from one category to another, each list contains
|
||||
# ranges stored as (source, target, length), ordered by start and
|
||||
# completed to have no "hole"
|
||||
maps: dict[tuple[str, str], list[tuple[int, int, int]]] = {}
|
||||
|
||||
# parsing
|
||||
index = 2
|
||||
while index < len(lines):
|
||||
p1, _, p2 = lines[index].split()[0].split("-")
|
||||
|
||||
# extract the existing ranges from the file - we store as (source, target, length)
|
||||
# whereas the file is in order (target, source, length)
|
||||
index += 1
|
||||
values: list[tuple[int, int, int]] = []
|
||||
while index < len(lines) and lines[index]:
|
||||
n1, n2, n3 = lines[index].split()
|
||||
values.append((int(n2), int(n1), int(n3)))
|
||||
index += 1
|
||||
|
||||
# sort by source value
|
||||
values.sort()
|
||||
|
||||
# add a 'fake' interval starting at 0 if missing
|
||||
if values[0][0] != 0:
|
||||
values.insert(0, (0, 0, values[0][0]))
|
||||
|
||||
# fill gaps between intervals
|
||||
for i in range(len(values) - 1):
|
||||
next_start = values[i + 1][0]
|
||||
end = values[i][0] + values[i][2]
|
||||
if next_start != end:
|
||||
values.insert(
|
||||
i + 1,
|
||||
(end, end, next_start - end),
|
||||
)
|
||||
|
||||
# add an interval covering values up to at least 2**32 at the end
|
||||
last_start, _, last_length = values[-1]
|
||||
values.append((last_start + last_length, last_start + last_length, 2**32))
|
||||
|
||||
assert all(v1[0] + v1[2] == v2[0] for v1, v2 in zip(values[:-1], values[1:]))
|
||||
assert values[0][0] == 0
|
||||
assert values[-1][0] + values[-1][-1] >= 2**32
|
||||
|
||||
maps[p1, p2] = values
|
||||
index += 1
|
||||
|
||||
|
||||
def find_range(
|
||||
values: tuple[int, int], map: list[tuple[int, int, int]]
|
||||
@ -111,19 +63,71 @@ def find_range(
|
||||
return ranges
|
||||
|
||||
|
||||
def find_location_ranges(seeds: Sequence[tuple[int, int]]) -> Sequence[tuple[int, int]]:
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = input.splitlines()
|
||||
|
||||
# mappings from one category to another, each list contains
|
||||
# ranges stored as (source, target, length), ordered by start and
|
||||
# completed to have no "hole"
|
||||
maps: dict[tuple[str, str], list[tuple[int, int, int]]] = {}
|
||||
|
||||
def find_location_ranges(
|
||||
seeds: Sequence[tuple[int, int]],
|
||||
) -> Sequence[tuple[int, int]]:
|
||||
for map1, map2 in zip(MAP_ORDER[:-1], MAP_ORDER[1:]):
|
||||
seeds = [s2 for s1 in seeds for s2 in find_range(s1, maps[map1, map2])]
|
||||
return seeds
|
||||
|
||||
# parsing
|
||||
index = 2
|
||||
while index < len(lines):
|
||||
p1, _, p2 = lines[index].split()[0].split("-")
|
||||
|
||||
# extract the existing ranges from the file - we store as (source, target, length)
|
||||
# whereas the file is in order (target, source, length)
|
||||
index += 1
|
||||
values: list[tuple[int, int, int]] = []
|
||||
while index < len(lines) and lines[index]:
|
||||
n1, n2, n3 = lines[index].split()
|
||||
values.append((int(n2), int(n1), int(n3)))
|
||||
index += 1
|
||||
|
||||
# sort by source value
|
||||
values.sort()
|
||||
|
||||
# add a 'fake' interval starting at 0 if missing
|
||||
if values[0][0] != 0:
|
||||
values.insert(0, (0, 0, values[0][0]))
|
||||
|
||||
# fill gaps between intervals
|
||||
for i in range(len(values) - 1):
|
||||
next_start = values[i + 1][0]
|
||||
end = values[i][0] + values[i][2]
|
||||
if next_start != end:
|
||||
values.insert(
|
||||
i + 1,
|
||||
(end, end, next_start - end),
|
||||
)
|
||||
|
||||
# add an interval covering values up to at least 2**32 at the end
|
||||
last_start, _, last_length = values[-1]
|
||||
values.append((last_start + last_length, last_start + last_length, 2**32))
|
||||
|
||||
assert all(
|
||||
v1[0] + v1[2] == v2[0] for v1, v2 in zip(values[:-1], values[1:])
|
||||
)
|
||||
assert values[0][0] == 0
|
||||
assert values[-1][0] + values[-1][-1] >= 2**32
|
||||
|
||||
maps[p1, p2] = values
|
||||
index += 1
|
||||
|
||||
# part 1 - use find_range() with range of length 1
|
||||
seeds_p1 = [(int(s), 1) for s in lines[0].split(":")[1].strip().split()]
|
||||
answer_1 = min(start for start, _ in find_location_ranges(seeds_p1))
|
||||
print(f"answer 1 is {answer_1}")
|
||||
yield min(start for start, _ in find_location_ranges(seeds_p1))
|
||||
|
||||
# # part 2
|
||||
parts = lines[0].split(":")[1].strip().split()
|
||||
seeds_p2 = [(int(s), int(e)) for s, e in zip(parts[::2], parts[1::2])]
|
||||
answer_2 = min(start for start, _ in find_location_ranges(seeds_p2))
|
||||
print(f"answer 2 is {answer_2}")
|
||||
yield min(start for start, _ in find_location_ranges(seeds_p2))
|
||||
|
@ -1,14 +1,17 @@
|
||||
import sys
|
||||
from collections import Counter
|
||||
from typing import Any, Iterator
|
||||
|
||||
values = list(map(int, sys.stdin.read().strip().split()))
|
||||
from ..base import BaseSolver
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
values = list(map(int, input.split()))
|
||||
|
||||
column_1 = sorted(values[::2])
|
||||
column_2 = sorted(values[1::2])
|
||||
|
||||
yield sum(abs(v1 - v2) for v1, v2 in zip(column_1, column_2, strict=True))
|
||||
|
||||
counter_2 = Counter(column_2)
|
||||
|
||||
answer_1 = sum(abs(v1 - v2) for v1, v2 in zip(column_1, column_2, strict=True))
|
||||
answer_2 = sum(value * counter_2.get(value, 0) for value in column_1)
|
||||
|
||||
print(f"answer 1 is {answer_1}")
|
||||
print(f"answer 2 is {answer_2}")
|
||||
yield sum(value * counter_2.get(value, 0) for value in column_1)
|
||||
|
@ -1,10 +1,7 @@
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
from ..base import BaseSolver
|
||||
|
||||
answer_1 = ...
|
||||
|
||||
answer_2 = ...
|
||||
|
||||
print(f"answer 1 is {answer_1}")
|
||||
print(f"answer 2 is {answer_2}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
@ -1,10 +1,7 @@
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
from ..base import BaseSolver
|
||||
|
||||
answer_1 = ...
|
||||
|
||||
answer_2 = ...
|
||||
|
||||
print(f"answer 1 is {answer_1}")
|
||||
print(f"answer 2 is {answer_2}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
@ -1,10 +1,7 @@
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
from ..base import BaseSolver
|
||||
|
||||
answer_1 = ...
|
||||
|
||||
answer_2 = ...
|
||||
|
||||
print(f"answer 1 is {answer_1}")
|
||||
print(f"answer 2 is {answer_2}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
@ -1,10 +1,7 @@
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
from ..base import BaseSolver
|
||||
|
||||
answer_1 = ...
|
||||
|
||||
answer_2 = ...
|
||||
|
||||
print(f"answer 1 is {answer_1}")
|
||||
print(f"answer 2 is {answer_2}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
@ -1,10 +1,7 @@
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
from ..base import BaseSolver
|
||||
|
||||
answer_1 = ...
|
||||
|
||||
answer_2 = ...
|
||||
|
||||
print(f"answer 1 is {answer_1}")
|
||||
print(f"answer 2 is {answer_2}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
@ -1,10 +1,7 @@
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
from ..base import BaseSolver
|
||||
|
||||
answer_1 = ...
|
||||
|
||||
answer_2 = ...
|
||||
|
||||
print(f"answer 1 is {answer_1}")
|
||||
print(f"answer 2 is {answer_2}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
@ -1,10 +1,7 @@
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
from ..base import BaseSolver
|
||||
|
||||
answer_1 = ...
|
||||
|
||||
answer_2 = ...
|
||||
|
||||
print(f"answer 1 is {answer_1}")
|
||||
print(f"answer 2 is {answer_2}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
@ -1,10 +1,7 @@
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
from ..base import BaseSolver
|
||||
|
||||
answer_1 = ...
|
||||
|
||||
answer_2 = ...
|
||||
|
||||
print(f"answer 1 is {answer_1}")
|
||||
print(f"answer 2 is {answer_2}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
@ -1,10 +1,7 @@
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
from ..base import BaseSolver
|
||||
|
||||
answer_1 = ...
|
||||
|
||||
answer_2 = ...
|
||||
|
||||
print(f"answer 1 is {answer_1}")
|
||||
print(f"answer 2 is {answer_2}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
@ -1,10 +1,7 @@
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
from ..base import BaseSolver
|
||||
|
||||
answer_1 = ...
|
||||
|
||||
answer_2 = ...
|
||||
|
||||
print(f"answer 1 is {answer_1}")
|
||||
print(f"answer 2 is {answer_2}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
@ -1,6 +1,10 @@
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
from ..base import BaseSolver
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
def is_safe(level: list[int]) -> bool:
|
||||
diff = [a - b for a, b in zip(level[:-1], level[1:], strict=True)]
|
||||
|
||||
@ -8,15 +12,12 @@ def is_safe(level: list[int]) -> bool:
|
||||
1 <= abs(d) <= 3 for d in diff
|
||||
)
|
||||
|
||||
|
||||
def is_any_safe(level: list[int]) -> bool:
|
||||
return any(is_safe(level[:i] + level[i + 1 :]) for i in range(0, len(level)))
|
||||
return any(
|
||||
is_safe(level[:i] + level[i + 1 :]) for i in range(0, len(level))
|
||||
)
|
||||
|
||||
levels = [[int(c) for c in r.split()] for r in input.splitlines()]
|
||||
|
||||
levels = [[int(c) for c in r.split()] for r in sys.stdin.read().strip().splitlines()]
|
||||
|
||||
answer_1 = sum(is_safe(level) for level in levels)
|
||||
answer_2 = sum(is_safe(level) or is_any_safe(level) for level in levels)
|
||||
|
||||
print(f"answer 1 is {answer_1}")
|
||||
print(f"answer 2 is {answer_2}")
|
||||
yield sum(is_safe(level) for level in levels)
|
||||
yield sum(is_safe(level) or is_any_safe(level) for level in levels)
|
||||
|
@ -1,10 +1,7 @@
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
from ..base import BaseSolver
|
||||
|
||||
answer_1 = ...
|
||||
|
||||
answer_2 = ...
|
||||
|
||||
print(f"answer 1 is {answer_1}")
|
||||
print(f"answer 2 is {answer_2}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
@ -1,10 +1,7 @@
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
from ..base import BaseSolver
|
||||
|
||||
answer_1 = ...
|
||||
|
||||
answer_2 = ...
|
||||
|
||||
print(f"answer 1 is {answer_1}")
|
||||
print(f"answer 2 is {answer_2}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
@ -1,10 +1,7 @@
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
from ..base import BaseSolver
|
||||
|
||||
answer_1 = ...
|
||||
|
||||
answer_2 = ...
|
||||
|
||||
print(f"answer 1 is {answer_1}")
|
||||
print(f"answer 2 is {answer_2}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
@ -1,10 +1,7 @@
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
from ..base import BaseSolver
|
||||
|
||||
answer_1 = ...
|
||||
|
||||
answer_2 = ...
|
||||
|
||||
print(f"answer 1 is {answer_1}")
|
||||
print(f"answer 2 is {answer_2}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
@ -1,10 +1,7 @@
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
from ..base import BaseSolver
|
||||
|
||||
answer_1 = ...
|
||||
|
||||
answer_2 = ...
|
||||
|
||||
print(f"answer 1 is {answer_1}")
|
||||
print(f"answer 2 is {answer_2}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
@ -1,10 +1,7 @@
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
from ..base import BaseSolver
|
||||
|
||||
answer_1 = ...
|
||||
|
||||
answer_2 = ...
|
||||
|
||||
print(f"answer 1 is {answer_1}")
|
||||
print(f"answer 2 is {answer_2}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
@ -1,13 +1,15 @@
|
||||
import re
|
||||
import sys
|
||||
from typing import Iterator
|
||||
from typing import Any, Iterator
|
||||
|
||||
from ..base import BaseSolver
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
def extract_multiply(line: str) -> Iterator[int]:
|
||||
for m in re.finditer(r"mul\(([0-9]{1,3}),\s*([0-9]{1,3})\)", line):
|
||||
yield int(m.group(1)) * int(m.group(2))
|
||||
|
||||
|
||||
def valid_memory_blocks(line: str) -> Iterator[str]:
|
||||
accumulate = True
|
||||
while line:
|
||||
@ -24,11 +26,5 @@ def valid_memory_blocks(line: str) -> Iterator[str]:
|
||||
else:
|
||||
line = ""
|
||||
|
||||
|
||||
line = sys.stdin.read().strip()
|
||||
|
||||
answer_1 = sum(extract_multiply(line))
|
||||
answer_2 = sum(sum(extract_multiply(block)) for block in valid_memory_blocks(line))
|
||||
|
||||
print(f"answer 1 is {answer_1}")
|
||||
print(f"answer 2 is {answer_2}")
|
||||
yield sum(extract_multiply(input))
|
||||
yield sum(sum(extract_multiply(block)) for block in valid_memory_blocks(input))
|
||||
|
@ -1,10 +1,15 @@
|
||||
import itertools as it
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
lines = sys.stdin.read().strip().splitlines()
|
||||
from ..base import BaseSolver
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = input.splitlines()
|
||||
n = len(lines)
|
||||
|
||||
answer_1 = sum(
|
||||
yield sum(
|
||||
line.count("XMAS") + line.count("SAMX")
|
||||
for i in range(n)
|
||||
for ri, rk, ro, ci, ck, cm in (
|
||||
@ -16,16 +21,17 @@ answer_1 = sum(
|
||||
(-1, -1, -1, 0, 1, n - i if i != 0 else 0),
|
||||
)
|
||||
if (
|
||||
line := "".join(lines[ri * i + rk * k + ro][ci * i + ck * k] for k in range(cm))
|
||||
line := "".join(
|
||||
lines[ri * i + rk * k + ro][ci * i + ck * k] for k in range(cm)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
answer_2 = sum(
|
||||
yield sum(
|
||||
lines[i][j] == "A"
|
||||
and "".join(lines[i + di][j + dj] for di, dj in it.product((-1, 1), (-1, 1)))
|
||||
and "".join(
|
||||
lines[i + di][j + dj] for di, dj in it.product((-1, 1), (-1, 1))
|
||||
)
|
||||
in {"MSMS", "SSMM", "MMSS", "SMSM"}
|
||||
for i, j in it.product(range(1, n - 1), range(1, n - 1))
|
||||
)
|
||||
|
||||
print(f"answer 1 is {answer_1}")
|
||||
print(f"answer 2 is {answer_2}")
|
||||
|
@ -1,10 +1,7 @@
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
from ..base import BaseSolver
|
||||
|
||||
answer_1 = ...
|
||||
|
||||
answer_2 = ...
|
||||
|
||||
print(f"answer 1 is {answer_1}")
|
||||
print(f"answer 2 is {answer_2}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
@ -1,10 +1,7 @@
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
from ..base import BaseSolver
|
||||
|
||||
answer_1 = ...
|
||||
|
||||
answer_2 = ...
|
||||
|
||||
print(f"answer 1 is {answer_1}")
|
||||
print(f"answer 2 is {answer_2}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
@ -1,10 +1,7 @@
|
||||
import sys
|
||||
from typing import Any, Iterator
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
from ..base import BaseSolver
|
||||
|
||||
answer_1 = ...
|
||||
|
||||
answer_2 = ...
|
||||
|
||||
print(f"answer 1 is {answer_1}")
|
||||
print(f"answer 2 is {answer_2}")
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
@ -1,9 +1,11 @@
|
||||
import argparse
|
||||
import importlib
|
||||
import os
|
||||
import logging
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from .base import BaseSolver
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser("Holt59 Advent-Of-Code Runner")
|
||||
@ -40,8 +42,7 @@ def main():
|
||||
day: int = args.day
|
||||
|
||||
# TODO: change this
|
||||
if verbose:
|
||||
os.environ["AOC_VERBOSE"] = "True"
|
||||
logging.basicConfig(level=logging.INFO if verbose else logging.WARNING)
|
||||
|
||||
if input_path is None:
|
||||
input_path = Path(__file__).parent.joinpath(
|
||||
@ -49,11 +50,18 @@ def main():
|
||||
)
|
||||
assert input_path.exists(), f"{input_path} missing"
|
||||
|
||||
solver_class: type[BaseSolver] = importlib.import_module(
|
||||
f".{year}.day{day}", __package__
|
||||
).Solver
|
||||
|
||||
solver = solver_class(logging.getLogger("AOC"), year, day)
|
||||
|
||||
data: str
|
||||
if stdin:
|
||||
importlib.import_module(f".{year}.day{day}", __package__)
|
||||
data = sys.stdin.read()
|
||||
else:
|
||||
with open(input_path) as fp:
|
||||
sys.stdin = fp
|
||||
importlib.import_module(f".{year}.day{day}", __package__)
|
||||
data = fp.read()
|
||||
|
||||
sys.stdin = sys.__stdin__
|
||||
for i_answer, answer in enumerate(solver.solve(data.strip())):
|
||||
print(f"answer {i_answer + 1} is {answer}")
|
||||
|
13
src/holt59/aoc/base.py
Normal file
13
src/holt59/aoc/base.py
Normal file
@ -0,0 +1,13 @@
|
||||
from abc import abstractmethod
|
||||
from logging import Logger
|
||||
from typing import Any, Final, Iterator
|
||||
|
||||
|
||||
class BaseSolver:
|
||||
def __init__(self, logger: Logger, year: int, day: int):
|
||||
self.logger: Final = logger
|
||||
self.year: Final = year
|
||||
self.day: Final = day
|
||||
|
||||
@abstractmethod
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
Loading…
Reference in New Issue
Block a user