Compare commits
135 Commits
master
...
377e501d34
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
377e501d34 | ||
|
|
d1f4f5bed0 | ||
|
|
03a950c485 | ||
|
|
22b1513271 | ||
|
|
1f5b21a13a | ||
|
|
8c707c00ba | ||
|
|
ae4f42517c | ||
|
|
17432f7ac6 | ||
|
|
664dcfe7ba | ||
|
|
a9bcf9ef8f | ||
|
|
1caf93b38b | ||
|
|
f9a3dee20b | ||
|
|
1a1ff0c64d | ||
|
|
d7621d09b5 | ||
|
|
b89d29e880 | ||
|
|
f1cd7e6c85 | ||
|
|
d16ee7f9ad | ||
| 0c46d3ed18 | |||
|
|
acb767184e | ||
|
|
cb0145baa2 | ||
|
|
a4ad0259a9 | ||
|
|
82452c0751 | ||
|
|
79cc208875 | ||
|
|
4dd2d5d9c9 | ||
|
|
def4305c1c | ||
|
|
3edaa249fc | ||
|
|
57fcb47fe9 | ||
|
|
cfa7718475 | ||
|
|
2d23e355b2 | ||
|
|
fab4899715 | ||
|
|
b6e20eefa3 | ||
|
|
872fd72dcd | ||
|
|
98f28e96f8 | ||
|
|
ed7aba80ad | ||
|
|
e507dad5e0 | ||
|
|
04172beb5a | ||
|
|
15ef67e757 | ||
|
|
cd0ada785c | ||
|
|
42bd8d6983 | ||
|
|
0567ab7440 | ||
|
|
7d2eb6b5ec | ||
|
|
3a9c7e728b | ||
|
|
d002e419c3 | ||
|
|
19d93e0c1d | ||
|
|
5c05ee5c85 | ||
|
|
103af21915 | ||
|
|
af2fbf2da1 | ||
|
|
c496ea25c9 | ||
|
|
5f8c74fd1c | ||
|
|
dda2be2505 | ||
|
|
12891194bb | ||
|
|
f15908876d | ||
|
|
5f5ebda674 | ||
|
|
5b30cc00d5 | ||
|
|
3a7f8e83dc | ||
|
|
ba5b01c594 | ||
|
|
d0970c090b | ||
|
|
8e90bf7002 | ||
| 9698dfcdac | |||
|
|
1a6ab1cc0e | ||
|
|
f5aabbee8f | ||
|
|
6c00341ab0 | ||
|
|
755e0bd4b3 | ||
|
|
a52d077a40 | ||
|
|
3fc0f94b1c | ||
|
|
8a0412f926 | ||
|
|
855efeb0aa | ||
|
|
f2a65e03e5 | ||
|
|
759f47bfab | ||
|
|
999207b007 | ||
|
|
d92e4744a4 | ||
|
|
8dbf0f101c | ||
|
|
b8d8df06d6 | ||
|
|
825ebea299 | ||
|
|
869cd4477f | ||
|
|
fd777627d6 | ||
|
|
98f605f30e | ||
|
|
d51fed283c | ||
|
|
e991cd8b04 | ||
|
|
10f67e6bfd | ||
|
|
f291b0aa3f | ||
|
|
0eb5b5a88f | ||
|
|
2ec0a3d5f9 | ||
|
|
0327a3f36a | ||
|
|
3732e70ef7 | ||
|
|
b0cc6b4a46 | ||
|
|
8c24b9f9e2 | ||
|
|
dca6f6a08f | ||
|
|
8d7a20f575 | ||
|
|
3934dfd152 | ||
|
|
b656e8929e | ||
|
|
c9c69f479b | ||
|
|
72ebcfff1f | ||
|
|
dd72bb3238 | ||
|
|
c1dd74c57d | ||
|
|
1bf2de62c7 | ||
|
|
df808bc98a | ||
|
|
f46e190e98 | ||
|
|
7f4a34b2d7 | ||
|
|
ddebd26db2 | ||
|
|
01300e23b2 | ||
|
|
b8e2faa8c9 | ||
|
|
ea5b757180 | ||
|
|
89a71c175f | ||
|
|
9ffb332dea | ||
|
|
8167ab34c7 | ||
|
|
100df02a09 | ||
|
|
15b987a590 | ||
|
|
b1578f5709 | ||
|
|
d80dbb6c7c | ||
|
|
b679c1f895 | ||
|
|
e9d5f9747b | ||
|
|
fe3aad7ddd | ||
|
|
7ac9981ae5 | ||
|
|
652756a341 | ||
|
|
c7ef505f1b | ||
|
|
c55f6ac8e1 | ||
|
|
726a6aecac | ||
|
|
291b188238 | ||
|
|
289e3b7d02 | ||
|
|
9820765e9c | ||
|
|
c6522de8a2 | ||
|
|
80465e5e53 | ||
|
|
af1428b5e1 | ||
|
|
fca283527d | ||
|
|
0d37458ec5 | ||
|
|
198927e4a3 | ||
|
|
4192c98bba | ||
|
|
7cb8317659 | ||
|
|
f46cb51c60 | ||
|
|
261a396ae7 | ||
|
|
4b3af377ab | ||
|
|
f697415ef2 | ||
|
|
ac2806b0fb | ||
|
|
c62b8abfd0 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,4 +4,3 @@ __pycache__
|
|||||||
.ruff_cache
|
.ruff_cache
|
||||||
.vscode
|
.vscode
|
||||||
build
|
build
|
||||||
files
|
|
||||||
|
|||||||
628
poetry.lock
generated
628
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -8,16 +8,14 @@ readme = "README.md"
|
|||||||
packages = [{ include = "holt59", from = "src" }]
|
packages = [{ include = "holt59", from = "src" }]
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.12"
|
python = "^3.10"
|
||||||
numpy = "^2.1.3"
|
numpy = "^2.1.3"
|
||||||
tqdm = "^4.67.1"
|
tqdm = "^4.67.1"
|
||||||
parse = "^1.20.2"
|
parse = "^1.20.2"
|
||||||
|
scipy = "^1.14.1"
|
||||||
sympy = "^1.13.3"
|
sympy = "^1.13.3"
|
||||||
networkx = "^3.4.2"
|
networkx = "^3.4.2"
|
||||||
pillow = "^11.0.0"
|
pandas = "^2.2.3"
|
||||||
imageio = "^2.36.1"
|
|
||||||
pygifsicle = "^1.1.0"
|
|
||||||
opencv-python = "^4.10.0.84"
|
|
||||||
|
|
||||||
[tool.poetry.group.dev.dependencies]
|
[tool.poetry.group.dev.dependencies]
|
||||||
pyright = "^1.1.389"
|
pyright = "^1.1.389"
|
||||||
@@ -27,13 +25,6 @@ ipykernel = "^6.29.5"
|
|||||||
networkx-stubs = "^0.0.1"
|
networkx-stubs = "^0.0.1"
|
||||||
types-networkx = "^3.4.2.20241115"
|
types-networkx = "^3.4.2.20241115"
|
||||||
|
|
||||||
[tool.poetry.group.cplex.dependencies]
|
|
||||||
docplex = "^2.30.251"
|
|
||||||
cplex = "^22.1.2.0"
|
|
||||||
|
|
||||||
[tool.poetry.group.ortools.dependencies]
|
|
||||||
ortools = "^9.11.4210"
|
|
||||||
|
|
||||||
[tool.poetry.scripts]
|
[tool.poetry.scripts]
|
||||||
holt59-aoc = "holt59.aoc.__main__:main"
|
holt59-aoc = "holt59.aoc.__main__:main"
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ class Solver(BaseSolver):
|
|||||||
m2 += molecule[i]
|
m2 += molecule[i]
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
|
# print(m2)
|
||||||
molecule = m2
|
molecule = m2
|
||||||
|
|
||||||
yield count
|
yield count
|
||||||
|
|||||||
@@ -173,6 +173,7 @@ class Solver(BaseSolver):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 1242 (not working)
|
||||||
yield sum(
|
yield sum(
|
||||||
c
|
c
|
||||||
for _, c in play(
|
for _, c in play(
|
||||||
|
|||||||
@@ -1,107 +0,0 @@
|
|||||||
import inspect
|
|
||||||
from typing import Any, Callable, Final, Iterator, Mapping
|
|
||||||
|
|
||||||
from ..base import BaseSolver
|
|
||||||
|
|
||||||
|
|
||||||
class Instruction:
|
|
||||||
def __init__(self, fn: Callable[..., None]):
|
|
||||||
self._fn = fn
|
|
||||||
|
|
||||||
args = inspect.getfullargspec(fn)
|
|
||||||
|
|
||||||
self._argtypes = [args.annotations[arg] for arg in args.args[1:]]
|
|
||||||
|
|
||||||
def __call__(self, args: tuple[str, ...]):
|
|
||||||
self._fn(
|
|
||||||
*(argtype(arg) for arg, argtype in zip(args, self._argtypes, strict=True))
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Machine:
|
|
||||||
def __init__(
|
|
||||||
self, instructions: list[str], registers: dict[str, int] = {"a": 0, "b": 1}
|
|
||||||
):
|
|
||||||
self.instructions: Final = [
|
|
||||||
(part[0], tuple(arg.strip() for arg in " ".join(part[1:]).split(",")))
|
|
||||||
for instruction in instructions
|
|
||||||
if (part := instruction.split())
|
|
||||||
]
|
|
||||||
|
|
||||||
self._fns = {
|
|
||||||
name: Instruction(getattr(self, name))
|
|
||||||
for name in ("hlf", "tpl", "inc", "jmp", "jie", "jio")
|
|
||||||
}
|
|
||||||
|
|
||||||
self._registers = registers.copy()
|
|
||||||
self._ip = 0
|
|
||||||
|
|
||||||
@property
|
|
||||||
def registers(self) -> Mapping[str, int]:
|
|
||||||
return self._registers
|
|
||||||
|
|
||||||
@property
|
|
||||||
def ip(self) -> int:
|
|
||||||
return self._ip
|
|
||||||
|
|
||||||
def reset(self, registers: dict[str, int] = {"a": 0, "b": 0}):
|
|
||||||
self._registers = registers.copy()
|
|
||||||
self._ip = 0
|
|
||||||
|
|
||||||
def hlf(self, register: str):
|
|
||||||
self._registers[register] //= 2
|
|
||||||
self._ip += 1
|
|
||||||
|
|
||||||
def tpl(self, register: str):
|
|
||||||
self._registers[register] *= 3
|
|
||||||
self._ip += 1
|
|
||||||
|
|
||||||
def inc(self, register: str):
|
|
||||||
self._registers[register] += 1
|
|
||||||
self._ip += 1
|
|
||||||
|
|
||||||
def jmp(self, offset: int):
|
|
||||||
self._ip += offset
|
|
||||||
assert 0 <= self._ip < len(self.instructions)
|
|
||||||
|
|
||||||
def jie(self, register: str, offset: int):
|
|
||||||
if self._registers[register] % 2 == 0:
|
|
||||||
self._ip += offset
|
|
||||||
else:
|
|
||||||
self._ip += 1
|
|
||||||
|
|
||||||
def jio(self, register: str, offset: int):
|
|
||||||
if self._registers[register] == 1:
|
|
||||||
self._ip += offset
|
|
||||||
else:
|
|
||||||
self._ip += 1
|
|
||||||
|
|
||||||
def _exec(self) -> bool:
|
|
||||||
# execute next instruction
|
|
||||||
if self._ip >= len(self.instructions):
|
|
||||||
return False
|
|
||||||
|
|
||||||
ins, args = self.instructions[self._ip]
|
|
||||||
|
|
||||||
if ins not in self._fns:
|
|
||||||
return False
|
|
||||||
|
|
||||||
self._fns[ins](args)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
while self._exec():
|
|
||||||
...
|
|
||||||
return self.registers
|
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
machine = Machine(input.splitlines())
|
|
||||||
|
|
||||||
registers = machine.run()
|
|
||||||
yield registers["b"]
|
|
||||||
|
|
||||||
machine.reset({"a": 1, "b": 0})
|
|
||||||
registers = machine.run()
|
|
||||||
yield registers["b"]
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
from typing import Any, Iterator, TypeAlias
|
|
||||||
|
|
||||||
from ..base import BaseSolver
|
|
||||||
|
|
||||||
TupleOfInts: TypeAlias = tuple[int, ...]
|
|
||||||
|
|
||||||
|
|
||||||
def check_n_groups(
|
|
||||||
target: int, groups: tuple[TupleOfInts, ...], numbers: TupleOfInts
|
|
||||||
) -> bool:
|
|
||||||
n_groups = len(groups)
|
|
||||||
groups_s = tuple(sum(group) for group in groups)
|
|
||||||
|
|
||||||
if all(target == group_s for group_s in groups_s):
|
|
||||||
return not numbers
|
|
||||||
|
|
||||||
if not numbers:
|
|
||||||
return False
|
|
||||||
|
|
||||||
head, *tail_l = numbers
|
|
||||||
tail, tail_s = tuple(tail_l), sum(tail_l)
|
|
||||||
|
|
||||||
return any(
|
|
||||||
groups_s[i] + head <= target
|
|
||||||
and sum(groups_s[j] for j in range(len(groups)) if i != j) + tail_s
|
|
||||||
>= (n_groups - 1) * target
|
|
||||||
and check_n_groups(
|
|
||||||
target, groups[:i] + ((groups[i] + (head,)),) + groups[i + 1 :], tail
|
|
||||||
)
|
|
||||||
for i in range(len(groups))
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def enumerate_single_subset(
|
|
||||||
target: int, numbers: TupleOfInts
|
|
||||||
) -> Iterator[tuple[int, TupleOfInts, TupleOfInts]]:
|
|
||||||
"""
|
|
||||||
Enumerate subset of numbers whose sum equals target.
|
|
||||||
|
|
||||||
Subset are enumerated in increasing order of length, then product (quantum value).
|
|
||||||
|
|
||||||
Args:
|
|
||||||
target: Target for the sum of the subset.
|
|
||||||
numbers: Tuple of integers to find the subset from.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
A generator (quantum, subset, remaining) where subset if the subset of numbers
|
|
||||||
whose sum equals target, quantum the product of the subset, and remaining the
|
|
||||||
remaining numbers.
|
|
||||||
"""
|
|
||||||
groups: list[tuple[int, TupleOfInts, TupleOfInts]] = [(1, (), numbers)]
|
|
||||||
|
|
||||||
for _ in range(len(numbers)):
|
|
||||||
new_groups: list[tuple[int, TupleOfInts, TupleOfInts]] = []
|
|
||||||
|
|
||||||
for g_quantum, group, remaining in groups:
|
|
||||||
sg = sum(group)
|
|
||||||
for i in range(len(remaining)):
|
|
||||||
if group and remaining[i] <= group[-1]:
|
|
||||||
continue
|
|
||||||
|
|
||||||
uv = remaining[:i] + remaining[i + 1 :]
|
|
||||||
kv = g_quantum * remaining[i], group + (remaining[i],), uv
|
|
||||||
|
|
||||||
if sg + remaining[i] == target:
|
|
||||||
yield kv
|
|
||||||
elif sg + remaining[i] < target:
|
|
||||||
new_groups.append(kv)
|
|
||||||
|
|
||||||
groups = new_groups
|
|
||||||
|
|
||||||
|
|
||||||
def find_min_quantum(numbers: tuple[int, ...], n_groups: int):
|
|
||||||
return next(
|
|
||||||
g_quantum
|
|
||||||
for g_quantum, group_1v2, group_234v2 in enumerate_single_subset(
|
|
||||||
sum(numbers) // n_groups, numbers
|
|
||||||
)
|
|
||||||
if check_n_groups(sum(group_1v2), ((),) * (n_groups - 1), group_234v2)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
numbers = tuple(map(int, input.split()))
|
|
||||||
|
|
||||||
yield find_min_quantum(numbers, 3)
|
|
||||||
yield find_min_quantum(numbers, 4)
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import re
|
|
||||||
from typing import Any, Iterator
|
|
||||||
|
|
||||||
from ..base import BaseSolver
|
|
||||||
from ..tools.math import pow_mod
|
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
m = re.search(r"row\s*([0-9]+)\s*,\s*column\s*([0-9]+)", input)
|
|
||||||
assert m is not None
|
|
||||||
|
|
||||||
row, col = int(m.group(1)), int(m.group(2))
|
|
||||||
n = (row * (row - 1)) // 2 + col * (col + 1) // 2 + (row - 1) * (col - 1)
|
|
||||||
|
|
||||||
yield (20151125 * pow_mod(252533, n - 1, 33554393)) % 33554393
|
|
||||||
@@ -1,17 +1,14 @@
|
|||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
values = [int(line) for line in lines]
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
# part 1
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
answer_1 = sum(v2 > v1 for v1, v2 in zip(values[:-1], values[1:]))
|
||||||
lines = input.splitlines()
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
values = [int(line) for line in lines]
|
# part 2
|
||||||
|
runnings = [sum(values[i : i + 3]) for i in range(len(values) - 2)]
|
||||||
# part 1
|
answer_2 = sum(v2 > v1 for v1, v2 in zip(runnings[:-1], runnings[1:]))
|
||||||
yield sum(v2 > v1 for v1, v2 in zip(values[:-1], values[1:]))
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|
||||||
# part 2
|
|
||||||
runnings = [sum(values[i : i + 3]) for i in range(len(values) - 2)]
|
|
||||||
yield sum(v2 > v1 for v1, v2 in zip(runnings[:-1], runnings[1:]))
|
|
||||||
|
|||||||
@@ -1,47 +1,11 @@
|
|||||||
from functools import reduce
|
import sys
|
||||||
from typing import Any, Iterator
|
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
BRACKETS = {"{": "}", "[": "]", "<": ">", "(": ")"}
|
# part 1
|
||||||
|
answer_1 = ...
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
CORRUPT_SCORES = {")": 3, "]": 57, "}": 1197, ">": 25137}
|
# part 2
|
||||||
COMPLETE_SCORES = {")": 1, "]": 2, "}": 3, ">": 4}
|
answer_2 = ...
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|
||||||
def corrupted_or_incomplete(line: str) -> tuple[bool, str]:
|
|
||||||
opens: list[str] = []
|
|
||||||
|
|
||||||
for c in line:
|
|
||||||
if c in BRACKETS:
|
|
||||||
opens.append(c)
|
|
||||||
elif BRACKETS[opens[-1]] != c:
|
|
||||||
return True, c
|
|
||||||
else:
|
|
||||||
opens.pop()
|
|
||||||
|
|
||||||
return (False, "".join(opens))
|
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
lines = input.splitlines()
|
|
||||||
|
|
||||||
answer_1: int = 0
|
|
||||||
incomplete_scores: list[int] = []
|
|
||||||
|
|
||||||
for line in lines:
|
|
||||||
c, r = corrupted_or_incomplete(line)
|
|
||||||
if c:
|
|
||||||
answer_1 += CORRUPT_SCORES[r]
|
|
||||||
else:
|
|
||||||
incomplete_scores.append(
|
|
||||||
reduce(
|
|
||||||
lambda s, c: s * 5 + COMPLETE_SCORES[BRACKETS[c]],
|
|
||||||
reversed(r),
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
yield answer_1
|
|
||||||
yield sorted(incomplete_scores)[len(incomplete_scores) // 2]
|
|
||||||
|
|||||||
@@ -1,66 +1,11 @@
|
|||||||
import itertools as it
|
import sys
|
||||||
from typing import Any, Iterator
|
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
# part 1
|
||||||
|
answer_1 = ...
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
def do_step(values: list[list[int]]) -> tuple[list[list[int]], set[tuple[int, int]]]:
|
# part 2
|
||||||
values = [[c + 1 for c in r] for r in values]
|
answer_2 = ...
|
||||||
flashed: set[tuple[int, int]] = set()
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|
||||||
while True:
|
|
||||||
found = False
|
|
||||||
|
|
||||||
for i_row, row in enumerate(values):
|
|
||||||
for i_col, col in enumerate(row):
|
|
||||||
if col <= 9 or (i_row, i_col) in flashed:
|
|
||||||
continue
|
|
||||||
|
|
||||||
found = True
|
|
||||||
flashed.add((i_row, i_col))
|
|
||||||
for dr, dc in it.product((-1, 0, 1), repeat=2):
|
|
||||||
if 0 <= i_row + dr < len(values) and 0 <= i_col + dc < len(
|
|
||||||
values[0]
|
|
||||||
):
|
|
||||||
values[i_row + dr][i_col + dc] += 1
|
|
||||||
|
|
||||||
if not found:
|
|
||||||
break
|
|
||||||
|
|
||||||
for i, j in flashed:
|
|
||||||
values[i][j] = 0
|
|
||||||
|
|
||||||
return values, flashed
|
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
|
||||||
def print_grid(self, values: list[list[int]], flashed: set[tuple[int, int]]):
|
|
||||||
for i_row, row in enumerate(values):
|
|
||||||
s_row = ""
|
|
||||||
for i_col, col in enumerate(row):
|
|
||||||
if (i_row, i_col) in flashed:
|
|
||||||
s_row += f"\033[0;31m{col}\033[0;00m"
|
|
||||||
else:
|
|
||||||
s_row += str(col)
|
|
||||||
self.logger.info(s_row)
|
|
||||||
self.logger.info("")
|
|
||||||
|
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
values_0 = [[int(c) for c in r] for r in input.splitlines()]
|
|
||||||
|
|
||||||
values = values_0
|
|
||||||
total_flashed: int = 0
|
|
||||||
for _ in range(100):
|
|
||||||
values, flashed = do_step(values)
|
|
||||||
total_flashed += len(flashed)
|
|
||||||
|
|
||||||
yield total_flashed
|
|
||||||
|
|
||||||
n_cells = len(values) * len(values[0])
|
|
||||||
flashed: set[tuple[int, int]] = set()
|
|
||||||
values, step = values_0, 0
|
|
||||||
while len(flashed) != n_cells:
|
|
||||||
values, flashed = do_step(values)
|
|
||||||
step += 1
|
|
||||||
|
|
||||||
yield step
|
|
||||||
|
|||||||
@@ -1,64 +1,11 @@
|
|||||||
import string
|
import sys
|
||||||
from collections import defaultdict
|
|
||||||
from functools import cache
|
|
||||||
from typing import Any, Iterator, Mapping, Sequence
|
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
# part 1
|
||||||
|
answer_1 = ...
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
@cache
|
# part 2
|
||||||
def is_small(node: str):
|
answer_2 = ...
|
||||||
return all(c in string.ascii_lowercase for c in node)
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|
||||||
|
|
||||||
def enumerate_paths(
|
|
||||||
neighbors: Mapping[str, Sequence[str]],
|
|
||||||
duplicate_smalls: int = 0,
|
|
||||||
start: str = "start",
|
|
||||||
current: tuple[str, ...] = ("start",),
|
|
||||||
) -> Iterator[tuple[str, ...]]:
|
|
||||||
if start == "end":
|
|
||||||
yield current
|
|
||||||
|
|
||||||
for neighbor in neighbors[start]:
|
|
||||||
if not is_small(neighbor):
|
|
||||||
yield from enumerate_paths(
|
|
||||||
neighbors, duplicate_smalls, neighbor, current + (neighbor,)
|
|
||||||
)
|
|
||||||
elif neighbor not in current:
|
|
||||||
yield from enumerate_paths(
|
|
||||||
neighbors, duplicate_smalls, neighbor, current + (neighbor,)
|
|
||||||
)
|
|
||||||
elif duplicate_smalls > 0:
|
|
||||||
yield from enumerate_paths(
|
|
||||||
neighbors, duplicate_smalls - 1, neighbor, current + (neighbor,)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
neighbors: dict[str, list[str]] = defaultdict(list)
|
|
||||||
|
|
||||||
for row in input.splitlines():
|
|
||||||
a, b = row.split("-")
|
|
||||||
if a != "end" and b != "start":
|
|
||||||
neighbors[a].append(b)
|
|
||||||
if b != "end" and a != "start":
|
|
||||||
neighbors[b].append(a)
|
|
||||||
|
|
||||||
if self.files:
|
|
||||||
graph = "graph {\n"
|
|
||||||
for node, neighbors_of in neighbors.items():
|
|
||||||
graph += (
|
|
||||||
" ".join(
|
|
||||||
f"{node} -- {neighbor};"
|
|
||||||
for neighbor in neighbors_of
|
|
||||||
if node <= neighbor or node == "start" or neighbor == "end"
|
|
||||||
)
|
|
||||||
+ "\n"
|
|
||||||
)
|
|
||||||
graph += "}\n"
|
|
||||||
self.files.create("graph.dot", graph.encode(), False)
|
|
||||||
|
|
||||||
yield len(list(enumerate_paths(neighbors)))
|
|
||||||
yield len(list(enumerate_paths(neighbors, 1)))
|
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
# part 1
|
||||||
|
answer_1 = ...
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
# part 2
|
||||||
def solve(self, input: str) -> Iterator[Any]: ...
|
answer_2 = ...
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
# part 1
|
||||||
|
answer_1 = ...
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
# part 2
|
||||||
def solve(self, input: str) -> Iterator[Any]: ...
|
answer_2 = ...
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
# part 1
|
||||||
|
answer_1 = ...
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
# part 2
|
||||||
def solve(self, input: str) -> Iterator[Any]: ...
|
answer_2 = ...
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
# part 1
|
||||||
|
answer_1 = ...
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
# part 2
|
||||||
def solve(self, input: str) -> Iterator[Any]: ...
|
answer_2 = ...
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
# part 1
|
||||||
|
answer_1 = ...
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
# part 2
|
||||||
def solve(self, input: str) -> Iterator[Any]: ...
|
answer_2 = ...
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
# part 1
|
||||||
|
answer_1 = ...
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
# part 2
|
||||||
def solve(self, input: str) -> Iterator[Any]: ...
|
answer_2 = ...
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
# part 1
|
||||||
|
answer_1 = ...
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
# part 2
|
||||||
def solve(self, input: str) -> Iterator[Any]: ...
|
answer_2 = ...
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,20 +1,17 @@
|
|||||||
|
import sys
|
||||||
from math import prod
|
from math import prod
|
||||||
from typing import Any, Iterator, Literal, TypeAlias, cast
|
from typing import Literal, TypeAlias, cast
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
Command: TypeAlias = Literal["forward", "up", "down"]
|
Command: TypeAlias = Literal["forward", "up", "down"]
|
||||||
|
|
||||||
|
commands: list[tuple[Command, int]] = [
|
||||||
class Solver(BaseSolver):
|
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
lines = input.splitlines()
|
|
||||||
|
|
||||||
commands: list[tuple[Command, int]] = [
|
|
||||||
(cast(Command, (p := line.split())[0]), int(p[1])) for line in lines
|
(cast(Command, (p := line.split())[0]), int(p[1])) for line in lines
|
||||||
]
|
]
|
||||||
|
|
||||||
def depth_and_position(use_aim: bool):
|
|
||||||
|
def depth_and_position(use_aim: bool):
|
||||||
aim, pos, depth = 0, 0, 0
|
aim, pos, depth = 0, 0, 0
|
||||||
for command, value in commands:
|
for command, value in commands:
|
||||||
d_depth = 0
|
d_depth = 0
|
||||||
@@ -34,5 +31,11 @@ class Solver(BaseSolver):
|
|||||||
|
|
||||||
return depth, pos
|
return depth, pos
|
||||||
|
|
||||||
yield prod(depth_and_position(False))
|
|
||||||
yield prod(depth_and_position(True))
|
# part 1
|
||||||
|
answer_1 = prod(depth_and_position(False))
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
|
# part 2
|
||||||
|
answer_2 = prod(depth_and_position(True))
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
# part 1
|
||||||
|
answer_1 = ...
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
# part 2
|
||||||
def solve(self, input: str) -> Iterator[Any]: ...
|
answer_2 = ...
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
# part 1
|
||||||
|
answer_1 = ...
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
# part 2
|
||||||
def solve(self, input: str) -> Iterator[Any]: ...
|
answer_2 = ...
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
# part 1
|
||||||
|
answer_1 = ...
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
# part 2
|
||||||
def solve(self, input: str) -> Iterator[Any]: ...
|
answer_2 = ...
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
# part 1
|
||||||
|
answer_1 = ...
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
# part 2
|
||||||
def solve(self, input: str) -> Iterator[Any]: ...
|
answer_2 = ...
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
# part 1
|
||||||
|
answer_1 = ...
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
# part 2
|
||||||
def solve(self, input: str) -> Iterator[Any]: ...
|
answer_2 = ...
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
# part 1
|
||||||
|
answer_1 = ...
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
# part 2
|
||||||
def solve(self, input: str) -> Iterator[Any]: ...
|
answer_2 = ...
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
|
import sys
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
from typing import Any, Iterator, Literal
|
from typing import Literal
|
||||||
|
|
||||||
from ..base import BaseSolver
|
|
||||||
|
|
||||||
|
|
||||||
def generator_rating(
|
def generator_rating(
|
||||||
@@ -21,23 +20,20 @@ def generator_rating(
|
|||||||
return values[0]
|
return values[0]
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
lines = sys.stdin.read().splitlines()
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
lines = input.splitlines()
|
|
||||||
|
|
||||||
# part 1
|
|
||||||
most_and_least_common = [
|
# part 1
|
||||||
tuple(
|
most_and_least_common = [
|
||||||
Counter(line[col] for line in lines).most_common(2)[m][0]
|
tuple(Counter(line[col] for line in lines).most_common(2)[m][0] for m in range(2))
|
||||||
for m in range(2)
|
|
||||||
)
|
|
||||||
for col in range(len(lines[0]))
|
for col in range(len(lines[0]))
|
||||||
]
|
]
|
||||||
gamma_rate = int("".join(most for most, _ in most_and_least_common), base=2)
|
gamma_rate = int("".join(most for most, _ in most_and_least_common), base=2)
|
||||||
epsilon_rate = int("".join(least for _, least in most_and_least_common), base=2)
|
epsilon_rate = int("".join(least for _, least in most_and_least_common), base=2)
|
||||||
yield gamma_rate * epsilon_rate
|
print(f"answer 1 is {gamma_rate * epsilon_rate}")
|
||||||
|
|
||||||
# part 2
|
# part 2
|
||||||
oxygen_generator_rating = int(generator_rating(lines, True, "1"), base=2)
|
oxygen_generator_rating = int(generator_rating(lines, True, "1"), base=2)
|
||||||
co2_scrubber_rating = int(generator_rating(lines, False, "0"), base=2)
|
co2_scrubber_rating = int(generator_rating(lines, False, "0"), base=2)
|
||||||
yield oxygen_generator_rating * co2_scrubber_rating
|
answer_2 = oxygen_generator_rating * co2_scrubber_rating
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,28 +1,23 @@
|
|||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
numbers = [int(c) for c in lines[0].split(",")]
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
boards = np.asarray(
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
lines = input.splitlines()
|
|
||||||
|
|
||||||
numbers = [int(c) for c in lines[0].split(",")]
|
|
||||||
|
|
||||||
boards = np.asarray(
|
|
||||||
[
|
[
|
||||||
[[int(c) for c in line.split()] for line in lines[start : start + 5]]
|
[[int(c) for c in line.split()] for line in lines[start : start + 5]]
|
||||||
for start in range(2, len(lines), 6)
|
for start in range(2, len(lines), 6)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
# (round, score) for each board (-1 when not found)
|
# (round, score) for each board (-1 when not found)
|
||||||
winning_rounds: list[tuple[int, int]] = [(-1, -1) for _ in range(len(boards))]
|
winning_rounds: list[tuple[int, int]] = [(-1, -1) for _ in range(len(boards))]
|
||||||
marked = np.zeros_like(boards, dtype=bool)
|
marked = np.zeros_like(boards, dtype=bool)
|
||||||
|
|
||||||
for round, number in enumerate(numbers):
|
for round, number in enumerate(numbers):
|
||||||
# mark boards
|
# mark boards
|
||||||
marked[boards == number] = True
|
marked[boards == number] = True
|
||||||
|
|
||||||
@@ -31,9 +26,7 @@ class Solver(BaseSolver):
|
|||||||
if winning_rounds[index][0] > 0:
|
if winning_rounds[index][0] > 0:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if np.any(
|
if np.any(np.all(marked[index], axis=0) | np.all(marked[index], axis=1)):
|
||||||
np.all(marked[index], axis=0) | np.all(marked[index], axis=1)
|
|
||||||
):
|
|
||||||
winning_rounds[index] = (
|
winning_rounds[index] = (
|
||||||
round,
|
round,
|
||||||
number * int(np.sum(boards[index][~marked[index]])),
|
number * int(np.sum(boards[index][~marked[index]])),
|
||||||
@@ -43,10 +36,10 @@ class Solver(BaseSolver):
|
|||||||
if np.all(marked.all(axis=1) | marked.all(axis=2)):
|
if np.all(marked.all(axis=1) | marked.all(axis=2)):
|
||||||
break
|
break
|
||||||
|
|
||||||
# part 1
|
# part 1
|
||||||
(_, score) = min(winning_rounds, key=lambda w: w[0])
|
(_, score) = min(winning_rounds, key=lambda w: w[0])
|
||||||
yield score
|
print(f"answer 1 is {score}")
|
||||||
|
|
||||||
# part 2
|
# part 2
|
||||||
(_, score) = max(winning_rounds, key=lambda w: w[0])
|
(_, score) = max(winning_rounds, key=lambda w: w[0])
|
||||||
yield score
|
print(f"answer 2 is {score}")
|
||||||
|
|||||||
@@ -1,15 +1,10 @@
|
|||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines: list[str] = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
sections: list[tuple[tuple[int, int], tuple[int, int]]] = [
|
||||||
class Solver(BaseSolver):
|
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
lines = input.splitlines()
|
|
||||||
|
|
||||||
sections: list[tuple[tuple[int, int], tuple[int, int]]] = [
|
|
||||||
(
|
(
|
||||||
(
|
(
|
||||||
int(line.split(" -> ")[0].split(",")[0]),
|
int(line.split(" -> ")[0].split(",")[0]),
|
||||||
@@ -21,19 +16,21 @@ class Solver(BaseSolver):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
for line in lines
|
for line in lines
|
||||||
]
|
]
|
||||||
|
|
||||||
np_sections = np.array(sections).reshape(-1, 4)
|
np_sections = np.array(sections).reshape(-1, 4)
|
||||||
|
|
||||||
x_max, y_max = (
|
x_min, x_max, y_min, y_max = (
|
||||||
|
min(np_sections[:, 0].min(), np_sections[:, 2].min()),
|
||||||
max(np_sections[:, 0].max(), np_sections[:, 2].max()),
|
max(np_sections[:, 0].max(), np_sections[:, 2].max()),
|
||||||
|
min(np_sections[:, 1].min(), np_sections[:, 3].min()),
|
||||||
max(np_sections[:, 1].max(), np_sections[:, 3].max()),
|
max(np_sections[:, 1].max(), np_sections[:, 3].max()),
|
||||||
)
|
)
|
||||||
|
|
||||||
counts_1 = np.zeros((y_max + 1, x_max + 1), dtype=int)
|
counts_1 = np.zeros((y_max + 1, x_max + 1), dtype=int)
|
||||||
counts_2 = counts_1.copy()
|
counts_2 = counts_1.copy()
|
||||||
|
|
||||||
for (x1, y1), (x2, y2) in sections:
|
for (x1, y1), (x2, y2) in sections:
|
||||||
x_rng = range(x1, x2 + 1, 1) if x2 >= x1 else range(x1, x2 - 1, -1)
|
x_rng = range(x1, x2 + 1, 1) if x2 >= x1 else range(x1, x2 - 1, -1)
|
||||||
y_rng = range(y1, y2 + 1, 1) if y2 >= y1 else range(y1, y2 - 1, -1)
|
y_rng = range(y1, y2 + 1, 1) if y2 >= y1 else range(y1, y2 - 1, -1)
|
||||||
|
|
||||||
@@ -44,5 +41,8 @@ class Solver(BaseSolver):
|
|||||||
for i, j in zip(y_rng, x_rng):
|
for i, j in zip(y_rng, x_rng):
|
||||||
counts_2[i, j] += 1
|
counts_2[i, j] += 1
|
||||||
|
|
||||||
yield (counts_1 >= 2).sum()
|
answer_1 = (counts_1 >= 2).sum()
|
||||||
yield (counts_2 >= 2).sum()
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
|
answer_2 = (counts_2 >= 2).sum()
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
from ..base import BaseSolver
|
values = [int(c) for c in sys.stdin.read().strip().split(",")]
|
||||||
|
|
||||||
|
days = 256
|
||||||
class Solver(BaseSolver):
|
lanterns = {day: 0 for day in range(days)}
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
for value in values:
|
||||||
values = [int(c) for c in input.split(",")]
|
|
||||||
|
|
||||||
days = 256
|
|
||||||
lanterns = {day: 0 for day in range(days)}
|
|
||||||
for value in values:
|
|
||||||
for day in range(value, days, 7):
|
for day in range(value, days, 7):
|
||||||
lanterns[day] += 1
|
lanterns[day] += 1
|
||||||
|
|
||||||
for day in range(days):
|
for day in range(days):
|
||||||
for day2 in range(day + 9, days, 7):
|
for day2 in range(day + 9, days, 7):
|
||||||
lanterns[day2] += lanterns[day]
|
lanterns[day2] += lanterns[day]
|
||||||
|
|
||||||
yield sum(v for k, v in lanterns.items() if k < 80) + len(values)
|
# part 1
|
||||||
yield sum(lanterns.values()) + len(values)
|
answer_1 = sum(v for k, v in lanterns.items() if k < 80) + len(values)
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
|
# part 2
|
||||||
|
answer_2 = sum(lanterns.values()) + len(values)
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,22 +1,19 @@
|
|||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
from ..base import BaseSolver
|
positions = [int(c) for c in sys.stdin.read().strip().split(",")]
|
||||||
|
|
||||||
|
min_position, max_position = min(positions), max(positions)
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
# part 1
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
answer_1 = min(
|
||||||
positions = [int(c) for c in input.split(",")]
|
|
||||||
|
|
||||||
min_position, max_position = min(positions), max(positions)
|
|
||||||
|
|
||||||
# part 1
|
|
||||||
yield min(
|
|
||||||
sum(abs(p - position) for p in positions)
|
sum(abs(p - position) for p in positions)
|
||||||
for position in range(min_position, max_position + 1)
|
for position in range(min_position, max_position + 1)
|
||||||
)
|
)
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
# part 2
|
# part 2
|
||||||
yield min(
|
answer_2 = min(
|
||||||
sum(abs(p - position) * (abs(p - position) + 1) // 2 for p in positions)
|
sum(abs(p - position) * (abs(p - position) + 1) // 2 for p in positions)
|
||||||
for position in range(min_position, max_position + 1)
|
for position in range(min_position, max_position + 1)
|
||||||
)
|
)
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import itertools
|
import itertools
|
||||||
from typing import Any, Iterator
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
from ..base import BaseSolver
|
VERBOSE = os.getenv("AOC_VERBOSE") == "True"
|
||||||
|
|
||||||
digits = {
|
digits = {
|
||||||
"abcefg": 0,
|
"abcefg": 0,
|
||||||
@@ -16,23 +17,19 @@ digits = {
|
|||||||
"abcdfg": 9,
|
"abcdfg": 9,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
# part 1
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
lengths = {len(k) for k, v in digits.items() if v in (1, 4, 7, 8)}
|
||||||
lines = input.splitlines()
|
answer_1 = sum(
|
||||||
|
len(p) in lengths for line in lines for p in line.split("|")[1].strip().split()
|
||||||
|
)
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
# part 1
|
# part 2
|
||||||
lengths = {len(k) for k, v in digits.items() if v in (1, 4, 7, 8)}
|
values: list[int] = []
|
||||||
yield sum(
|
|
||||||
len(p) in lengths
|
|
||||||
for line in lines
|
|
||||||
for p in line.split("|")[1].strip().split()
|
|
||||||
)
|
|
||||||
|
|
||||||
# part 2
|
for line in lines:
|
||||||
values: list[int] = []
|
|
||||||
|
|
||||||
for line in lines:
|
|
||||||
parts = line.split("|")
|
parts = line.split("|")
|
||||||
broken_digits = sorted(parts[0].strip().split(), key=len)
|
broken_digits = sorted(parts[0].strip().split(), key=len)
|
||||||
|
|
||||||
@@ -52,9 +49,7 @@ class Solver(BaseSolver):
|
|||||||
bd = [u for u in per_length[4][0] if u not in cf]
|
bd = [u for u in per_length[4][0] if u not in cf]
|
||||||
|
|
||||||
# the 3 digits of length 5 have a, d and g in common
|
# the 3 digits of length 5 have a, d and g in common
|
||||||
adg = [
|
adg = [u for u in per_length[5][0] if all(u in pe for pe in per_length[5][1:])]
|
||||||
u for u in per_length[5][0] if all(u in pe for pe in per_length[5][1:])
|
|
||||||
]
|
|
||||||
|
|
||||||
# we can remove a
|
# we can remove a
|
||||||
dg = [u for u in adg if u != a]
|
dg = [u for u in adg if u != a]
|
||||||
@@ -82,8 +77,11 @@ class Solver(BaseSolver):
|
|||||||
digit = "".join(sorted(mapping[c] for c in number))
|
digit = "".join(sorted(mapping[c] for c in number))
|
||||||
value = 10 * value + digits[digit]
|
value = 10 * value + digits[digit]
|
||||||
|
|
||||||
self.logger.info(f"value for '{line}' is {value}")
|
if VERBOSE:
|
||||||
|
print(value)
|
||||||
|
|
||||||
values.append(value)
|
values.append(value)
|
||||||
|
|
||||||
yield sum(values)
|
|
||||||
|
answer_2 = sum(values)
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
|
import sys
|
||||||
from math import prod
|
from math import prod
|
||||||
from typing import Any, Iterator
|
|
||||||
|
|
||||||
from ..base import BaseSolver
|
values = [[int(c) for c in row] for row in sys.stdin.read().splitlines()]
|
||||||
|
n_rows, n_cols = len(values), len(values[0])
|
||||||
|
|
||||||
|
|
||||||
def neighbors(point: tuple[int, int], n_rows: int, n_cols: int):
|
def neighbors(point: tuple[int, int]):
|
||||||
i, j = point
|
i, j = point
|
||||||
for di, dj in ((-1, 0), (+1, 0), (0, -1), (0, +1)):
|
for di, dj in ((-1, 0), (+1, 0), (0, -1), (0, +1)):
|
||||||
if 0 <= i + di < n_rows and 0 <= j + dj < n_cols:
|
if 0 <= i + di < n_rows and 0 <= j + dj < n_cols:
|
||||||
yield (i + di, j + dj)
|
yield (i + di, j + dj)
|
||||||
|
|
||||||
|
|
||||||
def basin(values: list[list[int]], start: tuple[int, int]) -> set[tuple[int, int]]:
|
def basin(start: tuple[int, int]) -> set[tuple[int, int]]:
|
||||||
n_rows, n_cols = len(values), len(values[0])
|
|
||||||
visited: set[tuple[int, int]] = set()
|
visited: set[tuple[int, int]] = set()
|
||||||
queue = [start]
|
queue = [start]
|
||||||
|
|
||||||
@@ -23,25 +23,22 @@ def basin(values: list[list[int]], start: tuple[int, int]) -> set[tuple[int, int
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
visited.add((i, j))
|
visited.add((i, j))
|
||||||
queue.extend(neighbors((i, j), n_rows, n_cols))
|
queue.extend(neighbors((i, j)))
|
||||||
|
|
||||||
return visited
|
return visited
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
low_points = [
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
values = [[int(c) for c in row] for row in input.splitlines()]
|
|
||||||
n_rows, n_cols = len(values), len(values[0])
|
|
||||||
|
|
||||||
low_points = [
|
|
||||||
(i, j)
|
(i, j)
|
||||||
for i in range(n_rows)
|
for i in range(n_rows)
|
||||||
for j in range(n_cols)
|
for j in range(n_cols)
|
||||||
if all(
|
if all(values[ti][tj] > values[i][j] for ti, tj in neighbors((i, j)))
|
||||||
values[ti][tj] > values[i][j]
|
]
|
||||||
for ti, tj in neighbors((i, j), n_rows, n_cols)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
yield sum(values[i][j] + 1 for i, j in low_points)
|
# part 1
|
||||||
yield prod(sorted(len(basin(values, point)) for point in low_points)[-3:])
|
answer_1 = sum(values[i][j] + 1 for i, j in low_points)
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
|
# part 2
|
||||||
|
answer_2 = prod(sorted(len(basin(point)) for point in low_points)[-3:])
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,12 +1,7 @@
|
|||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
from ..base import BaseSolver
|
blocks = sys.stdin.read().split("\n\n")
|
||||||
|
values = sorted(sum(map(int, block.split())) for block in blocks)
|
||||||
|
|
||||||
|
print(f"answer 1 is {values[-1]}")
|
||||||
class Solver(BaseSolver):
|
print(f"answer 2 is {sum(values[-3:])}")
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
blocks = input.split("\n\n")
|
|
||||||
values = sorted(sum(map(int, block.split())) for block in blocks)
|
|
||||||
|
|
||||||
yield values[-1]
|
|
||||||
yield sum(values[-3:])
|
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
cycle = 1
|
||||||
|
x = 1
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
values = {cycle: x}
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
lines = [line.strip() for line in input.splitlines()]
|
|
||||||
|
|
||||||
cycle, x = 1, 1
|
for line in lines:
|
||||||
values = {cycle: x}
|
|
||||||
|
|
||||||
for line in lines:
|
|
||||||
cycle += 1
|
cycle += 1
|
||||||
|
|
||||||
if line == "noop":
|
if line == "noop":
|
||||||
@@ -25,19 +22,17 @@ class Solver(BaseSolver):
|
|||||||
|
|
||||||
values[cycle] = x
|
values[cycle] = x
|
||||||
|
|
||||||
answer_1 = sum(c * values[c] for c in range(20, max(values.keys()) + 1, 40))
|
answer_1 = sum(c * values[c] for c in range(20, max(values.keys()) + 1, 40))
|
||||||
yield answer_1
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
yield (
|
|
||||||
"\n"
|
for i in range(6):
|
||||||
+ "\n".join(
|
for j in range(40):
|
||||||
"".join(
|
v = values[1 + i * 40 + j]
|
||||||
"#"
|
|
||||||
if j >= (v := values[1 + i * 40 + j]) - 1 and j <= v + 1
|
if j >= v - 1 and j <= v + 1:
|
||||||
else "."
|
print("#", end="")
|
||||||
for j in range(40)
|
else:
|
||||||
)
|
print(".", end="")
|
||||||
for i in range(6)
|
|
||||||
)
|
print()
|
||||||
+ "\n"
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import copy
|
import copy
|
||||||
|
import sys
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
from typing import Any, Callable, Final, Iterator, Mapping, Sequence
|
from typing import Callable, Final, Mapping, Sequence
|
||||||
|
|
||||||
from ..base import BaseSolver
|
|
||||||
|
|
||||||
|
|
||||||
class Monkey:
|
class Monkey:
|
||||||
@@ -120,28 +119,24 @@ def monkey_business(inspects: dict[Monkey, int]) -> int:
|
|||||||
return sorted_levels[-2] * sorted_levels[-1]
|
return sorted_levels[-2] * sorted_levels[-1]
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
monkeys = [parse_monkey(block.splitlines()) for block in sys.stdin.read().split("\n\n")]
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
monkeys = [parse_monkey(block.splitlines()) for block in input.split("\n\n")]
|
|
||||||
|
|
||||||
# case 1: we simply divide the worry by 3 after applying the monkey worry operation
|
# case 1: we simply divide the worry by 3 after applying the monkey worry operation
|
||||||
yield monkey_business(
|
answer_1 = monkey_business(
|
||||||
run(copy.deepcopy(monkeys), 20, me_worry_fn=lambda w: w // 3)
|
run(copy.deepcopy(monkeys), 20, me_worry_fn=lambda w: w // 3)
|
||||||
)
|
)
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
# case 2: to keep reasonable level values, we can use a modulo operation, we need to
|
# case 2: to keep reasonable level values, we can use a modulo operation, we need to
|
||||||
# use the product of all "divisible by" test so that the test remains valid
|
# use the product of all "divisible by" test so that the test remains valid
|
||||||
#
|
#
|
||||||
# (a + b) % c == ((a % c) + (b % c)) % c --- this would work for a single test value
|
# (a + b) % c == ((a % c) + (b % c)) % c --- this would work for a single test value
|
||||||
#
|
#
|
||||||
# (a + b) % c == ((a % d) + (b % d)) % c --- if d is a multiple of c, which is why here
|
# (a + b) % c == ((a % d) + (b % d)) % c --- if d is a multiple of c, which is why here
|
||||||
# we use the product of all test value
|
# we use the product of all test value
|
||||||
#
|
#
|
||||||
total_test_value = reduce(lambda w, m: w * m.test_value, monkeys, 1)
|
total_test_value = reduce(lambda w, m: w * m.test_value, monkeys, 1)
|
||||||
yield monkey_business(
|
answer_2 = monkey_business(
|
||||||
run(
|
run(copy.deepcopy(monkeys), 10_000, me_worry_fn=lambda w: w % total_test_value)
|
||||||
copy.deepcopy(monkeys),
|
)
|
||||||
10_000,
|
print(f"answer 2 is {answer_2}")
|
||||||
me_worry_fn=lambda w: w % total_test_value,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import heapq
|
import heapq
|
||||||
from typing import Any, Callable, Iterator, TypeVar
|
import sys
|
||||||
|
from typing import Callable, Iterator, TypeVar
|
||||||
from ..base import BaseSolver
|
|
||||||
|
|
||||||
Node = TypeVar("Node")
|
Node = TypeVar("Node")
|
||||||
|
|
||||||
@@ -69,6 +68,30 @@ def make_path(parents: dict[Node, Node], start: Node, end: Node) -> list[Node] |
|
|||||||
return list(reversed(path))
|
return list(reversed(path))
|
||||||
|
|
||||||
|
|
||||||
|
def print_path(path: list[tuple[int, int]], n_rows: int, n_cols: int) -> None:
|
||||||
|
end = path[-1]
|
||||||
|
|
||||||
|
graph = [["." for _c in range(n_cols)] for _r in range(n_rows)]
|
||||||
|
graph[end[0]][end[1]] = "E"
|
||||||
|
|
||||||
|
for i in range(0, len(path) - 1):
|
||||||
|
cr, cc = path[i]
|
||||||
|
nr, nc = path[i + 1]
|
||||||
|
|
||||||
|
if cr == nr and nc == cc - 1:
|
||||||
|
graph[cr][cc] = "<"
|
||||||
|
elif cr == nr and nc == cc + 1:
|
||||||
|
graph[cr][cc] = ">"
|
||||||
|
elif cr == nr - 1 and nc == cc:
|
||||||
|
graph[cr][cc] = "v"
|
||||||
|
elif cr == nr + 1 and nc == cc:
|
||||||
|
graph[cr][cc] = "^"
|
||||||
|
else:
|
||||||
|
assert False, "{} -> {} infeasible".format(path[i], path[i + 1])
|
||||||
|
|
||||||
|
print("\n".join("".join(row) for row in graph))
|
||||||
|
|
||||||
|
|
||||||
def neighbors(
|
def neighbors(
|
||||||
grid: list[list[int]], node: tuple[int, int], up: bool
|
grid: list[list[int]], node: tuple[int, int], up: bool
|
||||||
) -> Iterator[tuple[int, int]]:
|
) -> Iterator[tuple[int, int]]:
|
||||||
@@ -95,52 +118,17 @@ def neighbors(
|
|||||||
|
|
||||||
# === main code ===
|
# === main code ===
|
||||||
|
|
||||||
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
grid = [[ord(cell) - ord("a") for cell in line] for line in lines]
|
||||||
def print_path(
|
|
||||||
self, name: str, path: list[tuple[int, int]], n_rows: int, n_cols: int
|
|
||||||
) -> None:
|
|
||||||
if not self.files:
|
|
||||||
return
|
|
||||||
|
|
||||||
end = path[-1]
|
start: tuple[int, int] | None = None
|
||||||
|
end: tuple[int, int] | None = None
|
||||||
|
|
||||||
graph = [["." for _c in range(n_cols)] for _r in range(n_rows)]
|
# for part 2
|
||||||
graph[end[0]][end[1]] = "E"
|
start_s: list[tuple[int, int]] = []
|
||||||
|
|
||||||
for i in range(0, len(path) - 1):
|
for i_row, row in enumerate(grid):
|
||||||
cr, cc = path[i]
|
|
||||||
nr, nc = path[i + 1]
|
|
||||||
|
|
||||||
if cr == nr and nc == cc - 1:
|
|
||||||
graph[cr][cc] = "<"
|
|
||||||
elif cr == nr and nc == cc + 1:
|
|
||||||
graph[cr][cc] = ">"
|
|
||||||
elif cr == nr - 1 and nc == cc:
|
|
||||||
graph[cr][cc] = "v"
|
|
||||||
elif cr == nr + 1 and nc == cc:
|
|
||||||
graph[cr][cc] = "^"
|
|
||||||
else:
|
|
||||||
assert False, "{} -> {} infeasible".format(path[i], path[i + 1])
|
|
||||||
|
|
||||||
self.files.create(
|
|
||||||
f"graph_{name}.txt",
|
|
||||||
"\n".join("".join(row) for row in graph).encode(),
|
|
||||||
text=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
lines = input.splitlines()
|
|
||||||
|
|
||||||
grid = [[ord(cell) - ord("a") for cell in line] for line in lines]
|
|
||||||
|
|
||||||
start: tuple[int, int] | None = None
|
|
||||||
end: tuple[int, int] | None = None
|
|
||||||
|
|
||||||
# for part 2
|
|
||||||
start_s: list[tuple[int, int]] = []
|
|
||||||
|
|
||||||
for i_row, row in enumerate(grid):
|
|
||||||
for i_col, col in enumerate(row):
|
for i_col, col in enumerate(row):
|
||||||
if chr(col + ord("a")) == "S":
|
if chr(col + ord("a")) == "S":
|
||||||
start = (i_row, i_col)
|
start = (i_row, i_col)
|
||||||
@@ -150,27 +138,26 @@ class Solver(BaseSolver):
|
|||||||
elif col == 0:
|
elif col == 0:
|
||||||
start_s.append((i_row, i_col))
|
start_s.append((i_row, i_col))
|
||||||
|
|
||||||
assert start is not None
|
assert start is not None
|
||||||
assert end is not None
|
assert end is not None
|
||||||
|
|
||||||
# fix values
|
# fix values
|
||||||
grid[start[0]][start[1]] = 0
|
grid[start[0]][start[1]] = 0
|
||||||
grid[end[0]][end[1]] = ord("z") - ord("a")
|
grid[end[0]][end[1]] = ord("z") - ord("a")
|
||||||
|
|
||||||
lengths_1, parents_1 = dijkstra(
|
|
||||||
start=start,
|
|
||||||
neighbors=lambda n: neighbors(grid, n, True),
|
|
||||||
cost=lambda lhs, rhs: 1,
|
|
||||||
)
|
|
||||||
path_1 = make_path(parents_1, start, end)
|
|
||||||
assert path_1 is not None
|
|
||||||
|
|
||||||
self.print_path("answer1", path_1, n_rows=len(grid), n_cols=len(grid[0]))
|
lengths_1, parents_1 = dijkstra(
|
||||||
yield lengths_1[end] - 1
|
start=start, neighbors=lambda n: neighbors(grid, n, True), cost=lambda lhs, rhs: 1
|
||||||
|
)
|
||||||
|
path_1 = make_path(parents_1, start, end)
|
||||||
|
assert path_1 is not None
|
||||||
|
|
||||||
lengths_2, _ = dijkstra(
|
print_path(path_1, n_rows=len(grid), n_cols=len(grid[0]))
|
||||||
start=end,
|
|
||||||
neighbors=lambda n: neighbors(grid, n, False),
|
print(f"answer 1 is {lengths_1[end] - 1}")
|
||||||
cost=lambda lhs, rhs: 1,
|
|
||||||
)
|
lengths_2, parents_2 = dijkstra(
|
||||||
yield min(lengths_2.get(start, float("inf")) for start in start_s)
|
start=end, neighbors=lambda n: neighbors(grid, n, False), cost=lambda lhs, rhs: 1
|
||||||
|
)
|
||||||
|
answer_2 = min(lengths_2.get(start, float("inf")) for start in start_s)
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
import json
|
import json
|
||||||
|
import sys
|
||||||
from functools import cmp_to_key
|
from functools import cmp_to_key
|
||||||
from typing import Any, Iterator, TypeAlias, cast
|
from typing import TypeAlias, cast
|
||||||
|
|
||||||
from ..base import BaseSolver
|
blocks = sys.stdin.read().strip().split("\n\n")
|
||||||
|
|
||||||
|
pairs = [tuple(json.loads(p) for p in block.split("\n")) for block in blocks]
|
||||||
|
|
||||||
Packet: TypeAlias = list[int | list["Packet"]]
|
Packet: TypeAlias = list[int | list["Packet"]]
|
||||||
|
|
||||||
@@ -25,18 +28,14 @@ def compare(lhs: Packet, rhs: Packet) -> int:
|
|||||||
return len(rhs) - len(lhs)
|
return len(rhs) - len(lhs)
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
answer_1 = sum(i + 1 for i, (lhs, rhs) in enumerate(pairs) if compare(lhs, rhs) > 0)
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
print(f"answer_1 is {answer_1}")
|
||||||
blocks = input.split("\n\n")
|
|
||||||
pairs = [tuple(json.loads(p) for p in block.split("\n")) for block in blocks]
|
|
||||||
|
|
||||||
yield sum(i + 1 for i, (lhs, rhs) in enumerate(pairs) if compare(lhs, rhs) > 0)
|
dividers = [[[2]], [[6]]]
|
||||||
|
|
||||||
dividers = [[[2]], [[6]]]
|
packets = [packet for packets in pairs for packet in packets]
|
||||||
|
packets.extend(dividers)
|
||||||
|
packets = list(reversed(sorted(packets, key=cmp_to_key(compare))))
|
||||||
|
|
||||||
packets = [packet for packets in pairs for packet in packets]
|
d_index = [packets.index(d) + 1 for d in dividers]
|
||||||
packets.extend(dividers)
|
print(f"answer 2 is {d_index[0] * d_index[1]}")
|
||||||
packets = list(reversed(sorted(packets, key=cmp_to_key(compare))))
|
|
||||||
|
|
||||||
d_index = [packets.index(d) + 1 for d in dividers]
|
|
||||||
yield d_index[0] * d_index[1]
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
|
import sys
|
||||||
from enum import Enum, auto
|
from enum import Enum, auto
|
||||||
from typing import Any, Callable, Iterator, cast
|
from typing import Callable, cast
|
||||||
|
|
||||||
from ..base import BaseSolver
|
|
||||||
|
|
||||||
|
|
||||||
class Cell(Enum):
|
class Cell(Enum):
|
||||||
@@ -13,6 +12,26 @@ class Cell(Enum):
|
|||||||
return {Cell.AIR: ".", Cell.ROCK: "#", Cell.SAND: "O"}[self]
|
return {Cell.AIR: ".", Cell.ROCK: "#", Cell.SAND: "O"}[self]
|
||||||
|
|
||||||
|
|
||||||
|
def print_blocks(blocks: dict[tuple[int, int], Cell]):
|
||||||
|
"""
|
||||||
|
Print the given set of blocks on a grid.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
blocks: Set of blocks to print.
|
||||||
|
"""
|
||||||
|
x_min, y_min, x_max, y_max = (
|
||||||
|
min(x for x, _ in blocks),
|
||||||
|
0,
|
||||||
|
max(x for x, _ in blocks),
|
||||||
|
max(y for _, y in blocks),
|
||||||
|
)
|
||||||
|
|
||||||
|
for y in range(y_min, y_max + 1):
|
||||||
|
print(
|
||||||
|
"".join(str(blocks.get((x, y), Cell.AIR)) for x in range(x_min, x_max + 1))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def flow(
|
def flow(
|
||||||
blocks: dict[tuple[int, int], Cell],
|
blocks: dict[tuple[int, int], Cell],
|
||||||
stop_fn: Callable[[int, int], bool],
|
stop_fn: Callable[[int, int], bool],
|
||||||
@@ -65,53 +84,21 @@ def flow(
|
|||||||
|
|
||||||
# === inputs ===
|
# === inputs ===
|
||||||
|
|
||||||
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
paths: list[list[tuple[int, int]]] = []
|
||||||
def print_blocks(self, name: str, blocks: dict[tuple[int, int], Cell]):
|
for line in lines:
|
||||||
"""
|
|
||||||
Print the given set of blocks on a grid.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
blocks: Set of blocks to print.
|
|
||||||
"""
|
|
||||||
if not self.files:
|
|
||||||
return
|
|
||||||
|
|
||||||
x_min, y_min, x_max, y_max = (
|
|
||||||
min(x for x, _ in blocks),
|
|
||||||
0,
|
|
||||||
max(x for x, _ in blocks),
|
|
||||||
max(y for _, y in blocks),
|
|
||||||
)
|
|
||||||
|
|
||||||
self.files.create(
|
|
||||||
f"blocks_{name}.txt",
|
|
||||||
"\n".join(
|
|
||||||
"".join(
|
|
||||||
str(blocks.get((x, y), Cell.AIR)) for x in range(x_min, x_max + 1)
|
|
||||||
)
|
|
||||||
for y in range(y_min, y_max + 1)
|
|
||||||
).encode(),
|
|
||||||
True,
|
|
||||||
)
|
|
||||||
|
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
lines = [line.strip() for line in input.splitlines()]
|
|
||||||
|
|
||||||
paths: list[list[tuple[int, int]]] = []
|
|
||||||
for line in lines:
|
|
||||||
parts = line.split(" -> ")
|
parts = line.split(" -> ")
|
||||||
paths.append(
|
paths.append(
|
||||||
[
|
[
|
||||||
cast(
|
cast(tuple[int, int], tuple(int(c.strip()) for c in part.split(",")))
|
||||||
tuple[int, int], tuple(int(c.strip()) for c in part.split(","))
|
|
||||||
)
|
|
||||||
for part in parts
|
for part in parts
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
blocks: dict[tuple[int, int], Cell] = {}
|
|
||||||
for path in paths:
|
blocks: dict[tuple[int, int], Cell] = {}
|
||||||
|
for path in paths:
|
||||||
for start, end in zip(path[:-1], path[1:]):
|
for start, end in zip(path[:-1], path[1:]):
|
||||||
x_start = min(start[0], end[0])
|
x_start = min(start[0], end[0])
|
||||||
x_end = max(start[0], end[0]) + 1
|
x_end = max(start[0], end[0]) + 1
|
||||||
@@ -122,25 +109,32 @@ class Solver(BaseSolver):
|
|||||||
for y in range(y_start, y_end):
|
for y in range(y_start, y_end):
|
||||||
blocks[x, y] = Cell.ROCK
|
blocks[x, y] = Cell.ROCK
|
||||||
|
|
||||||
self.print_blocks("start", blocks)
|
print_blocks(blocks)
|
||||||
|
print()
|
||||||
|
|
||||||
y_max = max(y for _, y in blocks)
|
x_min, y_min, x_max, y_max = (
|
||||||
|
min(x for x, _ in blocks),
|
||||||
|
0,
|
||||||
|
max(x for x, _ in blocks),
|
||||||
|
max(y for _, y in blocks),
|
||||||
|
)
|
||||||
|
|
||||||
# === part 1 ===
|
# === part 1 ===
|
||||||
|
|
||||||
blocks_1 = flow(
|
blocks_1 = flow(
|
||||||
blocks.copy(), stop_fn=lambda x, y: y > y_max, fill_fn=lambda x, y: Cell.AIR
|
blocks.copy(), stop_fn=lambda x, y: y > y_max, fill_fn=lambda x, y: Cell.AIR
|
||||||
)
|
)
|
||||||
self.print_blocks("part1", blocks_1)
|
print_blocks(blocks_1)
|
||||||
yield sum(v == Cell.SAND for v in blocks_1.values())
|
print(f"answer 1 is {sum(v == Cell.SAND for v in blocks_1.values())}")
|
||||||
|
print()
|
||||||
|
|
||||||
# === part 2 ===
|
# === part 2 ===
|
||||||
|
|
||||||
blocks_2 = flow(
|
blocks_2 = flow(
|
||||||
blocks.copy(),
|
blocks.copy(),
|
||||||
stop_fn=lambda x, y: x == 500 and y == 0,
|
stop_fn=lambda x, y: x == 500 and y == 0,
|
||||||
fill_fn=lambda x, y: Cell.AIR if y < y_max + 2 else Cell.ROCK,
|
fill_fn=lambda x, y: Cell.AIR if y < y_max + 2 else Cell.ROCK,
|
||||||
)
|
)
|
||||||
blocks_2[500, 0] = Cell.SAND
|
blocks_2[500, 0] = Cell.SAND
|
||||||
self.print_blocks("part2", blocks_2)
|
print_blocks(blocks_2)
|
||||||
yield sum(v == Cell.SAND for v in blocks_2.values())
|
print(f"answer 2 is {sum(v == Cell.SAND for v in blocks_2.values())}")
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import itertools as it
|
import sys
|
||||||
from typing import Any, Iterator
|
from typing import Any, Iterator
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
@@ -21,7 +21,9 @@ class Solver(BaseSolver):
|
|||||||
no_beacons_row_l.append(sx + np.arange(0, d - abs(sy - row) + 1)) # type: ignore
|
no_beacons_row_l.append(sx + np.arange(0, d - abs(sy - row) + 1)) # type: ignore
|
||||||
|
|
||||||
beacons_at_row = set(bx for (bx, by) in sensor_to_beacon.values() if by == row)
|
beacons_at_row = set(bx for (bx, by) in sensor_to_beacon.values() if by == row)
|
||||||
no_beacons_row = set(it.chain(*no_beacons_row_l)).difference(beacons_at_row) # type: ignore
|
no_beacons_row = set(np.concatenate(no_beacons_row_l)).difference(
|
||||||
|
beacons_at_row
|
||||||
|
) # type: ignore
|
||||||
|
|
||||||
return len(no_beacons_row)
|
return len(no_beacons_row)
|
||||||
|
|
||||||
@@ -60,9 +62,8 @@ class Solver(BaseSolver):
|
|||||||
for (sx, sy), (bx, by) in sensor_to_beacon.items():
|
for (sx, sy), (bx, by) in sensor_to_beacon.items():
|
||||||
d = abs(sx - bx) + abs(sy - by)
|
d = abs(sx - bx) + abs(sy - by)
|
||||||
m.add_constraint(
|
m.add_constraint(
|
||||||
m.abs(x - sx) + m.abs(y - sy) >= d + 1, # type: ignore
|
m.abs(x - sx) + m.abs(y - sy) >= d + 1, ctname=f"ct_{sx}_{sy}"
|
||||||
ctname=f"ct_{sx}_{sy}",
|
) # type: ignore
|
||||||
)
|
|
||||||
|
|
||||||
m.set_objective("min", x + y)
|
m.set_objective("min", x + y)
|
||||||
|
|
||||||
@@ -91,5 +92,5 @@ class Solver(BaseSolver):
|
|||||||
|
|
||||||
# x, y, a2 = part2_cplex(sensor_to_beacon, xy_max)
|
# x, y, a2 = part2_cplex(sensor_to_beacon, xy_max)
|
||||||
x, y, a2 = self.part2_intervals(sensor_to_beacon, xy_max)
|
x, y, a2 = self.part2_intervals(sensor_to_beacon, xy_max)
|
||||||
self.logger.info(f"answer 2 is {a2} (x={x}, y={y})")
|
self.logger.info("answer 2 is {at} (x={x}, y={y})")
|
||||||
yield a2
|
yield a2
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ from __future__ import annotations
|
|||||||
import heapq
|
import heapq
|
||||||
import itertools
|
import itertools
|
||||||
import re
|
import re
|
||||||
|
import sys
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from typing import Any, FrozenSet, Iterator, NamedTuple
|
from typing import FrozenSet, NamedTuple
|
||||||
|
|
||||||
from ..base import BaseSolver
|
from tqdm import tqdm
|
||||||
|
|
||||||
|
|
||||||
class Pipe(NamedTuple):
|
class Pipe(NamedTuple):
|
||||||
@@ -35,8 +36,8 @@ def breadth_first_search(pipes: dict[str, Pipe], pipe: Pipe) -> dict[Pipe, int]:
|
|||||||
Runs a BFS from the given pipe and return the shortest distance (in term of hops)
|
Runs a BFS from the given pipe and return the shortest distance (in term of hops)
|
||||||
to all other pipes.
|
to all other pipes.
|
||||||
"""
|
"""
|
||||||
queue = [(0, pipe)]
|
queue = [(0, pipe_1)]
|
||||||
visited: set[Pipe] = set()
|
visited = set()
|
||||||
distances: dict[Pipe, int] = {}
|
distances: dict[Pipe, int] = {}
|
||||||
|
|
||||||
while len(distances) < len(pipes):
|
while len(distances) < len(pipes):
|
||||||
@@ -60,17 +61,12 @@ def update_with_better(
|
|||||||
node_at_times[flowing] = max(node_at_times[flowing], flow)
|
node_at_times[flowing] = max(node_at_times[flowing], flow)
|
||||||
|
|
||||||
|
|
||||||
# === MAIN ===
|
def part_1(
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
|
||||||
def part_1(
|
|
||||||
self,
|
|
||||||
start_pipe: Pipe,
|
start_pipe: Pipe,
|
||||||
max_time: int,
|
max_time: int,
|
||||||
distances: dict[tuple[Pipe, Pipe], int],
|
distances: dict[tuple[Pipe, Pipe], int],
|
||||||
relevant_pipes: FrozenSet[Pipe],
|
relevant_pipes: FrozenSet[Pipe],
|
||||||
):
|
):
|
||||||
node_at_times: dict[int, dict[Pipe, dict[FrozenSet[Pipe], int]]] = defaultdict(
|
node_at_times: dict[int, dict[Pipe, dict[FrozenSet[Pipe], int]]] = defaultdict(
|
||||||
lambda: defaultdict(lambda: defaultdict(lambda: 0))
|
lambda: defaultdict(lambda: defaultdict(lambda: 0))
|
||||||
)
|
)
|
||||||
@@ -102,17 +98,15 @@ class Solver(BaseSolver):
|
|||||||
for flow in nodes_of_pipe.values()
|
for flow in nodes_of_pipe.values()
|
||||||
)
|
)
|
||||||
|
|
||||||
def part_2(
|
|
||||||
self,
|
def part_2(
|
||||||
start_pipe: Pipe,
|
start_pipe: Pipe,
|
||||||
max_time: int,
|
max_time: int,
|
||||||
distances: dict[tuple[Pipe, Pipe], int],
|
distances: dict[tuple[Pipe, Pipe], int],
|
||||||
relevant_pipes: FrozenSet[Pipe],
|
relevant_pipes: FrozenSet[Pipe],
|
||||||
):
|
):
|
||||||
def compute(pipes_for_me: FrozenSet[Pipe]) -> int:
|
def compute(pipes_for_me: FrozenSet[Pipe]) -> int:
|
||||||
return self.part_1(
|
return part_1(start_pipe, max_time, distances, pipes_for_me) + part_1(
|
||||||
start_pipe, max_time, distances, pipes_for_me
|
|
||||||
) + self.part_1(
|
|
||||||
start_pipe, max_time, distances, relevant_pipes - pipes_for_me
|
start_pipe, max_time, distances, relevant_pipes - pipes_for_me
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -122,13 +116,17 @@ class Solver(BaseSolver):
|
|||||||
for relevant_pipes_1 in itertools.combinations(relevant_pipes, r)
|
for relevant_pipes_1 in itertools.combinations(relevant_pipes, r)
|
||||||
]
|
]
|
||||||
|
|
||||||
return max(compute(comb) for comb in self.progress.wrap(combs))
|
return max(compute(comb) for comb in tqdm(combs))
|
||||||
|
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
lines = [line.strip() for line in input.splitlines()]
|
|
||||||
|
|
||||||
pipes: dict[str, Pipe] = {}
|
# === MAIN ===
|
||||||
for line in lines:
|
|
||||||
|
|
||||||
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
|
||||||
|
pipes: dict[str, Pipe] = {}
|
||||||
|
for line in lines:
|
||||||
r = re.match(
|
r = re.match(
|
||||||
R"Valve ([A-Z]+) has flow rate=([0-9]+); tunnels? leads? to valves? (.+)",
|
R"Valve ([A-Z]+) has flow rate=([0-9]+); tunnels? leads? to valves? (.+)",
|
||||||
line,
|
line,
|
||||||
@@ -139,9 +137,9 @@ class Solver(BaseSolver):
|
|||||||
|
|
||||||
pipes[g[0]] = Pipe(g[0], int(g[1]), g[2].split(", "))
|
pipes[g[0]] = Pipe(g[0], int(g[1]), g[2].split(", "))
|
||||||
|
|
||||||
# compute distances from one valve to any other
|
# compute distances from one valve to any other
|
||||||
distances: dict[tuple[Pipe, Pipe], int] = {}
|
distances: dict[tuple[Pipe, Pipe], int] = {}
|
||||||
for pipe_1 in pipes.values():
|
for pipe_1 in pipes.values():
|
||||||
distances.update(
|
distances.update(
|
||||||
{
|
{
|
||||||
(pipe_1, pipe_2): distance
|
(pipe_1, pipe_2): distance
|
||||||
@@ -149,11 +147,12 @@ class Solver(BaseSolver):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# valves with flow
|
# valves with flow
|
||||||
relevant_pipes = frozenset(pipe for pipe in pipes.values() if pipe.flow > 0)
|
relevant_pipes = frozenset(pipe for pipe in pipes.values() if pipe.flow > 0)
|
||||||
|
|
||||||
# 1651, 1653
|
|
||||||
yield self.part_1(pipes["AA"], 30, distances, relevant_pipes)
|
|
||||||
|
|
||||||
# 1707, 2223
|
# 1651, 1653
|
||||||
yield self.part_2(pipes["AA"], 26, distances, relevant_pipes)
|
print(part_1(pipes["AA"], 30, distances, relevant_pipes))
|
||||||
|
|
||||||
|
# 1707, 2223
|
||||||
|
print(part_2(pipes["AA"], 26, distances, relevant_pipes))
|
||||||
|
|||||||
@@ -1,16 +1,23 @@
|
|||||||
from typing import Any, Iterator, Sequence, TypeAlias, TypeVar
|
import sys
|
||||||
|
from typing import Sequence, TypeVar
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from numpy.typing import NDArray
|
|
||||||
|
|
||||||
from ..base import BaseSolver
|
|
||||||
|
|
||||||
T = TypeVar("T")
|
T = TypeVar("T")
|
||||||
|
|
||||||
Tower: TypeAlias = NDArray[np.bool]
|
|
||||||
|
def print_tower(tower: np.ndarray, out: str = "#"):
|
||||||
|
print("-" * (tower.shape[1] + 2))
|
||||||
|
non_empty = False
|
||||||
|
for row in reversed(range(1, tower.shape[0])):
|
||||||
|
if not non_empty and not tower[row, :].any():
|
||||||
|
continue
|
||||||
|
non_empty = True
|
||||||
|
print("|" + "".join(out if c else "." for c in tower[row, :]) + "|")
|
||||||
|
print("+" + "-" * tower.shape[1] + "+")
|
||||||
|
|
||||||
|
|
||||||
def tower_height(tower: Tower) -> int:
|
def tower_height(tower: np.ndarray) -> int:
|
||||||
return int(tower.shape[0] - tower[::-1, :].argmax(axis=0).min() - 1)
|
return int(tower.shape[0] - tower[::-1, :].argmax(axis=0).min() - 1)
|
||||||
|
|
||||||
|
|
||||||
@@ -38,8 +45,8 @@ def build_tower(
|
|||||||
n_rocks: int,
|
n_rocks: int,
|
||||||
jets: str,
|
jets: str,
|
||||||
early_stop: bool = False,
|
early_stop: bool = False,
|
||||||
init: Tower = np.ones(WIDTH, dtype=bool),
|
init: np.ndarray = np.ones(WIDTH, dtype=bool),
|
||||||
) -> tuple[Tower, int, int, dict[int, int]]:
|
) -> tuple[np.ndarray, int, int, dict[int, int]]:
|
||||||
tower = EMPTY_BLOCKS.copy()
|
tower = EMPTY_BLOCKS.copy()
|
||||||
tower[0, :] = init
|
tower[0, :] = init
|
||||||
|
|
||||||
@@ -88,24 +95,26 @@ def build_tower(
|
|||||||
return tower, rock_count, done_at.get((i_rock, i_jet), -1), heights
|
return tower, rock_count, done_at.get((i_rock, i_jet), -1), heights
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
line = sys.stdin.read().strip()
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
tower, *_ = build_tower(2022, input)
|
|
||||||
yield tower_height(tower)
|
|
||||||
|
|
||||||
TOTAL_ROCKS = 1_000_000_000_000
|
tower, *_ = build_tower(2022, line)
|
||||||
_tower_1, n_rocks_1, prev_1, heights_1 = build_tower(TOTAL_ROCKS, input, True)
|
answer_1 = tower_height(tower)
|
||||||
assert prev_1 > 0
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
# 2767 1513
|
TOTAL_ROCKS = 1_000_000_000_000
|
||||||
remaining_rocks = TOTAL_ROCKS - n_rocks_1
|
tower_1, n_rocks_1, prev_1, heights_1 = build_tower(TOTAL_ROCKS, line, True)
|
||||||
n_repeat_rocks = n_rocks_1 - prev_1
|
assert prev_1 > 0
|
||||||
n_repeat_towers = remaining_rocks // n_repeat_rocks
|
|
||||||
|
|
||||||
base_height = heights_1[prev_1]
|
# 2767 1513
|
||||||
repeat_height = heights_1[prev_1 + n_repeat_rocks - 1] - heights_1[prev_1]
|
remaining_rocks = TOTAL_ROCKS - n_rocks_1
|
||||||
remaining_height = (
|
n_repeat_rocks = n_rocks_1 - prev_1
|
||||||
|
n_repeat_towers = remaining_rocks // n_repeat_rocks
|
||||||
|
|
||||||
|
base_height = heights_1[prev_1]
|
||||||
|
repeat_height = heights_1[prev_1 + n_repeat_rocks - 1] - heights_1[prev_1]
|
||||||
|
remaining_height = (
|
||||||
heights_1[prev_1 + remaining_rocks % n_repeat_rocks] - heights_1[prev_1]
|
heights_1[prev_1 + remaining_rocks % n_repeat_rocks] - heights_1[prev_1]
|
||||||
)
|
)
|
||||||
|
|
||||||
yield base_height + (n_repeat_towers + 1) * repeat_height + remaining_height
|
answer_2 = base_height + (n_repeat_towers + 1) * repeat_height + remaining_height
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,38 +1,33 @@
|
|||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from ..base import BaseSolver
|
xyz = np.asarray(
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
xyz = np.asarray(
|
|
||||||
[
|
[
|
||||||
tuple(int(x) for x in row.split(",")) # type: ignore
|
tuple(int(x) for x in row.split(",")) # type: ignore
|
||||||
for row in input.splitlines()
|
for row in sys.stdin.read().splitlines()
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
xyz = xyz - xyz.min(axis=0) + 1
|
xyz = xyz - xyz.min(axis=0) + 1
|
||||||
|
|
||||||
cubes = np.zeros(xyz.max(axis=0) + 3, dtype=bool)
|
cubes = np.zeros(xyz.max(axis=0) + 3, dtype=bool)
|
||||||
cubes[xyz[:, 0], xyz[:, 1], xyz[:, 2]] = True
|
cubes[xyz[:, 0], xyz[:, 1], xyz[:, 2]] = True
|
||||||
|
|
||||||
faces = [(-1, 0, 0), (1, 0, 0), (0, -1, 0), (0, 1, 0), (0, 0, -1), (0, 0, 1)]
|
n_dims = len(cubes.shape)
|
||||||
|
|
||||||
yield sum(
|
faces = [(-1, 0, 0), (1, 0, 0), (0, -1, 0), (0, 1, 0), (0, 0, -1), (0, 0, 1)]
|
||||||
1
|
|
||||||
for x, y, z in xyz
|
|
||||||
for dx, dy, dz in faces
|
|
||||||
if not cubes[x + dx, y + dy, z + dz]
|
|
||||||
)
|
|
||||||
|
|
||||||
visited = np.zeros_like(cubes, dtype=bool)
|
answer_1 = sum(
|
||||||
queue = [(0, 0, 0)]
|
1 for x, y, z in xyz for dx, dy, dz in faces if not cubes[x + dx, y + dy, z + dz]
|
||||||
|
)
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
n_faces = 0
|
visited = np.zeros_like(cubes, dtype=bool)
|
||||||
while queue:
|
queue = [(0, 0, 0)]
|
||||||
|
|
||||||
|
n_faces = 0
|
||||||
|
while queue:
|
||||||
x, y, z = queue.pop(0)
|
x, y, z = queue.pop(0)
|
||||||
|
|
||||||
if visited[x, y, z]:
|
if visited[x, y, z]:
|
||||||
@@ -42,9 +37,7 @@ class Solver(BaseSolver):
|
|||||||
|
|
||||||
for dx, dy, dz in faces:
|
for dx, dy, dz in faces:
|
||||||
nx, ny, nz = x + dx, y + dy, z + dz
|
nx, ny, nz = x + dx, y + dy, z + dz
|
||||||
if not all(
|
if not all(n >= 0 and n < cubes.shape[i] for i, n in enumerate((nx, ny, nz))):
|
||||||
n >= 0 and n < cubes.shape[i] for i, n in enumerate((nx, ny, nz))
|
|
||||||
):
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if visited[nx, ny, nz]:
|
if visited[nx, ny, nz]:
|
||||||
@@ -54,5 +47,4 @@ class Solver(BaseSolver):
|
|||||||
n_faces += 1
|
n_faces += 1
|
||||||
else:
|
else:
|
||||||
queue.append((nx, ny, nz))
|
queue.append((nx, ny, nz))
|
||||||
|
print(f"answer 2 is {n_faces}")
|
||||||
yield n_faces
|
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
from typing import Any, Iterator, Literal
|
import sys
|
||||||
|
from typing import Any, Literal
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import parse # pyright: ignore[reportMissingTypeStubs]
|
import parse # pyright: ignore[reportMissingTypeStubs]
|
||||||
from numpy.typing import NDArray
|
from numpy.typing import NDArray
|
||||||
|
|
||||||
from ..base import BaseSolver
|
|
||||||
|
|
||||||
Reagent = Literal["ore", "clay", "obsidian", "geode"]
|
Reagent = Literal["ore", "clay", "obsidian", "geode"]
|
||||||
REAGENTS: tuple[Reagent, ...] = (
|
REAGENTS: tuple[Reagent, ...] = (
|
||||||
"ore",
|
"ore",
|
||||||
@@ -63,6 +62,29 @@ def dominates(lhs: State, rhs: State):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
blueprints: list[dict[Reagent, IntOfReagent]] = []
|
||||||
|
for line in lines:
|
||||||
|
r: list[int] = parse.parse( # type: ignore
|
||||||
|
"Blueprint {}: "
|
||||||
|
"Each ore robot costs {:d} ore. "
|
||||||
|
"Each clay robot costs {:d} ore. "
|
||||||
|
"Each obsidian robot costs {:d} ore and {:d} clay. "
|
||||||
|
"Each geode robot costs {:d} ore and {:d} obsidian.",
|
||||||
|
line,
|
||||||
|
)
|
||||||
|
|
||||||
|
blueprints.append(
|
||||||
|
{
|
||||||
|
"ore": {"ore": r[1]},
|
||||||
|
"clay": {"ore": r[2]},
|
||||||
|
"obsidian": {"ore": r[3], "clay": r[4]},
|
||||||
|
"geode": {"ore": r[5], "obsidian": r[6]},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def run(blueprint: dict[Reagent, dict[Reagent, int]], max_time: int) -> int:
|
def run(blueprint: dict[Reagent, dict[Reagent, int]], max_time: int) -> int:
|
||||||
# since we can only build one robot per time, we do not need more than X robots
|
# since we can only build one robot per time, we do not need more than X robots
|
||||||
# of type K where X is the maximum number of K required among all robots, e.g.,
|
# of type K where X is the maximum number of K required among all robots, e.g.,
|
||||||
@@ -151,31 +173,11 @@ def run(blueprint: dict[Reagent, dict[Reagent, int]], max_time: int) -> int:
|
|||||||
return max(state.reagents["geode"] for state in state_after_t[max_time])
|
return max(state.reagents["geode"] for state in state_after_t[max_time])
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
answer_1 = sum(
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
blueprints: list[dict[Reagent, IntOfReagent]] = []
|
|
||||||
for line in input.splitlines():
|
|
||||||
r: list[int] = parse.parse( # type: ignore
|
|
||||||
"Blueprint {}: "
|
|
||||||
"Each ore robot costs {:d} ore. "
|
|
||||||
"Each clay robot costs {:d} ore. "
|
|
||||||
"Each obsidian robot costs {:d} ore and {:d} clay. "
|
|
||||||
"Each geode robot costs {:d} ore and {:d} obsidian.",
|
|
||||||
line,
|
|
||||||
)
|
|
||||||
|
|
||||||
blueprints.append(
|
|
||||||
{
|
|
||||||
"ore": {"ore": r[1]},
|
|
||||||
"clay": {"ore": r[2]},
|
|
||||||
"obsidian": {"ore": r[3], "clay": r[4]},
|
|
||||||
"geode": {"ore": r[5], "obsidian": r[6]},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
yield sum(
|
|
||||||
(i_blueprint + 1) * run(blueprint, 24)
|
(i_blueprint + 1) * run(blueprint, 24)
|
||||||
for i_blueprint, blueprint in enumerate(blueprints)
|
for i_blueprint, blueprint in enumerate(blueprints)
|
||||||
)
|
)
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
yield (run(blueprints[0], 32) * run(blueprints[1], 32) * run(blueprints[2], 32))
|
answer_2 = run(blueprints[0], 32) * run(blueprints[1], 32) * run(blueprints[2], 32)
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
from ..base import BaseSolver
|
|
||||||
|
|
||||||
|
|
||||||
def score_1(ux: int, vx: int) -> int:
|
def score_1(ux: int, vx: int) -> int:
|
||||||
@@ -35,23 +33,21 @@ def score_2(ux: int, vx: int) -> int:
|
|||||||
return (ux + vx - 1) % 3 + 1 + vx * 3
|
return (ux + vx - 1) % 3 + 1 + vx * 3
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
lines = sys.stdin.readlines()
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
lines = input.splitlines()
|
|
||||||
|
|
||||||
# the solution relies on replacing rock / paper / scissor by values 0 / 1 / 2 and using
|
# the solution relies on replacing rock / paper / scissor by values 0 / 1 / 2 and using
|
||||||
# modulo-3 arithmetic
|
# modulo-3 arithmetic
|
||||||
#
|
#
|
||||||
# in modulo-3 arithmetic, the winning move is 1 + the opponent move (e.g., winning move
|
# in modulo-3 arithmetic, the winning move is 1 + the opponent move (e.g., winning move
|
||||||
# if opponent plays 0 is 1, or 0 if opponent plays 2 (0 = (2 + 1 % 3)))
|
# if opponent plays 0 is 1, or 0 if opponent plays 2 (0 = (2 + 1 % 3)))
|
||||||
#
|
#
|
||||||
|
|
||||||
# we read the lines in a Nx2 in array with value 0/1/2 instead of A/B/C or X/Y/Z for
|
# we read the lines in a Nx2 in array with value 0/1/2 instead of A/B/C or X/Y/Z for
|
||||||
# easier manipulation
|
# easier manipulation
|
||||||
values = [(ord(row[0]) - ord("A"), ord(row[2]) - ord("X")) for row in lines]
|
values = [(ord(row[0]) - ord("A"), ord(row[2]) - ord("X")) for row in lines]
|
||||||
|
|
||||||
# part 1 - 13526
|
# part 1 - 13526
|
||||||
yield sum(score_1(*v) for v in values)
|
print(f"answer 1 is {sum(score_1(*v) for v in values)}")
|
||||||
|
|
||||||
# part 2 - 14204
|
# part 2 - 14204
|
||||||
yield sum(score_2(*v) for v in values)
|
print(f"answer 2 is {sum(score_2(*v) for v in values)}")
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
from ..base import BaseSolver
|
|
||||||
|
|
||||||
|
|
||||||
class Number:
|
class Number:
|
||||||
@@ -67,9 +65,10 @@ def decrypt(numbers: list[Number], key: int, rounds: int) -> int:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
numbers = [Number(int(x)) for i, x in enumerate(sys.stdin.readlines())]
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
numbers = [Number(int(x)) for x in input.splitlines()]
|
|
||||||
|
|
||||||
yield decrypt(numbers, 1, 1)
|
answer_1 = decrypt(numbers, 1, 1)
|
||||||
yield decrypt(numbers, 811589153, 10)
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
|
answer_2 = decrypt(numbers, 811589153, 10)
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import operator
|
import operator
|
||||||
from typing import Any, Callable, Iterator
|
import sys
|
||||||
|
from typing import Callable
|
||||||
from ..base import BaseSolver
|
|
||||||
|
|
||||||
|
|
||||||
def compute(monkeys: dict[str, int | tuple[str, str, str]], monkey: str) -> int:
|
def compute(monkeys: dict[str, int | tuple[str, str, str]], monkey: str) -> int:
|
||||||
@@ -78,15 +77,13 @@ def invert(
|
|||||||
return monkeys
|
return monkeys
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
lines = sys.stdin.read().splitlines()
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
lines = [line.strip() for line in input.splitlines()]
|
|
||||||
|
|
||||||
monkeys: dict[str, int | tuple[str, str, str]] = {}
|
monkeys: dict[str, int | tuple[str, str, str]] = {}
|
||||||
|
|
||||||
op_monkeys: set[str] = set()
|
op_monkeys: set[str] = set()
|
||||||
|
|
||||||
for line in lines:
|
for line in lines:
|
||||||
parts = line.split(":")
|
parts = line.split(":")
|
||||||
name = parts[0].strip()
|
name = parts[0].strip()
|
||||||
|
|
||||||
@@ -99,10 +96,12 @@ class Solver(BaseSolver):
|
|||||||
|
|
||||||
op_monkeys.add(name)
|
op_monkeys.add(name)
|
||||||
|
|
||||||
yield compute(monkeys.copy(), "root")
|
|
||||||
|
|
||||||
# assume the second operand of 'root' can be computed, and the first one depends on
|
answer_1 = compute(monkeys.copy(), "root")
|
||||||
# humn, which is the case is my input and the test input
|
print(f"answer 1 is {answer_1}")
|
||||||
assert isinstance(monkeys["root"], tuple)
|
|
||||||
p1, _, p2 = monkeys["root"] # type: ignore
|
# assume the second operand of 'root' can be computed, and the first one depends on
|
||||||
yield compute(invert(monkeys, "humn", compute(monkeys.copy(), p2)), "humn")
|
# humn, which is the case is my input and the test input
|
||||||
|
p1, _, p2 = monkeys["root"] # type: ignore
|
||||||
|
answer_2 = compute(invert(monkeys, "humn", compute(monkeys.copy(), p2)), "humn")
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,57 +1,51 @@
|
|||||||
import re
|
import re
|
||||||
from typing import Any, Callable, Iterator
|
import sys
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from ..base import BaseSolver
|
|
||||||
|
|
||||||
VOID, EMPTY, WALL = 0, 1, 2
|
VOID, EMPTY, WALL = 0, 1, 2
|
||||||
TILE_FROM_CHAR = {" ": VOID, ".": EMPTY, "#": WALL}
|
TILE_FROM_CHAR = {" ": VOID, ".": EMPTY, "#": WALL}
|
||||||
|
|
||||||
SCORES = {"E": 0, "S": 1, "W": 2, "N": 3}
|
SCORES = {"E": 0, "S": 1, "W": 2, "N": 3}
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
board_map_s, direction_s = sys.stdin.read().split("\n\n")
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
board_map_s, direction_s = input.split("\n\n")
|
|
||||||
|
|
||||||
# board
|
# board
|
||||||
board_lines = board_map_s.splitlines()
|
board_lines = board_map_s.splitlines()
|
||||||
max_line = max(len(line) for line in board_lines)
|
max_line = max(len(line) for line in board_lines)
|
||||||
board = np.array(
|
board = np.array(
|
||||||
[
|
[
|
||||||
[TILE_FROM_CHAR[c] for c in row] + [VOID] * (max_line - len(row))
|
[TILE_FROM_CHAR[c] for c in row] + [VOID] * (max_line - len(row))
|
||||||
for row in board_map_s.splitlines()
|
for row in board_map_s.splitlines()
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
directions = [
|
directions = [
|
||||||
int(p1) if p2 else p1
|
int(p1) if p2 else p1 for p1, p2 in re.findall(R"(([0-9])+|L|R)", direction_s)
|
||||||
for p1, p2 in re.findall(R"(([0-9])+|L|R)", direction_s)
|
]
|
||||||
]
|
|
||||||
|
|
||||||
# find on each row and column the first and last non-void
|
|
||||||
row_first_non_void = np.argmax(board != VOID, axis=1)
|
|
||||||
row_last_non_void = (
|
|
||||||
board.shape[1] - np.argmax(board[:, ::-1] != VOID, axis=1) - 1
|
|
||||||
)
|
|
||||||
col_first_non_void = np.argmax(board != VOID, axis=0)
|
|
||||||
col_last_non_void = (
|
|
||||||
board.shape[0] - np.argmax(board[::-1, :] != VOID, axis=0) - 1
|
|
||||||
)
|
|
||||||
|
|
||||||
faces = np.zeros_like(board)
|
# find on each row and column the first and last non-void
|
||||||
size = np.gcd(board.shape[0], board.shape[1])
|
row_first_non_void = np.argmax(board != VOID, axis=1)
|
||||||
for row in range(0, board.shape[0], size):
|
row_last_non_void = board.shape[1] - np.argmax(board[:, ::-1] != VOID, axis=1) - 1
|
||||||
|
col_first_non_void = np.argmax(board != VOID, axis=0)
|
||||||
|
col_last_non_void = board.shape[0] - np.argmax(board[::-1, :] != VOID, axis=0) - 1
|
||||||
|
|
||||||
|
|
||||||
|
faces = np.zeros_like(board)
|
||||||
|
size = np.gcd(board.shape[0], board.shape[1])
|
||||||
|
for row in range(0, board.shape[0], size):
|
||||||
for col in range(row_first_non_void[row], row_last_non_void[row], size):
|
for col in range(row_first_non_void[row], row_last_non_void[row], size):
|
||||||
faces[row : row + size, col : col + size] = faces.max() + 1
|
faces[row : row + size, col : col + size] = faces.max() + 1
|
||||||
|
|
||||||
SIZE = np.gcd(*board.shape)
|
SIZE = np.gcd(*board.shape)
|
||||||
|
|
||||||
# TODO: deduce this from the actual cube...
|
# TODO: deduce this from the actual cube...
|
||||||
faces_wrap: dict[int, dict[str, Callable[[int, int], tuple[int, int, str]]]]
|
faces_wrap: dict[int, dict[str, Callable[[int, int], tuple[int, int, str]]]]
|
||||||
|
|
||||||
if board.shape == (12, 16): # example
|
if board.shape == (12, 16): # example
|
||||||
faces_wrap = {
|
faces_wrap = {
|
||||||
1: {
|
1: {
|
||||||
"W": lambda y, x: (4, 4 + y, "S"), # 3N
|
"W": lambda y, x: (4, 4 + y, "S"), # 3N
|
||||||
@@ -79,7 +73,7 @@ class Solver(BaseSolver):
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
else:
|
else:
|
||||||
faces_wrap = {
|
faces_wrap = {
|
||||||
1: {
|
1: {
|
||||||
"W": lambda y, x: (3 * SIZE - y - 1, 0, "E"), # 4W
|
"W": lambda y, x: (3 * SIZE - y - 1, 0, "E"), # 4W
|
||||||
@@ -109,7 +103,8 @@ class Solver(BaseSolver):
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
def wrap_part_1(y0: int, x0: int, r0: str) -> tuple[int, int, str]:
|
|
||||||
|
def wrap_part_1(y0: int, x0: int, r0: str) -> tuple[int, int, str]:
|
||||||
if r0 == "E":
|
if r0 == "E":
|
||||||
return y0, row_first_non_void[y0], r0
|
return y0, row_first_non_void[y0], r0
|
||||||
elif r0 == "S":
|
elif r0 == "S":
|
||||||
@@ -121,14 +116,14 @@ class Solver(BaseSolver):
|
|||||||
|
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
def wrap_part_2(y0: int, x0: int, r0: str) -> tuple[int, int, str]:
|
|
||||||
|
def wrap_part_2(y0: int, x0: int, r0: str) -> tuple[int, int, str]:
|
||||||
cube = faces[y0, x0]
|
cube = faces[y0, x0]
|
||||||
assert r0 in faces_wrap[cube]
|
assert r0 in faces_wrap[cube]
|
||||||
return faces_wrap[cube][r0](y0, x0)
|
return faces_wrap[cube][r0](y0, x0)
|
||||||
|
|
||||||
def run(
|
|
||||||
wrap: Callable[[int, int, str], tuple[int, int, str]],
|
def run(wrap: Callable[[int, int, str], tuple[int, int, str]]) -> tuple[int, int, str]:
|
||||||
) -> tuple[int, int, str]:
|
|
||||||
y0 = 0
|
y0 = 0
|
||||||
x0 = np.where(board[0] == EMPTY)[0][0]
|
x0 = np.where(board[0] == EMPTY)[0][0]
|
||||||
r0 = "E"
|
r0 = "E"
|
||||||
@@ -137,9 +132,7 @@ class Solver(BaseSolver):
|
|||||||
if isinstance(direction, int):
|
if isinstance(direction, int):
|
||||||
while direction > 0:
|
while direction > 0:
|
||||||
if r0 == "E":
|
if r0 == "E":
|
||||||
xi = np.where(
|
xi = np.where(board[y0, x0 + 1 : x0 + direction + 1] == WALL)[0]
|
||||||
board[y0, x0 + 1 : x0 + direction + 1] == WALL
|
|
||||||
)[0]
|
|
||||||
if len(xi):
|
if len(xi):
|
||||||
x0 = x0 + xi[0]
|
x0 = x0 + xi[0]
|
||||||
direction = 0
|
direction = 0
|
||||||
@@ -155,14 +148,10 @@ class Solver(BaseSolver):
|
|||||||
x0 = row_last_non_void[y0]
|
x0 = row_last_non_void[y0]
|
||||||
direction = 0
|
direction = 0
|
||||||
else:
|
else:
|
||||||
direction = (
|
direction = direction - (row_last_non_void[y0] - x0) - 1
|
||||||
direction - (row_last_non_void[y0] - x0) - 1
|
|
||||||
)
|
|
||||||
y0, x0, r0 = y0_t, x0_t, r0_t
|
y0, x0, r0 = y0_t, x0_t, r0_t
|
||||||
elif r0 == "S":
|
elif r0 == "S":
|
||||||
yi = np.where(
|
yi = np.where(board[y0 + 1 : y0 + direction + 1, x0] == WALL)[0]
|
||||||
board[y0 + 1 : y0 + direction + 1, x0] == WALL
|
|
||||||
)[0]
|
|
||||||
if len(yi):
|
if len(yi):
|
||||||
y0 = y0 + yi[0]
|
y0 = y0 + yi[0]
|
||||||
direction = 0
|
direction = 0
|
||||||
@@ -178,9 +167,7 @@ class Solver(BaseSolver):
|
|||||||
y0 = col_last_non_void[x0]
|
y0 = col_last_non_void[x0]
|
||||||
direction = 0
|
direction = 0
|
||||||
else:
|
else:
|
||||||
direction = (
|
direction = direction - (col_last_non_void[x0] - y0) - 1
|
||||||
direction - (col_last_non_void[x0] - y0) - 1
|
|
||||||
)
|
|
||||||
y0, x0, r0 = y0_t, x0_t, r0_t
|
y0, x0, r0 = y0_t, x0_t, r0_t
|
||||||
elif r0 == "W":
|
elif r0 == "W":
|
||||||
left = max(x0 - direction - 1, 0)
|
left = max(x0 - direction - 1, 0)
|
||||||
@@ -188,10 +175,7 @@ class Solver(BaseSolver):
|
|||||||
if len(xi):
|
if len(xi):
|
||||||
x0 = left + xi[-1] + 1
|
x0 = left + xi[-1] + 1
|
||||||
direction = 0
|
direction = 0
|
||||||
elif (
|
elif x0 - direction >= 0 and board[y0, x0 - direction] == EMPTY:
|
||||||
x0 - direction >= 0
|
|
||||||
and board[y0, x0 - direction] == EMPTY
|
|
||||||
):
|
|
||||||
x0 = x0 - direction
|
x0 = x0 - direction
|
||||||
direction = 0
|
direction = 0
|
||||||
else:
|
else:
|
||||||
@@ -200,9 +184,7 @@ class Solver(BaseSolver):
|
|||||||
x0 = row_first_non_void[y0]
|
x0 = row_first_non_void[y0]
|
||||||
direction = 0
|
direction = 0
|
||||||
else:
|
else:
|
||||||
direction = (
|
direction = direction - (x0 - row_first_non_void[y0]) - 1
|
||||||
direction - (x0 - row_first_non_void[y0]) - 1
|
|
||||||
)
|
|
||||||
y0, x0, r0 = y0_t, x0_t, r0_t
|
y0, x0, r0 = y0_t, x0_t, r0_t
|
||||||
elif r0 == "N":
|
elif r0 == "N":
|
||||||
top = max(y0 - direction - 1, 0)
|
top = max(y0 - direction - 1, 0)
|
||||||
@@ -210,10 +192,7 @@ class Solver(BaseSolver):
|
|||||||
if len(yi):
|
if len(yi):
|
||||||
y0 = top + yi[-1] + 1
|
y0 = top + yi[-1] + 1
|
||||||
direction = 0
|
direction = 0
|
||||||
elif (
|
elif y0 - direction >= 0 and board[y0 - direction, x0] == EMPTY:
|
||||||
y0 - direction >= 0
|
|
||||||
and board[y0 - direction, x0] == EMPTY
|
|
||||||
):
|
|
||||||
y0 = y0 - direction
|
y0 = y0 - direction
|
||||||
direction = 0
|
direction = 0
|
||||||
else:
|
else:
|
||||||
@@ -222,9 +201,7 @@ class Solver(BaseSolver):
|
|||||||
y0 = col_first_non_void[x0]
|
y0 = col_first_non_void[x0]
|
||||||
direction = 0
|
direction = 0
|
||||||
else:
|
else:
|
||||||
direction = (
|
direction = direction - (y0 - col_first_non_void[x0]) - 1
|
||||||
direction - (y0 - col_first_non_void[x0]) - 1
|
|
||||||
)
|
|
||||||
y0, x0, r0 = y0_t, x0_t, r0_t
|
y0, x0, r0 = y0_t, x0_t, r0_t
|
||||||
else:
|
else:
|
||||||
r0 = {
|
r0 = {
|
||||||
@@ -236,8 +213,11 @@ class Solver(BaseSolver):
|
|||||||
|
|
||||||
return y0, x0, r0
|
return y0, x0, r0
|
||||||
|
|
||||||
y1, x1, r1 = run(wrap_part_1)
|
|
||||||
yield 1000 * (1 + y1) + 4 * (1 + x1) + SCORES[r1]
|
|
||||||
|
|
||||||
y2, x2, r2 = run(wrap_part_2)
|
y1, x1, r1 = run(wrap_part_1)
|
||||||
yield 1000 * (1 + y2) + 4 * (1 + x2) + SCORES[r2]
|
answer_1 = 1000 * (1 + y1) + 4 * (1 + x1) + SCORES[r1]
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
|
y2, x2, r2 = run(wrap_part_2)
|
||||||
|
answer_2 = 1000 * (1 + y2) + 4 * (1 + x2) + SCORES[r2]
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import itertools
|
import itertools
|
||||||
|
import sys
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from typing import Any, Iterator
|
|
||||||
|
|
||||||
from ..base import BaseSolver
|
|
||||||
|
|
||||||
Directions = list[
|
Directions = list[
|
||||||
tuple[
|
tuple[
|
||||||
@@ -20,10 +18,22 @@ DIRECTIONS: Directions = [
|
|||||||
|
|
||||||
|
|
||||||
def min_max_yx(positions: set[tuple[int, int]]) -> tuple[int, int, int, int]:
|
def min_max_yx(positions: set[tuple[int, int]]) -> tuple[int, int, int, int]:
|
||||||
ys, xs = {y for y, _x in positions}, {x for _y, x in positions}
|
ys, xs = {y for y, x in positions}, {x for y, x in positions}
|
||||||
return min(ys), min(xs), max(ys), max(xs)
|
return min(ys), min(xs), max(ys), max(xs)
|
||||||
|
|
||||||
|
|
||||||
|
def print_positions(positions: set[tuple[int, int]]):
|
||||||
|
min_y, min_x, max_y, max_x = min_max_yx(positions)
|
||||||
|
print(
|
||||||
|
"\n".join(
|
||||||
|
"".join(
|
||||||
|
"#" if (y, x) in positions else "." for x in range(min_x - 1, max_x + 2)
|
||||||
|
)
|
||||||
|
for y in range(min_y - 1, max_y + 2)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def round(
|
def round(
|
||||||
positions: set[tuple[int, int]],
|
positions: set[tuple[int, int]],
|
||||||
directions: Directions,
|
directions: Directions,
|
||||||
@@ -59,33 +69,30 @@ def round(
|
|||||||
directions.append(directions.pop(0))
|
directions.append(directions.pop(0))
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
POSITIONS = {
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
POSITIONS = {
|
|
||||||
(i, j)
|
(i, j)
|
||||||
for i, row in enumerate(input.splitlines())
|
for i, row in enumerate(sys.stdin.read().splitlines())
|
||||||
for j, col in enumerate(row)
|
for j, col in enumerate(row)
|
||||||
if col == "#"
|
if col == "#"
|
||||||
}
|
}
|
||||||
|
|
||||||
# === part 1 ===
|
# === part 1 ===
|
||||||
|
|
||||||
p1, d1 = POSITIONS.copy(), DIRECTIONS.copy()
|
p1, d1 = POSITIONS.copy(), DIRECTIONS.copy()
|
||||||
for _ in range(10):
|
for r in range(10):
|
||||||
round(p1, d1)
|
round(p1, d1)
|
||||||
|
|
||||||
min_y, min_x, max_y, max_x = min_max_yx(p1)
|
min_y, min_x, max_y, max_x = min_max_yx(p1)
|
||||||
yield sum(
|
answer_1 = sum(
|
||||||
(y, x) not in p1
|
(y, x) not in p1 for y in range(min_y, max_y + 1) for x in range(min_x, max_x + 1)
|
||||||
for y in range(min_y, max_y + 1)
|
)
|
||||||
for x in range(min_x, max_x + 1)
|
print(f"answer 1 is {answer_1}")
|
||||||
)
|
|
||||||
|
|
||||||
# === part 2 ===
|
# === part 2 ===
|
||||||
|
|
||||||
p2, d2 = POSITIONS.copy(), DIRECTIONS.copy()
|
p2, d2 = POSITIONS.copy(), DIRECTIONS.copy()
|
||||||
answer_2 = 0
|
answer_2 = 0
|
||||||
while True:
|
while True:
|
||||||
answer_2 += 1
|
answer_2 += 1
|
||||||
backup = p2.copy()
|
backup = p2.copy()
|
||||||
round(p2, d2)
|
round(p2, d2)
|
||||||
@@ -93,4 +100,4 @@ class Solver(BaseSolver):
|
|||||||
if backup == p2:
|
if backup == p2:
|
||||||
break
|
break
|
||||||
|
|
||||||
yield answer_2
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,46 +1,36 @@
|
|||||||
import heapq
|
import heapq
|
||||||
import math
|
import math
|
||||||
|
import sys
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from typing import Any, Iterator
|
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
winds = {
|
||||||
class Solver(BaseSolver):
|
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
lines = [line.strip() for line in input.splitlines()]
|
|
||||||
|
|
||||||
winds = {
|
|
||||||
(i - 1, j - 1, lines[i][j])
|
(i - 1, j - 1, lines[i][j])
|
||||||
for i in range(1, len(lines) - 1)
|
for i in range(1, len(lines) - 1)
|
||||||
for j in range(1, len(lines[i]) - 1)
|
for j in range(1, len(lines[i]) - 1)
|
||||||
if lines[i][j] != "."
|
if lines[i][j] != "."
|
||||||
}
|
}
|
||||||
|
|
||||||
n_rows, n_cols = len(lines) - 2, len(lines[0]) - 2
|
n_rows, n_cols = len(lines) - 2, len(lines[0]) - 2
|
||||||
CYCLE = math.lcm(n_rows, n_cols)
|
CYCLE = math.lcm(n_rows, n_cols)
|
||||||
|
|
||||||
east_winds = [
|
east_winds = [{j for j in range(n_cols) if (i, j, ">") in winds} for i in range(n_rows)]
|
||||||
{j for j in range(n_cols) if (i, j, ">") in winds} for i in range(n_rows)
|
west_winds = [{j for j in range(n_cols) if (i, j, "<") in winds} for i in range(n_rows)]
|
||||||
]
|
north_winds = [
|
||||||
west_winds = [
|
|
||||||
{j for j in range(n_cols) if (i, j, "<") in winds} for i in range(n_rows)
|
|
||||||
]
|
|
||||||
north_winds = [
|
|
||||||
{i for i in range(n_rows) if (i, j, "^") in winds} for j in range(n_cols)
|
{i for i in range(n_rows) if (i, j, "^") in winds} for j in range(n_cols)
|
||||||
]
|
]
|
||||||
south_winds = [
|
south_winds = [
|
||||||
{i for i in range(n_rows) if (i, j, "v") in winds} for j in range(n_cols)
|
{i for i in range(n_rows) if (i, j, "v") in winds} for j in range(n_cols)
|
||||||
]
|
]
|
||||||
|
|
||||||
def run(start: tuple[int, int], start_cycle: int, end: tuple[int, int]):
|
|
||||||
|
def run(start: tuple[int, int], start_cycle: int, end: tuple[int, int]):
|
||||||
def heuristic(y: int, x: int) -> int:
|
def heuristic(y: int, x: int) -> int:
|
||||||
return abs(end[0] - y) + abs(end[1] - x)
|
return abs(end[0] - y) + abs(end[1] - x)
|
||||||
|
|
||||||
# (distance + heuristic, distance, (start_pos, cycle))
|
# (distance + heuristic, distance, (start_pos, cycle))
|
||||||
queue = [
|
queue = [(heuristic(start[0], start[1]), 0, ((start[0], start[1]), start_cycle))]
|
||||||
(heuristic(start[0], start[1]), 0, ((start[0], start[1]), start_cycle))
|
|
||||||
]
|
|
||||||
visited: set[tuple[tuple[int, int], int]] = set()
|
visited: set[tuple[tuple[int, int], int]] = set()
|
||||||
distances: dict[tuple[int, int], dict[int, int]] = defaultdict(lambda: {})
|
distances: dict[tuple[int, int], dict[int, int]] = defaultdict(lambda: {})
|
||||||
|
|
||||||
@@ -64,17 +54,13 @@ class Solver(BaseSolver):
|
|||||||
n_cycle = (cycle + 1) % CYCLE
|
n_cycle = (cycle + 1) % CYCLE
|
||||||
|
|
||||||
if (ty, tx) == end:
|
if (ty, tx) == end:
|
||||||
heapq.heappush(
|
heapq.heappush(queue, (distance + 1, distance + 1, ((ty, tx), n_cycle)))
|
||||||
queue, (distance + 1, distance + 1, ((ty, tx), n_cycle))
|
|
||||||
)
|
|
||||||
break
|
break
|
||||||
|
|
||||||
if ((ty, tx), n_cycle) in visited:
|
if ((ty, tx), n_cycle) in visited:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if (ty, tx) != start and (
|
if (ty, tx) != start and (ty < 0 or tx < 0 or ty >= n_rows or tx >= n_cols):
|
||||||
ty < 0 or tx < 0 or ty >= n_rows or tx >= n_cols
|
|
||||||
):
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if (ty, tx) != start:
|
if (ty, tx) != start:
|
||||||
@@ -89,29 +75,24 @@ class Solver(BaseSolver):
|
|||||||
|
|
||||||
heapq.heappush(
|
heapq.heappush(
|
||||||
queue,
|
queue,
|
||||||
(
|
((heuristic(ty, tx) + distance + 1, distance + 1, ((ty, tx), n_cycle))),
|
||||||
(
|
|
||||||
heuristic(ty, tx) + distance + 1,
|
|
||||||
distance + 1,
|
|
||||||
((ty, tx), n_cycle),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return distances, next(iter(distances[end].values()))
|
return distances, next(iter(distances[end].values()))
|
||||||
|
|
||||||
start = (
|
|
||||||
|
start = (
|
||||||
-1,
|
-1,
|
||||||
next(j for j in range(1, len(lines[0]) - 1) if lines[0][j] == ".") - 1,
|
next(j for j in range(1, len(lines[0]) - 1) if lines[0][j] == ".") - 1,
|
||||||
)
|
)
|
||||||
end = (
|
end = (
|
||||||
n_rows,
|
n_rows,
|
||||||
next(j for j in range(1, len(lines[-1]) - 1) if lines[-1][j] == ".") - 1,
|
next(j for j in range(1, len(lines[-1]) - 1) if lines[-1][j] == ".") - 1,
|
||||||
)
|
)
|
||||||
|
|
||||||
distances_1, forward_1 = run(start, 0, end)
|
distances_1, forward_1 = run(start, 0, end)
|
||||||
yield forward_1
|
print(f"answer 1 is {forward_1}")
|
||||||
|
|
||||||
distances_2, return_1 = run(end, next(iter(distances_1[end].keys())), start)
|
distances_2, return_1 = run(end, next(iter(distances_1[end].keys())), start)
|
||||||
_distances_3, forward_2 = run(start, next(iter(distances_2[start].keys())), end)
|
distances_3, forward_2 = run(start, next(iter(distances_2[start].keys())), end)
|
||||||
yield forward_1 + return_1 + forward_2
|
print(f"answer 2 is {forward_1 + return_1 + forward_2}")
|
||||||
|
|||||||
@@ -1,22 +1,19 @@
|
|||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
coeffs = {"2": 2, "1": 1, "0": 0, "-": -1, "=": -2}
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
def snafu2number(number: str) -> int:
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
lines = [line.strip() for line in input.splitlines()]
|
|
||||||
|
|
||||||
coeffs = {"2": 2, "1": 1, "0": 0, "-": -1, "=": -2}
|
|
||||||
|
|
||||||
def snafu2number(number: str) -> int:
|
|
||||||
value = 0
|
value = 0
|
||||||
for c in number:
|
for c in number:
|
||||||
value *= 5
|
value *= 5
|
||||||
value += coeffs[c]
|
value += coeffs[c]
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def number2snafu(number: int) -> str:
|
|
||||||
|
def number2snafu(number: int) -> str:
|
||||||
values = ["0", "1", "2", "=", "-"]
|
values = ["0", "1", "2", "=", "-"]
|
||||||
res = ""
|
res = ""
|
||||||
while number > 0:
|
while number > 0:
|
||||||
@@ -25,4 +22,6 @@ class Solver(BaseSolver):
|
|||||||
number = number // 5 + int(mod >= 3)
|
number = number // 5 + int(mod >= 3)
|
||||||
return "".join(reversed(res))
|
return "".join(reversed(res))
|
||||||
|
|
||||||
yield number2snafu(sum(map(snafu2number, lines)))
|
|
||||||
|
answer_1 = number2snafu(sum(map(snafu2number, lines)))
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|||||||
@@ -1,28 +1,23 @@
|
|||||||
import string
|
import string
|
||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines = [line.strip() for line in sys.stdin.readlines()]
|
||||||
|
|
||||||
|
# extract content of each part
|
||||||
|
parts = [(set(line[: len(line) // 2]), set(line[len(line) // 2 :])) for line in lines]
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
# priorities
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
priorities = {c: i + 1 for i, c in enumerate(string.ascii_letters)}
|
||||||
lines = [line.strip() for line in input.splitlines()]
|
|
||||||
|
|
||||||
# extract content of each part
|
# part 1
|
||||||
parts = [
|
part1 = sum(priorities[c] for p1, p2 in parts for c in p1.intersection(p2))
|
||||||
(set(line[: len(line) // 2]), set(line[len(line) // 2 :])) for line in lines
|
print(f"answer 1 is {part1}")
|
||||||
]
|
|
||||||
|
|
||||||
# priorities
|
# part 2
|
||||||
priorities = {c: i + 1 for i, c in enumerate(string.ascii_letters)}
|
n_per_group = 3
|
||||||
|
part2 = sum(
|
||||||
# part 1
|
|
||||||
yield sum(priorities[c] for p1, p2 in parts for c in p1.intersection(p2))
|
|
||||||
|
|
||||||
# part 2
|
|
||||||
n_per_group = 3
|
|
||||||
yield sum(
|
|
||||||
priorities[c]
|
priorities[c]
|
||||||
for i in range(0, len(lines), n_per_group)
|
for i in range(0, len(lines), n_per_group)
|
||||||
for c in set(lines[i]).intersection(*lines[i + 1 : i + n_per_group])
|
for c in set(lines[i]).intersection(*lines[i + 1 : i + n_per_group])
|
||||||
)
|
)
|
||||||
|
print(f"answer 2 is {part2}")
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines = [line.strip() for line in sys.stdin.readlines()]
|
||||||
|
|
||||||
|
|
||||||
def make_range(value: str) -> set[int]:
|
def make_range(value: str) -> set[int]:
|
||||||
@@ -8,13 +8,10 @@ def make_range(value: str) -> set[int]:
|
|||||||
return set(range(int(parts[0]), int(parts[1]) + 1))
|
return set(range(int(parts[0]), int(parts[1]) + 1))
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
sections = [tuple(make_range(part) for part in line.split(",")) for line in lines]
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
lines = [line.strip() for line in input.splitlines()]
|
|
||||||
|
|
||||||
sections = [
|
answer_1 = sum(s1.issubset(s2) or s2.issubset(s1) for s1, s2 in sections)
|
||||||
tuple(make_range(part) for part in line.split(",")) for line in lines
|
print(f"answer 1 is {answer_1}")
|
||||||
]
|
|
||||||
|
|
||||||
yield sum(s1.issubset(s2) or s2.issubset(s1) for s1, s2 in sections)
|
answer_2 = sum(bool(s1.intersection(s2)) for s1, s2 in sections)
|
||||||
yield sum(bool(s1.intersection(s2)) for s1, s2 in sections)
|
print(f"answer 1 is {answer_2}")
|
||||||
|
|||||||
@@ -1,43 +1,41 @@
|
|||||||
import copy
|
import copy
|
||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
from ..base import BaseSolver
|
blocks_s, moves_s = (part.splitlines() for part in sys.stdin.read().split("\n\n"))
|
||||||
|
|
||||||
|
blocks: dict[str, list[str]] = {stack: [] for stack in blocks_s[-1].split()}
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
# this codes assumes that the lines are regular, i.e., 4 characters per "crate" in the
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
# form of '[X] ' (including the trailing space)
|
||||||
blocks_s, moves_s = (part.splitlines() for part in input.split("\n\n"))
|
#
|
||||||
|
for block in blocks_s[-2::-1]:
|
||||||
blocks: dict[str, list[str]] = {stack: [] for stack in blocks_s[-1].split()}
|
|
||||||
|
|
||||||
# this codes assumes that the lines are regular, i.e., 4 characters per "crate" in the
|
|
||||||
# form of '[X] ' (including the trailing space)
|
|
||||||
#
|
|
||||||
for block in blocks_s[-2::-1]:
|
|
||||||
for stack, index in zip(blocks, range(0, len(block), 4)):
|
for stack, index in zip(blocks, range(0, len(block), 4)):
|
||||||
crate = block[index + 1 : index + 2].strip()
|
crate = block[index + 1 : index + 2].strip()
|
||||||
|
|
||||||
if crate:
|
if crate:
|
||||||
blocks[stack].append(crate)
|
blocks[stack].append(crate)
|
||||||
|
|
||||||
# part 1 - deep copy for part 2
|
# part 1 - deep copy for part 2
|
||||||
blocks_1 = copy.deepcopy(blocks)
|
blocks_1 = copy.deepcopy(blocks)
|
||||||
|
|
||||||
for move in moves_s:
|
for move in moves_s:
|
||||||
_, count_s, _, from_, _, to_ = move.strip().split()
|
_, count_s, _, from_, _, to_ = move.strip().split()
|
||||||
|
|
||||||
for _i in range(int(count_s)):
|
for _i in range(int(count_s)):
|
||||||
blocks_1[to_].append(blocks_1[from_].pop())
|
blocks_1[to_].append(blocks_1[from_].pop())
|
||||||
|
|
||||||
# part 2
|
# part 2
|
||||||
blocks_2 = copy.deepcopy(blocks)
|
blocks_2 = copy.deepcopy(blocks)
|
||||||
|
|
||||||
for move in moves_s:
|
for move in moves_s:
|
||||||
_, count_s, _, from_, _, to_ = move.strip().split()
|
_, count_s, _, from_, _, to_ = move.strip().split()
|
||||||
count = int(count_s)
|
count = int(count_s)
|
||||||
|
|
||||||
blocks_2[to_].extend(blocks_2[from_][-count:])
|
blocks_2[to_].extend(blocks_2[from_][-count:])
|
||||||
del blocks_2[from_][-count:]
|
del blocks_2[from_][-count:]
|
||||||
|
|
||||||
yield "".join(s[-1] for s in blocks_1.values())
|
answer_1 = "".join(s[-1] for s in blocks_1.values())
|
||||||
yield "".join(s[-1] for s in blocks_2.values())
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
|
answer_2 = "".join(s[-1] for s in blocks_2.values())
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
from ..base import BaseSolver
|
|
||||||
|
|
||||||
|
|
||||||
def index_of_first_n_differents(data: str, n: int) -> int:
|
def index_of_first_n_differents(data: str, n: int) -> int:
|
||||||
@@ -10,7 +8,8 @@ def index_of_first_n_differents(data: str, n: int) -> int:
|
|||||||
return -1
|
return -1
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
data = sys.stdin.read().strip()
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
yield index_of_first_n_differents(input, 4)
|
|
||||||
yield index_of_first_n_differents(input, 14)
|
print(f"answer 1 is {index_of_first_n_differents(data, 4)}")
|
||||||
|
print(f"answer 2 is {index_of_first_n_differents(data, 14)}")
|
||||||
|
|||||||
@@ -1,35 +1,30 @@
|
|||||||
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Iterator
|
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
# we are going to use Path to create path and go up/down in the file tree since it
|
||||||
|
# implements everything we need
|
||||||
|
#
|
||||||
|
# we can use .resolve() to get normalized path, although this will add C:\ to all paths
|
||||||
|
# on Windows but that is not an issue since only the sizes matter
|
||||||
|
#
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
# mapping from path to list of files or directories
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
trees: dict[Path, list[Path]] = {}
|
||||||
lines = [line.strip() for line in input.splitlines()]
|
|
||||||
|
|
||||||
# we are going to use Path to create path and go up/down in the file tree since it
|
# mapping from paths to either size (for file) or -1 for directory
|
||||||
# implements everything we need
|
sizes: dict[Path, int] = {}
|
||||||
#
|
|
||||||
# we can use .resolve() to get normalized path, although this will add C:\ to all paths
|
|
||||||
# on Windows but that is not an issue since only the sizes matter
|
|
||||||
#
|
|
||||||
|
|
||||||
# mapping from path to list of files or directories
|
# first line must be a cd otherwise we have no idea where we are
|
||||||
trees: dict[Path, list[Path]] = {}
|
assert lines[0].startswith("$ cd")
|
||||||
|
base_path = Path(lines[0].strip("$").split()[1]).resolve()
|
||||||
|
cur_path = base_path
|
||||||
|
|
||||||
# mapping from paths to either size (for file) or -1 for directory
|
trees[cur_path] = []
|
||||||
sizes: dict[Path, int] = {}
|
sizes[cur_path] = -1
|
||||||
|
|
||||||
# first line must be a cd otherwise we have no idea where we are
|
for line in lines[1:]:
|
||||||
assert lines[0].startswith("$ cd")
|
|
||||||
base_path = Path(lines[0].strip("$").split()[1]).resolve()
|
|
||||||
cur_path = base_path
|
|
||||||
|
|
||||||
trees[cur_path] = []
|
|
||||||
sizes[cur_path] = -1
|
|
||||||
|
|
||||||
for line in lines[1:]:
|
|
||||||
# command
|
# command
|
||||||
if line.startswith("$"):
|
if line.startswith("$"):
|
||||||
parts = line.strip("$").strip().split()
|
parts = line.strip("$").strip().split()
|
||||||
@@ -58,7 +53,8 @@ class Solver(BaseSolver):
|
|||||||
trees[cur_path].append(path)
|
trees[cur_path].append(path)
|
||||||
sizes[path] = size
|
sizes[path] = size
|
||||||
|
|
||||||
def compute_size(path: Path) -> int:
|
|
||||||
|
def compute_size(path: Path) -> int:
|
||||||
size = sizes[path]
|
size = sizes[path]
|
||||||
|
|
||||||
if size >= 0:
|
if size >= 0:
|
||||||
@@ -66,16 +62,19 @@ class Solver(BaseSolver):
|
|||||||
|
|
||||||
return sum(compute_size(sub) for sub in trees[path])
|
return sum(compute_size(sub) for sub in trees[path])
|
||||||
|
|
||||||
acc_sizes = {path: compute_size(path) for path in trees}
|
|
||||||
|
|
||||||
# part 1
|
acc_sizes = {path: compute_size(path) for path in trees}
|
||||||
yield sum(size for size in acc_sizes.values() if size <= 100_000)
|
|
||||||
|
|
||||||
# part 2
|
# part 1
|
||||||
total_space = 70_000_000
|
answer_1 = sum(size for size in acc_sizes.values() if size <= 100_000)
|
||||||
update_space = 30_000_000
|
print(f"answer 1 is {answer_1}")
|
||||||
free_space = total_space - acc_sizes[base_path]
|
|
||||||
|
|
||||||
to_free_space = update_space - free_space
|
# part 2
|
||||||
|
total_space = 70_000_000
|
||||||
|
update_space = 30_000_000
|
||||||
|
free_space = total_space - acc_sizes[base_path]
|
||||||
|
|
||||||
yield min(size for size in acc_sizes.values() if size >= to_free_space)
|
to_free_space = update_space - free_space
|
||||||
|
|
||||||
|
answer_2 = min(size for size in acc_sizes.values() if size >= to_free_space)
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,20 +1,15 @@
|
|||||||
from typing import Any, Iterator
|
import sys
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from numpy.typing import NDArray
|
from numpy.typing import NDArray
|
||||||
|
|
||||||
from ..base import BaseSolver
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
trees = np.array([[int(x) for x in row] for row in lines])
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
# answer 1
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
highest_trees = np.ones(trees.shape + (4,), dtype=int) * -1
|
||||||
lines = [line.strip() for line in input.splitlines()]
|
highest_trees[1:-1, 1:-1] = [
|
||||||
|
|
||||||
trees = np.array([[int(x) for x in row] for row in lines])
|
|
||||||
|
|
||||||
# answer 1
|
|
||||||
highest_trees = np.ones(trees.shape + (4,), dtype=int) * -1
|
|
||||||
highest_trees[1:-1, 1:-1] = [
|
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
trees[:i, j].max(),
|
trees[:i, j].max(),
|
||||||
@@ -25,11 +20,13 @@ class Solver(BaseSolver):
|
|||||||
for j in range(1, trees.shape[1] - 1)
|
for j in range(1, trees.shape[1] - 1)
|
||||||
]
|
]
|
||||||
for i in range(1, trees.shape[0] - 1)
|
for i in range(1, trees.shape[0] - 1)
|
||||||
]
|
]
|
||||||
|
|
||||||
yield (highest_trees.min(axis=2) < trees).sum()
|
answer_1 = (highest_trees.min(axis=2) < trees).sum()
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
def viewing_distance(row_of_trees: NDArray[np.int_], value: int) -> int:
|
|
||||||
|
def viewing_distance(row_of_trees: NDArray[np.int_], value: int) -> int:
|
||||||
w = np.where(row_of_trees >= value)[0]
|
w = np.where(row_of_trees >= value)[0]
|
||||||
|
|
||||||
if not w.size:
|
if not w.size:
|
||||||
@@ -37,9 +34,10 @@ class Solver(BaseSolver):
|
|||||||
|
|
||||||
return w[0] + 1
|
return w[0] + 1
|
||||||
|
|
||||||
# answer 2
|
|
||||||
v_distances = np.zeros(trees.shape + (4,), dtype=int)
|
# answer 2
|
||||||
v_distances[1:-1, 1:-1, :] = [
|
v_distances = np.zeros(trees.shape + (4,), dtype=int)
|
||||||
|
v_distances[1:-1, 1:-1, :] = [
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
viewing_distance(trees[i - 1 :: -1, j], trees[i, j]),
|
viewing_distance(trees[i - 1 :: -1, j], trees[i, j]),
|
||||||
@@ -50,5 +48,6 @@ class Solver(BaseSolver):
|
|||||||
for j in range(1, trees.shape[1] - 1)
|
for j in range(1, trees.shape[1] - 1)
|
||||||
]
|
]
|
||||||
for i in range(1, trees.shape[0] - 1)
|
for i in range(1, trees.shape[0] - 1)
|
||||||
]
|
]
|
||||||
yield np.prod(v_distances, axis=2).max()
|
answer_2 = np.prod(v_distances, axis=2).max()
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
import itertools as it
|
import sys
|
||||||
from typing import Any, Iterator
|
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from ..base import BaseSolver
|
|
||||||
|
|
||||||
|
|
||||||
def move(head: tuple[int, int], command: str) -> tuple[int, int]:
|
def move(head: tuple[int, int], command: str) -> tuple[int, int]:
|
||||||
h_col, h_row = head
|
h_col, h_row = head
|
||||||
@@ -46,14 +43,17 @@ def run(commands: list[str], n_blocks: int) -> list[tuple[int, int]]:
|
|||||||
return visited
|
return visited
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
lines = sys.stdin.read().splitlines()
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
lines = [line.strip() for line in input.splitlines()]
|
|
||||||
|
|
||||||
# flatten the commands
|
# flatten the commands
|
||||||
commands = list(
|
commands: list[str] = []
|
||||||
it.chain(*(p[0] * int(p[1]) for line in lines if (p := line.split())))
|
for line in lines:
|
||||||
)
|
d, c = line.split()
|
||||||
|
commands.extend(d * int(c))
|
||||||
|
|
||||||
yield len(set(run(commands, n_blocks=2)))
|
|
||||||
yield len(set(run(commands, n_blocks=10)))
|
visited_1 = run(commands, n_blocks=2)
|
||||||
|
print(f"answer 1 is {len(set(visited_1))}")
|
||||||
|
|
||||||
|
visited_2 = run(commands, n_blocks=10)
|
||||||
|
print(f"answer 2 is {len(set(visited_2))}")
|
||||||
|
|||||||
@@ -83,17 +83,18 @@ class Solver(BaseSolver):
|
|||||||
if (i, j) in loop_s and lines[i][j] in "|LJ":
|
if (i, j) in loop_s and lines[i][j] in "|LJ":
|
||||||
cnt += 1
|
cnt += 1
|
||||||
|
|
||||||
if self.files:
|
if self.verbose:
|
||||||
rows = [["." for _j in range(len(lines[0]))] for _i in range(len(lines))]
|
for i in range(len(lines)):
|
||||||
rows[si][sj] = "\033[91mS\033[0m"
|
s = ""
|
||||||
|
for j in range(len(lines[0])):
|
||||||
for i, j in loop:
|
if (i, j) == (si, sj):
|
||||||
rows[i][j] = lines[i][j]
|
s += "\033[91mS\033[0m"
|
||||||
for i, j in inside:
|
elif (i, j) in loop:
|
||||||
rows[i][j] = "\033[92mI\033[0m"
|
s += lines[i][j]
|
||||||
|
elif (i, j) in inside:
|
||||||
self.files.create(
|
s += "\033[92mI\033[0m"
|
||||||
"output.txt", "\n".join("".join(row) for row in rows).encode(), True
|
else:
|
||||||
)
|
s += "."
|
||||||
|
self.logger.info(s)
|
||||||
|
|
||||||
yield len(inside)
|
yield len(inside)
|
||||||
|
|||||||
@@ -84,14 +84,9 @@ class Solver(BaseSolver):
|
|||||||
|
|
||||||
beams = propagate(layout, (0, 0), "R")
|
beams = propagate(layout, (0, 0), "R")
|
||||||
|
|
||||||
if self.files:
|
if self.verbose:
|
||||||
self.files.create(
|
for row in beams:
|
||||||
"beams.txt",
|
self.logger.info("".join("#" if col else "." for col in row))
|
||||||
"\n".join(
|
|
||||||
"".join("#" if col else "." for col in row) for row in beams
|
|
||||||
).encode(),
|
|
||||||
True,
|
|
||||||
)
|
|
||||||
|
|
||||||
# part 1
|
# part 1
|
||||||
yield sum(sum(map(bool, row)) for row in beams)
|
yield sum(sum(map(bool, row)) for row in beams)
|
||||||
|
|||||||
@@ -33,14 +33,10 @@ MAPPINGS: dict[Direction, tuple[int, int, Direction]] = {
|
|||||||
class Solver(BaseSolver):
|
class Solver(BaseSolver):
|
||||||
def print_shortest_path(
|
def print_shortest_path(
|
||||||
self,
|
self,
|
||||||
name: str,
|
|
||||||
grid: list[list[int]],
|
grid: list[list[int]],
|
||||||
target: tuple[int, int],
|
target: tuple[int, int],
|
||||||
per_cell: dict[tuple[int, int], list[tuple[Label, int]]],
|
per_cell: dict[tuple[int, int], list[tuple[Label, int]]],
|
||||||
):
|
):
|
||||||
if not self.files:
|
|
||||||
return
|
|
||||||
|
|
||||||
assert len(per_cell[target]) == 1
|
assert len(per_cell[target]) == 1
|
||||||
label = per_cell[target][0][0]
|
label = per_cell[target][0][0]
|
||||||
|
|
||||||
@@ -78,9 +74,8 @@ class Solver(BaseSolver):
|
|||||||
|
|
||||||
p_grid[0][0] = f"\033[92m{grid[0][0]}\033[0m"
|
p_grid[0][0] = f"\033[92m{grid[0][0]}\033[0m"
|
||||||
|
|
||||||
self.files.create(
|
for row in p_grid:
|
||||||
name, "\n".join("".join(row) for row in p_grid).encode(), True
|
self.logger.info("".join(row))
|
||||||
)
|
|
||||||
|
|
||||||
def shortest_many_paths(self, grid: list[list[int]]) -> dict[tuple[int, int], int]:
|
def shortest_many_paths(self, grid: list[list[int]]) -> dict[tuple[int, int], int]:
|
||||||
n_rows, n_cols = len(grid), len(grid[0])
|
n_rows, n_cols = len(grid), len(grid[0])
|
||||||
@@ -134,7 +129,6 @@ class Solver(BaseSolver):
|
|||||||
|
|
||||||
def shortest_path(
|
def shortest_path(
|
||||||
self,
|
self,
|
||||||
name: str,
|
|
||||||
grid: list[list[int]],
|
grid: list[list[int]],
|
||||||
min_straight: int,
|
min_straight: int,
|
||||||
max_straight: int,
|
max_straight: int,
|
||||||
@@ -223,7 +217,8 @@ class Solver(BaseSolver):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
self.print_shortest_path(f"shortest-path_{name}.txt", grid, target, per_cell)
|
if self.verbose:
|
||||||
|
self.print_shortest_path(grid, target, per_cell)
|
||||||
|
|
||||||
return per_cell[target][0][1]
|
return per_cell[target][0][1]
|
||||||
|
|
||||||
@@ -232,7 +227,7 @@ class Solver(BaseSolver):
|
|||||||
estimates = self.shortest_many_paths(data)
|
estimates = self.shortest_many_paths(data)
|
||||||
|
|
||||||
# part 1
|
# part 1
|
||||||
yield self.shortest_path("answer_1", data, 1, 3, lower_bounds=estimates)
|
yield self.shortest_path(data, 1, 3, lower_bounds=estimates)
|
||||||
|
|
||||||
# part 2
|
# part 2
|
||||||
yield self.shortest_path("answer_2", data, 4, 10, lower_bounds=estimates)
|
yield self.shortest_path(data, 4, 10, lower_bounds=estimates)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import sys
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from math import lcm
|
from math import lcm
|
||||||
from typing import Any, Iterator, Literal, TypeAlias
|
from typing import Any, Iterator, Literal, TypeAlias
|
||||||
@@ -66,7 +67,7 @@ class Solver(BaseSolver):
|
|||||||
def solve(self, input: str) -> Iterator[Any]:
|
def solve(self, input: str) -> Iterator[Any]:
|
||||||
self._modules = {}
|
self._modules = {}
|
||||||
|
|
||||||
lines = input.splitlines()
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
for line in lines:
|
for line in lines:
|
||||||
name, outputs_s = line.split(" -> ")
|
name, outputs_s = line.split(" -> ")
|
||||||
@@ -79,9 +80,10 @@ class Solver(BaseSolver):
|
|||||||
outputs,
|
outputs,
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.files:
|
if self.outputs:
|
||||||
contents = "digraph G {\n"
|
with open("./day20.dot", "w") as fp:
|
||||||
contents += "rx [shape=circle, color=red, style=filled];\n"
|
fp.write("digraph G {\n")
|
||||||
|
fp.write("rx [shape=circle, color=red, style=filled];\n")
|
||||||
for name, (type, outputs) in self._modules.items():
|
for name, (type, outputs) in self._modules.items():
|
||||||
if type == "conjunction":
|
if type == "conjunction":
|
||||||
shape = "diamond"
|
shape = "diamond"
|
||||||
@@ -89,13 +91,11 @@ class Solver(BaseSolver):
|
|||||||
shape = "box"
|
shape = "box"
|
||||||
else:
|
else:
|
||||||
shape = "circle"
|
shape = "circle"
|
||||||
contents += f"{name} [shape={shape}];\n"
|
fp.write(f"{name} [shape={shape}];\n")
|
||||||
for name, (type, outputs) in self._modules.items():
|
for name, (type, outputs) in self._modules.items():
|
||||||
for output in outputs:
|
for output in outputs:
|
||||||
contents += f"{name} -> {output};\n"
|
fp.write(f"{name} -> {output};\n")
|
||||||
contents += "}\n"
|
fp.write("}\n")
|
||||||
|
|
||||||
self.files.create("day20.dot", contents.encode(), False)
|
|
||||||
|
|
||||||
# part 1
|
# part 1
|
||||||
flip_flop_states: dict[str, Literal["on", "off"]] = {
|
flip_flop_states: dict[str, Literal["on", "off"]] = {
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ class Solver(BaseSolver):
|
|||||||
values.append(len(tiles := reachable(map, tiles, cycle)))
|
values.append(len(tiles := reachable(map, tiles, cycle)))
|
||||||
values.append(len(tiles := reachable(map, tiles, cycle)))
|
values.append(len(tiles := reachable(map, tiles, cycle)))
|
||||||
|
|
||||||
if self.files:
|
if self.verbose:
|
||||||
n_rows, n_cols = len(map), len(map[0])
|
n_rows, n_cols = len(map), len(map[0])
|
||||||
|
|
||||||
rows = [
|
rows = [
|
||||||
@@ -66,9 +66,8 @@ class Solver(BaseSolver):
|
|||||||
if (i // cycle) % 2 == (j // cycle) % 2:
|
if (i // cycle) % 2 == (j // cycle) % 2:
|
||||||
rows[i][j] = f"\033[91m{rows[i][j]}\033[0m"
|
rows[i][j] = f"\033[91m{rows[i][j]}\033[0m"
|
||||||
|
|
||||||
self.files.create(
|
for row in rows:
|
||||||
"cycle.txt", "\n".join("".join(row) for row in rows).encode(), True
|
self.logger.info("".join(row))
|
||||||
)
|
|
||||||
|
|
||||||
self.logger.info(f"values to fit: {values}")
|
self.logger.info(f"values to fit: {values}")
|
||||||
|
|
||||||
@@ -102,31 +101,32 @@ class Solver(BaseSolver):
|
|||||||
# depending on the number of cycles, either A or B will be in the center
|
# depending on the number of cycles, either A or B will be in the center
|
||||||
#
|
#
|
||||||
|
|
||||||
# counts = [
|
counts = [
|
||||||
# [
|
[
|
||||||
# sum(
|
sum(
|
||||||
# (i, j) in tiles
|
(i, j) in tiles
|
||||||
# for i in range(ci * cycle, (ci + 1) * cycle)
|
for i in range(ci * cycle, (ci + 1) * cycle)
|
||||||
# for j in range(cj * cycle, (cj + 1) * cycle)
|
for j in range(cj * cycle, (cj + 1) * cycle)
|
||||||
# )
|
)
|
||||||
# for cj in range(-2, 3)
|
for cj in range(-2, 3)
|
||||||
# ]
|
]
|
||||||
# for ci in range(-2, 3)
|
for ci in range(-2, 3)
|
||||||
# ]
|
]
|
||||||
|
|
||||||
# radius = (26501365 - rhombus) // cycle - 1
|
radius = (26501365 - rhombus) // cycle - 1
|
||||||
# A = counts[2][2] if radius % 2 == 0 else counts[2][1]
|
A = counts[2][2] if radius % 2 == 0 else counts[2][1]
|
||||||
# B = counts[2][2] if radius % 2 == 1 else counts[2][1]
|
B = counts[2][2] if radius % 2 == 1 else counts[2][1]
|
||||||
# answer_2 = (
|
answer_2 = (
|
||||||
# (radius + 1) * A
|
(radius + 1) * A
|
||||||
# + radius * B
|
+ radius * B
|
||||||
# + 2 * radius * (radius + 1) // 2 * A
|
+ 2 * radius * (radius + 1) // 2 * A
|
||||||
# + 2 * radius * (radius - 1) // 2 * B
|
+ 2 * radius * (radius - 1) // 2 * B
|
||||||
# + sum(counts[i][j] for i, j in ((0, 2), (-1, 2), (2, 0), (2, -1)))
|
+ sum(counts[i][j] for i, j in ((0, 2), (-1, 2), (2, 0), (2, -1)))
|
||||||
# + sum(counts[i][j] for i, j in ((0, 1), (0, 3), (-1, 1), (-1, 3)))
|
+ sum(counts[i][j] for i, j in ((0, 1), (0, 3), (-1, 1), (-1, 3)))
|
||||||
# * (radius + 1)
|
* (radius + 1)
|
||||||
# + sum(counts[i][j] for i, j in ((1, 1), (1, 3), (-2, 1), (-2, 3))) * radius
|
+ sum(counts[i][j] for i, j in ((1, 1), (1, 3), (-2, 1), (-2, 3))) * radius
|
||||||
# )
|
)
|
||||||
|
print(f"answer 2 (v1) is {answer_2}")
|
||||||
|
|
||||||
# version 2: fitting a polynomial
|
# version 2: fitting a polynomial
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
# pyright: reportUnknownMemberType=false
|
|
||||||
|
|
||||||
from typing import Any, Iterator
|
from typing import Any, Iterator
|
||||||
|
|
||||||
import networkx as nx
|
import networkx as nx
|
||||||
|
|||||||
@@ -1,35 +1,7 @@
|
|||||||
import itertools as it
|
|
||||||
from typing import Any, Iterator
|
from typing import Any, Iterator
|
||||||
|
|
||||||
from ..base import BaseSolver
|
from ..base import BaseSolver
|
||||||
|
|
||||||
|
|
||||||
def process(
|
|
||||||
grid: list[list[int]], current: tuple[int, int]
|
|
||||||
) -> set[tuple[tuple[int, int], ...]]:
|
|
||||||
row, col = current
|
|
||||||
value = grid[row][col] + 1
|
|
||||||
|
|
||||||
if grid[row][col] == 9:
|
|
||||||
return {((row, col),)}
|
|
||||||
|
|
||||||
return {
|
|
||||||
((row, col),) + path
|
|
||||||
for i, j in ((row - 1, col), (row, col + 1), (row + 1, col), (row, col - 1))
|
|
||||||
if 0 <= i < len(grid) and 0 <= j < len(grid[i]) and grid[i][j] == value
|
|
||||||
for path in process(grid, (i, j))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
class Solver(BaseSolver):
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
def solve(self, input: str) -> Iterator[Any]: ...
|
||||||
grid = [[int(col) for col in row] for row in input.splitlines()]
|
|
||||||
|
|
||||||
paths = {
|
|
||||||
(i, j): process(grid, (i, j))
|
|
||||||
for i, j in it.product(range(len(grid)), range(len(grid[0])))
|
|
||||||
if grid[i][j] == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
yield sum(len({path[-1] for path in paths[head]}) for head in paths)
|
|
||||||
yield sum(len(paths_of) for paths_of in paths.values())
|
|
||||||
|
|||||||
@@ -1,36 +1,7 @@
|
|||||||
from functools import cache
|
|
||||||
from typing import Any, Iterator
|
from typing import Any, Iterator
|
||||||
|
|
||||||
from ..base import BaseSolver
|
from ..base import BaseSolver
|
||||||
|
|
||||||
|
|
||||||
def n_digits(n: int) -> int:
|
|
||||||
c = int(n == 0)
|
|
||||||
while n > 0:
|
|
||||||
c, n = c + 1, n // 10
|
|
||||||
return c
|
|
||||||
|
|
||||||
|
|
||||||
@cache
|
|
||||||
def blink_one_stone(stone: int, round: int) -> int:
|
|
||||||
if round == 0:
|
|
||||||
return 1
|
|
||||||
|
|
||||||
if stone == 0:
|
|
||||||
return blink_one_stone(1, round - 1)
|
|
||||||
|
|
||||||
if (n := n_digits(stone)) % 2 == 0:
|
|
||||||
p = 10 ** (n // 2)
|
|
||||||
return blink_one_stone(stone // p, round - 1) + blink_one_stone(
|
|
||||||
stone % p, round - 1
|
|
||||||
)
|
|
||||||
|
|
||||||
return blink_one_stone(stone * 2024, round - 1)
|
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
class Solver(BaseSolver):
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
def solve(self, input: str) -> Iterator[Any]: ...
|
||||||
stones = list(map(int, input.split()))
|
|
||||||
|
|
||||||
yield sum(blink_one_stone(stone, 25) for stone in stones)
|
|
||||||
yield sum(blink_one_stone(stone, 75) for stone in stones)
|
|
||||||
|
|||||||
@@ -1,101 +1,7 @@
|
|||||||
import itertools as it
|
from typing import Any, Iterator
|
||||||
from dataclasses import dataclass
|
|
||||||
from typing import Any, Iterator, TypeAlias
|
|
||||||
|
|
||||||
from ..base import BaseSolver
|
from ..base import BaseSolver
|
||||||
|
|
||||||
Node: TypeAlias = tuple[int, int]
|
|
||||||
Edge: TypeAlias = tuple[Node, Node]
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
|
||||||
class Region:
|
|
||||||
value: str
|
|
||||||
cells: set[tuple[int, int]]
|
|
||||||
edges: set[Edge]
|
|
||||||
sides: list[tuple[Edge, ...]]
|
|
||||||
|
|
||||||
|
|
||||||
def extract_region(grid: list[str], cell: tuple[int, int]):
|
|
||||||
n_rows, n_cols = len(grid), len(grid[0])
|
|
||||||
row, col = cell
|
|
||||||
|
|
||||||
value = grid[row][col]
|
|
||||||
|
|
||||||
cells: set[tuple[int, int]] = set()
|
|
||||||
edges: set[Edge] = set()
|
|
||||||
sides: list[tuple[Edge, ...]] = []
|
|
||||||
|
|
||||||
queue: list[tuple[int, int]] = [(row, col)]
|
|
||||||
while queue:
|
|
||||||
row, col = queue.pop(0)
|
|
||||||
|
|
||||||
if (row, col) in cells:
|
|
||||||
continue
|
|
||||||
|
|
||||||
cells.add((row, col))
|
|
||||||
|
|
||||||
for ur, uc in (
|
|
||||||
(row - 1, col),
|
|
||||||
(row, col + 1),
|
|
||||||
(row + 1, col),
|
|
||||||
(row, col - 1),
|
|
||||||
):
|
|
||||||
if 0 <= ur < n_rows and 0 <= uc < n_cols and grid[ur][uc] == value:
|
|
||||||
queue.append((ur, uc))
|
|
||||||
continue
|
|
||||||
|
|
||||||
if ((row, col), (ur, uc)) in edges:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if col == uc:
|
|
||||||
mid, max = col, n_cols
|
|
||||||
|
|
||||||
def get(v: int):
|
|
||||||
return (row, v, ur, v)
|
|
||||||
else:
|
|
||||||
mid, max = row, n_rows
|
|
||||||
|
|
||||||
def get(v: int):
|
|
||||||
return (v, col, v, uc)
|
|
||||||
|
|
||||||
side: tuple[Edge, ...] = ((((row, col), (ur, uc))),)
|
|
||||||
for rng in (range(mid - 1, -1, -1), range(mid, max)):
|
|
||||||
for r2, c2, ur2, uc2 in map(get, rng):
|
|
||||||
if grid[r2][c2] != value or (
|
|
||||||
0 <= ur2 < n_rows
|
|
||||||
and 0 <= uc2 < n_cols
|
|
||||||
and grid[r2][c2] == grid[ur2][uc2]
|
|
||||||
):
|
|
||||||
break
|
|
||||||
side += ((((r2, c2), (ur2, uc2))),)
|
|
||||||
|
|
||||||
sides.append(side)
|
|
||||||
edges = edges.union(side)
|
|
||||||
|
|
||||||
return Region(value=value, cells=cells, edges=edges, sides=sides)
|
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
class Solver(BaseSolver):
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
def solve(self, input: str) -> Iterator[Any]: ...
|
||||||
grid = input.splitlines()
|
|
||||||
|
|
||||||
regions: list[Region] = []
|
|
||||||
to_visit: set[tuple[int, int]] = set(
|
|
||||||
it.product(range(len(grid)), range(len(grid[0])))
|
|
||||||
)
|
|
||||||
|
|
||||||
while to_visit:
|
|
||||||
region = extract_region(grid, next(iter(to_visit)))
|
|
||||||
|
|
||||||
self.logger.info(
|
|
||||||
f"region with {region.value}: "
|
|
||||||
f"{len(region.cells)} * {len(region.edges)} = {len(region.cells) * len(region.edges)}, "
|
|
||||||
f"{len(region.cells)} * {len(region.sides)} = {len(region.cells) * len(region.sides)}"
|
|
||||||
)
|
|
||||||
|
|
||||||
to_visit.difference_update(region.cells)
|
|
||||||
regions.append(region)
|
|
||||||
|
|
||||||
yield sum(len(region.cells) * len(region.edges) for region in regions)
|
|
||||||
yield sum(len(region.cells) * len(region.sides) for region in regions)
|
|
||||||
|
|||||||
@@ -1,79 +1,7 @@
|
|||||||
import math
|
|
||||||
from dataclasses import dataclass
|
|
||||||
from typing import Any, Iterator
|
from typing import Any, Iterator
|
||||||
|
|
||||||
import parse # pyright: ignore[reportMissingTypeStubs]
|
|
||||||
|
|
||||||
from ..base import BaseSolver
|
from ..base import BaseSolver
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
|
||||||
class Machine:
|
|
||||||
prize: tuple[int, int]
|
|
||||||
button_a: tuple[int, int]
|
|
||||||
button_b: tuple[int, int]
|
|
||||||
|
|
||||||
|
|
||||||
def read_machine(block: str) -> Machine:
|
|
||||||
ba = parse.parse( # type: ignore
|
|
||||||
"""Button A: X{bax:d}, Y{bay:d}
|
|
||||||
Button B: X{bbx:d}, Y{bby:d}
|
|
||||||
Prize: X={px:d}, Y={py:d}""",
|
|
||||||
block,
|
|
||||||
)
|
|
||||||
return Machine(
|
|
||||||
prize=(ba["px"], ba["py"]), # type: ignore
|
|
||||||
button_a=(ba["bax"], ba["bay"]), # type: ignore
|
|
||||||
button_b=(ba["bbx"], ba["bby"]), # type: ignore
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def diophantine(a: int, b: int, c: int) -> tuple[int, int]:
|
|
||||||
q, r = divmod(a, b)
|
|
||||||
if r == 0:
|
|
||||||
return (0, c // b)
|
|
||||||
else:
|
|
||||||
u, v = diophantine(b, r, c)
|
|
||||||
return (v, u - q * v)
|
|
||||||
|
|
||||||
|
|
||||||
def solve(machine: Machine) -> int:
|
|
||||||
(ax, ay), (bx, by), (px, py) = machine.button_a, machine.button_b, machine.prize
|
|
||||||
dx, dy = math.gcd(ax, bx), math.gcd(ay, by)
|
|
||||||
|
|
||||||
if px % dx != 0 or py % dy != 0:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
xa, xb = diophantine(ax, bx, px)
|
|
||||||
ya, yb = diophantine(ay, by, py)
|
|
||||||
|
|
||||||
# expr (x): xa - kx * bx / dx, xb + kx * ax / dx
|
|
||||||
# expr (y): ya - ky * by / dy, yb + ky * ay / dy
|
|
||||||
|
|
||||||
num = ay * (ya - xa) + by * (yb - xb)
|
|
||||||
den = (ax * by - ay * bx) // dx
|
|
||||||
|
|
||||||
if num % den != 0:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
kx = num // den
|
|
||||||
pa, pb = xa - kx * bx // dx, xb + kx * ax // dx
|
|
||||||
return 3 * pa + pb
|
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
class Solver(BaseSolver):
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
def solve(self, input: str) -> Iterator[Any]: ...
|
||||||
machines = [read_machine(block) for block in input.split("\n\n")]
|
|
||||||
|
|
||||||
yield sum(map(solve, machines))
|
|
||||||
|
|
||||||
shift = 10000000000000
|
|
||||||
machines = [
|
|
||||||
Machine(
|
|
||||||
prize=(shift + m.prize[0], shift + m.prize[1]),
|
|
||||||
button_a=m.button_a,
|
|
||||||
button_b=m.button_b,
|
|
||||||
)
|
|
||||||
for m in machines
|
|
||||||
]
|
|
||||||
yield sum(map(solve, machines))
|
|
||||||
|
|||||||
@@ -1,74 +1,7 @@
|
|||||||
import itertools as it
|
|
||||||
import operator as op
|
|
||||||
from math import prod
|
|
||||||
from typing import Any, Iterator
|
from typing import Any, Iterator
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
import parse # pyright: ignore[reportMissingTypeStubs]
|
|
||||||
|
|
||||||
from ..base import BaseSolver
|
from ..base import BaseSolver
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
class Solver(BaseSolver):
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
def solve(self, input: str) -> Iterator[Any]: ...
|
||||||
positions: list[tuple[int, int]] = []
|
|
||||||
velocities: list[tuple[int, int]] = []
|
|
||||||
|
|
||||||
for line in input.splitlines():
|
|
||||||
r = parse.parse("p={x:d},{y:d} v={vx:d},{vy:d}", line) # type: ignore
|
|
||||||
positions.append((r["y"], r["x"])) # type: ignore
|
|
||||||
velocities.append((r["vy"], r["vx"])) # type: ignore
|
|
||||||
|
|
||||||
n_rows, n_cols = 103, 101
|
|
||||||
if len(positions) < 20:
|
|
||||||
n_rows, n_cols = 7, 11
|
|
||||||
|
|
||||||
n_rounds = 100
|
|
||||||
new_positions = [
|
|
||||||
((row + v_row * n_rounds) % n_rows, (col + v_col * n_rounds) % n_cols)
|
|
||||||
for (row, col), (v_row, v_col) in zip(positions, velocities, strict=True)
|
|
||||||
]
|
|
||||||
|
|
||||||
midrow = n_rows // 2
|
|
||||||
midcol = n_cols // 2
|
|
||||||
|
|
||||||
yield prod(
|
|
||||||
(
|
|
||||||
sum(opr(row, midrow) and opc(col, midcol) for row, col in new_positions)
|
|
||||||
for opr, opc in it.product((op.gt, op.lt), repeat=2)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
new_positions = positions.copy()
|
|
||||||
for rnd in self.progress.wrap(range(10000)):
|
|
||||||
new_positions = [
|
|
||||||
((row + v_row) % n_rows, (col + v_col) % n_cols)
|
|
||||||
for (row, col), (v_row, v_col) in zip(
|
|
||||||
new_positions, velocities, strict=True
|
|
||||||
)
|
|
||||||
]
|
|
||||||
m = [[False for _ in range(n_cols)] for _ in range(n_rows)]
|
|
||||||
for row, col in new_positions:
|
|
||||||
m[row][col] = True
|
|
||||||
|
|
||||||
found = False
|
|
||||||
for row in m:
|
|
||||||
if sum(row) <= 10:
|
|
||||||
continue
|
|
||||||
if any(all(row[i : i + 10]) for i in range(n_cols - 10)):
|
|
||||||
if self.files:
|
|
||||||
self.files.create(
|
|
||||||
f"result_{rnd+1}.txt",
|
|
||||||
"\n".join(
|
|
||||||
"".join("#" if m[i][j] else "." for j in range(n_cols))
|
|
||||||
for i in range(n_rows)
|
|
||||||
).encode(),
|
|
||||||
True,
|
|
||||||
)
|
|
||||||
self.files.image(f"result_{rnd+1}.png", np.array(m))
|
|
||||||
yield rnd + 1
|
|
||||||
# found = True
|
|
||||||
break
|
|
||||||
|
|
||||||
if found:
|
|
||||||
break
|
|
||||||
|
|||||||
@@ -1,282 +1,7 @@
|
|||||||
from typing import Any, Callable, Final, Iterator, TypeAlias
|
from typing import Any, Iterator
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
from numpy.typing import NDArray
|
|
||||||
|
|
||||||
from ..base import BaseSolver
|
from ..base import BaseSolver
|
||||||
|
|
||||||
ImageGrid: TypeAlias = NDArray[np.uint8]
|
|
||||||
|
|
||||||
|
|
||||||
class Grid:
|
|
||||||
FREE: Final = 0
|
|
||||||
BLOCK: Final = 1
|
|
||||||
ROBOT: Final = 2
|
|
||||||
|
|
||||||
robot: tuple[int, int]
|
|
||||||
|
|
||||||
def __init__(self, grid_s: list[str], large: bool):
|
|
||||||
grid: list[list[int]] = []
|
|
||||||
robot: tuple[int, int] | None = None
|
|
||||||
box_counter = 4 if not large else 5
|
|
||||||
for i_row, row in enumerate(grid_s):
|
|
||||||
row_u: list[int] = []
|
|
||||||
for i_col, col in enumerate(row):
|
|
||||||
if col in ".@":
|
|
||||||
row_u.extend((Grid.FREE, Grid.FREE) if large else (Grid.FREE,))
|
|
||||||
if col == "@":
|
|
||||||
robot = (i_row, i_col * 2 if large else i_col)
|
|
||||||
elif col == "#":
|
|
||||||
row_u.extend((Grid.BLOCK, Grid.BLOCK) if large else (Grid.BLOCK,))
|
|
||||||
else:
|
|
||||||
row_u.extend(
|
|
||||||
(box_counter, -box_counter) if large else (box_counter,)
|
|
||||||
)
|
|
||||||
box_counter += 2
|
|
||||||
grid.append(row_u)
|
|
||||||
|
|
||||||
self.grid = np.array(grid)
|
|
||||||
|
|
||||||
assert robot is not None
|
|
||||||
self.robot = robot
|
|
||||||
|
|
||||||
@property
|
|
||||||
def n_rows(self):
|
|
||||||
return len(self.grid)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def n_columns(self):
|
|
||||||
return len(self.grid[0])
|
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
return self.n_rows
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
return iter(self.grid)
|
|
||||||
|
|
||||||
def __getitem__(self, index: tuple[int, int]):
|
|
||||||
return self.grid[*index]
|
|
||||||
|
|
||||||
def __setitem__(self, index: tuple[int, int], value: int):
|
|
||||||
self.grid[*index] = value
|
|
||||||
|
|
||||||
def is_free(self, row: int, col: int):
|
|
||||||
return self[row, col] == Grid.FREE
|
|
||||||
|
|
||||||
def is_block(self, row: int, col: int):
|
|
||||||
return self[row, col] == Grid.BLOCK
|
|
||||||
|
|
||||||
def is_box(self, row: int, col: int):
|
|
||||||
return (c := self[row, col]) >= 4 and c % 2 == 0
|
|
||||||
|
|
||||||
def is_open_or_close_box(self, row: int, col: int):
|
|
||||||
return abs(c := self[row, col]) >= 4 and c % 2 == 1
|
|
||||||
|
|
||||||
def is_open_box(self, row: int, col: int):
|
|
||||||
return (c := self[row, col]) >= 4 and c % 2 == 1
|
|
||||||
|
|
||||||
def is_close_box(self, row: int, col: int):
|
|
||||||
return self[row, col] < 0
|
|
||||||
|
|
||||||
def _to_char(self, row: int, col: int):
|
|
||||||
if self.is_free(row, col):
|
|
||||||
return "."
|
|
||||||
elif self.is_block(row, col):
|
|
||||||
return "#"
|
|
||||||
elif self.is_box(row, col):
|
|
||||||
return "O"
|
|
||||||
elif self.is_open_box(row, col):
|
|
||||||
return "["
|
|
||||||
else:
|
|
||||||
return "]"
|
|
||||||
|
|
||||||
def as_numpy(self):
|
|
||||||
arr = self.grid.copy()
|
|
||||||
arr[*self.robot] = Grid.ROBOT
|
|
||||||
return arr
|
|
||||||
|
|
||||||
def as_printable(self):
|
|
||||||
grid_s = [
|
|
||||||
[self._to_char(row, col) for col in range(self.n_columns)]
|
|
||||||
for row in range(self.n_rows)
|
|
||||||
]
|
|
||||||
grid_s[self.robot[0]][self.robot[1]] = "\033[31;1m@\033[00m"
|
|
||||||
return "\n".join("".join(row) for row in grid_s)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.as_printable()
|
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
class Solver(BaseSolver):
|
||||||
def save_grid(self, name: str, grid: Grid):
|
def solve(self, input: str) -> Iterator[Any]: ...
|
||||||
if self.files:
|
|
||||||
self.files.create(name, grid.as_printable().encode(), True)
|
|
||||||
|
|
||||||
def step_part1(self, grid: Grid, move: str):
|
|
||||||
match move:
|
|
||||||
case "^":
|
|
||||||
d_row, d_col = -1, 0
|
|
||||||
case ">":
|
|
||||||
d_row, d_col = 0, 1
|
|
||||||
case "v":
|
|
||||||
d_row, d_col = 1, 0
|
|
||||||
case "<":
|
|
||||||
d_row, d_col = 0, -1
|
|
||||||
case _:
|
|
||||||
assert False
|
|
||||||
|
|
||||||
row, col = grid.robot
|
|
||||||
if grid.is_free(row + d_row, col + d_col):
|
|
||||||
grid.robot = (row + d_row, col + d_col)
|
|
||||||
elif not grid.is_block(row + d_row, col + d_col):
|
|
||||||
n = 1
|
|
||||||
while grid.is_box(row + n * d_row, col + n * d_col):
|
|
||||||
n += 1
|
|
||||||
|
|
||||||
if grid.is_free(row + n * d_row, col + n * d_col):
|
|
||||||
grid.robot = (row + d_row, col + d_col)
|
|
||||||
for k in range(2, n + 1):
|
|
||||||
grid[row + k * d_row, col + k * d_col] = grid[
|
|
||||||
row + (k - 1) * d_row, col + (k - 1) * d_col
|
|
||||||
]
|
|
||||||
grid[row + d_row, col + d_col] = Grid.FREE
|
|
||||||
|
|
||||||
return grid
|
|
||||||
|
|
||||||
def step_part2(self, grid: Grid, move: str):
|
|
||||||
match move:
|
|
||||||
case "^":
|
|
||||||
d_row, d_col = -1, 0
|
|
||||||
case ">":
|
|
||||||
d_row, d_col = 0, 1
|
|
||||||
case "v":
|
|
||||||
d_row, d_col = 1, 0
|
|
||||||
case "<":
|
|
||||||
d_row, d_col = 0, -1
|
|
||||||
case _:
|
|
||||||
assert False
|
|
||||||
|
|
||||||
row, col = grid.robot
|
|
||||||
if grid.is_free(row + d_row, col + d_col):
|
|
||||||
grid.robot = (row + d_row, col + d_col)
|
|
||||||
elif grid.is_block(row + d_row, col + d_col):
|
|
||||||
...
|
|
||||||
elif move in "<>":
|
|
||||||
n = 1
|
|
||||||
while grid.is_open_or_close_box(row, col + n * d_col):
|
|
||||||
n += 1
|
|
||||||
|
|
||||||
if grid.is_free(row, col + n * d_col):
|
|
||||||
grid.robot = (row, col + d_col)
|
|
||||||
for k in range(n, 1, -1):
|
|
||||||
grid[row, col + k * d_col] = grid[row, col + (k - 1) * d_col]
|
|
||||||
grid[row + d_row, col + d_col] = Grid.FREE
|
|
||||||
|
|
||||||
elif move in "^v":
|
|
||||||
n = 1
|
|
||||||
boxes: list[set[int]] = [{col}]
|
|
||||||
while True:
|
|
||||||
to_move = boxes[-1]
|
|
||||||
if any(grid.is_block(row + n * d_row, c) for c in to_move):
|
|
||||||
break
|
|
||||||
if all(grid.is_free(row + n * d_row, c) for c in to_move):
|
|
||||||
break
|
|
||||||
|
|
||||||
as_move: set[int] = set()
|
|
||||||
|
|
||||||
for c in to_move:
|
|
||||||
if grid.is_close_box(row + n * d_row, c):
|
|
||||||
as_move.update({c - 1, c})
|
|
||||||
elif grid.is_open_box(row + n * d_row, c):
|
|
||||||
as_move.update({c, c + 1})
|
|
||||||
|
|
||||||
boxes.append(as_move)
|
|
||||||
n += 1
|
|
||||||
|
|
||||||
if all(grid.is_free(row + n * d_row, c) for c in boxes[-1]):
|
|
||||||
for k, to_move in zip(range(n, 1, -1), boxes[-1:0:-1], strict=True):
|
|
||||||
for c in to_move:
|
|
||||||
grid[row + k * d_row, c] = grid[row + (k - 1) * d_row, c]
|
|
||||||
grid[row + (k - 1) * d_row, c] = Grid.FREE
|
|
||||||
grid.robot = (row + d_row, col + d_col)
|
|
||||||
|
|
||||||
return grid
|
|
||||||
|
|
||||||
def run(
|
|
||||||
self,
|
|
||||||
name: str,
|
|
||||||
grid: Grid,
|
|
||||||
moves: str,
|
|
||||||
fn: Callable[[Grid, str], Grid],
|
|
||||||
generate: bool,
|
|
||||||
) -> tuple[Grid, list[ImageGrid]]:
|
|
||||||
# initialize
|
|
||||||
images: list[ImageGrid] = []
|
|
||||||
|
|
||||||
if generate:
|
|
||||||
images.append(grid.as_numpy())
|
|
||||||
|
|
||||||
self.save_grid(f"initial_grid_{name}.txt", grid)
|
|
||||||
|
|
||||||
for move in self.progress.wrap(moves):
|
|
||||||
self.logger.debug(f"Move '{move}'...")
|
|
||||||
grid = fn(grid, move)
|
|
||||||
|
|
||||||
if generate:
|
|
||||||
images.append(grid.as_numpy())
|
|
||||||
|
|
||||||
self.save_grid(f"final_grid_{name}.txt", grid)
|
|
||||||
|
|
||||||
return grid, images
|
|
||||||
|
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
grid_s, moves = input.split("\n\n")
|
|
||||||
moves = "".join(moves.split())
|
|
||||||
|
|
||||||
n_boxes = grid_s.count("O")
|
|
||||||
colors = np.concatenate(
|
|
||||||
[
|
|
||||||
np.array(
|
|
||||||
[[255, 255, 255], [64, 64, 64], [255, 0, 0]],
|
|
||||||
dtype=np.uint8,
|
|
||||||
),
|
|
||||||
np.random.randint(0, 256, size=(n_boxes, 3), dtype=np.uint8),
|
|
||||||
],
|
|
||||||
dtype=np.uint8,
|
|
||||||
)
|
|
||||||
|
|
||||||
grid, images = self.run(
|
|
||||||
"part1",
|
|
||||||
Grid(grid_s.splitlines(), False),
|
|
||||||
moves,
|
|
||||||
self.step_part1,
|
|
||||||
self.files is not None,
|
|
||||||
)
|
|
||||||
if self.files:
|
|
||||||
images = np.stack(images, axis=0)
|
|
||||||
images[images >= 2] = 1 + images[images >= 2] // 2
|
|
||||||
self.files.video("anim_part1.webm", colors[images])
|
|
||||||
yield sum(
|
|
||||||
100 * row + col
|
|
||||||
for row in range(grid.n_rows)
|
|
||||||
for col in range(grid.n_columns)
|
|
||||||
if grid.is_box(row, col)
|
|
||||||
)
|
|
||||||
|
|
||||||
grid, images = self.run(
|
|
||||||
"part2",
|
|
||||||
Grid(grid_s.splitlines(), True),
|
|
||||||
moves,
|
|
||||||
self.step_part2,
|
|
||||||
self.files is not None,
|
|
||||||
)
|
|
||||||
if self.files:
|
|
||||||
images = np.abs(np.stack(images, axis=0))
|
|
||||||
images[images >= 2] = 1 + images[images >= 2] // 2
|
|
||||||
self.files.video("anim_part2.webm", colors[images])
|
|
||||||
yield sum(
|
|
||||||
100 * row + col
|
|
||||||
for row in range(grid.n_rows)
|
|
||||||
for col in range(grid.n_columns)
|
|
||||||
if grid.is_open_box(row, col)
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -1,62 +1,7 @@
|
|||||||
import heapq
|
from typing import Any, Iterator
|
||||||
from collections import defaultdict
|
|
||||||
from typing import Any, Iterator, TypeAlias
|
|
||||||
|
|
||||||
from ..base import BaseSolver
|
from ..base import BaseSolver
|
||||||
|
|
||||||
Position: TypeAlias = tuple[int, int]
|
|
||||||
Direction: TypeAlias = tuple[int, int]
|
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
class Solver(BaseSolver):
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
def solve(self, input: str) -> Iterator[Any]: ...
|
||||||
grid = [list(r) for r in input.splitlines()]
|
|
||||||
n_rows, n_cols = len(grid), len(grid[0])
|
|
||||||
rein = next(
|
|
||||||
(i, j) for i in range(n_rows) for j in range(n_cols) if grid[i][j] == "S"
|
|
||||||
)
|
|
||||||
target = next(
|
|
||||||
(i, j) for i in range(n_rows) for j in range(n_cols) if grid[i][j] == "E"
|
|
||||||
)
|
|
||||||
|
|
||||||
queue: list[tuple[int, Position, Direction, tuple[Position, ...]]] = [
|
|
||||||
(0, rein, (0, 1), (rein,))
|
|
||||||
]
|
|
||||||
|
|
||||||
max_score = n_rows * n_cols * 1000
|
|
||||||
target_score: int = max_score
|
|
||||||
scores: dict[tuple[Position, Direction], int] = defaultdict(lambda: max_score)
|
|
||||||
visited: set[Position] = set()
|
|
||||||
|
|
||||||
while queue:
|
|
||||||
score, pos, dir, path = heapq.heappop(queue)
|
|
||||||
|
|
||||||
if target_score < score:
|
|
||||||
break
|
|
||||||
|
|
||||||
if pos == target:
|
|
||||||
target_score = score
|
|
||||||
visited |= set(path)
|
|
||||||
continue
|
|
||||||
|
|
||||||
scores[pos, dir] = score
|
|
||||||
|
|
||||||
row, col = pos
|
|
||||||
d_row, d_col = dir
|
|
||||||
|
|
||||||
for cost, n_pos, n_dir in (
|
|
||||||
(1, (row + d_row, col + d_col), dir),
|
|
||||||
(1000, pos, (1, 0) if d_row == 0 else (0, 1)),
|
|
||||||
(1000, pos, (-1, 0) if d_row == 0 else (0, -1)),
|
|
||||||
):
|
|
||||||
n_row, n_col = n_pos
|
|
||||||
score_n = score + cost
|
|
||||||
if grid[n_row][n_col] != "#" and score_n < scores[n_pos, n_dir]:
|
|
||||||
heapq.heappush(
|
|
||||||
queue,
|
|
||||||
(score_n, n_pos, n_dir, path + (n_pos,)),
|
|
||||||
)
|
|
||||||
|
|
||||||
assert target_score is not None
|
|
||||||
yield target_score
|
|
||||||
yield len(visited)
|
|
||||||
|
|||||||
@@ -3,128 +3,5 @@ from typing import Any, Iterator
|
|||||||
from ..base import BaseSolver
|
from ..base import BaseSolver
|
||||||
|
|
||||||
|
|
||||||
def combo(registers: dict[str, int], operand: int):
|
|
||||||
if operand < 4:
|
|
||||||
return operand
|
|
||||||
assert operand < 7
|
|
||||||
return registers["ABC"[operand - 4]]
|
|
||||||
|
|
||||||
|
|
||||||
def adv(registers: dict[str, int], operand: int) -> int | None:
|
|
||||||
registers["A"] = registers["A"] >> combo(registers, operand)
|
|
||||||
|
|
||||||
|
|
||||||
def bxl(registers: dict[str, int], operand: int) -> int | None:
|
|
||||||
registers["B"] ^= operand
|
|
||||||
|
|
||||||
|
|
||||||
def bst(registers: dict[str, int], operand: int) -> int | None:
|
|
||||||
registers["B"] = combo(registers, operand) % 8
|
|
||||||
|
|
||||||
|
|
||||||
def jnz(registers: dict[str, int], operand: int) -> int | None:
|
|
||||||
if registers["A"] != 0:
|
|
||||||
return operand
|
|
||||||
|
|
||||||
|
|
||||||
def bxc(registers: dict[str, int], operand: int) -> int | None:
|
|
||||||
registers["B"] = registers["B"] ^ registers["C"]
|
|
||||||
|
|
||||||
|
|
||||||
def bdv(registers: dict[str, int], operand: int) -> int | None:
|
|
||||||
registers["B"] = registers["A"] >> combo(registers, operand)
|
|
||||||
|
|
||||||
|
|
||||||
def cdv(registers: dict[str, int], operand: int) -> int | None:
|
|
||||||
registers["C"] = registers["A"] >> combo(registers, operand)
|
|
||||||
|
|
||||||
|
|
||||||
def run(registers: dict[str, int], program: list[int]):
|
|
||||||
outputs: list[int] = []
|
|
||||||
|
|
||||||
def out(registers: dict[str, int], operand: int) -> int | None:
|
|
||||||
outputs.append(combo(registers, operand) % 8)
|
|
||||||
|
|
||||||
instructions = [adv, bxl, bst, jnz, bxc, out, bdv, cdv]
|
|
||||||
|
|
||||||
index = 0
|
|
||||||
while index < len(program):
|
|
||||||
instruction, operand = instructions[program[index]], program[index + 1]
|
|
||||||
|
|
||||||
ret = instruction(registers, operand)
|
|
||||||
|
|
||||||
if ret is None:
|
|
||||||
index += 2
|
|
||||||
else:
|
|
||||||
index = ret
|
|
||||||
|
|
||||||
return outputs
|
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
class Solver(BaseSolver):
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
def solve(self, input: str) -> Iterator[Any]: ...
|
||||||
register_s, program_s = input.split("\n\n")
|
|
||||||
|
|
||||||
registers = {
|
|
||||||
p[0][-1]: int(p[1].strip())
|
|
||||||
for line in register_s.splitlines()
|
|
||||||
if (p := line.split(":"))
|
|
||||||
}
|
|
||||||
program = [int(c) for c in program_s.split(":")[1].strip().split(",")]
|
|
||||||
|
|
||||||
self.logger.info(f"program ({len(program)}): " + ",".join(map(str, program)))
|
|
||||||
|
|
||||||
instruction_s = [
|
|
||||||
"A = A >> {}",
|
|
||||||
"B = B ^ {}",
|
|
||||||
"B = {} % 8",
|
|
||||||
"JMP {}",
|
|
||||||
"B = B ^ C",
|
|
||||||
"OUT {} % 8",
|
|
||||||
"B = A >> {}",
|
|
||||||
"C = A >> {}",
|
|
||||||
]
|
|
||||||
|
|
||||||
self.logger.info("PROGRAM:")
|
|
||||||
for index in range(0, len(program), 2):
|
|
||||||
self.logger.info(
|
|
||||||
instruction_s[program[index]].format(
|
|
||||||
""
|
|
||||||
if program[index] == 4
|
|
||||||
else (
|
|
||||||
program[index + 1]
|
|
||||||
if program[index] in (1, 3) or program[index + 1] < 4
|
|
||||||
else "ABC"[program[index + 1] - 4]
|
|
||||||
)
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
yield ",".join(map(str, run(registers.copy(), program)))
|
|
||||||
|
|
||||||
# last instruction is JNZ 0 (jump at the beginning), and it is the only jump
|
|
||||||
# in the program
|
|
||||||
jnz_indices = [i for i in range(0, len(program), 2) if program[i] == 3]
|
|
||||||
assert jnz_indices == [len(program) - 2] and program[-1] == 0
|
|
||||||
|
|
||||||
# previous instruction is dividing A by 8, or A = A >> 3
|
|
||||||
assert program[-4:-2] == [0, 3]
|
|
||||||
|
|
||||||
# previous instruction is a OUT B % 8, and it is the only OUT in the program
|
|
||||||
out_indices = [i for i in range(0, len(program), 2) if program[i] == 5]
|
|
||||||
assert out_indices == [len(program) - 6] and program[len(program) - 5] == 5
|
|
||||||
|
|
||||||
valid: list[int] = [0]
|
|
||||||
for p in reversed(program):
|
|
||||||
new_valid: list[int] = []
|
|
||||||
for v in valid:
|
|
||||||
a_high = v << 3
|
|
||||||
for a_low in range(0, 2**3):
|
|
||||||
registers["A"] = a_high | a_low
|
|
||||||
run(registers, program[:-6])
|
|
||||||
if registers["B"] % 8 == p:
|
|
||||||
new_valid.append(a_high | a_low)
|
|
||||||
valid = new_valid
|
|
||||||
|
|
||||||
assert run(registers | {"A": min(valid)}, program) == program
|
|
||||||
|
|
||||||
yield min(valid)
|
|
||||||
|
|||||||
@@ -1,58 +1,7 @@
|
|||||||
from typing import Any, Iterator
|
from typing import Any, Iterator
|
||||||
|
|
||||||
from ..base import BaseSolver
|
from ..base import BaseSolver
|
||||||
from ..tools import graphs
|
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
class Solver(BaseSolver):
|
||||||
def print_grid(self, grid: list[tuple[int, int]], n_rows: int, n_cols: int):
|
def solve(self, input: str) -> Iterator[Any]: ...
|
||||||
values = set(grid)
|
|
||||||
if self.files:
|
|
||||||
self.files.create(
|
|
||||||
"graph.txt",
|
|
||||||
"\n".join(
|
|
||||||
"".join(
|
|
||||||
"#" if (row, col) in values else "." for col in range(n_cols)
|
|
||||||
)
|
|
||||||
for row in range(n_rows)
|
|
||||||
).encode(),
|
|
||||||
text=True,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
for row in range(n_rows):
|
|
||||||
self.logger.info(
|
|
||||||
"".join(
|
|
||||||
"#" if (row, col) in values else "." for col in range(n_cols)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def dijkstra(self, corrupted: list[tuple[int, int]], n_rows: int, n_cols: int):
|
|
||||||
return graphs.dijkstra(
|
|
||||||
(0, 0),
|
|
||||||
(n_rows - 1, n_cols - 1),
|
|
||||||
graphs.make_neighbors_grid_fn(n_rows, n_cols, set(corrupted)),
|
|
||||||
)
|
|
||||||
|
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
values = [
|
|
||||||
(int(p[0]), int(p[1])) for r in input.splitlines() if (p := r.split(","))
|
|
||||||
]
|
|
||||||
|
|
||||||
_is_test = len(values) < 100
|
|
||||||
|
|
||||||
n_rows, n_cols, n_bytes_p1 = (7, 7, 12) if _is_test else (71, 71, 1024)
|
|
||||||
|
|
||||||
bytes_p1 = values[:n_bytes_p1]
|
|
||||||
self.print_grid(bytes_p1, n_rows, n_cols)
|
|
||||||
|
|
||||||
path_p1, cost_p1 = self.dijkstra(bytes_p1, n_rows, n_cols) or ((), -1)
|
|
||||||
yield cost_p1
|
|
||||||
|
|
||||||
path = path_p1
|
|
||||||
for b in range(n_bytes_p1, len(values)):
|
|
||||||
if values[b] not in path:
|
|
||||||
continue
|
|
||||||
path, _ = self.dijkstra(values[: b + 1], n_rows, n_cols) or (None, -1)
|
|
||||||
if path is None:
|
|
||||||
yield ",".join(map(str, values[b]))
|
|
||||||
break
|
|
||||||
|
|||||||
@@ -1,42 +1,7 @@
|
|||||||
from functools import cache
|
|
||||||
from typing import Any, Iterator
|
from typing import Any, Iterator
|
||||||
|
|
||||||
from ..base import BaseSolver
|
from ..base import BaseSolver
|
||||||
|
|
||||||
|
|
||||||
@cache
|
|
||||||
def is_valid(design: str, towels: tuple[str, ...]) -> bool:
|
|
||||||
if not design:
|
|
||||||
return True
|
|
||||||
|
|
||||||
return any(
|
|
||||||
design.startswith(towel) and is_valid(design[len(towel) :], towels)
|
|
||||||
for towel in towels
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@cache
|
|
||||||
def count_valid(design: str, towels: tuple[str, ...]) -> int:
|
|
||||||
if not design:
|
|
||||||
return 1
|
|
||||||
|
|
||||||
return sum(
|
|
||||||
design.startswith(towel) and count_valid(design[len(towel) :], towels)
|
|
||||||
for towel in towels
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
class Solver(BaseSolver):
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
def solve(self, input: str) -> Iterator[Any]: ...
|
||||||
towels_s, designs_s = input.split("\n\n")
|
|
||||||
|
|
||||||
towels = tuple(s.strip() for s in towels_s.split(","))
|
|
||||||
|
|
||||||
designs = [
|
|
||||||
design
|
|
||||||
for design in self.progress.wrap(designs_s.splitlines())
|
|
||||||
if is_valid(design, towels)
|
|
||||||
]
|
|
||||||
|
|
||||||
yield len(designs)
|
|
||||||
yield sum(count_valid(design, towels) for design in self.progress.wrap(designs))
|
|
||||||
|
|||||||
@@ -1,95 +1,7 @@
|
|||||||
import itertools
|
from typing import Any, Iterator
|
||||||
from collections import Counter
|
|
||||||
from typing import Any, Callable, Iterable, Iterator, Sequence, TypeAlias
|
|
||||||
|
|
||||||
from ..base import BaseSolver
|
from ..base import BaseSolver
|
||||||
from ..tools.graphs import dijkstra, make_neighbors_grid_fn
|
|
||||||
|
|
||||||
Node: TypeAlias = tuple[int, int]
|
|
||||||
|
|
||||||
|
|
||||||
def make_neighbors_fn(grid: list[str], cheat_length: int):
|
|
||||||
n_rows, n_cols = len(grid), len(grid[0])
|
|
||||||
|
|
||||||
def _fn(node: Node):
|
|
||||||
row, col = node
|
|
||||||
return (
|
|
||||||
((row_n, col_n), abs(row_n - row) + abs(col_n - col))
|
|
||||||
for row_d in range(-cheat_length, cheat_length + 1)
|
|
||||||
for col_d in range(
|
|
||||||
-cheat_length + abs(row_d), cheat_length - abs(row_d) + 1
|
|
||||||
)
|
|
||||||
if 0 <= (row_n := row + row_d) < n_rows
|
|
||||||
and 0 <= (col_n := col + col_d) < n_cols
|
|
||||||
and grid[row_n][col_n] != "#"
|
|
||||||
)
|
|
||||||
|
|
||||||
return _fn
|
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
class Solver(BaseSolver):
|
||||||
def find_cheats(
|
def solve(self, input: str) -> Iterator[Any]: ...
|
||||||
self,
|
|
||||||
path: Sequence[Node],
|
|
||||||
cost: float,
|
|
||||||
costs_to_target: dict[Node, float],
|
|
||||||
neighbors_fn: Callable[[Node], Iterable[tuple[Node, float]]],
|
|
||||||
):
|
|
||||||
cheats: dict[tuple[tuple[int, int], tuple[int, int]], float] = {}
|
|
||||||
|
|
||||||
for i_node, node in enumerate(self.progress.wrap(path)):
|
|
||||||
for reach_node, reach_cost in neighbors_fn(node):
|
|
||||||
n_cost = (
|
|
||||||
i_node + reach_cost + costs_to_target.get(reach_node, float("inf"))
|
|
||||||
)
|
|
||||||
if n_cost < cost:
|
|
||||||
cheats[node, reach_node] = cost - n_cost
|
|
||||||
|
|
||||||
return cheats
|
|
||||||
|
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
grid = input.splitlines()
|
|
||||||
n_rows, n_cols = len(grid), len(grid[0])
|
|
||||||
start = next(
|
|
||||||
(i, j) for i in range(n_rows) for j in range(n_cols) if grid[i][j] == "S"
|
|
||||||
)
|
|
||||||
target = next(
|
|
||||||
(i, j) for i in range(n_rows) for j in range(n_cols) if grid[i][j] == "E"
|
|
||||||
)
|
|
||||||
|
|
||||||
reachable = dijkstra(
|
|
||||||
target,
|
|
||||||
None,
|
|
||||||
make_neighbors_grid_fn(
|
|
||||||
n_rows,
|
|
||||||
n_cols,
|
|
||||||
excluded=(
|
|
||||||
(i, j)
|
|
||||||
for i in range(n_rows)
|
|
||||||
for j in range(n_cols)
|
|
||||||
if grid[i][j] == "#"
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
# note: path is inverted here
|
|
||||||
path, cost = reachable[start]
|
|
||||||
costs_to_target = {k: c for k, (_, c) in reachable.items()}
|
|
||||||
|
|
||||||
self.logger.info(f"found past from start to target with cost {cost}")
|
|
||||||
|
|
||||||
for cheat_length in (2, 20):
|
|
||||||
cheats = self.find_cheats(
|
|
||||||
list(reversed(path)),
|
|
||||||
cost,
|
|
||||||
costs_to_target,
|
|
||||||
make_neighbors_fn(grid, cheat_length),
|
|
||||||
)
|
|
||||||
|
|
||||||
for saving, count in sorted(Counter(cheats.values()).items()):
|
|
||||||
self.logger.debug(
|
|
||||||
f"There are {count} cheats that save {saving} picoseconds."
|
|
||||||
)
|
|
||||||
|
|
||||||
target_saving = 100 if len(grid) > 20 else 50
|
|
||||||
yield sum(saving >= target_saving for saving in cheats.values())
|
|
||||||
|
|||||||
@@ -1,85 +1,7 @@
|
|||||||
import itertools
|
from typing import Any, Iterator
|
||||||
from functools import cache
|
|
||||||
from typing import Any, Iterator, Literal
|
|
||||||
|
|
||||||
from ..base import BaseSolver
|
from ..base import BaseSolver
|
||||||
|
|
||||||
NUM_PAD_P = {
|
|
||||||
v: (i, j)
|
|
||||||
for i, r in enumerate(("789", "456", "123", " 0A"))
|
|
||||||
for j, v in enumerate(r)
|
|
||||||
if v.strip()
|
|
||||||
}
|
|
||||||
MOV_PAD_P = {
|
|
||||||
v: (i, j)
|
|
||||||
for i, r in enumerate((" ^A", "<v>"))
|
|
||||||
for j, v in enumerate(r)
|
|
||||||
if v.strip()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def path(start: tuple[int, int], end: tuple[int, int], pad: Literal["num", "mov"]):
|
|
||||||
# a move in the grid is composed of at most two straight line: up/down and
|
|
||||||
# left/right, since doing some kind of diagonal moves would create long path for
|
|
||||||
# the robot above (since this involves going back-and-forth to the letter 'A')
|
|
||||||
#
|
|
||||||
row_s, col_s = start
|
|
||||||
row_e, col_e = end
|
|
||||||
|
|
||||||
le, de, ue, re = (
|
|
||||||
"<" * max(0, col_s - col_e),
|
|
||||||
"v" * max(0, row_e - row_s),
|
|
||||||
"^" * max(0, row_s - row_e),
|
|
||||||
">" * max(0, col_e - col_s),
|
|
||||||
)
|
|
||||||
|
|
||||||
# when the robot starts or ends on the row/column with the empty cell, there is
|
|
||||||
# only one way to move
|
|
||||||
#
|
|
||||||
if pad == "num" and (row_s, col_e) == (3, 0):
|
|
||||||
return ue + le
|
|
||||||
elif pad == "num" and (col_s, row_e) == (0, 3):
|
|
||||||
return re + de
|
|
||||||
elif pad == "mov" and col_s == 0:
|
|
||||||
return re + ue
|
|
||||||
elif pad == "mov" and col_e == 0:
|
|
||||||
return de + le
|
|
||||||
|
|
||||||
# otherwise, we need to decide if we want to go up/down first, or left/right, and
|
|
||||||
# apparently this is the best way to do it...
|
|
||||||
return le + de + ue + re
|
|
||||||
|
|
||||||
|
|
||||||
@cache
|
|
||||||
def v_clicks(clicks: str, depth: int) -> int:
|
|
||||||
if depth == 0:
|
|
||||||
return len(clicks)
|
|
||||||
|
|
||||||
n_clicks = 0
|
|
||||||
at = "A"
|
|
||||||
for _, group in itertools.groupby(clicks):
|
|
||||||
group = list(group)
|
|
||||||
n_clicks += v_clicks(
|
|
||||||
path(MOV_PAD_P[at], MOV_PAD_P[group[0]], "mov") + "A" * len(group),
|
|
||||||
depth - 1,
|
|
||||||
)
|
|
||||||
at = group[0]
|
|
||||||
|
|
||||||
return n_clicks
|
|
||||||
|
|
||||||
|
|
||||||
def path_length(code: str, depth: int):
|
|
||||||
return sum(
|
|
||||||
v_clicks(path(NUM_PAD_P[start], NUM_PAD_P[end], "num") + "A", depth)
|
|
||||||
for start, end in zip("A" + code[:-1], code, strict=True)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
class Solver(BaseSolver):
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
def solve(self, input: str) -> Iterator[Any]: ...
|
||||||
yield sum(
|
|
||||||
path_length(code, 2) * int(code[:-1], 10) for code in input.splitlines()
|
|
||||||
)
|
|
||||||
yield sum(
|
|
||||||
path_length(code, 25) * int(code[:-1], 10) for code in input.splitlines()
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -3,57 +3,5 @@ from typing import Any, Iterator
|
|||||||
from ..base import BaseSolver
|
from ..base import BaseSolver
|
||||||
|
|
||||||
|
|
||||||
def mix(secret: int, value: int) -> int:
|
|
||||||
return secret ^ value
|
|
||||||
|
|
||||||
|
|
||||||
def prune(secret: int) -> int:
|
|
||||||
return secret % 16777216
|
|
||||||
|
|
||||||
|
|
||||||
def next_number(secret: int) -> int:
|
|
||||||
# Calculate the result of multiplying the secret number by 64. Then, mix this
|
|
||||||
# result into the secret number. Finally, prune the secret number.
|
|
||||||
secret = prune(mix(secret, secret * 64))
|
|
||||||
|
|
||||||
# Calculate the result of dividing the secret number by 32. Round the result down
|
|
||||||
# to the nearest integer. Then, mix this result into the secret number. Finally,
|
|
||||||
# prune the secret number.
|
|
||||||
secret = prune(mix(secret, secret // 32))
|
|
||||||
|
|
||||||
# Calculate the result of multiplying the secret number by 2048. Then, mix this
|
|
||||||
# result into the secret number. Finally, prune the secret number.
|
|
||||||
secret = prune(mix(secret, secret * 2048))
|
|
||||||
|
|
||||||
return secret
|
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
class Solver(BaseSolver):
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
def solve(self, input: str) -> Iterator[Any]: ...
|
||||||
starts = [int(r) for r in input.splitlines()]
|
|
||||||
|
|
||||||
ends: list[int] = []
|
|
||||||
prices: list[int] = [0 for _ in range(2**16)]
|
|
||||||
|
|
||||||
for secret in self.progress.wrap(starts):
|
|
||||||
checked: list[bool] = [False] * len(prices)
|
|
||||||
hashed: int = 0
|
|
||||||
|
|
||||||
for i in range(2000):
|
|
||||||
last = secret % 10
|
|
||||||
secret = next_number(secret)
|
|
||||||
next = secret % 10
|
|
||||||
|
|
||||||
hashed = ((hashed << 4) & 0xFFFF) | ((last - next) & 0xF)
|
|
||||||
|
|
||||||
if i >= 3 and not checked[hashed]:
|
|
||||||
checked[hashed] = True
|
|
||||||
prices[hashed] += next
|
|
||||||
|
|
||||||
ends.append(secret)
|
|
||||||
|
|
||||||
for start, end in zip(starts, ends, strict=True):
|
|
||||||
self.logger.info(f"{start}: {end}")
|
|
||||||
|
|
||||||
yield sum(ends)
|
|
||||||
yield max(prices)
|
|
||||||
|
|||||||
@@ -1,36 +1,7 @@
|
|||||||
from collections import defaultdict
|
|
||||||
from typing import Any, Iterator
|
from typing import Any, Iterator
|
||||||
|
|
||||||
from ..base import BaseSolver
|
from ..base import BaseSolver
|
||||||
from ..tools.graphs import iter_max_cliques
|
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
class Solver(BaseSolver):
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
def solve(self, input: str) -> Iterator[Any]: ...
|
||||||
connections: dict[str, set[str]] = defaultdict(set)
|
|
||||||
for row in input.splitlines():
|
|
||||||
src, dst = row.split("-")
|
|
||||||
connections[src].add(dst)
|
|
||||||
connections[dst].add(src)
|
|
||||||
|
|
||||||
if self.files:
|
|
||||||
content = "graph G {\n"
|
|
||||||
for row in input.splitlines():
|
|
||||||
src, dst = row.split("-")
|
|
||||||
content += f"{src} -- {dst}\n"
|
|
||||||
content += "}"
|
|
||||||
self.files.create("graph.dot", content.encode(), False)
|
|
||||||
|
|
||||||
cliques: set[frozenset[str]] = set()
|
|
||||||
|
|
||||||
for node1, neighbors in connections.items():
|
|
||||||
for node2 in neighbors:
|
|
||||||
for node3 in connections[node2].intersection(neighbors):
|
|
||||||
cliques.add(frozenset({node1, node2, node3}))
|
|
||||||
|
|
||||||
self.logger.info(f"found {len(cliques)} cliques of size 3")
|
|
||||||
yield sum(any(node.startswith("t") for node in clique) for clique in cliques)
|
|
||||||
|
|
||||||
# clique = max(nx.algorithms.clique.find_cliques(G), key=len)
|
|
||||||
clique = max(iter_max_cliques(connections), key=len)
|
|
||||||
yield ",".join(sorted(clique))
|
|
||||||
|
|||||||
@@ -1,170 +1,7 @@
|
|||||||
from dataclasses import dataclass
|
from typing import Any, Iterator
|
||||||
from typing import Any, Iterator, Literal, TypeAlias, cast
|
|
||||||
|
|
||||||
from ..base import BaseSolver
|
from ..base import BaseSolver
|
||||||
|
|
||||||
GateType: TypeAlias = Literal["and", "or", "xor"]
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True, eq=True)
|
|
||||||
class Gate:
|
|
||||||
type: GateType
|
|
||||||
lhs: str
|
|
||||||
rhs: str
|
|
||||||
|
|
||||||
def __call__(self, lhs: int, rhs: int) -> Any:
|
|
||||||
match self.type:
|
|
||||||
case "or":
|
|
||||||
return int(lhs or rhs)
|
|
||||||
case "and":
|
|
||||||
return int(lhs and rhs)
|
|
||||||
case "xor":
|
|
||||||
return int(lhs != rhs)
|
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
class Solver(BaseSolver):
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
def solve(self, input: str) -> Iterator[Any]: ...
|
||||||
inputs_s, gates_s = input.split("\n\n")
|
|
||||||
|
|
||||||
wires: dict[str, int | None] = {}
|
|
||||||
for row in inputs_s.splitlines():
|
|
||||||
parts = row.split(": ")
|
|
||||||
wires[parts[0]] = int(parts[1])
|
|
||||||
|
|
||||||
gates: dict[str, Gate] = {}
|
|
||||||
for row in gates_s.splitlines():
|
|
||||||
parts = row.split()
|
|
||||||
assert parts[4] not in gates
|
|
||||||
assert parts[4] not in wires
|
|
||||||
|
|
||||||
lhs, rhs = sorted([parts[0], parts[2]])
|
|
||||||
|
|
||||||
gates[parts[4]] = Gate(cast(GateType, parts[1].lower()), lhs, rhs)
|
|
||||||
wires[parts[4]] = None
|
|
||||||
|
|
||||||
if self.files:
|
|
||||||
content = "digraph G {\n"
|
|
||||||
for wire in wires:
|
|
||||||
content += f'{wire} [label="{wire}"]\n'
|
|
||||||
for wire, gate in gates.items():
|
|
||||||
gate_n = f"G_{wire}"
|
|
||||||
content += f'{gate_n} [label="{gate.type.upper()}"]\n'
|
|
||||||
content += f"{gate.lhs} -> {gate_n}\n"
|
|
||||||
content += f"{gate.rhs} -> {gate_n}\n"
|
|
||||||
content += f"{gate_n} -> {wire}\n"
|
|
||||||
content += "}\n"
|
|
||||||
self.files.create("gates.dot", content.encode(), text=False)
|
|
||||||
|
|
||||||
wires_to_find = set(gates)
|
|
||||||
|
|
||||||
while wires_to_find:
|
|
||||||
wires_found: list[str] = []
|
|
||||||
for wire in wires_to_find:
|
|
||||||
gate = gates[wire]
|
|
||||||
|
|
||||||
lhs, rhs = wires[gate.lhs], wires[gate.rhs]
|
|
||||||
|
|
||||||
if lhs is None or rhs is None:
|
|
||||||
continue
|
|
||||||
|
|
||||||
assert wires[wire] is None
|
|
||||||
wires[wire] = gate(lhs, rhs)
|
|
||||||
|
|
||||||
wires_found.append(wire)
|
|
||||||
|
|
||||||
wires_to_find.difference_update(wires_found)
|
|
||||||
|
|
||||||
z_wires = sorted((wire for wire in wires if wire.startswith("z")))
|
|
||||||
self.logger.info(
|
|
||||||
"binary value is '{}'".format(
|
|
||||||
"".join(str(wires[w]) for w in reversed(z_wires))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
yield int("".join(str(wires[w]) for w in reversed(z_wires)), base=2)
|
|
||||||
|
|
||||||
# e00 = x00 ^ y00
|
|
||||||
# z00 = e00
|
|
||||||
# r00 = x00 & y00
|
|
||||||
|
|
||||||
# e01 = x01 ^ y01
|
|
||||||
# z01 = r00 ^ e01
|
|
||||||
# a01 = x01 & y01
|
|
||||||
# b01 = r00 & e01
|
|
||||||
# r01 = a01 | (r00 & e01)
|
|
||||||
|
|
||||||
assert gates["z00"] == Gate("xor", "x00", "y00")
|
|
||||||
|
|
||||||
# normalized names -> gate name
|
|
||||||
m_gates: dict[str, str] = {}
|
|
||||||
|
|
||||||
def find_gate(type: GateType, lhs: str, rhs: str):
|
|
||||||
try:
|
|
||||||
return next(
|
|
||||||
wire
|
|
||||||
for wire, gate in gates.items()
|
|
||||||
if gate.type == type
|
|
||||||
and {gate.lhs, gate.rhs}
|
|
||||||
== {m_gates.get(lhs, lhs), m_gates.get(rhs, rhs)}
|
|
||||||
)
|
|
||||||
except StopIteration as ex:
|
|
||||||
self.logger.info(
|
|
||||||
f"gate {lhs} [{m_gates.get(lhs, lhs)}] {type} {rhs} [{m_gates.get(rhs, rhs)}] not found"
|
|
||||||
)
|
|
||||||
raise ex
|
|
||||||
|
|
||||||
# find the r00 gate (= x00 & y00)
|
|
||||||
m_gates["r00"] = find_gate("and", "x00", "y00")
|
|
||||||
|
|
||||||
swapped: list[str] = []
|
|
||||||
|
|
||||||
for i_wire, z_wire in enumerate(z_wires[1:-1], start=1):
|
|
||||||
i2d = f"{i_wire:02d}"
|
|
||||||
r0n = f"r{i_wire - 1:02d}"
|
|
||||||
m_gates[f"e{i2d}"] = find_gate("xor", f"x{i2d}", f"y{i2d}")
|
|
||||||
|
|
||||||
try:
|
|
||||||
z_gate = find_gate("xor", r0n, f"e{i2d}")
|
|
||||||
except StopIteration:
|
|
||||||
# gate xor not found -> one of the input gate has been swapped
|
|
||||||
#
|
|
||||||
# assume there is a XOR gate with the remainder, so it is the other
|
|
||||||
# input that has been swapped
|
|
||||||
assert gates[z_wire].type == "xor"
|
|
||||||
assert m_gates.get(r0n, r0n) in (gates[z_wire].lhs, gates[z_wire].rhs)
|
|
||||||
|
|
||||||
wrong_wire_1 = (
|
|
||||||
gates[z_wire].lhs
|
|
||||||
if gates[z_wire].rhs == m_gates.get(r0n, r0n)
|
|
||||||
else gates[z_wire].rhs
|
|
||||||
)
|
|
||||||
wrong_wire_2 = m_gates[f"e{i2d}"]
|
|
||||||
|
|
||||||
# we are going to fix all the gates (there is probably only 2 but
|
|
||||||
# eh...) whose wires needs to be swapped
|
|
||||||
|
|
||||||
self.logger.info(f"swapping {wrong_wire_1} <> {wrong_wire_2}")
|
|
||||||
switch = {wrong_wire_1: wrong_wire_2, wrong_wire_2: wrong_wire_1}
|
|
||||||
|
|
||||||
for wire, gate in list(gates.items()):
|
|
||||||
lhs, rhs = (
|
|
||||||
switch.get(gate.lhs, gate.lhs),
|
|
||||||
switch.get(gate.rhs, gate.rhs),
|
|
||||||
)
|
|
||||||
if lhs != gate.lhs or rhs != gate.rhs:
|
|
||||||
gates[wire] = Gate(gate.type, lhs, rhs)
|
|
||||||
|
|
||||||
swapped.extend((wrong_wire_1, wrong_wire_2))
|
|
||||||
|
|
||||||
z_gate = find_gate("xor", r0n, f"e{i2d}")
|
|
||||||
|
|
||||||
if z_gate != z_wire:
|
|
||||||
self.logger.info(f"swapping {z_gate} <> {z_wire}")
|
|
||||||
gates[z_gate], gates[z_wire] = gates[z_wire], gates[z_gate]
|
|
||||||
swapped.extend((z_gate, z_wire))
|
|
||||||
|
|
||||||
m_gates[f"a{i2d}"] = find_gate("and", f"x{i2d}", f"y{i2d}")
|
|
||||||
m_gates[f"b{i2d}"] = find_gate("and", r0n, f"e{i2d}")
|
|
||||||
m_gates[f"r{i2d}"] = find_gate("or", f"a{i2d}", f"b{i2d}")
|
|
||||||
|
|
||||||
assert len(swapped) == 8
|
|
||||||
yield ",".join(sorted(swapped))
|
|
||||||
|
|||||||
@@ -1,40 +1,7 @@
|
|||||||
import itertools as it
|
|
||||||
from typing import Any, Iterator
|
from typing import Any, Iterator
|
||||||
|
|
||||||
from ..base import BaseSolver
|
from ..base import BaseSolver
|
||||||
|
|
||||||
|
|
||||||
def read_locks_and_keys(input: str):
|
|
||||||
locks: list[tuple[int, ...]] = []
|
|
||||||
keys: list[tuple[int, ...]] = []
|
|
||||||
|
|
||||||
for block in map(str.splitlines, input.split("\n\n")):
|
|
||||||
n_rows, n_cols = len(block), len(block[0])
|
|
||||||
if block[0] == "#" * n_cols:
|
|
||||||
locks.append(
|
|
||||||
tuple(
|
|
||||||
next(i for i in range(n_rows) if block[i][j] == ".") - 1
|
|
||||||
for j in range(n_cols)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
keys.append(
|
|
||||||
tuple(
|
|
||||||
n_rows - next(i for i in range(n_rows) if block[i][j] == "#") - 1
|
|
||||||
for j in range(n_cols)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
return locks, keys
|
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
class Solver(BaseSolver):
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
def solve(self, input: str) -> Iterator[Any]: ...
|
||||||
locks, keys = read_locks_and_keys(input)
|
|
||||||
assert len(set(locks)) == len(locks)
|
|
||||||
assert len(set(keys)) == len(keys)
|
|
||||||
|
|
||||||
yield sum(
|
|
||||||
all(c1 + c2 <= 5 for c1, c2 in zip(lock, key, strict=True))
|
|
||||||
for lock, key in it.product(locks, keys)
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -4,64 +4,4 @@ from ..base import BaseSolver
|
|||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
class Solver(BaseSolver):
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
def solve(self, input: str) -> Iterator[Any]: ...
|
||||||
blocks: list[tuple[int, int]] = []
|
|
||||||
frees: list[tuple[int, int]] = []
|
|
||||||
|
|
||||||
contents_0: list[int | None] = [None for _ in range(sum(map(int, input)))]
|
|
||||||
|
|
||||||
acc = 0
|
|
||||||
for i, c in enumerate(input):
|
|
||||||
if i % 2 == 0:
|
|
||||||
for j in range(acc, acc + int(c)):
|
|
||||||
contents_0[j] = i // 2
|
|
||||||
blocks.append((acc, int(c)))
|
|
||||||
else:
|
|
||||||
frees.append((acc, int(c)))
|
|
||||||
acc += int(c)
|
|
||||||
|
|
||||||
assert contents_0[-1] is not None
|
|
||||||
|
|
||||||
contents = contents_0.copy()
|
|
||||||
|
|
||||||
free_0 = next(i for i, c in enumerate(contents) if c is None)
|
|
||||||
next_b = len(contents) - 1
|
|
||||||
|
|
||||||
while free_0 < next_b:
|
|
||||||
contents[free_0], contents[next_b] = contents[next_b], contents[free_0]
|
|
||||||
|
|
||||||
free_0 += 1
|
|
||||||
while free_0 < len(contents) and contents[free_0] is not None:
|
|
||||||
free_0 += 1
|
|
||||||
|
|
||||||
next_b -= 1
|
|
||||||
while next_b >= 0 and contents[next_b] is None:
|
|
||||||
next_b -= 1
|
|
||||||
|
|
||||||
yield sum(i * c for i, c in enumerate(contents) if c is not None)
|
|
||||||
|
|
||||||
contents = contents_0.copy()
|
|
||||||
|
|
||||||
for block_start, block_length in self.progress.wrap(blocks[::-1]):
|
|
||||||
try:
|
|
||||||
i_free = next(
|
|
||||||
i_free
|
|
||||||
for i_free, (free_start, free_length) in enumerate(frees)
|
|
||||||
if free_start < block_start and free_length >= block_length
|
|
||||||
)
|
|
||||||
except StopIteration:
|
|
||||||
continue
|
|
||||||
|
|
||||||
free_start, free_length = frees[i_free]
|
|
||||||
|
|
||||||
contents[free_start : free_start + block_length] = contents[
|
|
||||||
block_start : block_start + block_length
|
|
||||||
]
|
|
||||||
contents[block_start : block_start + block_length] = [None] * block_length
|
|
||||||
|
|
||||||
if free_length == block_length:
|
|
||||||
del frees[i_free]
|
|
||||||
else:
|
|
||||||
frees[i_free] = (free_start + block_length, free_length - block_length)
|
|
||||||
|
|
||||||
yield sum(i * c for i, c in enumerate(contents) if c is not None)
|
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
from collections import Counter
|
|
||||||
from typing import Any, Iterator, Literal, cast
|
|
||||||
|
|
||||||
from ..base import BaseSolver
|
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
data = [
|
|
||||||
(cast(Literal["R", "L"], row[0]), int(row[1:]))
|
|
||||||
for row in input.splitlines()
|
|
||||||
]
|
|
||||||
|
|
||||||
count, dial = 0, 50
|
|
||||||
for sense, value in data:
|
|
||||||
dial = (dial + (-1 if sense == "L" else 1) * value) % 100
|
|
||||||
if dial == 0:
|
|
||||||
count += 1
|
|
||||||
|
|
||||||
yield count
|
|
||||||
|
|
||||||
count, dial = 0, 50
|
|
||||||
for sense, value in data:
|
|
||||||
if dial == 0 and sense == "L":
|
|
||||||
dial = dial - value + 100
|
|
||||||
else:
|
|
||||||
dial = dial + (-1 if sense == "L" else 1) * value
|
|
||||||
|
|
||||||
while dial < 0:
|
|
||||||
count, dial = count + 1, dial + 100
|
|
||||||
|
|
||||||
if dial == 0:
|
|
||||||
count += 1
|
|
||||||
|
|
||||||
while dial >= 100:
|
|
||||||
count, dial = count + 1, dial - 100
|
|
||||||
|
|
||||||
self.logger.info(
|
|
||||||
f"after {sense}{value:<3d} dial is at {dial:>2d}, count is {count}"
|
|
||||||
)
|
|
||||||
|
|
||||||
yield count
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
from typing import Any, Iterator
|
|
||||||
|
|
||||||
from ..base import BaseSolver
|
|
||||||
|
|
||||||
|
|
||||||
class Solver(BaseSolver):
|
|
||||||
def solve(self, input: str) -> Iterator[Any]:
|
|
||||||
yield 0
|
|
||||||
yield 0
|
|
||||||
@@ -1,47 +1,114 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import importlib
|
import importlib
|
||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
import logging.handlers
|
||||||
import sys
|
import sys
|
||||||
from datetime import datetime
|
from datetime import datetime, timedelta
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import Any, Iterable, Iterator, Literal, Sequence, TextIO, TypeVar
|
||||||
|
|
||||||
|
from tqdm import tqdm
|
||||||
|
|
||||||
from .base import BaseSolver
|
from .base import BaseSolver
|
||||||
from .utils.api import FileHandlerAPI, LoggerAPIHandler, ProgressAPI, dump_answer
|
|
||||||
from .utils.files import SimpleFileHandler
|
_T = TypeVar("_T")
|
||||||
from .utils.progress import ProgressNone, ProgressTQDM
|
|
||||||
|
|
||||||
|
|
||||||
def find_input_file(folder: Path, day: int, target: Path | None):
|
def dump_api_message(
|
||||||
if (path := folder.joinpath(f"day{day}.txt")).exists():
|
type: Literal["log", "answer", "progress-start", "progress-step", "progress-end"],
|
||||||
return path
|
content: Any,
|
||||||
|
file: TextIO = sys.stdout,
|
||||||
|
):
|
||||||
|
print(
|
||||||
|
json.dumps(
|
||||||
|
{"type": type, "time": datetime.now().isoformat(), "content": content}
|
||||||
|
),
|
||||||
|
flush=True,
|
||||||
|
file=file,
|
||||||
|
)
|
||||||
|
|
||||||
if (
|
|
||||||
target is not None
|
class LoggerAPIHandler(logging.Handler):
|
||||||
and (path := folder.joinpath(f"day{day}_v{target}.txt")).exists()
|
def __init__(self, output: TextIO = sys.stdout):
|
||||||
|
super().__init__()
|
||||||
|
self.output = output
|
||||||
|
|
||||||
|
def emit(self, record: logging.LogRecord):
|
||||||
|
dump_api_message(
|
||||||
|
"log", {"level": record.levelname, "message": record.getMessage()}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ProgressAPI:
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
min_step: int = 1,
|
||||||
|
min_time: timedelta = timedelta(milliseconds=100),
|
||||||
|
output: TextIO = sys.stdout,
|
||||||
):
|
):
|
||||||
return path
|
super().__init__()
|
||||||
|
|
||||||
|
self.counter = 0
|
||||||
|
self.output = output
|
||||||
|
self.min_step = min_step
|
||||||
|
self.min_time = min_time
|
||||||
|
|
||||||
|
def wrap(
|
||||||
|
self, values: Sequence[_T] | Iterable[_T], total: int | None = None
|
||||||
|
) -> Iterator[_T]:
|
||||||
|
total = total or len(values) # type: ignore
|
||||||
|
|
||||||
|
current = self.counter
|
||||||
|
self.counter += 1
|
||||||
|
|
||||||
|
dump_api_message("progress-start", {"counter": current, "total": total})
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return next(path for path in sorted(folder.glob(f"day{day}*.txt")))
|
percent = 0
|
||||||
except StopIteration:
|
time = datetime.now()
|
||||||
...
|
|
||||||
|
|
||||||
return folder.joinpath(f"day{day}.txt")
|
for i_value, value in enumerate(values):
|
||||||
|
yield value
|
||||||
|
|
||||||
|
if datetime.now() - time < self.min_time:
|
||||||
|
continue
|
||||||
|
|
||||||
|
time = datetime.now()
|
||||||
|
|
||||||
|
c_percent = round(i_value / total * 100)
|
||||||
|
|
||||||
|
if c_percent >= percent + self.min_step:
|
||||||
|
dump_api_message(
|
||||||
|
"progress-step", {"counter": current, "percent": c_percent}
|
||||||
|
)
|
||||||
|
percent = c_percent
|
||||||
|
finally:
|
||||||
|
dump_api_message(
|
||||||
|
"progress-end",
|
||||||
|
{"counter": current},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ProgressTQDM:
|
||||||
|
def wrap(
|
||||||
|
self, values: Sequence[_T] | Iterable[_T], total: int | None = None
|
||||||
|
) -> Iterator[_T]:
|
||||||
|
return iter(tqdm(values, total=total))
|
||||||
|
|
||||||
|
|
||||||
|
class ProgressNone:
|
||||||
|
def wrap(
|
||||||
|
self, values: Sequence[_T] | Iterable[_T], total: int | None = None
|
||||||
|
) -> Iterator[_T]:
|
||||||
|
return iter(values)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser("Holt59 Advent-Of-Code Runner")
|
parser = argparse.ArgumentParser("Holt59 Advent-Of-Code Runner")
|
||||||
parser.add_argument("-v", "--verbose", action="store_true", help="verbose mode")
|
parser.add_argument("-v", "--verbose", action="store_true", help="verbose mode")
|
||||||
parser.add_argument("-t", "--test", action="store_true", help="test mode")
|
parser.add_argument("-t", "--test", action="store_true", help="test mode")
|
||||||
|
|
||||||
parser.add_argument("-a", "--api", action="store_true", help="API mode")
|
parser.add_argument("-a", "--api", action="store_true", help="API mode")
|
||||||
parser.add_argument(
|
|
||||||
"-o",
|
|
||||||
"--output",
|
|
||||||
type=Path,
|
|
||||||
default=Path("files"),
|
|
||||||
help="output folder for created files",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-u", "--user", type=str, default="holt59", help="user input to use"
|
"-u", "--user", type=str, default="holt59", help="user input to use"
|
||||||
)
|
)
|
||||||
@@ -58,7 +125,7 @@ def main():
|
|||||||
default=None,
|
default=None,
|
||||||
help="input to use (override user and test)",
|
help="input to use (override user and test)",
|
||||||
)
|
)
|
||||||
parser.add_argument("-y", "--year", type=int, help="year to run", default=2025)
|
parser.add_argument("-y", "--year", type=int, help="year to run", default=2024)
|
||||||
parser.add_argument("day", type=int, help="day to run")
|
parser.add_argument("day", type=int, help="day to run")
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
@@ -68,24 +135,20 @@ def main():
|
|||||||
test: bool = args.test
|
test: bool = args.test
|
||||||
stdin: bool = args.stdin
|
stdin: bool = args.stdin
|
||||||
user: str = args.user
|
user: str = args.user
|
||||||
files_output: Path = args.output
|
|
||||||
input_path: Path | None = args.input
|
input_path: Path | None = args.input
|
||||||
|
|
||||||
year: int = args.year
|
year: int = args.year
|
||||||
day: int = args.day
|
day: int = args.day
|
||||||
|
|
||||||
|
# TODO: change this
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
level=logging.INFO if verbose else logging.WARNING,
|
level=logging.INFO if verbose or api else logging.WARNING,
|
||||||
handlers=[LoggerAPIHandler()] if api else None,
|
handlers=[LoggerAPIHandler()] if api else None,
|
||||||
)
|
)
|
||||||
|
|
||||||
if input_path is None or not input_path.exists():
|
if input_path is None:
|
||||||
input_path = find_input_file(
|
input_path = Path(__file__).parent.joinpath(
|
||||||
Path(__file__).parent.joinpath(
|
"inputs", "tests" if test else user, str(year), f"day{day}.txt"
|
||||||
"inputs", "tests" if test else user, str(year)
|
|
||||||
),
|
|
||||||
day,
|
|
||||||
input_path,
|
|
||||||
)
|
)
|
||||||
assert input_path.exists(), f"{input_path} missing"
|
assert input_path.exists(), f"{input_path} missing"
|
||||||
|
|
||||||
@@ -103,11 +166,7 @@ def main():
|
|||||||
else ProgressTQDM()
|
else ProgressTQDM()
|
||||||
if verbose
|
if verbose
|
||||||
else ProgressNone(), # type: ignore
|
else ProgressNone(), # type: ignore
|
||||||
files=FileHandlerAPI(files_output)
|
outputs=not api,
|
||||||
if api and verbose
|
|
||||||
else SimpleFileHandler(logging.getLogger("AOC"), files_output)
|
|
||||||
if verbose
|
|
||||||
else None,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
data: str
|
data: str
|
||||||
@@ -120,7 +179,7 @@ def main():
|
|||||||
start = datetime.now()
|
start = datetime.now()
|
||||||
last = start
|
last = start
|
||||||
|
|
||||||
it = solver.solve(data.rstrip())
|
it = solver.solve(data.strip())
|
||||||
|
|
||||||
if it is None:
|
if it is None:
|
||||||
solver.logger.error(f"no implementation for {year} day {day}")
|
solver.logger.error(f"no implementation for {year} day {day}")
|
||||||
@@ -130,11 +189,14 @@ def main():
|
|||||||
current = datetime.now()
|
current = datetime.now()
|
||||||
|
|
||||||
if api:
|
if api:
|
||||||
dump_answer(
|
dump_api_message(
|
||||||
part=i_answer + 1,
|
"answer",
|
||||||
answer=answer,
|
{
|
||||||
answer_time=current - last,
|
"answer": i_answer + 1,
|
||||||
total_time=current - start,
|
"value": answer,
|
||||||
|
"answerTime_s": (current - last).total_seconds(),
|
||||||
|
"totalTime_s": (current - start).total_seconds(),
|
||||||
|
},
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
print(
|
print(
|
||||||
|
|||||||
@@ -1,78 +1,18 @@
|
|||||||
from abc import abstractmethod
|
from abc import abstractmethod
|
||||||
from logging import Logger
|
from logging import Logger
|
||||||
from pathlib import Path
|
from typing import Any, Final, Iterable, Iterator, Protocol, Sequence, TypeVar, overload
|
||||||
from typing import (
|
|
||||||
Any,
|
|
||||||
Final,
|
|
||||||
Iterable,
|
|
||||||
Iterator,
|
|
||||||
Protocol,
|
|
||||||
Sequence,
|
|
||||||
TypeVar,
|
|
||||||
overload,
|
|
||||||
)
|
|
||||||
|
|
||||||
from numpy.typing import NDArray
|
|
||||||
|
|
||||||
_T = TypeVar("_T")
|
_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 FileHandler:
|
|
||||||
@abstractmethod
|
|
||||||
def make_path(self, filename: str) -> Path: ...
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def notify_created(self, path: Path): ...
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def _create(
|
|
||||||
self, path: Path, content: bytes, text: bool = False
|
|
||||||
) -> Path | None: ...
|
|
||||||
|
|
||||||
def create(self, filename: str, content: bytes, text: bool = False):
|
|
||||||
path = self._create(self.make_path(filename), content, text)
|
|
||||||
|
|
||||||
if path is not None:
|
|
||||||
self.notify_created(path)
|
|
||||||
|
|
||||||
def image(self, filename: str, image: NDArray[Any]):
|
|
||||||
import imageio.v3 as iio
|
|
||||||
from pygifsicle import optimize # type: ignore
|
|
||||||
|
|
||||||
path = self.make_path(filename)
|
|
||||||
|
|
||||||
iio.imwrite(path, image) # type: ignore
|
|
||||||
optimize(path, options=["--no-warnings"])
|
|
||||||
|
|
||||||
self.notify_created(path)
|
|
||||||
|
|
||||||
def video(self, filename: str, video: NDArray[Any]):
|
|
||||||
import cv2
|
|
||||||
|
|
||||||
path = self.make_path(filename)
|
|
||||||
fps = 5
|
|
||||||
out = cv2.VideoWriter(
|
|
||||||
path.as_posix(),
|
|
||||||
cv2.VideoWriter_fourcc(*"vp80"), # type: ignore
|
|
||||||
fps,
|
|
||||||
(video.shape[2], video.shape[1]),
|
|
||||||
True,
|
|
||||||
)
|
|
||||||
|
|
||||||
for picture in video:
|
|
||||||
out.write(picture)
|
|
||||||
|
|
||||||
out.release()
|
|
||||||
|
|
||||||
self.notify_created(path)
|
|
||||||
|
|
||||||
|
|
||||||
class BaseSolver:
|
class BaseSolver:
|
||||||
@@ -83,14 +23,15 @@ class BaseSolver:
|
|||||||
year: int,
|
year: int,
|
||||||
day: int,
|
day: int,
|
||||||
progress: ProgressHandler,
|
progress: ProgressHandler,
|
||||||
files: FileHandler | None = None,
|
outputs: bool = False,
|
||||||
):
|
):
|
||||||
self.logger: Final = logger
|
self.logger: Final = logger
|
||||||
self.verbose: Final = verbose
|
self.verbose: Final = verbose
|
||||||
self.year: Final = year
|
self.year: Final = year
|
||||||
self.day: Final = day
|
self.day: Final = day
|
||||||
self.progress: Final = progress
|
self.progress: Final = progress
|
||||||
self.files: Final = files
|
self.outputs = outputs
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def solve(self, input: str) -> Iterator[Any] | None: ...
|
def solve(self, input: str) -> Iterator[Any] | None:
|
||||||
|
...
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
jio a, +19
|
|
||||||
inc a
|
|
||||||
tpl a
|
|
||||||
inc a
|
|
||||||
tpl a
|
|
||||||
inc a
|
|
||||||
tpl a
|
|
||||||
tpl a
|
|
||||||
inc a
|
|
||||||
inc a
|
|
||||||
tpl a
|
|
||||||
tpl a
|
|
||||||
inc a
|
|
||||||
inc a
|
|
||||||
tpl a
|
|
||||||
inc a
|
|
||||||
inc a
|
|
||||||
tpl a
|
|
||||||
jmp +23
|
|
||||||
tpl a
|
|
||||||
tpl a
|
|
||||||
inc a
|
|
||||||
inc a
|
|
||||||
tpl a
|
|
||||||
inc a
|
|
||||||
inc a
|
|
||||||
tpl a
|
|
||||||
inc a
|
|
||||||
tpl a
|
|
||||||
inc a
|
|
||||||
tpl a
|
|
||||||
inc a
|
|
||||||
tpl a
|
|
||||||
inc a
|
|
||||||
inc a
|
|
||||||
tpl a
|
|
||||||
inc a
|
|
||||||
inc a
|
|
||||||
tpl a
|
|
||||||
tpl a
|
|
||||||
inc a
|
|
||||||
jio a, +8
|
|
||||||
inc b
|
|
||||||
jie a, +4
|
|
||||||
tpl a
|
|
||||||
inc a
|
|
||||||
jmp +2
|
|
||||||
hlf a
|
|
||||||
jmp -7
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
1
|
|
||||||
3
|
|
||||||
5
|
|
||||||
11
|
|
||||||
13
|
|
||||||
17
|
|
||||||
19
|
|
||||||
23
|
|
||||||
29
|
|
||||||
31
|
|
||||||
41
|
|
||||||
43
|
|
||||||
47
|
|
||||||
53
|
|
||||||
59
|
|
||||||
61
|
|
||||||
67
|
|
||||||
71
|
|
||||||
73
|
|
||||||
79
|
|
||||||
83
|
|
||||||
89
|
|
||||||
97
|
|
||||||
101
|
|
||||||
103
|
|
||||||
107
|
|
||||||
109
|
|
||||||
113
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
To continue, please consult the code grid in the manual. Enter the code at row 3010, column 3019.
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
<[<<({{<{<[[([()][()()])<{[]<>}{<>}>><<<[]{}>>{<<><>>({}{})}>][<<<{}<>>([])>{<{}><()>}>]><(<{(()[]){[](
|
|
||||||
<{([({{[(<[({({}{})[()<>]}{{<>{}}[(){}]})]>({(<<<><>>{{}()}>)<<<[]><{}<>>><[{}[]]<<>[]>>>}))[{(<{([]
|
|
||||||
([<([({(<([<({()()}(<>[]))[<[]()>{<>{}}]>]<{{{{}{}}{()()})({[]}[<>{}])}>)>)}){<<{{(<<<()<>><<><>>>
|
|
||||||
[{{[<<[{([[{{[<>{}]<()<>>}[(()<>)[{}<>]]}<<[{}[]]([]<>)>{{[]{}}{()()}}>]][[{<({}{})<[]{}>>
|
|
||||||
<<{{<([(((([{<[]<>>{()<>}}(<<>[]>{(){}})]([{{}<>}<[]>](<[][]><{}()>)))))[({{{<[]{}>[()]}<<<><>>
|
|
||||||
<(<[{(<[{{{<{[[]<>]{<>()}}><[[{}()][(){}]]>}}<[<[<()()>({}<>)]><[{[]()}([][])](<(){}>[<><>])>]{
|
|
||||||
{[[<{{<<[[<<(({}<>){<><>})[[<>()][[]{})]>[[[{}[]]<<>>]{(<>[])}]>{{<<()[]>{<>{}}>[{[]<>}<[]{}>]
|
|
||||||
({[((((([{[({[{}[]]<[]()>}[({}{})<<>[]>])<[(()[])<{}()>]{[[]<>]{[]()})>](([({}<>)(()[])][<[]{}>])
|
|
||||||
{[[{[({(<<{<([{}<>])<({}<>)({}<>}>>[<[{}()]([]<>)>((<>())<[]{}>)]}<([(<>())[(){}]]{[{}<>]<[][]>}){<{<><
|
|
||||||
(<{<<[<<([[([<<><>>]<<{}()><[]<>>>)]][{(({<>{}}(()())))(<[()()]<[]()>>)}[[<<<>()><<>{}>>([{}<>][{}[]])]{<{(
|
|
||||||
<<[({{{{{[<([((){})([]())]<((){})({}[])>)[{[{}()]{[]<>}}]>([<{{}<>}><({}<>)({}[])>]<[{<>{}}
|
|
||||||
(([[{{({{{[<<{[]()}({})>{{{}()}[[]<>]}>{<([])>[[[]{}]]}](([<[]{}>]<<[]<>><{}[]>>))}}}(([[[{[<><>
|
|
||||||
<<[(<[{{<((<[<()>[<><>]][[<><>]([]())]>[({<>})<<()<>><{}[]>>])[[(<[]<>>([]())){{<>[]}(()())}]]){(<(<[]<>>
|
|
||||||
({[<<[[{<[[{{[()()]{()[]}}}]<{([{}{}]{[]()})[[()[]]<<>>]}>]>}[({((<{<><>)>{{[]()}{{}[]}}){([{}[]]<{}{}>)<
|
|
||||||
([{{<{[(<[<<[({}())({}())]>>[{[<<>[]>[<>()]]<(<>[]){()[]}>}(<<<>[]>[<>[]]>{<<>[]>{{}()}})]]{
|
|
||||||
<[{{<[((<([[{<<><>>{()}}{<{}[]><[]()]}]])<{({<()>{()[]}}(<(){}><[]<>>)){[({}[]){<>[]}]}}<<([()()]<()(
|
|
||||||
<{<{[(({(({({<[]>([])}<<()<>>{<>()}>){[[()[]]<{}()>]{({}[])[()<>]}}}<[<<{}()><[]{}>>({[][]}[()<>])}{<<[]
|
|
||||||
<[{{[<({(<[<[[()<>]({}[])]([{}[]]([]))>]{[{{<>[]}[[]{}]}(({}<>)<()[]>)]<<[()[]]>({(){}}<{}()>)>}>)}<<[[[[<<>(
|
|
||||||
{{<(<[((({(<[<[]{}>[(){}]](<{}<>>((){}))>){(({[]{}}<{}[]>){{<><>}[[]{}]}))}<([<(<>)>[<<>{}>[{}
|
|
||||||
<([({[<[(({[(({}))(<{}()><<>{}>)]<[{{}[]}{{}<>}]{[{}()]{{}()}}>})([[<(<>())({}{})>[<[]<>>[
|
|
||||||
{((<<<{<(<[[[<{}<>}]<(<><>)>]]<(([(){}]{[]()}))<({{}<>}<()<>>){<()<>>{(){}}}>>>{({({()[]}[<>
|
|
||||||
([<[[((<(<[<([{}[]])>{<(()<>)((){})>{<<>>(()<>)}}][{[(<>[])(<>[])]}[[{{}[]}[()()]]<<[]<>>{(){}}>]]><({(
|
|
||||||
[{<([[[{([{<<([]<>){<><>}>[<(){}>]><{[<>[]](()<>)}[{()()}]>}<({{{}{}}}{[{}{}]<<>()>})<(<[]<
|
|
||||||
(<({[{{[[(<[<(<>[])[[][]]>]{((<>[])({}<>))({[]<>})}>({<[()[]]]<{()[]}>})){(<(<<>[]>[<>{}])>{[({}<
|
|
||||||
(<{<(({[(({[[<<>{}>({}<>)]{({}{}){(){}}}]{(<(){}>[[][]])<{()<>}>}}[[[{[]{}}[()]]](([[]()][(){}]))])
|
|
||||||
([({<{[{<[{<({{}()}{{}()})>}]>}<<[[{{((){})<<>{}>}(({}[]){<>[]})}]]><[{{<({}<>)(()())>[{<>()}{{}()}]}{<{
|
|
||||||
<[{[({[<<[[<<{{}{}}<{}{}>>([<>][(){}])><<<{}{}>>>]]{([{[[]()][[][]]}<{[]<>}>]<<[<>[]][[]()]><<()[
|
|
||||||
[{({{{<<{[{([[()]({}[])]{[()()]})(((<>{})[[][]])<{{}{}}>)}]}>>}[((({{<([[]()][[]])}}{{<({}[])[{}
|
|
||||||
{[({<{<<{[(([<<>[]>({}{})>))]{(<{{{}<>}<<>{}>}>)}}><(<(({([]())(<>[])}{{[]()}{[][]}})<{(()[])[<>{}]}>){({
|
|
||||||
[<((<[<<(<<{<(<>)<[]{}>>[<[]{}><[]()>]}<((()[])((){}))[({}[]){[]{}}]>>([<[{}()][[]{}]>{{()[]}}][{[{}<>]<[]<
|
|
||||||
[<[({({[([{<(([]<>)({}[]))<{{}[]}[<>[]]>><[<{}[]>({}<>)]<(())>>]]([[[{[]<>}({}[])](<[]{}>{<>()
|
|
||||||
{[<<{(<[{(<[({[]{}}{[]{}}}]({<()[]><<>[]>}{<[]()>[{}{}]})>)}{[{(((<><>))(<[]<>>(()[])))[[<[]()>[{}()]](((
|
|
||||||
({[<<([[{(<<<{<>()}<{}<>>>[[[]{}){()}]><[[(){}]<[]<>>]({(){}}[[]{}])>>{[{[()<>][{}()]}][[[{}{}]<<>()
|
|
||||||
([(<((<{[[[[[{{}()}{()[]}]]<([[]<>])<[()<>][[][]]>>]][{([{()[]}(()[])]({<>{}}{[]()}))}({([[]
|
|
||||||
(({{[<<{(([{<{()()}[[]()]>{<()<>>[[]{}]}}{[<()()>[[]{}]]{([]())({}[])}}][(<{<>[]}[()()]><<()>(()())>)
|
|
||||||
[<(<{{{<{(<{(<<>[]><<>()>){<{}()><()<>>}}(<[<>{}]{<>{}}><[{}{}][<>()]>)>)}{{{(<(<><>)(<>())><{[]}([][
|
|
||||||
<<<{([[<[[[(([[]{}])<({}())(<>())>)({[<>{}]{[]()}}<<(){}>{(){}}>)]{([(()()>({}[])]((<><>)<
|
|
||||||
{{({<<<[[<(<{{{}<>}({}[])}{<{}<>><<>()>}>{({{}<>}({}()}){[[]<>]([]{})}}){{[[[][]](()())]}([<<>{}
|
|
||||||
<<[[<{{({<{[{<<>()><()()>}<[()<>]<()()>>]{(([]<>)[{}[]]){{{}<>}{[]<>})}}>{{<[<{}<>>({}())]
|
|
||||||
({[<[[{<<{{[{(<>{})}]{<[{}{}][[]()]>[[[]{}][()()]]}}[(<<{}[]>{<>[]}>{{{}<>}[(){}]}){{[<>{}]<{}{}>}{
|
|
||||||
(([<{<[[([[(((()<>))({{}[]}<()<>>))[[({}[])(())]<{(){})>]][{((()){[]()}){{()<>}{<><>}}}[{{()}{()[]}}]]]){{(({
|
|
||||||
{<[{(<[{[{{[<([]<>)<{}<>>>]}}]}]><{{<[[([{<>()}[[]{}]]({{}()}{<>{}}))]{([<[]{}>(()<>)]<[[]<>]([])
|
|
||||||
{[<<[<(<[{<<[{{}()}{<>{}}](<{}<>>({}<>))>><{<({}[])<()<>>>[[<>[]][<><>]]}[<(<><>){{}<>}>[<[]()>{[]}]]>}]{[<{<
|
|
||||||
(<({{[{<(<<<{[{}<>]({}[])}{[[]{}]<()[]>}>(<[[]()][()()]><[()[]][<>()]>)>>[(<<<{}()>{<><>}>>){<<{<><>}(
|
|
||||||
(<{[[{{<(<(<({{}<>}{{}()}){[()<>]<{}[]>}>[(<{}{}><[]()>)<({}<>){()()}>]){[[([]{}){{}[]}]<[{}{}]<[][]>>][{<()
|
|
||||||
[(<([({[[[<[[[[][]][{}{}]]([{}()]{<>{}})]{<{()()}<()<>>><{{}<>}<(){}>>}>]{{[([[][]]<()()>)
|
|
||||||
(<(<<({{(<[{{[()<>][<>{}]}[<[]<>>]}<<{[]{}}>[[{}()]{()()}]>]{[([()()]<<>>)({()<>}[<>[]])][{{[][]}(<>())}
|
|
||||||
[[((({(({{{[{{<>[]}[<>{}]}[[{}<>]([]())]][{(<><>)}]}][(<{{[][]}(<><>)}<[[]()]>>([[{}()]<[]<>>][<[][]>[()()]])
|
|
||||||
<{({(([((<[<{(()[])<[][]>}{<<><>><[]<>>}><<([]<>)([]<>)>>]{[<([]{}]{<>{}}>]}>[{[(([]{})[{}{}])[<<>{}
|
|
||||||
{(([<{(({<({{{{}{}}}[[[]]{[]()}]}{<[[]]<<>()>>(<()>[()<>])})>{{[(([]<>){{}()}){[{}]{{}<>}}]}([[([]{})]<[[](
|
|
||||||
<{[({<{[[[{{{[{}{}]}}([<[][]>[<>[]}][<<>()>{()}])}((<({}[])[<><>]>(((){})[{}()]))[[<{}[]>[(
|
|
||||||
{<[([(<((<<<<[{}[]]({}{})>((()())[(){}])><([[]{}][()<>])<<<>[]>([]<>)>>><[[((){}){[][]}}{[[]]
|
|
||||||
[{(<{<{<<({({(()<>){{}[]}}([[]()]{()<>}))(([[]<>](())))}<{({()[]}{[][]})}])>>}>(({[{[{{([]())(<><>)
|
|
||||||
<[[<([<<({[[(<[]()><<><>>)({<>})]{{<<><>>[()[]]}([()<>](()[]))}]((<{<>{}}<(){}>>))}<<[(<(){}><<>{}>)[[()[
|
|
||||||
<[{<<<{[{<{(<[<>{}][{}()]>((<>[])[<><>]))<[({}<>)<<>[]>]<(<><>)(<>{})>>}({<<[][]>([]<>)>([<>{}><<>[]>
|
|
||||||
[<<(<{((<([<({{}{}](<>[]))[[()<>]([][])]>((([])<(){}>))]){<{{<()[]>(()<>)}(<[]<>>([][]))}><[([(
|
|
||||||
{[[[{{<[[{<[<<<>[]>{<><>}>{<<>{}><[]<>>}]((<{}()>(<>[])))><<{<<>{}>{(){}}}([{}{}]<<>()>)><[{<>{}}]>>}]
|
|
||||||
((((([[(([{<({()[]}<()<>>)><<<<>()>({}{})>{{(){}}(<>[])}>}<<<{<><>}>><(((){})<[]()>){{()()}({}<>)}>
|
|
||||||
<<[<[{<[<[<{[[()[]]({}[])]{<{}<>>[{}{}]}}[([[][]])[([]())[[]<>]]]>[(<<{}()>(()<>)>{{[]{}}<{}{}>})({([
|
|
||||||
[{<(<{(<[<[[[{()<>}[[][]]][(()<>){{}[]}]](<{<>{}}[()[]]>(<[]>[{}()]))]([([<>{}]<()[]>){{<>{}}{()
|
|
||||||
<[<({<({[{({{(<>{}){[]()}}<{[]<>}[(){}]>}({[<>[]]{[]<>}}))<{([{}[]])(({}[]){(){}})}[{[[]<>]}[({}())[(){}]]]
|
|
||||||
[[[{<[((<[<{([[]<>]{<><>})<<{}[]>[[][]]>}{[[<>{}]]<<{}>([]<>)>}>{<{{<>[]}}[(<><>)[[]<>]])<{[(){}]<()()>}>}]{{
|
|
||||||
([(<({[[{<([{{<>{}}([]<>)}[[{}[]]{<>{}}]](<[{}<>]{[]()}><((){})[[][])>)){({{{}{}}{{}{}}}[<{}{}>({}<
|
|
||||||
<[{(((({[[{{({{}[]]<<>>)<{[]()}<()<>>>}((<(){}>([]{})))}{({[()()]([]<>)}<([]<>)[()()]>)<[{{}[
|
|
||||||
<[({[<<<<{[({{(){}}[{}<>}}(<<>[]>[[]()])){(<()[]><<>()>)}]}><({<[{()()}]({[]{}}<{}>)>[({[]
|
|
||||||
<<([[<{{([{<{([]{})[(){}]}{([]{})<{}[]>}><<(<>{})[<>()]>({{}<>})>}<[(<<>()><{}()>)<{()<>}<<>>
|
|
||||||
<[[[({[({<[{((<>[]]<{}<>>){<<>()>{[]()}}}<{<{}{}>[<>{}]}{{{}[]}{{}()}}>]{<{{()()}<[]<>>}((
|
|
||||||
[[({(([[(([<[([]<>){{}()}]>(<{{}{}}(()<>)>[{<><>}{{}<>}])]{{<[[]<>]>[[{}()]]}([<{}()>][([]{})<{}
|
|
||||||
<(([<{([[<[((([]<>)<<><>>){[[]()]({}{})})({{(){}}((){}]}({{}()}))]([<{<>()}<[]{}>><{[]{}}<(){}>>])>
|
|
||||||
<<[[{<<{[(<<{{[][]}[[]<>]}<<[][]><<>[]>]>([{<>}[<>[]]]{{[]()}<{}()>})>{({({}<>){[]<>}}[{<>{}}[<>[]]
|
|
||||||
((<<<<[[(({[[<()<>>[(){}]]{(<>()){<>{}}}]}{(([<>[]><<>()>)<<(){}><()()>>)[(<{}{}>((){}))[{[][]}(()<>)]]})){
|
|
||||||
[({(<{{<<<{<[{[]()}<<><>>][[()[]][<>[]]]>}>([([<[]<>>]{<<>()><()<>>})({<{}[]><()()>}[[[]()]])]<{<(()
|
|
||||||
([(<({[([{{{((()())[<>[]]){{[]<>}[{}{}]}}([{()<>}<{}()>])}}<{[({(){}}(<><>)}<(<>())>][<[(){}]{(){}}
|
|
||||||
{[[{((((([[{{[[]{}]({}{})}{[[]<>](()[])}}[{[()()]}((<>{})<(){}>)]]{(<{<>()}<(){}>>){(<{}()>{{}<>})({<>(
|
|
||||||
([[{<[<[[<<{<{()<>}[<>()]>[[[]{}]{{}{}}]}<[{{}[]}]>>{<{{<>{}}([]())}>[(<<>()>)(<{}()>[<>()])]}>{({<[()<>]
|
|
||||||
{(([{[{{(({(<[()[]][<>[]]>)<[(()<>){{}{}}]>}[(<<{}{}><{}<>>>){<[()()]<()()>>({[][]}<<><>>)}
|
|
||||||
<[{<(<<[{[({[({}<>)<<>[]>](<<>()>(<><>))})[([{<><>}<()()>])]]}]><<[<({{{<>}}<([]][<>{}]>}[<(())<<><>>>])
|
|
||||||
(<(({<[[{{[<[{<>[]}[()<>])((()()){{}[]})>]}}]]((<<<((({}{})<{}>){{{}<>}{<>}})[({{}()}{<>()}){{{}()}}]
|
|
||||||
{[<[{(([<[{{[([]{})<[][]>]{([][])[()<>]}}<<(()<>)>>}[[(({}{}){{}<>})]]]{{[(<{}{}>[{}()])({()()}
|
|
||||||
[{{((<<[[((<<{[]<>}<{}>>(<{}<>>{[]()})>({<()>([][])><[{}{}]{{}()}>))(({([]<>)([]())}<{[][]}<()>>)
|
|
||||||
({([{({[({[<({{}{}}([]()))(((){}){{}{}}>>({(()()){{}()}})]<[[{{}{}}<{}[]>]{<[][]><<>[]>}]({<<>[]>
|
|
||||||
{[({[{{[<[{([<{}{}>[(){}]](<{}<>>{{}()}))([([]()){()[]}]([{}<>]{<>{}}))}]>[{{[[{[][]}]]<((()[])([]{}))<[()
|
|
||||||
[[(({{{(([[[{[()()]([]())}((<>){{}{}])]]({<[<>]({}{})>([<>{}]{{}{}})})]))}[(<[[(([[][]]{<>{}}){{(){}}})
|
|
||||||
<(<({<{<[<(<{<()><<><>>}<<{}[]>([]<>)>>)<{<{[]{}}[{}()]>}([(()[]){[]<>}]{{<>()}{{}<>}})>}{[[{(()[]){(
|
|
||||||
[(<(<([{<[{<(<()>([]<>))[{()()}<{}<>>]><{([]())<<>()>}(<{}{}>[()[]])>}]<{<({[][]}<[]()>){{{}[
|
|
||||||
[<({<{(<<[[[<{()[]}{{}[]}>{[<><>]}]{[<()<>>({}<>)]}]][[{<[<>[]>([]())><{()()}{[]{}}>}([({}{})[[](
|
|
||||||
<<[[{{<<([[{[(()())[()]][[{}[]]{{}}]}[[({}<>){[]{}}]{{<><>}[()[]]}]]{<[(<>())]>{({{}()}(()<>))}}])
|
|
||||||
{<[{({[({{<({[{}()]([][])}([{}<>]{[]()}))[<(<><>)([]{})><{()()}(<>[])>]>{{(<[]<>>[{}])}[<{(){}}(<>
|
|
||||||
<{{(({([[<[{<(<>)([]{})>{<<>{}>{(){}}}}]{[<([]{})<{}{}>>[[<>{}]{()<>}]][{{<><>}([]())}({()<>}<()>)]}>]
|
|
||||||
{<{[{[({[(({<[{}()]({}[]}>[<()>]}{(<<>>)}))]})]{<{<{[[{(<>())[()[]]}[[{}{}][[]]]][([[]()]<{}<>>)[<[]{}>([]<>
|
|
||||||
((<{{<[[<{{([([]{})<<>()>]<(<>{})(()<>)))([{()()}(<><>)]<(<>)(<>{})>)}([<{(){}}<<>{}>>]<[([]<
|
|
||||||
[<<<{(((<<{([<()[]>({})]({<>()}(()())))({([])<<>>}((()[])[()[]]))}{<[<{}()>]<[{}{}]({}<>)>>{<<
|
|
||||||
[[[<<<<[{(<<[{{}[]}]<(<><>)(<>[])>><<<<><>][[][]]>(([]{}))>>([<[[]<>]<[]<>>><{()<>}([][])>]))}<(
|
|
||||||
<<{[[[{{{{[[(([]{}))([<>[]]<()>)][{(<>()){[]()}})]{(({<><>}{<>[]})[<<>[]>[()()]])}}}<{(<((<><>)(<>{}))<{
|
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
4738615556
|
|
||||||
6744423741
|
|
||||||
2812868827
|
|
||||||
8844365624
|
|
||||||
4546674266
|
|
||||||
4518674278
|
|
||||||
7457237431
|
|
||||||
4524873247
|
|
||||||
3153341314
|
|
||||||
3721414667
|
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
xq-XZ
|
|
||||||
zo-yr
|
|
||||||
CT-zo
|
|
||||||
yr-xq
|
|
||||||
yr-LD
|
|
||||||
xq-ra
|
|
||||||
np-zo
|
|
||||||
end-LD
|
|
||||||
np-LD
|
|
||||||
xq-kq
|
|
||||||
start-ra
|
|
||||||
np-kq
|
|
||||||
LO-end
|
|
||||||
start-xq
|
|
||||||
zo-ra
|
|
||||||
LO-np
|
|
||||||
XZ-start
|
|
||||||
zo-kq
|
|
||||||
LO-yr
|
|
||||||
kq-XZ
|
|
||||||
zo-LD
|
|
||||||
kq-ra
|
|
||||||
XZ-yr
|
|
||||||
LD-ws
|
|
||||||
np-end
|
|
||||||
kq-yr
|
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
14567892107654348943218769016567650154541210421036
|
|
||||||
03456783298993267654309458122168743243450344323145
|
|
||||||
12567654456780154327812367433059804012769455410234
|
|
||||||
03498012349876065016901056544965418765898766708943
|
|
||||||
12345101212145076545411034545878329658981055899854
|
|
||||||
09876876705034187632110123656789421047432765988765
|
|
||||||
67878965896123298901001656743078431236598894012034
|
|
||||||
50965014387654567650012349856127340012367653213125
|
|
||||||
41234321298347656543243492347833458903458743404987
|
|
||||||
30087430178298343650156781016942167812769252985676
|
|
||||||
21196567069121243761056432679851043212890101679854
|
|
||||||
33203498451080252852347841589765654301285234521763
|
|
||||||
14512432347890161943210950432106567610106501430012
|
|
||||||
01693501036543270856102167645656788943217432567897
|
|
||||||
32789672321015389987343078938765497654998549879898
|
|
||||||
45679987410234578101256560129812321067801456734787
|
|
||||||
03478756500187665432107452121901054328982340125676
|
|
||||||
12568767891098987013898943030810167017654321010210
|
|
||||||
21079458910127698123965436945107878988901267124378
|
|
||||||
30980349821034787654876327876716901210985458095469
|
|
||||||
45671210136765693454761016329825432345671329186954
|
|
||||||
12789800345876548763876125419434501654510413277843
|
|
||||||
03543211238989439012985630308765898746701204567832
|
|
||||||
14623400141232323101234521678906567239874343236901
|
|
||||||
25710519850541014143219834567611452108965650145690
|
|
||||||
76897678769650001054301712106320143210345789036781
|
|
||||||
87678989678742112363212601235431234321276988325432
|
|
||||||
90549876349233678478004592347842389123489676710876
|
|
||||||
21632305256104569589123487656965476016512369856945
|
|
||||||
52301014107012345670149874565456365017603450747832
|
|
||||||
65490123458912396501234563432147454328214921632401
|
|
||||||
86985432167905487654341012563038901039309834521321
|
|
||||||
97876789001856778761232127678127612398712701100410
|
|
||||||
89810678012760869890103238999210543125625632234509
|
|
||||||
76701549013451987217876434785695610034534548765678
|
|
||||||
05432432174012987301987325654780123435210159854789
|
|
||||||
12980120985123673458986510783279234987346543123898
|
|
||||||
43878921976034562567603412892168765679857012010187
|
|
||||||
34565437852178901070412103601001410012768001921236
|
|
||||||
45430566543065012181543014580432321003459122876545
|
|
||||||
50121098767654327892678877698569457654219433468904
|
|
||||||
23292145678954218983019988087658768894308596567812
|
|
||||||
14587239010563007654128679112565489765107687656521
|
|
||||||
05674678323472167659436543203474321087230156785430
|
|
||||||
96983565401089898748540987654589321098543243896543
|
|
||||||
87874328992396701037621296562105465407698012565432
|
|
||||||
78765017687478632128760345673456978312789801478521
|
|
||||||
29653078596569543019656921087567889213456700329650
|
|
||||||
12532169430430156010567892193610367804765410418789
|
|
||||||
03445678321321060123456543012323458912894321001678
|
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
2 77706 5847 9258441 0 741 883933 12
|
|
||||||
|
|||||||
@@ -1,140 +0,0 @@
|
|||||||
QQQQQQCCCCCCCCCCCCXXXXXXXXXXXXXXUUUUUUJEEJJJJJQQQQIIISSVVVVVVVVVMMMMMMMMMMMMMMMMMMVVVVVWWWWFFFFFFFFFFFFAFZZZZZZZZZZZMMMMMMMMMMMMMMMMMMVMMQQQ
|
|
||||||
QQQQQCCCCCCCCCCCCCCCCXXXXXXXXXXUUUUUUUJJJJJJJJIIIQIIIIVVVVVVVVVVMMMMMMFMMMMMMMMMMMMVVVWWWWWFFFFFFFFFFFFFFZZZZZZZZLLZMMMMMMMMMMMMMMMMMMMMQQQQ
|
|
||||||
QQQQQQCCCCCCCCCCCCCCCCCCCXXXXXXUUUUUUJJJJJJJJJIIIIIIIIIVVVVVVVVMMMFFFFFMMMMMMMMMMMWWWWWWWWFFFFFFFFFFFFFFFZZZZZZZZLLZMMMMMMMMMMMMMMMHMQQMQQQQ
|
|
||||||
QQQQQCCCCCCCCCCCCCCCCCCCXXXXXXXUUUUUUUJJJJJJJJIIIIIIIIIIVVVVVVVVMMMMFFFMMMMMMMMMMMWWFFWWWWFFFFFFFFFFFFFFFZZZZZZZZMMMMMMMMMMMMMMMHHMHQQQQQQQQ
|
|
||||||
QQQQQQCCCCCCCCCCCCCCCCCXXZXXXXXXUUUUUUJJJJJJJYIIIIIIIIIIVVVVVVVVVVVFFFBBBMMMMMMMMFFWFFWWWWFFFFFFFFFFFFZZZZZZZZZZZLLMMMMMMMMMHMMHHHHHQQQQQQQQ
|
|
||||||
QQQQQQCCCCCCCCCCCCCCCZZZZZXXXXXXXUUUUUJJJOJJJYIIIIIIIIIVVVVVVVVVVVBFFFBBBBMMMMMMFFFFFFWZWWWWFFFFFFFFFFZZZZZZZZZZLLMMMMMMMMHHHHHRHHHHHHQQQQQQ
|
|
||||||
QQQQQQCCCCCCCCCCCCCCCZZZZTTXXXUUUUUUUUUUUOJJJJIIIIIIIIIIVVVVVVVVVVBBFBBBBBMMMMMMFFFFZDZZZWWWFFFFFFFFFFZZZZZZZZZZLLMMMMMMMMMHHHHHHHHHHHQQQQQQ
|
|
||||||
QQQQQQCCCCCCCCCCCCCCZZZZPTTTXXXXXUXXUUUUUOOJUUUUUIIIIIIIVVVVVVVVVBBBBBBBBBBBMMMFFFFFZZZZWWWAAAFFFFFFFFZZZZZZZZZZZLMMMMMMMMMMMHHHHHHHHHQQQQQQ
|
|
||||||
QIIIIIICCIWCCCCCCCCZZTTTTTTTTXXXXXXXXUUUUOXJUXUUUIIIQQQQQQQVVVVVVBBBBBBBBBBBMFFFFFFFZZZZAAAAAFFFFFFFDZZZZZZZZLLLZLLLMMMMMMMMMHHHHHHJJQQQQQQQ
|
|
||||||
IIIIIIICCIIMMQCCCCZZTTTTTTTTXXXXRRXXXUUUGXXXXXUUUIIIQQQQQQQVVVVVVBBBBBBBABMBMFFEFFFFFZZZZAAAAFFFFFFFDAZZZAAAALLLLLLMMMMMMMMMHHHHHHHJJQQQQQQQ
|
|
||||||
IIIIIIIIIIIMMMCCCCTTTTTTTTTXXXXXRTRXXXRRRXXXKKUUUUIOQQQQQQQVVVVVBBBBBBBBBBMMMFFFFFFFZZZZZAAAAFFFFAAFFAZZAAAAALLLLLLLLLLMMMMMHRHHHHHHJJJQQQQE
|
|
||||||
IMIIIIIIIIINNNNNNNNTTTTTTTTTTXRRRRRRRRRRRXXXXKKUUKOOQQQQQQQTVVVVBBBBBBBBBMMMFFFFFFFFZZZZZZZAAAAAAAABAAAAAAAAALLLLLLLLLMMMMMRRRRHHHPIJJJJBBBE
|
|
||||||
GIIIIIIIIIINNNNNNNNTTTTTTTTTTXRRRRRRRRRRXXKXXKKUUKOOQQQQQQQTVVVBBBBBUUUUMMMMFFFFFFFFFZZZZFAAAAAAAAAAAAAAAAAAIILLLLLLLLFMMMMRRRRHHIIIJJJJBBBB
|
|
||||||
GIIIIIIIIIINNNNNNNNTTTTTTTTTXXRRRRRRRRRXXXKKKKKUUKOOQQQQQQQQQBBBBBBBUUUUMMMMFFFFFFFFFZZZFFFAAAAAAAAAAAAAAAAAAATLLLLLLLFMMMMRRRRIIIIIJJBJBBBB
|
|
||||||
GIIIIIIIIIINNNNNNNNTTTTTTTTYXYRRRRRRRRRRRRPKKKKKKKOOQQQQQQQQQBBBBUUBUUUVUMMMFFFFFFFFFZZHFAAAAAAAAAAAAAAAAAAAGTTTLLLLJLLJMRRRRRIIIIIIIBBBBBBB
|
|
||||||
GGGIIIIIIIINNNNNNNNNNNNNTTCYYYRRRRRRRRRRRRPKKKKKKKKKQQQQQQQQQBBUUUUUUUUUUMMMMFFSFFFFFFFFFAAAAAAAAAAAAAAAAAAAATTTLLLLJJLJRRRRRRIIIIIIIBBBBBBB
|
|
||||||
GGGIIBIIIIINNNNNNNNNNNNNTTCYYYYYRRRRRRRRRRKKKKKKKKKVQQQQQQQTUBBUVUUUUUUUUUUMMMFFFFFFFFFFFAAAAAAAAAAAAAAAAAAATTTTTTTJJJJJRRRRRRRPIIIIIBBBBBBB
|
|
||||||
GGGGGGIIIKINNNNNNNNNNNNNTTCYYYYYRRRRRRRRRKKKKKKKKKKKQQQQQQQFFFFFFFFFFUUUUJUFFFFFFXXFFFFFFAAAAAAAAAAAAAVAEACATTTTTTTTTJJRRRRRRRRPIIZZIBBBBBBB
|
|
||||||
GGGGGGIIKKKNNNNNNNNNNNNNTTTYYYYYRRRRRRRRHKKKKKKKKKKKQQQQQQQFFFFFFFFFFUQUUUGGPGFFFFXFFFAFAAAAAAAAAAAAAAAAERCTTTTTTTTTVVVNNNRRRRRPIIZLLPBWBBBB
|
|
||||||
GGGGGGGKKKKKPPNNNNNNNNNNPPPPPPYYRRRRRRRHHHKKKKKKKKKKTTTTTTTFFFFFFFFFFUUUUHGGGGFXFXXFFFAAAAAAAAAAAAAAAAAARRRTTTSVTTTVVVVNNNNNRRRRNILLLLWWBBBB
|
|
||||||
GGGGGGKKKKPPPPNNNNNNNNNNPFPPPPPPRRRRRRRRRRKKKKKKKKIIITTTTTTFFFFFFFFFFOUUHHGGGGFXXXXXFFFAAAAAAAAAAAAAAAARRRRTTAVVVVVVVBVVVNNNNVVLLLLLLLWBBBBB
|
|
||||||
GGGGGIIIKKKKPPNNNNNNNNNNPPPPPPPPPJJJIRRIIIKKKKKKKIIIITTTTTTFFFFFFFFFFODUHHGGGGGXXXXXXRFAAAAAAAAAAAAAAARRRRROTTVVVVVVVVVHVNNVVVVVVLVVLBBBBBBB
|
|
||||||
GGGGGGIIIKIKPPNNNNNNNNNNPPPPPPPPPJJIIIIIIIIIGIIIKIIIIITTTTFFFFFFFFFFFYDYHGGGGGXXXXXXXXCAAAAAAAAAAAAAAARRRRRRRRRRVVVVVVVHVVVVVVVVVLVVRRBBBBBB
|
|
||||||
GGGGIIIIIIIKPPNNNNNNNNNNPPPPPPPPPPJIIIIIIIIIIJIIIIIIIIPTTTFFFFFFFFFFFYYYHGGGGGGGXGXXXXCAAAAAAAAAAAAAARRRRRRRRRRVVVVVVVVHYVVVVVVVVVVVRRBBBBBB
|
|
||||||
GGGHIIIIIIIIPPNNNNNNNNNNPPPPPPPPPPIIIPPPPPPIIJIIIIIIIIIIGTFFFFFFFFFFFYYBBBBGGGGGGGGGCCCCCACAAAAAAAAAARRRRRRRRRRVRRVVVVVHYYVVVVVVVVVVVRRBBBGB
|
|
||||||
GGGGFFIIIIIIZZNNNNNNNNZPPPPPPPPPPIIPIPPPPPPIIIIIIIIIIIIIITFFFFFFFFFFFYYBBBBGGBGGGGCCCCCCCCCAAAAAAAARRXRRRRRRRRRRRRVVVVVVWYVVVVVVVVVVRRRBBGGG
|
|
||||||
TGGGIIIIIIIIZYNNNNNNNNZPPPPPPPPPPIIPPPPPPPPIIIIIIIIIIIIIDDFFFFFFFFFFFHHBBBBJGBGGGGCCCCCCCCAAACCCADDRRRRRRRRRRRRRRRRVLYYYYYYYVVVVVVVVRRGGHGGG
|
|
||||||
GGGIIIIIIIIIIINNNNNNNNPPPPPPPPPPPIIPPPPPPPPIIIIIIIIIIIICCDFFFFFFDDHHHHHBBBBBBBGGGGGGCCCCCCCCCCICDDDRRRRRRRRRRRRRRRXVLLYYYYYYVVVVVVVVVGGGHGGG
|
|
||||||
GGGIIIDIDIIIIYNNNNNNNNPPPPPPPPPPPPIIIIPPPPPIIIIIIIIIICCCCCFFFFFFDDHHHHBBBBBBBBBGGGGGCCCCCCCJJCCDDDDRRRRRRRRRRRUUUUYYYYYYYYYYYMMVVVVVZZGGGGGG
|
|
||||||
DGGGDDDDDIIIYYYYYYPPPPPPPPPIPPPPPPPIIIPPXXPPPXIIIIIIIICCCCFFFFFFDDDHHBBBBBBBBBBGGGGGCCCCCJJJJCDDHHHJHNNRRQRRRSSUUUUSYYYYYYYYYYYAVVVVVZGGGGGG
|
|
||||||
DDDDDDDDDDDYYYYYYYYYPPPPPPPIIPPPIIIIIIXXXXXPXXIIIIICCCCCCVFFFFFFDDDDHBBBBBBBBBBBAAGGCAADDDDDDDDDHHHJHNHHRRRMMSSUUUSSYYYYYYYYYYYQVVXXGGGEGGGG
|
|
||||||
DDDDDDDDDDYYYYYYYYYPPPIPPIIIIIIIIIIIIIIIXXXPXXXBBXCCCCCCFTFFFFFFDDDDHDBBBBBBBBBAAAAAXAAAAAADDDHHHHHHHHHHHMMMSSSUSSSSYYYYYYYYYYYQQVQQQGGGGGGG
|
|
||||||
DDDDDDDDYYYYYYYYYYYPPPIIIIIIIIIIIIIIIXXXXXXPXXXXXXCJCCCFFFFFFFDDDDDDDDDBBBBBBBBAAAAAAAAAAAADDDDHHHHHHHHHHMMHDSSSSSSSYYYYYYYYYUYYQQQGGGGGGGGG
|
|
||||||
DDDDDEDDYYYSYYYYYYYYTYIIIIIIIIIIIIIIIXXXXXXXXXXXXCCJCCCCFFFFFFDDDDDDBBBBBBBBBBBAAAAAAAAAAAAAAHHHHHHHHHHHHHMHHSSSSSSSYYYYYYYYYYYLQQQGGGGGGGGG
|
|
||||||
DDDDEEDDYYYYYYYYYYYYTYIYIYIIIIIIIIIIIIXXXXXXXXXXYJCJCCFFFFFFFFFDDDDDZZBBBBBBBBBAAAAAAAAAAAAAAHHHHHHHHHHHHHHHJJIBSSSSSYYYCYYQQQFQQQQNGGGGGGGG
|
|
||||||
DDDEEEEEEEYWYYYYYYYYYYIYYYIIIIIIIIIIXXXXXXXXXXXXJJJJJJFFFFFFFFFDDDDDZZBBBBBBBBAAAAAAAAAAAAANHHHHHHHHHHIIHHHJJIIBSSQYYYYYYQYQXXQQQQAKKGKGGGGG
|
|
||||||
EEEEEEEEEEEWWYYYYYYYYYYYYYYYIIIIXIXXXXXXXXXXXXXXXJJJJFFFFFFFFFFDDDDDDZZBBBBBBBAAAAAAAAAAAAAATHHHHHHHHHIIIIIIIIIIIQQQQYYYYQQQXXXQQQKAKKKKKKGK
|
|
||||||
EEEEEEEEEEEWWYWYYYYYYYYYYYYYYYIIXXXXXXXXXXXXXXXXJJJJFFFFFFFFFFFDDDDZZZZZBBBBBBBBAAAAAAAAAAAAAAHHHHHHHIIIIIIIIIIIIIQQQQQYYQQQQXQQQQKKKKKKKKKK
|
|
||||||
EEEEEEEEEEWWWWWYYDYYYYYYYYYYYYYIIXXXXXXXXXXXKKKJJJJJFFFFFFFFFFFFDDDDDZZZZZZZBBBBAAAAAAAAAAAAAEMHHHHHHIIIIIIIIIIIIIQQQQQQQQQQQQQQQQQQKKKKKKKK
|
|
||||||
EEEEEEEWWWWWWWWWWYYYYYYYYYYYYYYYIXNNNNXXXXXXXXJJJJJJJFFFFFFFFFFFFDDTZZZZZZBBBBBBAAJAAAAAAAAMMLLLLLLLLIIIXIIIIIIIIIQQQQQQQQQQQQQQQQQQKKKKKKKK
|
|
||||||
EEEEEEKKWWWWWWWWWYYYYYYYYYYYYYYVAZXXXXXXXXXXXXJJJJJJJFFFFFFFFFFFWDDDZZZZZZBBBBBBAPJJAAAAAAAAMLLLLLLLLIIIIIIIIIIIIIIQQQQQQQQQQQQQQQKKKKKKKKKK
|
|
||||||
EEEEKKKKKKKKWWWWTJYTYYYYYYYAYYAAAAFFVVVXXXXXXXXXJJJJJJFFFFFJFFBFGGGGDDZZZBBBBBBNPPPAARRRRMAMLLLLLLLLLIIIIIIIIIIIIIQQQQQQQQQQQQQQQQMMMKMBKKKB
|
|
||||||
EEEKKKKKKKKKWWWTTTTTTTYYYAYAAAAAAAAAVVVXXXXXXXJJJJJJJJJFFFFJJFBBGGGGGGGGGGZBBBBPPPPPARRRRMMMLLLLLLLLIIIIIKKKKKKKKKKKKQQQQQPQQQMQMQIMMKMBBBBB
|
|
||||||
GKKKKKKKKKKWWTTTTTTTTTYAYAAABAAAAAAAVVVVVXXVVBBJJJCCCJJJFFJJJMBBGGGGGGGGGGZBBBBPPPPPPRRRRMMMLLLLLLLLIIWIVKKKKKKKKKKKKQQQQPPQQQMQMMMMMMMBBBBB
|
|
||||||
GKKKKKKKKKKWWTTTTTTRTTYAAAAAAAAAAAAAVVVVVVVVVVJJJCCCCCJJJJJJJMMMGGGGGGGGGGBBBBBPPPPPJRRRRLRRRRRRRRLLMMIIIKKKKKKKKKKKKQQPQPNNNQMMMMMMMMMCBBBB
|
|
||||||
KKKKKKKKKKKKKETTTTTTTTAAAAAAAAAAAAAAAVVVVVVVVNCLJCCCCCJJJJJJJMMMGGGGGGGGGGBBBPBPPPPPJRRRRMRRRRRRRRLLVMMMVKKKKKKKKKKICCCPPPNNNQMMMMMMWWMMMMBB
|
|
||||||
KKKKKKKKKKKKKEETTTXXTAAAAAAAAAAAAAAAAVVVVVVVVLCCCCCCCJJJJJJJJJMGGGGGGGGGGGBBBPPPPPPPPRRRRRRRRRRRRRLLVVVVVKKKKKKKKKKCCCPPPPPNNNMMMMMMMMMMMMBB
|
|
||||||
KKKKKKKKKKKKKEEEEMXXXAAAAAAAAAAAAAAMAVVVVVVVLLLLLCCCCJJJJJJJJJMGGGGGGGGGGBBBBPPPPPPPPRRRRRRRRRRRRRLLVVVVVKKKKKKKKKKCCCPPPPPPNUMMMMMMMMMBBBBB
|
|
||||||
KKKKKKKKKKKKEEEEMMMMXXAAAAAAAAAAAAAAVVVVVVVVLLLCCCCCCJJJJJJJJJJGGGGGGGGGGBBBBPPPPPPPPRRRRRRRRRRRRRLVVVVVVKKKKKKKKKKCCPPPPPPPCMMMMMMMMMMMBBBB
|
|
||||||
KKKKKKKKYKKKKKKKKMMMMXAAQAAAAAAAAAAAVVVVVVVVLLGGCCCCCJJJJJJJJJJGGGGGGGGGGBBBBBPPPPPPPRRRRJRRRRRRRRLVVVVVVKKKKKKKKKKCCPPPPPMMMMMMMMMMMMMMBBBB
|
|
||||||
KKKKKKKKKKKKKKKKMMMMKMMQQQAAAAAAAAAAAVVVVVVVVVCCCCCCCJJJJJJJJJJGGGGGGGGGGUBBBPPPPPPPPRRRRJJJMLLLLLLVVVVVVKKKKKKKKKKPPPPPPPPPMMMMMMMMMMMMBBBB
|
|
||||||
ZKKKTTKKMMKKMMMMMMMMMMMMQQQAQAAAAAAAVVVVVVVVVVCCCCCJJJJJJJJJJJJGGGGGGGGGGUBBBBPPPPPAPPJJJJJJJJVVVZVVVVVVVKKKKKKKKKKKKKKKPPPPPMMMMMMMMMMMMBBB
|
|
||||||
ZZZTTTKKMMMMMMMMMMMMMMMMMQQQQAAAAAAVVVVVVVVVVCCCCCCJJJJJJJJJJJYGGGGGGGGGGUUBPPPPPPPPEJJJJJJJJJVZZZVVVVVVVVWWKKKKKKKKKKKKPPPPPAAMMMMMMMBMMBBB
|
|
||||||
ZZZTTTTMMMMMMMMTTTTMMMMQQQQQQAAAAOAAVVVVVVVVVXCKCCCCJJJJJJJJJJYGGGGGGGGGGBBBPPPPPJJJJJJJJJJJJZZZZZZVVVVVVVWWKKKKKKKKKKKKPPPQPAAMMMCMMMBMBBBB
|
|
||||||
ZZZTZTTMMMMMMMMTTTTMQQMQQRRQQQQAOOOOVVVVVVVVVXVVCCCCCJJJJJJJJJUUUUUUUUUUUBBBBBBBBBBJJJJJJJJJJZZZZZZVVZZZZWWWKKKKKKCCCCPMPPPAPPAAMMCMBMBBBBBB
|
|
||||||
ZZZZZZTMMMMMMMMTTTTTQQQQQRRQQQQOOOOOOOVOVVVVVVVVGGCCJJJJJJJJJJUUUUUUUUUUUBBBBBBBBBJJJJJJJJJJZZZZZZZZVZZZZZWWKKKKKKBCCCCPPPLAAAAAAABBBBBBBBBB
|
|
||||||
ZZZZZZZCCMMMMMMTTTTTQQQQQRRQROOOOOOOOOVOVVIIIVRVGGJJJJJJJJJUUVUUUUUUUUUUUUUBBBBBBBBBJDDJJJJJJZZZZZZZZZZZZZZWKKKKKKBBBCPPPPAAAAAAABBBBBBBBBBB
|
|
||||||
ZZZZZZCCCMMMMMTTTTTTQQQQQRQQRRROOOOOOOOOVVIIIVIGGJJJJJJJJJUUUUUUUUUUUUUUUBBBBBBBBBBJJJJJJJKKJJZZZZZZZZZZZZZWKKKKKKBBBKPKNKAAAAAAABBBBBBBBBBB
|
|
||||||
ZZZAZZCCCCMMMDTTTTTQQQQQQQRRRRROOOOOOOOOOIIIIIIGGGJJJJJJJJJUUUUUUUUUUUUUVVVVVVVVVBRJJJJJJJKIIIIIIIIIZZZZZWWWKKKKKKBBFKKKKKAAAAAAAABBAABBBBBB
|
|
||||||
ZZZAZZCCCCCMMDDKTTTQQQQQRRRRRROOOOOOOOOOOOIIIIIGAAJJJJJJJJJUUUUUUUUUVVYVVVVVVVVVVBRRJJJJJUUIIIIIIIIIZZZZZZWWKKKKKKBBBKKKIIIAAAAAAAAAAAAABBBB
|
|
||||||
ZAAAZZCCCMMMMDTTTTTQQQQQRRRRRRSOOOOOOOOOGOIIIIIAAAAJJJJJJJJMMMUUJUUXVVVVVVVVVVVVVBRRJJJZIIIIIIIIIIIIZZZZZZWWKKKKKKBBKKIIIIHHHZAAAAAAAAAABBBB
|
|
||||||
AAAROZOMMMMDDDGGTTTTQQRRRRRKRMOOOOOOOOOOOOIIAAAPAAAAAAAJJJJMVVVVVUUUVVVVVVVVVVVVVVRRRPJZIIIIIIIIIIIIZZZZZZWWWWWWWBBBKKKIHHHHHZAAAAAAAAAAAABB
|
|
||||||
AAOOOOOOMMDDDDDTTTTTQQRTRYRKROOOOOOOOOOOOOIIIAAAAAAAAAJJJJJVVVVVCCCCCVVVVVVVVVVVVVRRPPJZIIIIIIIIIIIIZZZZZWWWWWTWWWWBAAAHHHHHHHHHHAAAAAAAAABB
|
|
||||||
AAOOOOOODDDDDDQQTTTQQQRYYYRRYYOOOOOOOOOOOIIIIIAAAAAAAAAJJJVVVVVCCCCCCVVVVVVVVVVVVVVVVVWUIIIIIIIIIIIIZZZZZWWWWWTTWWWBBAAHHHHHHHHHMARAAAAOAAOC
|
|
||||||
AAAOOOOODDDDDDDQQTTQQQQYYYYYYYYOOOOOOOZOOIIIIAAAAAAAAAJJJJJVVVVCVCCCCVVVVVVVVVVVVVVVPUWUIIIIIIIIIIIIZZZZZWWWWZZZZZZZZHAHHHHHHHHHHAAOOOOOOOOC
|
|
||||||
AAAAAOJJDJDDDDDQQQQQQQQQYYOYYYYYYOOOOZZOZIIIIAAAAAAAAAJJJJJVVVVVVCCCCVVVVVVVVVVVVVVVNUUUIIIIIIIIIUGGZZZZWWWWWZZZZZZZZHHHHHHHHHHHMCOOOOOOOOOO
|
|
||||||
AAAAAAAJJJJDDDQQQQQQQQQQQYOYYYYYYYDOOZZOZIIIIAAAAAAAAAJJJJJJJVVVVVCCCCVVVVVVVVVVVVVVNNFUIIIIIIIIIUZZZZZZZTTWWZZZZZZZZHHHHHHHHHHHHCOOOOOOOOOO
|
|
||||||
AAAAAAAAJJDDDDDQQQQQQQQQQOOOWOOOODDOZZZZZZIIAAAAAAAAAAJJJJJJJVJVVDDDCCCVVVVVVVVVVVVNNNNUIIIIIIIIIUUUZZZZZPTTWTTTTWWHHHHHHHHHHHHHCCCCOOOOOOOO
|
|
||||||
AAAAAAAAAJJJDDQQQQQQQQQQOOOOOOODDDDZZZZZZZIIAAAAAAAAAAAJJJJJJJJJVDDDCCCCDKVVVVVVVVNNNNUUUUIIIIIIIUUUUZZZZTTTTITTTTWHHHHHHHHHHHHHCCCCCCCOOOOO
|
|
||||||
AAAAAAAAAAJBBQQBBBQQQQQOOOOOOOODZDDDZZZZZZIIAAAAAAAAAAAAJJJJJJJJDDDDDDDDDDDDVVVVVNNNNNNUUUIIIIIIIUUUUUZZZTTTTTTTTTHHHHHHHHHHHHHHCCCCCCCCOOOO
|
|
||||||
AAAAAAAAAAJBBBBBEBBBQQQOOOOOOOODZZZZZZZZZZZAAAAAAAAAAAAJJJJJJJJDDDDDDDDDDDDVVVVVNNNNNNNUUUIIIIIIIUUUUUUZTTTTTTTTTTTTHHRRHHHHHHHCCCCCCCOOOOOO
|
|
||||||
AAAAAAAAAAJBBBBBBBBBBOOOOOOOOOOOOOZZZZOZAAAAAAAAAAAAAAAAAJJJJJDDDDDDDDDDDDDVVVVVNNNNNNNNNNIIIIIIIUUUPPPKKKKTTTTTTTTTTHRRRHCCCHCCCCCCCCOOOOOO
|
|
||||||
AAAAAAAAAABBBBBBBBBBBOOOOOOOOOOOOOZZZZOZAOOAAAAAAAAGGGJJAJJJJJDDDDDDDDDDDDVVVVVVVVNNNNNNNNIIIIIIIUUPPPPKKKKTTTTTTTTTTTTRTTCCCFCCCCCCCCCOOOOO
|
|
||||||
AAAAPAAAAABBBBBBBBBBBYYOOOOOOOOOPOOOZOOOOOOOAAAAAAGGGGJJJJJJJDDDDDDDDDDDDDVVVVVVVVNNNNNXXNNNNNNNPPPPPPPKKKKTTTTTTTTTTTTTTCCCCCCCCCCCCCCCOOOO
|
|
||||||
AAAAPAAAAABBBABBBBBBBBYOOOOOOOOOOOOOOOOOOOAAAALALAGGGGGJJJJJDDDDDDDDDDDDDDDVVVVOOVVVXXXXXNNNNNNNPZZZZZZZZZZKTKTTKSTTNLLTTNCCCCCCCCCCCCCCCOOO
|
|
||||||
AAAAPPPAABBBBABBBBBBBBBBOOOOOOLLOOGGGOOOAAAAAALLLLLGGJJJJJJJDDDDDDDDDDDDDDDDVVOOOVVVWXXXXNNNNNNNPZZZZZZZZZZKKKKYYYYYYYYYYNNCCCCCCCCCCCCCCOOO
|
|
||||||
AAAAPPAAABBBBABBBBBBBBBBOOOOOOLOOOGGGOOOOAAAAAAALLLLJJJJJJJJJLLLDDDDDDDDDDDDDVOOOOVOWXXXXNNNNNPPPZZZZZZZZZZZZKKYYYYYYYYYYNNCCCCCCCCCBBCCOOOO
|
|
||||||
AAAPPPAPAAAABABBBBBBBBBPOXOOOOLOOOGGGOOOOOOAAAAALLLLLLJJJJJJJLLLLDDDDDDDDDOOOOOOOOOOWXXXXNNNNNNNPZZZZZZZZZZZZKAYYYYYYYYYYYYCCCCCCCXCBBCYOOOO
|
|
||||||
APPPPPPPPAAAAABBBBBBBBFZZXZZKKOOOOGGGOOOOOOAAAAALLLLZLJJJLJJJJLLLDDDDDDDDUUOOOOOOOOOOORRRRONOOPPPZZZZZZZZZZZZKAYYYYYYYYYYYYNCCUCCCCVBBCCPOHO
|
|
||||||
PPPPPPPPPAAAAAABBBBBBBBZZZZMOOOOOGGGGGOOOOOAAALLLLLLLLJJLLLLLLLLLLDDDDDDOOOOOOOOOOSOOOORDDOOOOPPMMMPPPPZZZZZZAAYYYYYYYYYYYYJMCCCCVVVBVPPPVVV
|
|
||||||
PPPPPPPPPAAAAAABBBBBBZBZZZZMMGGGGGGGGGGGGOOAZALLLLLLLLLLLLLLLLLLLLDDDDDOOOOOOOOOOOOOOOORDOOOOOPPMMMPPPPZZZZZZAAYYYYYYYYYYYYJMMMCCCVVVVVVVVVV
|
|
||||||
PPPPPPPPPAAAAAABBBBBBZZZZZZMMGGGGGGGGGGGGAAAZALLLZLLLLLLLLLLLLLLLLLDDDOOOOOOOOOOOOOOOOOOOOOOOOOPMMMPPPPPZZZZZAAYYYYYYYYYYYYJMJMMVVVVVVVVVVVV
|
|
||||||
XPPPPPPPAAAAAABBBTBBYZZZZZZZZYGGGGGGGGGGGGAAZZZLZZZLLLLBBBBLLLLLLLDDDDDOOOOOOOOOOOOOOOOOOOOOMMMMMMMPPPPPZZZZZAOYYYYYYYYYYYJJJJVVVVVVVVVVVVVV
|
|
||||||
XPPPPPPPAAJJAABAACBBYYZZZZYZYYGGGGGGGGGGGGAAZZZZZZLLBBBBBBBLLLLLBBBBBOOOOOOOOOOOOOOOOOOOOOOMMMMMMMMJJJPLZZZZZAZYYYYYYYYYYYJJJJJJBJVVVVVVVVVV
|
|
||||||
XPPPPPPPJJJJAAAACCYBYYZYYYYYYYYGGGGGGGGGGGAAZZZZZZZZBBBBBBBLLLLLBBBBBBBBOOOOOOOOOOOOOOOOOOOMMMMMMMMMJJZZZZZZZZZYYYYYYYYYYYJJJJJJJJBVVVVVVVVV
|
|
||||||
XPPXPPPPJJJJAAACCCYYYYZYHYHYYYHGGGGGGGGGGGAAAZZZZZZZBBBBBBBBBLLBBBBBBBBBOOOOOOOXOOOOOOOOOOOMMMMMMMMMJJZZZZZZZZZZOOOOJJJYYYJJJJJJVJBVVVVVVVVV
|
|
||||||
XXXPPPPJJJJJJAACCYYHYYYHHHHHHHHGGGGGGGGGGGEAEZZZZZZZBBUBBBBBBBBBIIIBBBBOOOOOOOOOOOOOOOOOOOOOMMMMMMMMJJZZZZZZZZZOOOOOOJJYYYJJJJJJJJVVVVVVVVVV
|
|
||||||
XXXPPPPPPJJJJPACCCHHHYHHHHHHHHHGGGGGGGGGGEEEEZZZZZZZZUUUUBBBUUBBBIIIBIBBBOOOOOOOOOOOOOOOOOOOMMMMMZZZZZZZZKKZZZZZOOOOCCYYYYYYJJJJJJVVVVVVVVVV
|
|
||||||
XXXXPPPPPJJJPPAAAAHHHHHHHHHHHHYYYGGGGGEEEEEEZZZZZZZZZZUUUUUUUBBBIIIIIIIBBBOOOOMMMOOOOOOOOOYOMMMMMZZZZZZZZKKZZZZZZZOCCCYYYYYYJJJJJJVVQQVQQVVV
|
|
||||||
XXXPPPPJJQJJPPPAAHHOHHHHHHHHHHYYYYEEWEEEEEEEEZZZZZZZZUUUUUUUUUUIIIIIIIIIBOOOOOMMMMOMOOSOOOOOOMMMMZZZZZZZZKKZZZZZZZCCCCYYYYYYJJJJJJJJOQQQVVVV
|
|
||||||
XXXXXPPJJJJPPPPRROOOHHHHHHHHYYYYYYYEEEEEEEEEEEEZZZZUUUUUUUUUUUIIIIIIIIIIMMOOOMMMMMOMNNNOOOONNNNJEZZZZZZZZKKZZZZZZZCCCCYYYYYYJJJJJJJXQQQQQQQQ
|
|
||||||
XXJXXJJJJJJPPPRRRROOHHHHHHHHYYYYEEEEEEEEEEEEEEEZZZZZUUUUUUIIIIIIIIIIIIBBMMOOMMMMMMMMNNNCNNNNNNJJFZZZZZZZZKKKZZZCCCCCCCYYYYYYJJJJJJJQQQQUQQQQ
|
|
||||||
XXJJJJJJJJJPPYPVRJJHHPHHHHHHYYYYEEEEEEEEEEEEEEZZZZZZUUUUUTTIIIIIIINIIBBIMMMMMMMMMMMMNNNNNNNNNNFFFKKKKKKKKKKKZZZCCCCCCCYYYYYYJJJJJJCQQQQQQQQQ
|
|
||||||
XXJJJJJJJJPPJPPPPPJJJPPPHHHHHYYYEEEEEEEEEEEEXPZZZZZZZZUUUTTINNNNINNKIBIIMMMMMMMMMMMMMNNNNNNNNFFFFFKKKKKKKKKKZZZCCCCCCCYYYYYYJJJJJQQQQQQQQQQQ
|
|
||||||
XJJJJJJJPPPPPPPPPPJJJHHHHHHDHDYYYYYEEEEEEEEXXXZGGZZZZZUUUNNNNNNNNNNIIIIIMMMMMMMMMMMMNNNNNNNNNFFFFKKKKKKKKKKKKKKCCCCCCCYYYYYYYYYZZQQQQQQQQQQQ
|
|
||||||
JJJJJJJPPPPPPPPPPJJJJJJJJHHDDDDYYYYYEEEEEEEXXGGGGEEZZZUUDNANNNNNNNAIIIIIMMMMMQMMMMMMNNNNNNNNFFFFFKKKKKKKKKKKKKKCCCCCCCYYYYYYYYYZQQQQQQQQQQQQ
|
|
||||||
JJJJJJJJPPPPPPPPPJJJJJJJJJDDDDDYYYYEEEEEEXXXXXGGGGEEEZEUDNNNNNNNNAAAIIIIMMMMQQQQMMNNNNNNNNNNFFFFFCKKKKKKKKKKKKKKWCCCCIYYYYYYYYYZZZXQXQQQQQQQ
|
|
||||||
JJJJJJPPPPPPPPPPPJJJJJJJJJDDDDDDDYYEEEEEEXXXXGGSEEEEEEEENNNNNNNNNVVAAIIMMMMQQQQQMMNNNNNNNNNNOFFFFFKKKKKKKKKKKUUKKUCCCCCCCZYYYYYZZZXXXXQQQQQQ
|
|
||||||
HJJJJJPPPPPPPPPPPPPJJJJJJJJDDDDDDYYYEEEEEXXXSSSSEEEEEEEENNNNNNNNNNVAAAVVMQQQQQQQMMNNNNNNNHNNNFFFFFKKKKKKKKKKKUUUUUCCUUUUCCYYYYYXXXXXXXQQQQQQ
|
|
||||||
HJJJJNPPPPPPPPPPFPPJJJJJJJJDDDDYYYYXXNNEXXXSSSSSEEEEEEENNNNNNNNNNVVVVAVVQQQQQQQQMNNNHHNNNHNNNFFFFFKKKKKKKKKKKUUUUUUUUUUUUUUUHZZZXXXXXQQQQQQQ
|
|
||||||
HHJVJRPPPPPPPPPPPPPPLJJJJJJDDDLLLLXXXXXEXXXXXXXSUUUUNNNNNNNNNNNNNVVVVVVVQQQQQQQQMMMNHHHNNHHHHHHHHFHHHKKKKKKKKUUUUUUUUUUUUUHHHHHXXXXXXXQQQQQQ
|
|
||||||
HRRRRRRPRPUPPPPPPPPLLLLJJJDDDLLLLUUUXXXXXXXXXXXXXXUUUUNNNNNNNNNNNVVVVVVVQQQQQQQQMMMMHHHHHHHHHHHHHHHHHKHHHKKKKUUUUUUUUUUUUHHHHHHHHXXXXXXXQQQQ
|
|
||||||
HHHHRRRRRRRRRRPPPPWLLLLLLLLLDLLLLUUUVVVXXXCCCXXXXXXXKNNNNNNNNNNNNVVFVVVTTQQQQQQTMMMHHHHHHHHHHHHHHHHHHHHHHHKKUUUUUUUUUUUUUUHHHHHXXXXXHQHXQQQQ
|
|
||||||
HRRRRRRRRRRRRRRPPBGLLLLLJLLLLLLLLULUVVVXXCCCCCXXXXXXKKNNNNNNNNNNVVVVTTTTTTTTQQQTTTMLLHHHHHHHHHHHHHQQQHHHHUKUUUUUUUUUUUUQUUHHHXXXXXXXHHHHQHAH
|
|
||||||
RRRRRRRRRRRRRRRRPPGLLLJJJLJLLLLLLLLUVVVXCCCCCCXXXXXKKKNNNNNNNNNNVVVVTTTTTTTTTTTTTMMLLHLHHHHHHHHHHHQQQQHHHUUUUUUUUUUUUUUQUQHSXXXXXXXXXXHHHHHH
|
|
||||||
RRRRRRRRRRRRRRRRRGGGLJJJJJJLLLLLLLVVVVVECCCCMMMMMMKKKKKKNNNNNNNNNVVTTTTTTTTTTTTTULLLLLLHHHHHHHHHQQQQQHHHUUUUUUUUUUUUUQQQQQQSXXXXXXXXXXXHHHHH
|
|
||||||
RRRRRRRRRRRRRRRRRGGGGJJJJJJLLLLLLJVVVVVVGCCCMMMMMMKKKKKNNSSNNNNNNVTTTTTTTTTTTTTULLLLLLHHHHGGGGGHHQQQHHHHHUUUUUUUUUUUUQQQQQQSSXXXXXXXXXHHHHHH
|
|
||||||
VRRRRRRRRRRRRRRRRGGGJJJJJJJLLLLLLJVVVVVVGCCCMMMMMMKKKKNNGSGNNNNNYYTTTTTTTTTTTTLLLLLLLLLHHHGGGGQQQQQQHQHHHUUUUUUUUUUUUQQQQQQQSXXXAXXXXXHHHHHH
|
|
||||||
VVVRTRRRRRRRRRRRJGGGGQJJJJJJJLLLGVVVVVVGGCCCMMMMMMKKGKGGGGGGGGYYYYDTDTTTTTTTTTLLLLLLLLLHHHGGGGQQQQQQQQHHOOOOUUOOUUUUUQQQQQQQQXUAAXXMHHHHHHHH
|
|
||||||
VRRRTTTTRFFRRJRRGGGGQQJUJJJJJJGLLGGGGVGGGGGCMMMMMMKKGGGGGGGFFFYYDDDDDDDDTTTTTTTLLLLLLLLLHHGGGGQQQQQQQQQOOOOOUUOOUOUZUQQQQPQQUUUTTTTTHHHHHHHH
|
|
||||||
VVRAAATTYTFRYDDFGDGGQQJJJJJJGGGGGGGGGGGGGTTTTTTTMMKZGGGGFGGFFFYYDDDDDDDCTTTTTTTLLLLLLLLHHGGGGGGQQQQQQQOOOOOOOUOOOOOUGUUQQQQQUUUTTWTTKKNNHHNN
|
|
||||||
VVUUATTTTTDDDDDDMDGGQQJJJJJJGDGGGGGGGGGGGTTTTTTTKKZZGIIIFFFFFFYDDDDDDDDDDDTTTTTLLLLLLLLGGGGGGGGQQQQQQQOOOOOOOOOOOOWUUUUUUUUUUUUUUUKKKKKNHNNN
|
|
||||||
UUUUTTTTTQDDDDDDMDDDQQQQJJJJGDGGGGGGGGGGGTTTTTTTKKZZZIIIIFFFFDDDDDDDDDDHHHHTTTHLLLLLLLLIIGGGGGGQQQQQQOOOOOOOOOOOOOWKWWUUUUUUUUUUUUNNNNNNNNNN
|
|
||||||
UUUUTTTTTTDDDDDDDDDDDQQJJJCCDDGGGGGGGGTTTTTTTTTTCZZZIIIIIIFFFFDDDDDDDEDHHHHTHHHHLLLLLLLLLGGGGGGQQQQOQOOOOOOOOWOOOWWWWUUUUUUUUUUUUGNNNNNNNNNN
|
|
||||||
UUUUUTBTTTDDDDDDDDDDDDQJJJCCDDDGGDGGDGTTTTTTTTTTZZTZZIFFIFFFFFFDDDDDDDHHHHHHHHHLLLLLLLLLLGGGGGGQQQQOOOOOOOOOOWWWWWWWWUUUUUUUUUUUUNNNNNNNNNNN
|
|
||||||
UUUUUUUTTTTDDDDDDDDDDQQQQDDDDDDGDDDDDDTTTTTTTTTTNZZZZIIFFFFFFFFFDDDDDDDHHHHHHHHHHHLLLLLGGGGGGGGGGGOOOOOOOOOOOWWWWWWWWUUUUUUUUUUUUUNNNNNNNNNN
|
|
||||||
UUUUUUUTUUUDDDDDDDDDQQQQQQDDDDDDDDDDDDTTTTTTTTTTZZZZZFFFFFFFFFFFDFDDDZZZHHHHHHHHHHHHGGGGGGGGGGGGGOOOOOOOOOOOOOWWWWWWWWWWUUUUUUUUUNMNNNNNNNNN
|
|
||||||
UUUUUUUUUUDQDDDDDDDDQQQQQQDDDDDDDDDDDDTTTTTTTTTTZZZZZZZFFFFFFFFFFFDDDDZZHHHHHHHHHHGGGGGGGGGGGGGGGOOOOOOOOOOOOWWWWWWWWWWUUUUUUUUUUNNNNNNNNNNN
|
|
||||||
UUUUUUUUUDDDDDDDDDQQQQQQQDDDDDDDDDDDAZTTTTTTTTTTNZZZZFFFFFFFFFFFDDDDJJZZZHHHHFFFFFGGGGGGGGGGGGGGGOOOOOOOOOOOOOWWWWWWWWWUUUUUUUUUUUNNNNNNNNNN
|
|
||||||
UUUUUUUDDDDDDDDDDDQQQQQQQDDDDDDDDDDDDETTTTTTTTTTNPZZZFFFFFFFFFFFFIIZZZZZZZZFFFFFFFXGGGGGGGGLGGGGGGGOOOAAOOOOOOWWWWWWWWWUUUUUUUUUDUDNNNNNNNNN
|
|
||||||
UUUUUUUDDDDDDDDDDQQQQQQQQQDDDDDDDDDDDEEEVVVVVVVNNPZZZFFFFFFFFFFFDIDZZZZZZZZIIIIIIFXXXXGGGGGLLGGGGGOOOOOAOOOOOOOWWWWWWWUUUUUUUUDDDDDNNNNNNNNN
|
|
||||||
UUUUUUUDDDDDDDDQQQQQQQQQQVVVDDDDDDDDEEEEVVVVHHPNPPPZZZZFFFFFFFWWDDDZZZZZZZZZIIIIIIJXXJJGJJLLLLGGLGGOWWFAOAOOAOWWWWWWWWWWUUUUUUDDDDDDNNNNNNNN
|
|
||||||
UUUUUUUUDIDDDDDQQQQQQQQQQQVDDDDDDDDDDDEEEEVVVHPPPPPZZZZFZZZZZZWWDDDDDZZZZZZZIIIIIIJJJJJJJJLLLLLGLGGOWWFFFAAAAAWWWWWWWWWWUUZZUUUDDDDDDNNCNNNH
|
|
||||||
UUUUUUUUPDDDDDJJQQQQQQQVVVVDDDDDDDDDDEEEEEEVGPPPPPPZPZZFZZZZZWNWWWDDDDZZZZZZIIIIIIIJJIIILLLLLLLLLGLOWFFFFAAAAAWWWWWWWWWWWUZZUDDDDDDDDDNNNNNN
|
|
||||||
UUUUUUUUUDDDDDJJJQQQQQQQQQQQDTDDDDDDDDEEEEEPPPPPPPPPPPZZZZZZZWWWWWDDDDDZZZZZZNIIIIIIIIICCLLLLLLLLLLBFFFFFFFAAEWWWWWWWWWZZZZZZDDDDDDDDDDNNNNN
|
|
||||||
UUUUGGUUEEDDDDJJJJJJJQQQQQQQQDDDQDDDDEEEEEEEKPPPPPPPPPPZZZZWWWWPWDDDDDDZZZZZZNNIIIIIIILLLLLLLLLLLLLLFFFFFFFFFEWWWWWWWWWZZZZZDDDDDDDDDDDNNNNN
|
|
||||||
UUGUGGGEEEDJJJJJJJJJJJQQQQQQQDDDQQDDEEEEEEEEPPPPPPPPPPPZZWWWWWWWWDWDDDDZZZZZNNNNNIIIIILLLLLLLLLLLLLLLGFFFFFFEEEEEEWWWWZZQZZZDDDDDDDNNDNNNNNN
|
|
||||||
UGGGGGGGEEEJJJJJJJJJJJQQQQQQQQDQQQEEEEEEEEEEPPPPPPPPPPZZZWWWWWWWWWWWDDDZZZZINNNIIIIIIILLLLLLLLLLLLMGGGFEEEEEEEEEEWWWWWWZZZZZZDDDDNNNNNNNNNNN
|
|
||||||
UGGGGGGGGEJJJJJJJJQJQQQQQQQQQQQQQEEEEEEEEPPPPPPPPPPPPZZZZWWWWWWWWWWWDDZZNNNINNIIIIIIIILLGHLLLLLLLLLGGEEEEEEEEEEEEWWWWWZZZZZZZDDDDNNNNNNNNNNN
|
|
||||||
UGGGGGGGGGQJJJJJJJQQQQQQQQQQQQQQQQEEYEEYYYOPPPPPPPPPZZZWWWWWWWWWWWWWDDDNNNNNNNNIIINIIIIAGLLLLLLLLLLLGEEEEEEEEEEECPPPZZZZZZZZZDDNNNNNNNNNNNNN
|
|
||||||
SGGGGGGGGGJJJJJJJJQGQQQQQQQQQQQQQQQYYYYYYYYPYPPPBPZZZZZZWWWWWWWWWWWWNNNNNNNNNNNNNINIIIIGGLGGLLLLLLGGGGEEEEEEEEEECCPPPPPPZZZOZDNNNNNNNNNNNNNN
|
|
||||||
GGGGGGGGGGAJJJJJJJJQQQQQQQQQQQQQQQQYYYYYYYYYYPPPPZZZZZZZZZWWWWWWWWWRRRNNNNNNNNNNNNNIGIIIGGGLLLLGGGGGGEEEEEEEEEMMPCPPPPPPPPZZPPPPNNNNNNNNNNNN
|
|
||||||
GGGGGGGGGGGGJLJJJJJJDQQQTTTQQQQQQQQYYYYYYYYYYPYPYZZZZZZZZZZZWWWWWWWRRRNNNNNNNNNVVGGGGGGGGGGGLLGGGGGGGRNEEEEEEEMMPPPQPPPPPPPPPPPUNNNNNNNNNNNN
|
|
||||||
GGGGGGGGGGGGLLJJJJJTTDTQTTTQQQQQQEEEEEYYYYYYYYYYYYZZZZJZZWWWWWWWWWWRRRNNNNNNNNNNNRLLGGGGGGGGGGGGGGRRRRRREKKEEEMMPPPPPPPPPPPPPPPPZZZZZNNNNNNN
|
|
||||||
GGGGGGGGGGGGLYPPJJTTTTTTTQQQQQQQQEEEEEYYYYYYYYYYYYZZJJJJJJMWWWWWWWWWRRRRRNNNNRRRRRLLLGLGGGGGGGGGGGGRRRREEKKKKKKKUUPBPPPPPPPPZZZZZZZZNNNNNNNN
|
|
||||||
GGGGGGGGGGGGYYPPJJTTTTTTTTTTQQQQQEEEEEYPYYYYYYYYYZZZJJJJJJMMMWWWWWWWRRRRRRRRRRRRRLLLLLLGGGGGGGGGGGGRRRRRERKKKKKKKUPBBPPPPPPPZZZZZZZZZNNNNNNN
|
|
||||||
GGGGGGGGGGGYYYYYJJTTTTTTTTTQQQQQEOEEEEEYYYYYYYYYYZZZQJJJJJJJMWWWWWWWRRRRRRRRRRRRRLPLLLLLGGGGGGGGGGGRRERRRRRKKKKKKPPPPPPPPPPPZZZZZPZPPPPPNNNN
|
|
||||||
GGGGGGGGGGGYYYYYYJPTTTTTTTTTQQQQEEEEEEEYYYYYYYYYYYZJJJJJJJJJWWWWWRRWRRRRRRRRRRRRRLLLLLLLLGGGGGGGGGGGGRRRRRRRTKKKKPPPPPPPPPPPZZZZPPPPPPPPNNPP
|
|
||||||
GGGGGGGGGGYYYYYYYTTTTTTTTTTQQQQQEQEEEEEYYYYYYYYYYYZJJJJJJJJJJJWWRRRRRRRRRRRRRRRRRRRRLLLLLGGGGGGGGGGRRRRRRRRTTTTKTTPRPPPPPPPPZZFZPPPPPPPPNPPP
|
|
||||||
GGGGGGGGGGKKKKKKKKTTTTTTTTQQQQQQQQEYEEHHHHHHYYYYYYJJJJJJJJJJJJJRRRRRRRRRRRRRRRRRRRRRLLLLGGGGGGGGGGGGGRRRRRRRTTTTTTTPPPPPPPPRZZFZPPPPPPPPPPPP
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,500 +0,0 @@
|
|||||||
p=99,12 v=19,18
|
|
||||||
p=90,98 v=47,-52
|
|
||||||
p=86,3 v=82,-13
|
|
||||||
p=13,8 v=-67,-47
|
|
||||||
p=36,45 v=28,65
|
|
||||||
p=71,35 v=-8,-62
|
|
||||||
p=75,8 v=-30,-21
|
|
||||||
p=3,46 v=-38,-96
|
|
||||||
p=1,89 v=78,18
|
|
||||||
p=47,59 v=-63,99
|
|
||||||
p=92,78 v=68,48
|
|
||||||
p=42,31 v=78,94
|
|
||||||
p=75,29 v=9,83
|
|
||||||
p=46,12 v=-29,48
|
|
||||||
p=80,16 v=-70,33
|
|
||||||
p=18,66 v=57,-97
|
|
||||||
p=60,12 v=89,-90
|
|
||||||
p=21,36 v=-41,-78
|
|
||||||
p=75,53 v=52,-62
|
|
||||||
p=18,79 v=45,51
|
|
||||||
p=20,29 v=63,-97
|
|
||||||
p=22,68 v=23,1
|
|
||||||
p=6,67 v=-24,-44
|
|
||||||
p=44,35 v=-54,29
|
|
||||||
p=33,80 v=28,-56
|
|
||||||
p=48,78 v=55,-22
|
|
||||||
p=88,79 v=99,69
|
|
||||||
p=12,96 v=-50,-59
|
|
||||||
p=6,57 v=80,61
|
|
||||||
p=98,31 v=-77,14
|
|
||||||
p=91,65 v=-13,20
|
|
||||||
p=52,53 v=-85,41
|
|
||||||
p=94,94 v=-15,5
|
|
||||||
p=69,75 v=-41,-11
|
|
||||||
p=98,77 v=71,-54
|
|
||||||
p=23,47 v=-61,-27
|
|
||||||
p=32,74 v=-11,96
|
|
||||||
p=22,87 v=-5,-75
|
|
||||||
p=65,22 v=26,71
|
|
||||||
p=1,67 v=13,69
|
|
||||||
p=32,96 v=-90,-94
|
|
||||||
p=17,17 v=-5,71
|
|
||||||
p=57,85 v=-92,28
|
|
||||||
p=52,32 v=-41,69
|
|
||||||
p=13,85 v=-43,-83
|
|
||||||
p=51,39 v=-38,32
|
|
||||||
p=64,17 v=91,82
|
|
||||||
p=97,86 v=-69,-70
|
|
||||||
p=98,94 v=46,-21
|
|
||||||
p=43,31 v=61,-24
|
|
||||||
p=42,58 v=-51,-42
|
|
||||||
p=5,46 v=-4,91
|
|
||||||
p=65,52 v=10,50
|
|
||||||
p=23,6 v=-42,29
|
|
||||||
p=54,25 v=4,44
|
|
||||||
p=5,19 v=-77,-74
|
|
||||||
p=44,77 v=-23,-26
|
|
||||||
p=10,70 v=6,-72
|
|
||||||
p=38,101 v=-50,-36
|
|
||||||
p=9,49 v=35,72
|
|
||||||
p=64,14 v=77,-78
|
|
||||||
p=21,2 v=-67,-6
|
|
||||||
p=34,97 v=-73,-37
|
|
||||||
p=77,13 v=-30,60
|
|
||||||
p=50,40 v=83,-58
|
|
||||||
p=99,85 v=-59,-87
|
|
||||||
p=65,0 v=-76,-48
|
|
||||||
p=44,94 v=-45,34
|
|
||||||
p=5,59 v=92,35
|
|
||||||
p=73,100 v=93,-71
|
|
||||||
p=50,20 v=-74,-97
|
|
||||||
p=9,33 v=-10,-89
|
|
||||||
p=54,49 v=-46,99
|
|
||||||
p=99,100 v=92,51
|
|
||||||
p=84,94 v=-53,-45
|
|
||||||
p=92,13 v=-61,69
|
|
||||||
p=19,52 v=56,-12
|
|
||||||
p=20,52 v=-38,-90
|
|
||||||
p=98,12 v=99,-22
|
|
||||||
p=46,23 v=95,-32
|
|
||||||
p=84,100 v=-70,70
|
|
||||||
p=19,69 v=58,-52
|
|
||||||
p=77,67 v=-51,31
|
|
||||||
p=11,6 v=18,-67
|
|
||||||
p=11,22 v=-50,-82
|
|
||||||
p=73,43 v=25,79
|
|
||||||
p=60,16 v=-58,-36
|
|
||||||
p=86,18 v=-88,71
|
|
||||||
p=21,50 v=-50,-88
|
|
||||||
p=17,20 v=-65,-54
|
|
||||||
p=38,26 v=67,71
|
|
||||||
p=22,60 v=-46,15
|
|
||||||
p=81,46 v=-39,16
|
|
||||||
p=25,98 v=22,-41
|
|
||||||
p=9,72 v=-94,8
|
|
||||||
p=82,59 v=-46,-34
|
|
||||||
p=71,41 v=-23,45
|
|
||||||
p=74,1 v=-70,32
|
|
||||||
p=96,17 v=-37,95
|
|
||||||
p=39,45 v=-6,-23
|
|
||||||
p=46,4 v=61,55
|
|
||||||
p=41,100 v=-35,-10
|
|
||||||
p=65,75 v=-1,-26
|
|
||||||
p=8,21 v=7,-32
|
|
||||||
p=43,71 v=-12,73
|
|
||||||
p=85,67 v=58,-41
|
|
||||||
p=73,7 v=31,-89
|
|
||||||
p=85,71 v=-93,-72
|
|
||||||
p=54,83 v=-46,-75
|
|
||||||
p=13,66 v=-24,-98
|
|
||||||
p=67,13 v=21,-21
|
|
||||||
p=1,33 v=24,-66
|
|
||||||
p=71,27 v=54,-78
|
|
||||||
p=69,86 v=42,35
|
|
||||||
p=17,28 v=-83,94
|
|
||||||
p=92,19 v=25,-68
|
|
||||||
p=92,84 v=-31,16
|
|
||||||
p=32,26 v=-6,54
|
|
||||||
p=20,97 v=-16,36
|
|
||||||
p=1,102 v=13,9
|
|
||||||
p=59,26 v=-68,91
|
|
||||||
p=92,44 v=-20,30
|
|
||||||
p=16,45 v=-83,34
|
|
||||||
p=30,69 v=-75,-46
|
|
||||||
p=51,64 v=-73,68
|
|
||||||
p=53,29 v=-57,-61
|
|
||||||
p=14,100 v=-15,86
|
|
||||||
p=80,41 v=-20,-81
|
|
||||||
p=5,92 v=-60,1
|
|
||||||
p=91,10 v=-49,98
|
|
||||||
p=0,62 v=-79,9
|
|
||||||
p=40,1 v=3,-70
|
|
||||||
p=81,32 v=-53,41
|
|
||||||
p=53,18 v=-46,94
|
|
||||||
p=69,96 v=-95,-82
|
|
||||||
p=32,92 v=-69,-30
|
|
||||||
p=73,83 v=-59,-65
|
|
||||||
p=74,67 v=-8,-99
|
|
||||||
p=71,45 v=-58,60
|
|
||||||
p=35,29 v=-51,-92
|
|
||||||
p=68,15 v=-92,-55
|
|
||||||
p=74,3 v=26,30
|
|
||||||
p=67,25 v=-58,22
|
|
||||||
p=31,46 v=-73,-92
|
|
||||||
p=29,69 v=45,23
|
|
||||||
p=48,78 v=-23,-29
|
|
||||||
p=41,13 v=-45,-78
|
|
||||||
p=57,8 v=-3,26
|
|
||||||
p=45,53 v=45,4
|
|
||||||
p=37,23 v=-62,41
|
|
||||||
p=41,90 v=-35,55
|
|
||||||
p=88,96 v=53,-71
|
|
||||||
p=38,15 v=-90,71
|
|
||||||
p=62,20 v=4,-88
|
|
||||||
p=64,19 v=15,-85
|
|
||||||
p=96,61 v=10,81
|
|
||||||
p=19,81 v=57,-45
|
|
||||||
p=53,11 v=67,44
|
|
||||||
p=51,83 v=66,85
|
|
||||||
p=29,76 v=-84,-26
|
|
||||||
p=63,23 v=-13,14
|
|
||||||
p=23,51 v=-18,-52
|
|
||||||
p=23,41 v=73,-55
|
|
||||||
p=99,75 v=-32,-14
|
|
||||||
p=68,20 v=79,45
|
|
||||||
p=27,74 v=45,42
|
|
||||||
p=55,96 v=47,-73
|
|
||||||
p=87,29 v=-93,22
|
|
||||||
p=20,76 v=-49,88
|
|
||||||
p=11,78 v=-67,-41
|
|
||||||
p=31,78 v=-12,-99
|
|
||||||
p=21,49 v=64,9
|
|
||||||
p=56,45 v=10,-4
|
|
||||||
p=67,97 v=-59,92
|
|
||||||
p=96,58 v=-49,96
|
|
||||||
p=36,51 v=-68,8
|
|
||||||
p=18,10 v=-79,-60
|
|
||||||
p=25,7 v=47,-55
|
|
||||||
p=12,101 v=40,-52
|
|
||||||
p=83,57 v=-42,-38
|
|
||||||
p=62,89 v=77,20
|
|
||||||
p=8,49 v=51,-54
|
|
||||||
p=12,98 v=-20,53
|
|
||||||
p=47,89 v=35,68
|
|
||||||
p=46,16 v=89,6
|
|
||||||
p=72,34 v=37,45
|
|
||||||
p=61,31 v=49,76
|
|
||||||
p=42,98 v=64,17
|
|
||||||
p=27,41 v=71,27
|
|
||||||
p=50,8 v=-1,-63
|
|
||||||
p=97,5 v=-56,9
|
|
||||||
p=41,58 v=5,-38
|
|
||||||
p=66,101 v=-64,13
|
|
||||||
p=67,95 v=-40,18
|
|
||||||
p=94,41 v=-37,73
|
|
||||||
p=89,102 v=-4,2
|
|
||||||
p=44,51 v=-84,65
|
|
||||||
p=9,89 v=29,89
|
|
||||||
p=28,29 v=5,29
|
|
||||||
p=76,4 v=-89,8
|
|
||||||
p=75,93 v=-75,89
|
|
||||||
p=38,6 v=-73,-2
|
|
||||||
p=19,1 v=-95,-6
|
|
||||||
p=61,76 v=-69,23
|
|
||||||
p=6,27 v=64,-24
|
|
||||||
p=97,76 v=47,28
|
|
||||||
p=62,86 v=50,-61
|
|
||||||
p=85,50 v=-93,-92
|
|
||||||
p=10,76 v=-83,31
|
|
||||||
p=58,42 v=52,-81
|
|
||||||
p=47,42 v=16,38
|
|
||||||
p=3,17 v=-66,52
|
|
||||||
p=58,84 v=-59,-36
|
|
||||||
p=91,76 v=20,-68
|
|
||||||
p=9,62 v=-10,-23
|
|
||||||
p=45,99 v=-85,-2
|
|
||||||
p=0,8 v=-77,17
|
|
||||||
p=53,70 v=-41,-23
|
|
||||||
p=32,96 v=6,89
|
|
||||||
p=67,33 v=26,37
|
|
||||||
p=94,86 v=47,47
|
|
||||||
p=26,74 v=-39,12
|
|
||||||
p=19,15 v=-55,16
|
|
||||||
p=60,76 v=93,-98
|
|
||||||
p=44,71 v=-49,-38
|
|
||||||
p=35,77 v=-1,-7
|
|
||||||
p=68,98 v=32,89
|
|
||||||
p=10,54 v=-23,-24
|
|
||||||
p=63,10 v=-77,50
|
|
||||||
p=75,61 v=71,80
|
|
||||||
p=35,78 v=-5,-55
|
|
||||||
p=74,23 v=15,-45
|
|
||||||
p=10,68 v=52,-34
|
|
||||||
p=45,43 v=8,-67
|
|
||||||
p=12,76 v=24,-75
|
|
||||||
p=62,73 v=-86,77
|
|
||||||
p=9,82 v=-38,-64
|
|
||||||
p=1,95 v=25,-64
|
|
||||||
p=67,30 v=-69,-20
|
|
||||||
p=92,25 v=-79,75
|
|
||||||
p=42,19 v=-46,-78
|
|
||||||
p=3,98 v=35,-83
|
|
||||||
p=89,102 v=53,90
|
|
||||||
p=25,10 v=-5,37
|
|
||||||
p=46,0 v=-74,29
|
|
||||||
p=12,40 v=-79,92
|
|
||||||
p=13,21 v=-56,-44
|
|
||||||
p=63,49 v=77,-27
|
|
||||||
p=3,12 v=83,-67
|
|
||||||
p=48,42 v=72,-62
|
|
||||||
p=37,74 v=-46,16
|
|
||||||
p=25,75 v=51,-26
|
|
||||||
p=84,35 v=81,-43
|
|
||||||
p=38,40 v=-63,19
|
|
||||||
p=77,13 v=-64,-48
|
|
||||||
p=95,13 v=-82,-44
|
|
||||||
p=81,41 v=-19,-81
|
|
||||||
p=33,81 v=-64,41
|
|
||||||
p=69,75 v=65,35
|
|
||||||
p=30,76 v=45,39
|
|
||||||
p=48,72 v=-29,39
|
|
||||||
p=74,10 v=78,-61
|
|
||||||
p=70,17 v=9,52
|
|
||||||
p=11,67 v=46,-87
|
|
||||||
p=35,72 v=-11,-46
|
|
||||||
p=86,37 v=-82,60
|
|
||||||
p=99,24 v=-91,56
|
|
||||||
p=92,46 v=-54,-23
|
|
||||||
p=93,12 v=76,-9
|
|
||||||
p=92,43 v=-97,-75
|
|
||||||
p=3,72 v=10,-79
|
|
||||||
p=13,83 v=13,8
|
|
||||||
p=78,80 v=3,-60
|
|
||||||
p=81,41 v=84,-73
|
|
||||||
p=93,9 v=-25,36
|
|
||||||
p=78,96 v=20,-37
|
|
||||||
p=40,50 v=-78,59
|
|
||||||
p=66,21 v=85,78
|
|
||||||
p=37,67 v=56,53
|
|
||||||
p=49,62 v=-91,-63
|
|
||||||
p=59,54 v=60,-69
|
|
||||||
p=57,81 v=77,39
|
|
||||||
p=51,79 v=-19,-11
|
|
||||||
p=65,27 v=74,95
|
|
||||||
p=33,56 v=44,-27
|
|
||||||
p=7,43 v=80,38
|
|
||||||
p=11,19 v=36,-88
|
|
||||||
p=27,15 v=-95,44
|
|
||||||
p=2,76 v=-15,-53
|
|
||||||
p=90,40 v=-14,56
|
|
||||||
p=93,52 v=30,-92
|
|
||||||
p=31,42 v=56,-16
|
|
||||||
p=86,64 v=-25,-51
|
|
||||||
p=97,81 v=-76,-76
|
|
||||||
p=11,36 v=35,-77
|
|
||||||
p=9,94 v=-10,-48
|
|
||||||
p=35,3 v=68,-6
|
|
||||||
p=10,84 v=69,58
|
|
||||||
p=12,17 v=18,71
|
|
||||||
p=61,62 v=77,-4
|
|
||||||
p=6,93 v=29,-82
|
|
||||||
p=91,71 v=-49,62
|
|
||||||
p=84,5 v=26,-17
|
|
||||||
p=100,1 v=-22,-38
|
|
||||||
p=90,27 v=-34,-39
|
|
||||||
p=84,21 v=-68,-62
|
|
||||||
p=72,10 v=-70,63
|
|
||||||
p=83,20 v=42,-74
|
|
||||||
p=51,99 v=-57,51
|
|
||||||
p=13,56 v=-78,76
|
|
||||||
p=21,88 v=80,81
|
|
||||||
p=40,97 v=76,85
|
|
||||||
p=61,92 v=-97,-15
|
|
||||||
p=29,58 v=56,-88
|
|
||||||
p=90,0 v=-34,-2
|
|
||||||
p=35,46 v=-23,-35
|
|
||||||
p=88,49 v=82,-67
|
|
||||||
p=83,23 v=98,-1
|
|
||||||
p=19,80 v=-5,-98
|
|
||||||
p=21,45 v=-90,45
|
|
||||||
p=79,3 v=-14,-86
|
|
||||||
p=49,37 v=27,-54
|
|
||||||
p=95,0 v=-93,36
|
|
||||||
p=55,46 v=-63,26
|
|
||||||
p=38,78 v=-61,-97
|
|
||||||
p=91,61 v=-60,-92
|
|
||||||
p=44,15 v=-51,75
|
|
||||||
p=82,86 v=20,-72
|
|
||||||
p=93,69 v=8,-95
|
|
||||||
p=93,59 v=-37,50
|
|
||||||
p=73,50 v=-84,22
|
|
||||||
p=8,7 v=-50,25
|
|
||||||
p=97,46 v=-14,22
|
|
||||||
p=43,2 v=-96,44
|
|
||||||
p=29,32 v=-33,34
|
|
||||||
p=30,64 v=-56,-95
|
|
||||||
p=12,65 v=-38,54
|
|
||||||
p=64,54 v=-12,-54
|
|
||||||
p=32,29 v=66,-4
|
|
||||||
p=80,84 v=-24,34
|
|
||||||
p=2,93 v=53,-87
|
|
||||||
p=77,14 v=59,-82
|
|
||||||
p=12,25 v=-77,78
|
|
||||||
p=65,74 v=76,-61
|
|
||||||
p=93,89 v=-26,59
|
|
||||||
p=1,35 v=25,-12
|
|
||||||
p=100,26 v=1,48
|
|
||||||
p=28,79 v=-96,16
|
|
||||||
p=18,1 v=-16,2
|
|
||||||
p=42,38 v=-39,-31
|
|
||||||
p=35,76 v=-76,-93
|
|
||||||
p=28,6 v=78,24
|
|
||||||
p=36,33 v=-34,-5
|
|
||||||
p=26,73 v=-95,-95
|
|
||||||
p=96,22 v=-83,-25
|
|
||||||
p=82,74 v=-30,-76
|
|
||||||
p=9,98 v=46,-52
|
|
||||||
p=80,3 v=13,-65
|
|
||||||
p=65,11 v=68,-58
|
|
||||||
p=68,57 v=-13,57
|
|
||||||
p=91,2 v=27,-94
|
|
||||||
p=2,96 v=-16,-29
|
|
||||||
p=65,67 v=-6,-55
|
|
||||||
p=79,63 v=88,-19
|
|
||||||
p=17,12 v=-27,52
|
|
||||||
p=10,6 v=52,-86
|
|
||||||
p=3,74 v=-37,-61
|
|
||||||
p=90,47 v=14,68
|
|
||||||
p=77,87 v=-59,20
|
|
||||||
p=80,63 v=-98,8
|
|
||||||
p=20,27 v=-64,10
|
|
||||||
p=93,60 v=-54,-38
|
|
||||||
p=93,14 v=52,95
|
|
||||||
p=53,79 v=-63,-87
|
|
||||||
p=12,21 v=-10,-70
|
|
||||||
p=71,62 v=76,-19
|
|
||||||
p=77,13 v=-3,-48
|
|
||||||
p=51,99 v=-46,-36
|
|
||||||
p=58,50 v=77,-31
|
|
||||||
p=59,62 v=54,43
|
|
||||||
p=66,66 v=-86,12
|
|
||||||
p=34,87 v=-93,-88
|
|
||||||
p=93,64 v=-47,71
|
|
||||||
p=11,5 v=1,-67
|
|
||||||
p=54,11 v=-80,-13
|
|
||||||
p=74,31 v=-30,-85
|
|
||||||
p=25,60 v=6,-34
|
|
||||||
p=94,77 v=81,73
|
|
||||||
p=62,70 v=-41,54
|
|
||||||
p=44,70 v=-68,80
|
|
||||||
p=25,78 v=42,71
|
|
||||||
p=46,0 v=-29,82
|
|
||||||
p=6,4 v=9,76
|
|
||||||
p=34,40 v=-52,3
|
|
||||||
p=62,23 v=2,50
|
|
||||||
p=85,72 v=31,27
|
|
||||||
p=85,67 v=1,1
|
|
||||||
p=3,37 v=-15,-96
|
|
||||||
p=99,29 v=-65,15
|
|
||||||
p=65,67 v=-22,-99
|
|
||||||
p=72,65 v=55,6
|
|
||||||
p=38,97 v=56,-52
|
|
||||||
p=16,13 v=35,82
|
|
||||||
p=0,7 v=-8,-86
|
|
||||||
p=47,4 v=33,-14
|
|
||||||
p=50,34 v=-26,59
|
|
||||||
p=27,61 v=60,81
|
|
||||||
p=100,11 v=13,-93
|
|
||||||
p=94,33 v=-26,-35
|
|
||||||
p=9,43 v=52,68
|
|
||||||
p=23,73 v=-1,-50
|
|
||||||
p=76,88 v=62,-78
|
|
||||||
p=62,28 v=43,3
|
|
||||||
p=95,22 v=-80,79
|
|
||||||
p=43,81 v=-84,40
|
|
||||||
p=19,10 v=85,2
|
|
||||||
p=40,31 v=-45,-81
|
|
||||||
p=33,59 v=11,-80
|
|
||||||
p=53,66 v=27,12
|
|
||||||
p=52,94 v=5,24
|
|
||||||
p=3,96 v=-71,-33
|
|
||||||
p=18,48 v=28,-27
|
|
||||||
p=76,18 v=34,-7
|
|
||||||
p=75,73 v=93,-53
|
|
||||||
p=48,9 v=-12,48
|
|
||||||
p=65,51 v=-69,-66
|
|
||||||
p=78,10 v=-14,-40
|
|
||||||
p=44,32 v=-52,7
|
|
||||||
p=36,20 v=-68,48
|
|
||||||
p=4,58 v=63,61
|
|
||||||
p=12,62 v=-39,-53
|
|
||||||
p=31,36 v=56,-85
|
|
||||||
p=14,58 v=-51,-61
|
|
||||||
p=86,11 v=-76,-17
|
|
||||||
p=45,38 v=-79,-1
|
|
||||||
p=60,41 v=29,18
|
|
||||||
p=28,8 v=-22,-59
|
|
||||||
p=66,47 v=-13,72
|
|
||||||
p=91,15 v=-31,-55
|
|
||||||
p=69,73 v=15,-87
|
|
||||||
p=52,49 v=71,-76
|
|
||||||
p=73,69 v=-47,-49
|
|
||||||
p=87,7 v=-20,-94
|
|
||||||
p=1,0 v=-76,40
|
|
||||||
p=96,48 v=-14,88
|
|
||||||
p=52,36 v=-46,26
|
|
||||||
p=94,48 v=3,-39
|
|
||||||
p=36,38 v=-71,-93
|
|
||||||
p=64,8 v=55,-47
|
|
||||||
p=75,63 v=59,-38
|
|
||||||
p=64,97 v=15,-94
|
|
||||||
p=63,102 v=4,-40
|
|
||||||
p=41,78 v=16,-87
|
|
||||||
p=63,82 v=58,50
|
|
||||||
p=32,24 v=48,42
|
|
||||||
p=57,69 v=-35,31
|
|
||||||
p=73,26 v=-2,-28
|
|
||||||
p=31,89 v=28,32
|
|
||||||
p=82,93 v=-14,62
|
|
||||||
p=61,87 v=-12,-26
|
|
||||||
p=58,36 v=-72,-13
|
|
||||||
p=80,49 v=-59,15
|
|
||||||
p=34,10 v=72,40
|
|
||||||
p=4,82 v=41,16
|
|
||||||
p=46,12 v=5,82
|
|
||||||
p=81,17 v=75,-36
|
|
||||||
p=69,12 v=99,90
|
|
||||||
p=98,16 v=-55,-24
|
|
||||||
p=49,39 v=38,-89
|
|
||||||
p=91,1 v=92,-32
|
|
||||||
p=91,99 v=-48,-33
|
|
||||||
p=16,44 v=-60,53
|
|
||||||
p=26,60 v=-56,-31
|
|
||||||
p=31,32 v=28,-16
|
|
||||||
p=36,40 v=33,-47
|
|
||||||
p=60,18 v=-97,-51
|
|
||||||
p=5,2 v=36,-21
|
|
||||||
p=83,8 v=20,-47
|
|
||||||
p=32,40 v=-16,-39
|
|
||||||
p=65,11 v=-84,11
|
|
||||||
p=58,31 v=-80,-5
|
|
||||||
p=96,38 v=-42,-65
|
|
||||||
p=40,23 v=14,87
|
|
||||||
p=36,81 v=67,77
|
|
||||||
p=13,74 v=35,96
|
|
||||||
p=6,58 v=-36,-64
|
|
||||||
p=73,23 v=-53,-5
|
|
||||||
p=22,18 v=45,-58
|
|
||||||
p=67,29 v=-81,-52
|
|
||||||
p=14,18 v=-33,-17
|
|
||||||
p=51,28 v=43,-55
|
|
||||||
p=98,11 v=-72,95
|
|
||||||
p=80,17 v=-53,10
|
|
||||||
p=76,54 v=65,-77
|
|
||||||
p=76,98 v=-74,66
|
|
||||||
p=12,50 v=97,64
|
|
||||||
p=53,27 v=67,26
|
|
||||||
p=22,89 v=57,-60
|
|
||||||
p=23,34 v=40,-43
|
|
||||||
p=35,85 v=17,-6
|
|
||||||
|
|||||||
@@ -1,71 +0,0 @@
|
|||||||
##################################################
|
|
||||||
##.OO.O.O#........#..O.......O......O..O..O.O...O#
|
|
||||||
#O.O#.O......#.#O......O....O.O.....#.#.......#..#
|
|
||||||
#.##O.O..#OO...O..O.O..O#.#.O.............O..OO..#
|
|
||||||
#.OO#......OOO.OO.OO.O...O.O.................O.O.#
|
|
||||||
#.#....#O.......O.#OO.#..O#.O...O.O...O....O.O#O.#
|
|
||||||
#O..O...#O.O..#OO#O....O...#....OOO...O.###.#.OO.#
|
|
||||||
#.....O.....OO..O......O......O..........OOO..OO##
|
|
||||||
#.O#..O...O.......O.....OO...O#...O..OO...O......#
|
|
||||||
#O....O...#O......O..O.OO....O..O.OO....#......O##
|
|
||||||
##.O..O..#.OO#....#..O.#......O....#.....O..O#..##
|
|
||||||
#..#....OO.##.......O..O..#.#..O.O...OO#..O#....O#
|
|
||||||
##O.O....O.O.O....OO...O.......O#..........O..O..#
|
|
||||||
#.##.O.OO..................#.##O.O...#OO.......OO#
|
|
||||||
#O....#O.....OOOO.O.#.OOO#O.....OO...OO..O....#..#
|
|
||||||
#.#O.O.......OO..OO.O..O..#.O.O......O.O..#O.O...#
|
|
||||||
##..OO.O...#.....O#O.O..O.OO#.O.OOO...O....#O.#.O#
|
|
||||||
#....O.....O#O..O.O..O...............OO.O.O.O.OO.#
|
|
||||||
#.OO.O...O..O..OO#O..#....OO...O...O.O#.O.#......#
|
|
||||||
#..OO.....O...O..#O........O..O.O.O..#...O...#...#
|
|
||||||
#O......OO.O.........O#OOO.O..O...OO..........#O.#
|
|
||||||
#.O.....#.......#O......O........#.O.O...OO.O..OO#
|
|
||||||
#.#OO...#.#.O...OO.O.....#OO.O...O.....O.O#.O.O..#
|
|
||||||
#.O........#.O..O.O..#.#O#.OOO.....O..#.....#....#
|
|
||||||
#..O.O..#O#....OO#OO.#O#@.O..O.O.#...#.O.........#
|
|
||||||
#O....O.....O...O.#........O.OO.O..#...O....OO...#
|
|
||||||
#..OO.....O#.........O#........OOO...OO...#O#O..O#
|
|
||||||
#O....O...#O.O......O..OOO....OO#O..OO...........#
|
|
||||||
#O#.O..O...OO..........O.O...O.......OOO.........#
|
|
||||||
#...O.....O...O..#OOOO..O......#....#.O....O.....#
|
|
||||||
#..O..O.OOOO.O.......O.....O...#....O...O..OO.O.O#
|
|
||||||
#..OOO..O..OO.OO..O......O...#O...#.....O.....O..#
|
|
||||||
#..OO.O..O..#O....OO.....OO..O#O..#..O.#..#....O.#
|
|
||||||
#.O.#.#..##O.....O.....#OO...#......O.OO.O..OOOO.#
|
|
||||||
#..OO.O..O#.....#....O#......#......#.O..#..O..O.#
|
|
||||||
#O#...O.O..#....O.OO#.O.#....O.....#O......O..O.##
|
|
||||||
#......##O.OO.O#.O...O..OO#.O..###........O.OOO..#
|
|
||||||
#...O..#..O....O.#..#......O..O..#O...O...O......#
|
|
||||||
#.OO.OOOO.OO..#...OO......O.O.....O...O....#..O#O#
|
|
||||||
#O..#OOOO..#.O.O.......O...O.OO...O.........OO...#
|
|
||||||
#.O.....OO..O.....O.O#..OO...O#......O.....O....O#
|
|
||||||
#O.O..O.O...OO.O.....##...O..O....#O...OOO...O.#.#
|
|
||||||
##.O..O.O.O..##O#......O.OOO.#.....O.....O..#....#
|
|
||||||
#....#...O#...#..##.O.............O..#O..O..#.O..#
|
|
||||||
#...O..O#O....O...O...#.....O#OO...O.....#.O.....#
|
|
||||||
#.#O...O.O.O..O.#.O....O..O#..O.OOO..O....OO.....#
|
|
||||||
#......O..........O..#.#.....O...O..OO..O.O.##..##
|
|
||||||
#.O..O..OO.OOO..O...O.....O....O.......OOOOOO.O..#
|
|
||||||
#...#.O.#O#....#.O....OO..O.##....O.O.#.....#..O.#
|
|
||||||
##################################################
|
|
||||||
|
|
||||||
>vv^v>^^<>vv>v>^^<<^^>>^><^v<v<^>>v^><><<<<vv<^vv<^<>>><<v<^>>>>^^>>>v^v>^<v>>^^<>>^>^v><vv>v<^<^>><<v>^v^^v<^><<<<^><^v>^<>>^^vv<<<v^^><>vv<<<^<^v<>v<<<>>>v>v^>><v<>>^v^<v^v><<v<<^>^^<<^v>^v>vv^<><v^<v<^>v^<>^><<<^>>>^v^>>^^^^<<v<^>vv<^<><<>vvv<><vv><><v><^<v^^^v><<<<<vvv<>^<^>>vv^^^>v^>^v^^^v>^^><<<>^^v>^<^<>vv>>v^v<^^<<v><>>><^^v^<^<^v<^><^vv>vvvvv><>v<^^v<^v<<v>>>v<v<<>>^<v^>vv^>v<<^^<^<>v<><^v>vv>>^>><v<v<>^^<^><>v<v<>^^<v^vvv>>><v>><vvv><>v^v^<^<<v<v^^v<^^v^>^vv>^^<>v^^^^>vv<v^^^<^^v^^<>^><v><>v>^<v^vvv^<<^>>^^>^<>vv>v>v<^><v^v^<>^<^^><>^<v>vv<>v>^>>v^^^^>>v<v<^v<<v<>v<>^<>vv<>><<>v<vv^^<v<v^<^><v>^^^<^>vvv<^<<vv<v>^^^^<^>>><>>>v>>v><^<vv^<v^<^vv>><>v^<v<>>>><<v><v^>v^v^^<v<v<^v>^><<>>>v<v^<<>^^^^^v^^^<<v^<v>>>v<^vvv^>>^v^<^vv^v>^vvv>>^^^>v^>>^><^>^^<^<<^v><^<^<<>^^<<^<vv>>v^vvvvvv><v<^^v><^><><>^<<>v^><<>v<v>><<v^^vv^^v<>^>>>>>^>>^>><<v>v<v<>^>v<v^v^^<^<vv^^>>v>v<<<>^v^<<<^>^>^vv^^>v>>>^^>><v><>^<><^>><v>>v^<<<<^v^>v^>^v^v<>v^>v<^v><<>^^<>>v<>^<>vv^>v>^v<^><v>v><^><<<^>>v^<<>>^v
|
|
||||||
<>>>^v<<>^<<v<>^<>>><^v<<<>^<^<<vvv>^<v><>^vv^<<>v^vvv<<^v><>^v>^v><v<>>>^vv^v<vvv>^<>^<v<^^<>vvv<<^>v^^^v^>>^vv>^vv>^^>>>^<v<^v<vv>^>v>v<v<>><vv<^v>^^^vvv^^vv<>^<v><^>^<^>>v>><>><^v>^>^>^^<<vv>v>v>>^<^><<^<v<<<^<v><<^v^><^><v^^<^^<<<><>>^v><^^<<>>v^^<^v><^<v>v><>><>v<>^v^<<>>v^<>><<^<<v>^<^>v<v<vv<<v><<^<<>>v>>^>v<v^><^>^><<<><v<<<^^>vv<v^^vv^>>><v^<>v>^v<<><^<^<<>>>^vv^>^^<<<<vv>v>^^<><><^>>v>v>v>v<><vvv^>>^<>v^<^v^>v^<<><vv^>^^vvv<<<<v>^<vv<<>>>v^v^v^<><<v^<^<>><^^vv^v><v^vv<<^^<v^<>v><^><v^<>^^>^<<>vv<^><>^vv>><v>v><><<vv<v>>^><<^^><^>^vv>^v^><>v>v<>^<<v<<>^>><>v^vv>vvv>v>v>v^v^>^<vv>^<<v>^>v<^vvvv<<^^v<^^<>v<>v^>>v^v^<^v>v>><<<^v>v><vvvv<v>^<^<<<><>v>v<<^>><^vvv><<>^<>>vv>^>^<v>>>vv^<v^>><><^vv>v>v<^^><<<<<<v>^v>v>^^<v>v><<v^^v^vv>>><^v<<<v^v<<>><>^v<>>^<^v^^vv>>>^>v>^vv<<vv>^><^<>>vv>>^^<^><^^>><v^vv^<v^>vv<v<vvv>>vv^v<<>v^>><<vv>><^<>v>vv>^<v>^^>>v><<><^<>><><>^^^^v><^>^^<v^<>v>^^<^<v<vv^^^<>>v^vv^>>^^^vv<<>^^>>^v>>>>^><^^<^<v<>>><v<^<^>vv^v>^^^v^>><>vv><v<>^>>^<<v^v^v^^vv^<v>^<
|
|
||||||
><<vv<v^^^<>>>^>v>^<^^^<v<vv<^^<>><^<>><^>><<>v<^>v^><<^><>><<v^>^<<v><^>v>><vv<^v>><>v<<^^v>v><>>><^>v>>^v>>^v<>v>><v^<v<<>>>>^v><<v>^<>>v^^v><>^v<v>>v><^^<vv<<<v><^><><<><^><v^^>v^>>^<<>^v<<^^^v^<<<><^^<><vv<>>^>^>^^>>^><>>v>v><v^>><<v^v<>^v>^^^^<^>>>>vvv>v^v>v>^<>v>v<v>>>^vv<>^><v>^<^<v<<<<>vv^v<v<v^<>^>^^^><>v^^^>v^<>>^vvv^^<>>>^<<<vv>>^v<><^>vv>v^^^<v^>>v>^v>v^>vv>vv>>>vv^vv>>v<>v^vv<v<^><^v^><^vvv^vv<vv^>vvvv<vvv><><>><^<<<^>vv^>>>v<<>v><<^>v^<<<><v<<^^<><<<><<^><>v<><<>v<^v<^^v^^>>><<^vvv<<>>^>><<vv<v<^<<^<^<<<>><<v>^v<>^^^>>>^^<^^^v^^v<<^^v^>v^<<^<>^><>^v>>>^^vvvv>v^<v^<^<v<>><v^^>>v^v^^v^^><v^^^^^^v^v><^<><><<^<vvv^><vv^<<^<v<v<^^^^><>^vvv<v>>>v<v<<v^>v>vv<>^>><<v<v<v^^^>v<<>v<><v>v>><><<v><<^^^v>^vvv>^<^>^v<<>>^><>>v><><^v<v<<^v^<<v^v>v^^<^v>>^v^v>^^^<<<<>v^>>vv<vv<<><>>^^^v^v^^^><><v<><v<<v><<v>vvv>>^^<v>v^^>^><<v<v>>>vv<>^<>^>>v>>^>v>^v>^v>>vv<^<>v>>vv<<v><>^^>><>vv<<><<^>v>>^>><>><<>v><<v>><v^<>v<>>>>v<<v>>v^>^<^>>^<>^v<<vv^<<^v>>v<>v>^>v>>^<>^<vv><^v><>^<<v>^v^^^v>^>v>^^v
|
|
||||||
<v^<^^vvv^v<<^<v^<^vv^v>><>><<><>^v^^v^^^<v>v<^v<v^><v<>vv^<vv<^>^>^^>v<>vv^v^^><^^>>><vv<>><v><^>vv>>><^>v>v<^<<><<<v>v<v<>^>>>>v<^><^v^<>^>^><v>^vv<<^>>^v>^^^>^>v^v<>>^<>vv^^v^^<^<vv>v>^v>>>vv^>><v>vv<>><^<><v><v>^v>>>>^<^^<<>v<^vv><<^^<<v<v<v<<v>v>^vv>>vv<<>><^<^<v<>v<>^<^<<>v^vv>v<>^vvv>^<vv><v>^^vvv^^^>^v<^v^v^<<>^vvv>^>^vv>v^>^><vv^^v>vv<<v^><v>v<>>>>>^^>vv>vvv<vv<<^v<^<^v>^<^><v>^><<^<^<v<vv<><<v>^v><<v>>v^vv<^<<v<^>^>v<vv<^v><v^>^<v<>>v<>>^v^v^><^<<^v<vv><v^^^v<>>><>v<vvv><>^vv<>^><v>^><<<^v>>v^^>^^<^v>><^^>v<^<<>^v>><<v<^>>v<><>vv>vv>^^<v<^^<^<<^^<^^><v^>v>><<^^>v<<<^<v^><<^vv><>>v<><>^>v<^<<^>^>v><>v>^vvv<<<^>^^vv^>v<<v>^^^v<<>v^>v>><>>^v<^^><>><>v<v<vv>v<<>^>>^v^^<vv<^>^^>vvv^>v^>><><^<<>^<^<>v^>>^^^<^^v<vv>^<<<<<^vvv<><>^>>><^v<>^^^^v<^>>v>^v<<>>v^v<^>vvv<v^vvv><^^<>^v>^v>>>>^^<^^<<v><<>>>>>^v><>^><^v<>v>v<^^v^vv^^^<^>v^>^^<<v>^>>>^>^^vv<v<^v^<>v<vv^^vv^<^>v>v<<>>>^><<<^v>v<<vv^<>><v<><<>v^<^vv<>v><<^<>^><vvvv>v><<><^^<>v>>^<>vvvvv<<^^^>><v^<v>><>v><><^>><>^>>^><^<^^^^v^^vv
|
|
||||||
>v^v^^v^>v>^vv<>^<^^vvvv<>^vvv^<^<><v<vv^^>v^^^>^vv>>^^<^<^v^>v^v<^>>v^>^^v>v^<v<^>^>v>^^^<v^v^<v>><v^^^v^>vv^v<>^>>^^<v><^^<><<<v^v><v^v<><^>v^<^<<>>^v><>^^>^^<v^<<><>v<>v<><^<>v<>vv<<^><vv>v>^<>^v^v<v<^^>>^><<v>^<vv^v^^v<^^^v>v<v<vv>>v^>v<^>>^<v<^^>^vv<v^<><>vv><>v<><<>v><v>>>><<<vv>^<<><^>>^vv^>v<^<>v<^^v<v>vv^>v><<v<^^><>><v^<^v^^>>>>>>>v^<v>^>^^<^><^v>^^<<>^^>>^><v>^<vv<^^<<^v>v<^>>vv<^^>vvvv>^^>v>>>^^<<<^<^<^^<^<^v>>^>vv^<v<v^v^<v<><<>v^v^<><<vv>><^<^^v<<vvvv<<<<>>^v><>v^v^<^<^<v^<>vvv^v^>^vv^>^<^><><^v>^v<v>>^v<v^^^v^v^v><v<<v^><<>v<^>^<>v><><>><>v<>v^<v^><v^^<>^^<>v><v>^^>^^v^>v>v<^^<>^>^>v^vvv<>vvv<<^vv<v^^^vvvv^^<<vvvvvv>v<^>>^^vv<^^><<<>v<^^<v><v^>v<^^v><v^<><^<><><^^<<><><<vvv^<<^^><>>v^^<v^^v^>v>vv>^v<^><>vv^^>v<>^v<^^><>^^^><^<<v>v^<<<v<>vv>vv<><^<^<^<^<v>v<v>^v^vv<v<><>v<<^v^^>^>>v>^>v^>^v^<^^^<<<^<<<>^<^v<>v<<vvv<>><<<v^<<>^v<<><vv^<>^vv<^^<<>v<<<^^^<v<v<>v^<^^vvv<<^^^>><^<>v><v<><v<><v^<<vv^^v>>v<v<v><vv<^v><v>v>>v^v^^v><^v><>^v^v^^v^<^^v>><<<vv><^<v^^v>><>^^<v^>^>>><^
|
|
||||||
^v^vv>><^><^>>>v>>>>v<>><<vv<vvv^<><>^^>v<<><><^^>>^><^><><^^^^v<^^<><>>>^^<<<^v>>>><<^^^<>v<v>><<v<v^^v^<^>v<^<v>><>v^>v>>^><vvv^^>^v<><><vv>^<<<^vv^<^vv<v>v>v>^<>>^<<v^^^v^>v^<<<v<^^^^v^v<v>>><<<>v>v^><>^vvv<v<v<<<><>><^v^>>^<><<v^v^>vvv^v>^^^><<^v>^>v>^<<^^v>v>>^<v^^<vvv>^>vv^^><<><v<^^<v><>>>^<>><v<<<^^v^v>v^>v<<<^<^<^<^v^>^^v<^<v<>><<>>v<vv^<^>v<^vvv<^>v><>>>^>vv^^>><^>^<v<><v<v^v<<>^^<^^><>^v>^^v^^vv^<>v><^v<>^v<v^v>><v^^<v^<vv<<<<^><^^^^vvv>^v^>^<><v<^>>v><<v><^^>v<^v<v>>><v><<^v^<v^><<<v<>vv>vv<^^vv^^^v<>vv^<v<vv>^v><v<vv>v<<>^^vv>v^<<^<^^v><>vv<>v<v>vv^<v<^><<<v><^v<><<<v^<>>vv>v<v>^v^>v<<<>v^v<^>^^^^^<v<<<v^<^^^<vv>^><>>>v>v<^<v^^>^><<<^^><><v<v<^v>vv^^^<^<>>>^>^v<>v^><>><v^^v>vv<>^<^vv^<<>><>>v^<>>v>>>>^^<v^v<^<v^v^^>v><>v<v^^v^>v^<^^>^^^vv^v<>vvv>^>^^<v^v<^^v>^^v^<>v<^<vvvvvv>>^v<^^v>^<^^<><<v<>>>vv^v<<^<vv>^^><<<<<>^<^v<<v^v<<<<<vvvv<v<>v><^^<>^<<>^v<>^v><>v<v>><^<>><v<><v^>>^<>vv^<v^v<^vv^<><<<v^<>><^>v>v^>v>v^>>^^^>>^>v<<^<>v<>^^v>>>>>v^>v<<^^^^<^^^v<>^>^^v^<<><>><>^<v>v
|
|
||||||
v>v^^^^><v^v<vv>v>vv^v>v><>^>v<^><^>>v<>v<<<<v^v^^^^<<<<v^>^<v<v>><v>><^>v><<v><v>^vv^<vvv^^<<<>^<^<v^v>^^<^>v>>vv^vvv<v^><^^v><v<<^<^^<<^^><>>^vvv^<^<>v^>>^v><v<^^<v^<v>v^>^^<<v^<>^<<^<vv^^v<<^v<^vv><^^^v>^vv^v>v>^><^>^^^^<>^^^>v>>v<^v^v>>v>^<<>^<^^<>v^<><<^>^v^v^v^>v<<^vvvv^<<^^<^<^vv>^v>v<^<><v>^><^<><v<<<>>v^<<^<^^^^v>v^<^>v^>>^v^<>v>^v<>>>v>^>^^>>v>>>^^^^><^v<^>vv^>v<>>>v^v^vv^<>^><><^<>^<><vv<v^v>v<^v><>^<<v>>vv<><vvvv>vvvv<^v<<<>vv^<^<^v^<>v^v<v^<<>^v^<vv>>v>><vvv<^>>v^^v>vv^vv<v^<v^v>^^>vv^^>^<>^<^><><<>^>^^<<<>^v>v^<>v^>>><<>>^<>v<<v<^v<v>vvvvv><<<v<^<<>>v^>v^^<^v><^>vv^>vv^<><<>vv>vv^<>^^v^v<vv<>v>^<><^<<>^v<v<^^<>^<>>^<<>^^^<<v>^>><v<^^<><v><><v<v>^>v^<vv<<>>^v<>>^>v^v^>^vvv^><<v<<v<^<v<<><^^^^<<^^<<^<v>^>^>^<>>>^^>v<<^<>v<^<^<>><>v^>v>>>^^^v<^^><^><>v<v>>v^^vv>^v<v<^<^<^>^v>>^<^vv>^^<^^^<^>^<^<v^^<><v^><v^v<v<<^v^<>v>v^^v>^vvv^<^^v<^<>vv<v<v<^v<><^v<>v^><<^vv<v^<<<v<<v<vv<^v<>>^^<v<v>^v<<>v<^^<>v<^^^^<vv^^v<^><<v^>>^<<^<<<<><>>^v<<<>^><<^>vvv^v<^v<v^vv<vv^<>^^<^^^<<^<^<><<v
|
|
||||||
>vv^>^vv^<>^>>>^<^<vv<v><>>v>^>>v^<><<<^vv^<v^^v^vvv><<^>>v<^v>><^><vvv^>^v^<><<v<^>>^<>^v><v>^<>><><<<^>^<v^<<v<>><^^v><>^<><<<<v<^>>>v>v>v^v<^<^v>^>^><vv<>>><><^v>^v>>v^^>^<v<><^>>>vv>^v>^<>>v><^>^>^v>v<>^>vvv<>>^>vv>^v<><<<<v>>>v<<v^v^<v^vvv>><>^^<vv<^>v>vv<<^^<>^^v^>vv^>>v><><v><^><><v><<^><<^v^>><><><><^^^vv>vvv>v<>>v<><>^<><vv^v<^^>v>><>^>^>^^^v^>v>><><v^vv^>^^<^vvvvv^^<vv^<<v^v<<^^^<<v^^><^v<^>>>^v>v<<<^^><<v<>^vvv^<>^^<^^^v^<^v<<>>^v<<^^^vvv<v><vv><<vvvvv^^vv>><<^><<vv^><<v^v^>^^<>>v^<<>vv>v^v>><^<^>^^<><<v>^^^v<^<<^v>>^>vv^<<>>^v<>v^><<v^vvvv^^<<vv^<><^^^<>v>>^><<^vv><^><<v><<<<v>v^v<^^<v^v^>>><^v<^><<v^vv^^>v>v><>v^<v^<^<<v^^<<^^<>><v^<>^><<>><<>v>><<>^>>^v<^<^>vv<<<^<v>^v<^<v^^>v>>v<v^<<<v^<^v>v^v<^><vv^v<<<<^v>^<>^<<^>v<vv<<^><v<>^>^>v^<<^^v<<^>^>>>v^^^>>v><vvv<^vvv<><^>^>^v^<<^<^v>v^^<><vv^^><^v<<vv^^^<v^vv<<>><<<^<>><v<v<v<<^<<v>>><^vv^v><v^v<<<>v^^><>^<v<vv^^<<^<>v>v<^<vv>^>^v><v>^<^<<^<^^v<v^^v<^><v<<vv>vv<vv<<<vvvv><>^^v>vv>^<<^vvv>vvv<^^<^<<>v^v<v<>^vv><<>^>v>>^<vvv^>
|
|
||||||
vvvv^v^^>^>v^<>><<>>^>>>v<><>v<v>v>v><<<^^<>^^v^^^<>vv<v^^<<^v>>^vv^><^^>>>>^^^<<^<<>^>>vv^<>^^^>>vv<>>>^v>v^^<>>>>^^vv>^><^^vvv<^>^^>v>^<<^^><><>>v<>>^<v>>><^<<v>vv>v><^v^^v<<vv>^<v><<>vvv^>^>^<<^>>>^v^><>^^^v<<^v^>>v>v><>vv^v><vvv>vv^<<v<<^^<v<vv<<v>v<^^>>v>>v><>><>v><>v>vv<^^v><v<vv^v<>v<v<<v><<<<<>><>>v^>^^<^<<v<^^^>>^>>v>>>^v>v>^><<<^^>v>^<v^><v>v<>>^<<>^<>v<<^^<<<^<>><^<>v<>vvv<v<<><v^<v<>^><^^<^<^>>>v^>v^>v<v<v<^><>v<>v>^v>v<>><^<^<<><<^<<<>vvv>>>^^^<<vvv>^>^<v<>v^v<<^vvv><>>v>v><vv^vv^^<>^<>v>>^^<<>>><^>><v^<vvvv^>v<^v<<<><>vv^v^>^v>>>^v^<<v<>^>>^>>v>^vvv^v^^<<^^<>vvvvvv>>>v^>>>^vv>^v<<><><v<<^<>vv^^v^<^vv<<<><^v^vvv>v<>>vv>>vv<v<^^<vv<v^<<>vv^v^<<>><^v^^^>^v<<^><>^>><>v>^^<v^><v^>vvv^<>vv<<^^>><^<v<v<>vv>v<v^v<><vv^<<<>v><v>^>^>^<^v>^<^v<^>^^<v^<<<>^<^^v><>v<<^vv><<><vv<v<vv>v^v^v>>v>v>>^^><v<^v^<v>v<>vv^<<v><>><vv>>v<>^>^vv><>^^>v<<^v<v<v>>vv^>><<<v^<><<<^^><<^v^v^<^^<>v^>>>><>^<vv<v>^<v<<^>v^>vv<<<<v><v<v^>>^>v<vv^>vv<^^>^v>>^^^v>>^^v>>^>^<v<^<<<^<v><^>^^<v^>^>><>>>^v>>^<^<^
|
|
||||||
>><>>>v^><^>>>^<^>v^<^^<><^<^>v<><^><^>v^<><<v>>>>>^>vvv<^><>^>vv>>^^<v<<v^^>>>>^<>><v^>>^v^^^^^>>><<<<>>v<^^v><>>vv^>>vv^v^v<^<^<>>v><>v^^>v><>v>^^<^v<^>>>>>vv<v^vv^<><^^^v^vv>v><<^<v<vv^v>vv^^<^vv<v<v<<<>v<>>vv<><<>v><^<<vv^^v^^<v^v<vv>><^<><^>v<^<><><<^<><^v^<^^v<^<vv^>^<^vv^v>^<^<^<>v^v^<v<v^><><>v>>v<><v<^v^^<<<^>^^^<v><>><><>>>v^>>^>vv>>^vvv^^><^<<<>^^v^v^>v>^v><>^^vvv<^<^^><v^>^>>>^vv^><v<<<<^><<>v>><v<>>v<>^^^>><<<<v^<>^>^v^^<<v^>^^<v<>^v^<>^^<>><<^v<<^>^v>>^><^^<^>^^<<^^<<v<v^<vv^v>^>v^><>>^^^vv><^>>>>>^^v>^<>^<<^^v^^>>v^<<><^v<^v^v>v>v<><^vv<vv>v^^^<v<^^<^<^<^<>^^^<vv^<>v<><<><<v<v<<>v^>>v<>^<^^^^^><<<^>v<v><><>><^<<^^>^>>vvv^><>>><^>>vvv^^>><>^>>vv>v><^>^<v<v<^v^>vv>>v^v>vvvv^^^>vv<<<v>><v<v<>^>v<v^v<><v<>vv^^<vv><^^^v>^v>>v>^v><v<^<<v>vv>vv><<>>>><^v<<^>v>>^<vv^<v<^<v>v>vv^v^v>>>v><<^v^v^v>vvv<>>>>v>v^<<<<^^>^^>v^vv><v^v<vv<^<^^>>v^v><<><v><vv<<vv<v>^<>v^>>v^v>>>>^<>><>v^<^>v^<^<>>^vv<><v<<^v><>^>^<^v>><v^<>v><^v^>^^>v^>^vvv^<<>v^^^>>^<<<v<^v^^><^v^>vv>^vv^v^<>^>vv>vv>>>^>v
|
|
||||||
^^^^^>>><<^v><v>>v^>^<^>>>>v^>v>vv<>><^^^v^>^^^v<<><^v^^<^<<^<v<v<v>>v^><v^>^^^^><><<<^vv><<v^^>^v^<>v>^>^>>v>v^v^<>^v^>v^<v><>^<v>v><v^^>^><v^v<>^<v><>^>><vv>^v<>><v^v^v>vv^^<vv>^<^>><^v^^^vv>v>v<<^v>>>^^>v^>^<><^^>^<<v<v>^<<><v><>^^<<>vv>^>vv^vvv>><>>v<>>^vvv><>^^<vvv<<>>><^<v<v<<^>><<<>v^>^<v<>^^<^^<>vvv^v<^^vv<^^^>vv>>v<>v^v<<<>v>>^>v><vv>v^<vv><><>v>>vvvv^>v^v^vv>vv>^>^^<v^^>vv^^v>>^><>>>v<<<>^>^vvv^v^v><>v^^^>^>>v^><><v<^v>v>v>v>vv><<<><<^<>^vvv<<^<><v>vv>^^<<><^v>v>v>v>^vvv<>^v<v^<^^^>>vv^>v<^<<>^<>vv<v<^<vv><v^>^<^>^vv>^^>^>>>>>^vvv>^<<<v^v^v<<>v>^>>>^^<^>vvv>^v>^<v>v>>v><<^<>><^<^^^<>^<v^<><v^vv>^^><^^^<>><v<^>><v^^^v<<>><>><>><>>^^v<>>v><<v^<^^<vv^v^v<v^<v^v><<^v^>v>><v^><v<><^v>^<v^<<^>>^>vv>>v<><>v<v<<>><vvv><^>vv><v^v^^^<>v>v<^v^v<v>v<v>^^>v><><<v>>^>v<vv<>>^v>><^v^>><<>^>>v^v<>vv>^^^>^^vv^<^>v^^^>^<<vv<<^>^>^><>vv<^vv<^^<v<v<><<^v><^>>><^>^v>^v<<^^<<>^<v^v>^v<>>>^>v>v<vv^<v^vv<>>>^vv>><vv>^<vv^^>^^>>>vv>v>v^v>^vv<><>^<>>v<^^<>>v^>>>v>^>>^>v<<<>v^<^vvvv>v>^<v>^<^vv>>><vv^v
|
|
||||||
<^><>v><><>^vv^^v^<^<>>^>>v<><<<^>>^<vvvv<>vvv><>v>^>^<^^v<>^<<v^v>vv<v>v<<^v^<>>v>v>^>v>^^v^v^^<^v>^v<<><^v<<<<><<^><^>^v^^vv><>^^vvv<vvv>^>v^v^<>vv>v>^^^v>v>^<<vv^v<>^<^<vvvv^<>v><v^<<<>>vvv^>^^>>v<<v>^^<^v<<v>>v<>><>>^><v<v>>^><^<v^vvv^^>>>>>^>>>vv<v>^>v>>^<<>>v^v^^vv^>v<<><^><v><>^^<>^vvv^v<<^<^v<<><><v>v>>^>v><v>^>v<v^<v>><vv><><><v^v^^>^v<v>>>vv<^><<<v<^v^><<v><<v<^^v>>>vvv^>vv^<v^^><v^<<>v<v>^<>vvv<<^><<>^<^><^><><>>v><>>^vv<^^^^vvv<^v>>v>^<>>>^vv<>^^v<^v<<^><v^^^v<vvvvv><<vvv>v<<v><v<<v<vvv<<^>v^^v^>>^v^<^<vv^v<vvv^<<<><>>^>v>^v<^<>vv>>^><v^>^<<><^>^>><^<><^>v>^^^><v^<><v<v>^<><>>^^>^vv<v^>><>^>>><><>^<<<<v^<<^<v^>^<v<v^^<v<<<v>v<><v^<<^>^^>^>^><^vv>v>>v><v^v<^^v>>v<<>v<^^>v>vv^<v^^<v><v^^<vv<^<v><<vv^v>>^><vv<<><^>^>>v^vv><><^^<<>^^^<>^>>>^v^<>v<<v><vvv<^>v>^<>v^^<^^<v<^^<^v^<><<^<^^<vv^<<<v^><v><<><>><<<v>>v^>><vv<vv^<^>v>v>vvv><^<^v^^<>^<<>>><<^>>vv>v<v<v>vv>>>v^v><<v<>vv^>v<>>v^^<v^v^><^^^<^<>^><<<v^>^>^<>v>vv<<>^v>^<<><^^vv<v>>vvv>>^<<^>^vv<^>>>vv^<^<vv>v<v<<^>vv^<^v>>v>v^
|
|
||||||
^<^><v<<>v>v<<^<>^>>v^>>>vv<>v^^<vvv><<v^<<<v>>>vvvv><v<^<<^<>^vv<v^vv>>^^^v^<vv<<v^<>vv^<^vv<<>^^><v<vvvv<<>>v<^<<>^><<><<v<><<v>^><^v^v>v>v<>^vv^v<>>>^v^^>v^>v^v<vv^^>v^><^^^^>>v<vv<^>v>>^^><^<^>>v><v<><<<<v^<>^>><v>>>v^>>v>v^>v<vvv<^^>v<>^<^<^v^^v><^>>v<<v<<<<>v<^^vv>^vv>^^v<>^><>v<<v^<>v>><<^^<v>>^^<<<^v<v<<v^<<v<^v><>^<vv<<>><<v^^^<v>>^<v<^>^>v^>^>vv<v>^v<<>vv<^vv^<<<vv<<><v^^v>^^vvv^v>^<vv>><><<<<v^v^<v^v^>^vvv^v^<<>^>^<<<<^><><>>vv<>^v^<>>vv<>^^><>vv>v>vv><><^<<^<^vv>>v>>^<^^v<v>^^<v<^v<v<vvv>^><>v>v^v>>>vv^<^^^v^<^^>vv>^vvv^v^^v<vv^^<^^v><^v<<<^>v>vv^>^^<^<>vv>^<v^>vvv>^<>>>>vvvvv^^^<^v^>>>v<v>>>v^>^^<<><<v><v^>>^<^vv>^<<v^v^v>v>v<vv<<^<^^^<><^^><>v>^>v<^<^^^^^<^^^>^vv<>>>v><><>v<<<>v>vv><v><><^>^<<v^<^vv<>v^><^vv^^<<>v<<<>v><<>^<^>^^^><<v^>><<<vv^^v>^^<^^vv<<<vvvv^><v>>>v<<<<>^^<<<<>v^<<>^<v^v^>v><v<v><><<>>^^<>^v>^v>>vv^<<<v<><<^v>><v>><<>>^>vv>v>v>>v<>>^><><<><<<><>v<>>^^vv<>^<<<^^><>><v^<v<^>^<v<^^<<<>v>><^<<>v<v^>>^^>^^vv^<^>^^^v^^<v<<<^<vv^<<>>vv>vvv>^>v^vv<><^><>v^^<>vv<
|
|
||||||
^v^v>v^><^<<vv^<>^vv^v>>^>v>v^vvv>^>^v<<<<>^<v>>>v^vv>v>>^vv^<><<^><>v>>>v>v>^>v^vvv>^>^^<<<<^<vv^<v<<><>^^v^>vvv>>>^<>>^v<>^^>>>^<<>^>v>>>v<<><v>><<v<<<vv^<><v<^v>>>^vv>>>^>^^<>v^vvv<>vv<v<^<^vv<^^>>>v>v^^^v><^>>vv>>v<<vv^>v>^><<v>^vv^v<><v>^v>vvv^<<<^^>>>>^^v^vv><<<<<<<><^^v^^<v^v^>^^v^^v<>><v^>>v>>v<^^vv>^<^<<v>^<v<<v<>>vv<^<vvv<^v^<v><^<><<<^>>>><>^^v>v<^v<^<vvvv^^<v<^<v<^<>vvv>><<<vv^<vv><vv^v<><<>^v^<^<<v>^>>><^>^^>^<^>^vv^^<>v<^>v^^^^^><<<vv><>v<^v^<>v^>^><>v<<^v>>>^v<^v<^<^vvv>vv<>^v^>>^v^v>vv<v>>v>v^v^>>v>><><v^v<^>vv<<vvv^^<<vv^^<^v^<>v>^<<^>^<<<>v><^<<v>><^vv>^>>vv^vv^<^^^<^v>vvv<v<^v^<>^>>>^v<<<>v^^<^v<>^^^<^v^<>>>v<^<<^vv<>v>^^<v^><<vv<^v<<^v<v<v^<v<<^<<v<^>>>v><>^<><<^^^<^>^>vv<^vvv^><v^v>^^<v^<>^<^<^<<<^v>^^<v<vv>vvvv^<<<>^<^>v^^>^>>vv>^v^><>>^<<^^v>>v<^v>v>^^^>v^^>^>>>>><^^>>v^>^v<>><<vv^^v<^>v^v^vv><<>v^><<>v^>^^^vvvvv^^^>^^>v<>>>^><^v^<^>v><>>>>>vv^^<^v<<<<<<v^^^<^>v<^><><<^v^^<v><<<v>>^^<<v<>v<<>>v>v<<>v^v>vv<>>^><^<>v<v<<^>v^<v<^^^v>^<<v>>vv>>v^<<><<<<<^<<>vv^><^^>>
|
|
||||||
<><>^v^^^<vv><<^>^><^<><<v>^<v<>><v><<v>>vv^<^^^<v<^v>^^<^>v<v>v^v^<^><>>^>^^^v>^v^>>><v>^^^^vv<>v>>>^v<<<v<<v<^<v^v>>^>>>>vv><><^^<><vv<^v<vv<v<vv<vv>v<>v<^v>>^>v<><v>^^v^^>^^<<^><<v<<<<v<v><^^v^<^<<<>v>v^<^v<>>^>vv<^>^<>v>v^<^vv^<>>^^v>><vv^<>v>^<<<><^<>v<<v<<>^>><vv>^>v^><<v^>>vvv^v>>>^^<v<<v<v<^>^vv^v>>^^v^>vv>^>>v<>v<>v>><^<v^v>^<^^v<<>v<vv><vv^^>>v>v>v<><^v^v<<>^v>>>><v<>vv^><<>v<v^>>v^^v><<^<vvv^><<^><v<^^v^>^>v<>^<<^><^<>><>>v^<>^v^^<^<>>>><<<v>^^^vvv<<vv>v^<vv^^<^<v><v<vvvvvv>>vvvv^<v<^^>v<>><^<v^>^<^<^<>v<>^>v<>^^>v^^>vv>><v>^>^v^<>vv>>>^>vvv>^<>^<^<>^>v^v^<vv<>vv^<>^<v>><>^^>>vv^<><vv^^v><^>^^vv<>^<<<<vv<<vv^<v<v>^vv><^<<><v<vv^<<v<><>^>v<^^vvv^<^v>v^>>>^<v><^v<<v>^v<vvv>^^<^^vv>>v^^>v<<^>v>><^<v><v^>^>v^^<<v^vv^^vv>^^^<<<v><<<^<^v<v<^>v<^>>v^<<^<^>^v><<<>>>>>><>v^v^><>v^><^^^v>>v^v<<^v^<vv<>>^^<v^vv>v<^<v>>^<<<>><^<>^v>>><>>>^>>^v<<vvv^<<^<v>>^v>vvv<^^^^vv>v<>><>^<<><<vvv>^<^<^v>><>v<^>v^>v>v<<<>vv<>^v^^>>>>^<<>v><>>>^v^>^><<<>v<>><^>>^^<vv^^>^<^vv>>v<v>vv<<><^><<^v<>^v<<v<
|
|
||||||
v>^><v^^vvv>>>^<<<>v<v^v>>v>^<^>v^<<^>>^^<^vv>>>><>^><^^^vv><v<^^<<^<<>v^><<v<<v><>v>v<>^>>v^<<^>^<<v>^><^^v<<^>>vv>^^^^^v<^>>>v^v<^v>>>^^>v^<><<vvvv<^<v^>^<><^v^vvvvv^^<<>><<>>v^vv<^v<>>^<<vv<vv>^<<v>^^>v>>^<>><v>>v^v>v>^><<<>>>><<<<<v>^v>>>>^vv<<<^>^>vv><v^v^^vv^v^<v^<^>v><><v>><^^<^>>v^^<^><^<<v<<v>^v>vv^<^><<>v^>><>>v<^>^><vvv<>vv<<vv>^v>v<<^>^<v><<<<>^<^^v<vv<>>><^vv^v<<<>^^v<<><v^v^v>^<v>v^<<v^><v<<^v^^>v^^^^<>^<<>v<>>^>vvv<^^v><^><<vv<<^<<vvv^<>^^<<>v^<^^<<<>^v^<^<><v>v<^v>v<^v>^^<<^^><<<v<^<v>^<<^^><^>><^^<v>v<^^<vv<<>>^v^>^<^<^>v>>^<^>v>vv^<v>vv>vv<<<<<<<<v^<^<v<^<^v<>^<v>^v>^>vv<<^^<v><v<^<v<^>vv>v>^^v^v<>>^^>>>v<^^>><>>vvv^v^<>>vv^<>v^v^v<^>>^>><^><^<v^^vv<<><<<v<^v^vv<<<>vvv>^v^<>><v<v<<<^^^^v^>^><>^v^v>vv^v><^>^<vv^>vv<^<^>>vv<^^^><v^v^>^>v>><<v^v>vvvv^<>v<^>^vv^^^v^<^^v>v>^v>v>>^<v^>v>>>v^^<^v><<<>v<v^v<v^v<vv<<>vv^^<>vvv<><>^<v^>^v<^<^>v>^vv><>vvv^<>><<^v<>^^^<<<vvv^^>^vv<<^>><^v><>vv>vv<^<vv<^v><^>vvv<<^>^^<<^<^>v<^><^^v^^<v<<v>^v<^v>^^<<^^<>v^v^v^<^v^>>><>v^v^v^<<^<><v
|
|
||||||
<vv>^<v<<^<v>^^v><>vvvvvvvvv<vv<^v<>v<v><v>^><v<^^v^<^^v^v><v^^^<<<vvv<v^^^><><<<>><^><^vv<<><<^vv<>^v^<>>v>^vv^>v>v<^vvv^><<vv<vvv<v^^>v^v>v>v><v^><v^<^v<v^>>^<>v<>>^<^<^^><vv^^^>>v^^><<>^<^v^^vv^<<vv^<>><v^v^<^^v^v^>>^^<>v<^v>v>v<vvv>^^v<><>>vv>v<v>><^v>^>^>v<^<>^v<<vvv^v>^v>^^>>>vv<>v><vv>>>>^>>v^<<v^v<>v><><^^v>v<v^<vv^>>><<>>>vvv<>^<<v<<<<vv<>>>vv><^vv>><<v>><^v>^<<^v^vvv^v^>^>^v<v^<>v>><v<^v^>><>>>vv^>^>v<^><^^>>><^^v^<>v^^<^>>^<vv^>>v><^^>^^>^^v^>>v^<>^^<<<>><><>>^>^<>^><^><<^>><v>>vvvv^^^vv<><<>>^v<<<<>^^v><^v<<v>vv>>v<><>^^^>^<>v>>v^v<v<>^<<^>v^vv>^^v>v<>^>vvv^^v>^^v<^<>^v><<v^v^<>^^><^vv<<>>>^>v^>^>>><<<v^<<v<<<^v><^^>^v^^>v^^v<^v<>^>^<v<>><^>>>^>><<v^^<<<^><<<v><^>><^>>><v<>^><^vv<^>v>vvv^<^><^v<<<^v^^vv<^<v<>^vvv<>v>^<^><>>>^v^v^^>^^<<>>>^<>>^>^><><><^^<^^^<>>^<^>^><<vv>^<v><^>^^v><>>^>^>v^v<<<v<>v^<><^>v>v>v<>^^>vv^><v>>^v^<>^^>v<><><^<>><^><^v<<<<v^vv><^^v<<^v<v<<<v^<vv^<<<vv>v<<<>vvv<^^<<vv^>^<^vvv^^v^<>v>v^>><>^v>><v^^^><^^<<>^<>^<v>v^<<vv>><<^>><>^v>>>^v^vvv<v^vv^>^>v<
|
|
||||||
^>v^^<>^>v^^<>^<<v<><v^>^><<^<>^vv^vvv>>v^vv<<^^>^v<v^<vv>>^^^^vvv>>^^<>^v><<^^>>^><^<^>^v>^v<>^v<<v<<v>^><<v<v^vvv>v<v<<^^>>>^vv^vvv>vv<>^>v<vvv<^^vv>^v^><v^>vv><>><^>^^>^v^^<<^vvvv<v^v>>^>><^>>^<<v^>v>^v><v<<<v>>v<^<>^^^^vv>v>><>><v><><vv<<v<<^<^<^<^v<v^^>>>^<^<v^>>^v<><^<>^<vv<^<v<v^>>vv^>>>v<v^<^v^v^^>v><>^^v<<^^><^^>v^>v^^>>v^^<vv<v^>>^v>><>v>>>^v<<>^vv<^^>>>><v<>^>vvv>^v^>v^>^^<^>>>>>v^^<<>v>v<<>>>><>v<<>>>v^v<><>><<>^vvv<^^^>^v<^<v<^<><<<><^^<<>>v^^<v>^vv<^^v^^^>v^<><<^^v^^v<<<>v>^^^<>v<v<^>>>v^^>^v^^v>^^^v<>^^^>>v^^>>^v^<v<<>>><>><^>^><^v<<<^<<vvv^>>vv<v<vv^><>>^>^^v>v<^v>^^><>>v>>v>v>^^<>^vv<^v^vv^>vv>v<^v>><^v>vv^^>^vv<v<^>v<^v<<<^>^^>^<>>^<v<^>^<^>>v<vv^^<^<>^v<^v^<>>^^v^vv^>v<v^<<vv^<><^v><><^^<v^v<v^><<<>><><<^<^^^vv^v<v<><vvvv<>v<>vv^v^v>v<^v><^>v<<v>><^v<v<<^v<><^^^^v>v^v>v<^^^v^>v<vv>v<<vvv^<^v^<^>><<v<^v<><v<<vv^<>v<v<<>>v>v>>v^^v<<^v>><^<<<><>^^v^^<v<><>^<vv<>v<^<><>>v>v<^<^>><v<<><<>>>^v>^<v>><^>^v^vv<<^>^^v<^v<^^<<>^^vvv<>v<v<>>><v^^v^^v^^>^^<^^>v>^^<<>^>^^^><v>v>v>
|
|
||||||
v>v^vvvv^<<<>v<v>v><<<vv<>^>>v<><<<vvv>v>v^^<<<v<^v<<v<>v>v<^v>v^^><^<^^>><^^><^^^><^^v^v^<>>^<^v^^^>^<>^>v<<<vvv^<<^>><<>^<><<v^^<<<vvv><^v>vv<^>v>v>^vv>^<vvv<<v>v<<<>v<>vvv<v^^v<><v<v^v>>v^<<^v>^v^^>>v<>^<<>v>><^^^><^<<><v>><>^^>>^vv^<^^<v^^><<^v^^v<>v<>vv>v^>^>^>^<><><^^<^v>^><^^v^>v>>>^<^^^>vv^^>^>^^<vv><^><><^<<>^v<^<v^<^<v<v<^v<<<>vvv^>^^<><^^<<v>><^>v<^^^>v<v^><v>>>>^v<v>><^v<>v><^^vv^^<v<v<v<v>^<^v>vv><v>^<^<v^v>^<<><^<^v<>vv<<v>v>^<v<<^v<<^<<>^<<v<^>vvv^>^>v<>>^<v^^<^<>v>>v<>^v>>v<v^<>^>>^<^<v^vv>v>>v>>>v>^<<><^<>><><><vv>^<<<<v<<<v^^>^<^<vv>v<>^^>v^^<>v>><^>><vv<vv>>v<vv^v><<<<^>^<<<>><v>>^^^>^>^^v>>>^<<v^v><<^v><>v>^>>>>v^^^<^v>v^>>>^<>^<vv<>v^<><>>>^>^>^^^^<<<>>v><^^<<^><>vv>^<>^<><^vv<^>>vv^^>v^vv<v^<^^^^vv>vv>vv^vv^^^vvv^<>^v^<vv<><^^<<><>v^<^^^<v^<<>>^><<v<^v^><<^>v>>v^<v>^<>>>^v>^<<<v^^v<^>vv^^v<^v^vv>><>><^>^^>v>^^v^<^^v^^><>v<<<v>^>vv^><>v^v^><<>^^<v^<><v><v><>^v><>v><^^v^<v>^><<v>v<v>>>^v><<>^>^^>>v<v<v<vv<<<^>><^<vv<^v>^vvv>>v>>^<<>><v<^>vvv^v^^v><v<><<v<v>v^v^v<<v^
|
|
||||||
>>^v<v^v><>^^>v<>>v<v^^<vv>^v^>v<v^>>^>><^v>^^>^<^v<>v>>^>v<v>v><vvv^><vv^^^<v>>>>^<><v<^<>v>^v<^v^vv<>^<v>^vvv^>^><v<^v^<<<^^^>>>^<<^v^vv^>>^v^v^^<^v><<v<>^v<v>vv<v^vvv^<<>vvvv<^^v<^<vv<><v<^<>v^^<<>v<<>v^^<<><<<<>v^>^v<^^^<^^<^<^^><>>^<v>^^<^vv<>v>>^^^<>><^<^^v<vv><v^<><<^v><><<^v^>^>^^^<^^><vvv>^>v^<^v>v^>v<v<v^>><<v^^><^v^<<vvv^<>vv>^v<><v>>><>^v<v>^<<<v<>v>v>^<<<^^v<>>v<>v<>v<>v>^<^v><^^v<<^^>v><<<<>^^<vvv>>^^><<v<>><<v><^v^^vv><vv^>^^><v<>^v>^>vv>^<^><>^<v>v>><<^><>>>v^v>>^>v^><^<v<<><<>^vvv<v<<^>vv>v^<><<v^^<v<^<<><v<<>>^><v><>^^^^<v^v<^><>^<^<^<v><<v>v<^v>v<>><>>vv<v^>>v<^<<^^>^<<^^^^<v<v>^v^<^^v^vvv><<v>>>v<<v^><<^>>v>>v<<^^>>v^v><<<^>^^<vv<^^^<<vv>>^vv>>^<vv><<v>vvvv<<<<>vv>^<>>v<^<v>^<v^>><^<^>^vv^<vv><<<<<<<<>v>>>^v<>>^>^<^^><v>vv^v>^<^^<<<v^>^>^^v><vv^^<><v>><<^<<>v<vv^v<vvv<<v<^<^^v>^v<^^<v^>vv<>vv>>^>v<<>^vv^<>>^>vvv<>^^^v^<v^><>>vv^vv^^>>v^v<^^<>>v<>v>>>^<vv>^<><<>v<><>vv^v^v>^<<v^<^>><vv^v>vv>v>>>>^^^vv<^>v>vv^<<><>^^><^<<^>vv^>^^<<>><<><>^>^^<>>v^v<v^v^vvv><^v^^v<>vvv
|
|
||||||
|
|||||||
@@ -1,141 +0,0 @@
|
|||||||
#############################################################################################################################################
|
|
||||||
#.................#.................#.............#.......#...................#.......#.............................#...#.......#.........#E#
|
|
||||||
#.#.###############.#####.#####.###.#.#########.###.#.###.#.#################.#.#####.#.#.#####.#################.#.###.#.###.#.#.#.#.###.#.#
|
|
||||||
#.#.#.....#.........#...#.#...#.#.#.#.........#.....#.#...#.....#...#.........#.#.......#.#.....#.....#.#.........#...#.......#.#.#.#...#.#.#
|
|
||||||
###.#.###.#.#########.#.###.#.#.#.#.###.#############.#.###.###.#.###.#########.#.#####.#.#######.###.#.#.#######.###.#######.#.#.#.#.#.#.#.#
|
|
||||||
#...#...#...#...#...#.#.#...#...#.....#.#...#.........#...#...#.#.#...#.......#.#...#.....#.......#...#.#.#.#.......#.#...#...#.#.#.#.#...#.#
|
|
||||||
#.#####.#####.###.#.#.#.#.###.#######.###.#.#.###########.#####.#.#.###.#####.#.###.#.#.###.#######.###.#.#.#.###.###.#.#.#.#.#.#.#.#####.#.#
|
|
||||||
#.......#...#...#.#.#.#...#...#...#.................................#...#...#...#...#.#.#.....#.............#...#.....#.#...#.#...#.....#...#
|
|
||||||
#.#######.#.#.#.#.#.#.#######.#.#.#.###.###.#.#.#.#####.###.#.###.#.#.#####.###.#.###.#.#.###.#.#.#.#.###.#####.#.#####.#####.###.#####.#.###
|
|
||||||
#.#.....#.....#.#.#...#.....#.#.#.#.....#.#.#.#.....#.#...#...#...#.#.....#.....#...#...#.#.....#...#.....#...#.......#.#...#...#.....#.....#
|
|
||||||
#.#.###.#####.#.#.#####.###.#.#.#.#######.#.#.#####.#.#.#######.#.#.#.###.#####.###.###.#.#.#.#############.#.###.###.#.###.#.#.#####.###.#.#
|
|
||||||
#.#...#.....#.#.#.#.....#...#.#.#.....#.....#...#.#...#...#.............#.....#...#...#...#.#.#.....#.....#.#.....#...#...#...#...#...#.....#
|
|
||||||
#.###.#####.###.#.#.#####.#####.#####.#.#####.#.#.#.#####.#.###########.#####.###.###.#####.#.#.###.#.###.#.#####.#.#####.#.#.###.###.#.#.###
|
|
||||||
#.....#.....#...#.#.#.....#.....#.....#.....#.#.#...#.....#.#.........#.....#...#...#.....#.......#.....#...#...#.#.......#.....#...#.#.....#
|
|
||||||
#######.#####.#.#.#.#.#####.#.###.#########.#.#.#.###.###.#.#####.###.#########.#######.#####.#########.#.###.#.#.#########.#.#.###.#######.#
|
|
||||||
#.....#.#.....#.#...#.......#...#.......#.#.#.#.#.#.#.#...#.#...#.#.......#.....#...#...#.....#.......#.#.....#...#.....#.....#...#...#.....#
|
|
||||||
#.###.#.#.###.#.###.#########.#.#####.#.#.#.###.#.#.#.#.###.#.#.#.#######.#.#####.#.#.###.###.#.#####.#.#.###########.#.#.###.#.#.###.#.###.#
|
|
||||||
#.#...#.#.#...#.#.............#.#.......#.#.....#.#.#.#...#...#.#...#.....#.#.....#.#...#.#...#...#...#.#.#.....#.....#.#...#...#...#.......#
|
|
||||||
#.#.###.###.###.###.#########.###.#######.#####.#.#.#.#########.#.#.#.#####.#.#####.#.#.#.#.#####.###.#.#.#.#.###.#.###.#####.#.#####.#.#.#.#
|
|
||||||
#.#.#...#...#.#...#.#.......#...#.#.............#...#.........#.#.#.#.#...#.......#...#.#.#.....#...#.....#.#.#...#...#.......#.#.......#...#
|
|
||||||
#.#.#.###.###.###.#.#####.#####.#.#.#.#############.#########.#.###.#.###.#.#######.#.#.#.#####.###.#########.#.#####.###########.#####.###.#
|
|
||||||
#.#...............#...#...#.....#...#.......#.......#.......#.....#.#...#...#.....#.#...#.#...#...#.........#...#...#.........#.............#
|
|
||||||
#.#.#.#.###.#.#######.#.#.#.###.###.#.#####.#.###########.#######.#.###.#####.###.#######.###.###.#.#######.#.#####.#########.#.###.#####.#.#
|
|
||||||
#.#...#...#.#.#.....#...#.#.#.....#.#...#.#.......#.......#...#.#...#.#.....#.#...#.......#.....#.#.......#.#.....#.......#...#...#...#.#.#.#
|
|
||||||
#.#######.#.#.#.###.#######.#.#####.###.#.#######.#.###.###.#.#.#####.#####.#.#.#.#.#######.#.###.#######.#.#####.#.###.#.#.#####.###.#.#.#.#
|
|
||||||
#.#.......#.#.#...#.......#.#.#.#...#.....#...#.#...#...#...#.#...........#.#.#...#.#...#...#.#...#...#...#.#...#.#.#...#.......#.#.....#.#.#
|
|
||||||
#.#####.###.#.###.#######.#.#.#.#.#########.#.#.#####.###.###.#.###.#.#.#.#.#.#.###.#.#.#.#.###.###.#.#.###.#.#.#.#.#.###.###.###.#.#####.###
|
|
||||||
#.......#.........#.....#...#...#.....#.....#.........#.......#...#...#.#.....#...#.#.#...#.....#...#.#...#.#.#...#.#.#...#...#...#.#...#...#
|
|
||||||
#########.#.#########.#.#.#####.#####.#.#####.#.###.###.###.#####.#####.#########.#.#.#.#.#########.#.#.###.#.#####.#.#.###.#.#.#####.#.###.#
|
|
||||||
#.#.......#...#.......#...#...#.#...#...#...#.#.......#.#.#.....#.#...#...#.......#.#...............#.#.#...#...#.#.#.#.#...#.#.......#.....#
|
|
||||||
#.#.#.#########.#.#########.#.#.#.#######.#.#.#####.###.#.#####.#.#.#####.#.#######.#.###############.#.#.#####.#.#.#.#.#.#.###.###########.#
|
|
||||||
#...#.......#...#.....#.....#...#.......#.#.#.#.........#.#.....#...#.....#.........#...#...........#.#.#.#...#.#.#.#.....#...#.#.......#...#
|
|
||||||
#.#########.#.#######.#.#############.#.#.#.#.#.#########.#.#####.###.#######.#########.#.#########.#.###.#.###.#.#.#.###.###.#.#.#####.###.#
|
|
||||||
#...#.....#...#.#.....#...#...#.....#.#.#.#.#...#.........#.....#.#...#.......#...#.....#.#.#.......#.....#...#.#...#.#.#...#.#.#.#...#...#.#
|
|
||||||
###.###.#######.#.###.###.#.#.#.#.#.#.#.#.#.#####.#######.#####.#.#.###.#####.#.#.#.#####.#.#.###.#########.#.#.#####.#.###.#.#.#.###.###.###
|
|
||||||
#.#...#.#.......#.#.#.#...#.#...#.#.#.#...#.....#...#.#...#...#.#.#.....#.#.....#.#.#...#...#.#.#.#.............#.....#.....#...#...#...#...#
|
|
||||||
#.###.#.#.#####.#.#.#.#.#########.#.###.#####.#####.#.#.#.#.#.#.#.#######.#.#####.#.#.#####.#.#.#.#.#.#####.#.###.###.#############.#.#####.#
|
|
||||||
#.....#.....#...#.#...#...........#.........#...#.....#.#...#.#.#.........#.#.#...#.........#.#...#.#.....#.#.....#...#.............#.#.....#
|
|
||||||
#.#########.#.###.#########################.###.#.#####.#####.#.#########.#.#.#.#####.#.#####.#.###.###.#.#.#######.###.#############.#.#####
|
|
||||||
#.......#.#.#...#.............#.......#.......#.#.#...#.#.......#.....#...#...#...#...#.#.....#...#.....#.#...#...#.#...#...#.........#.....#
|
|
||||||
#######.#.#.###.###########.#.#.#.###.#.#.###.#.#.#.#.#.#.#####.#.###.#######.###.#####.#.#####.#####.###.###.#.###.#.###.#.#.#.#####.#####.#
|
|
||||||
#...#...#.#...#.#.......#...#.#.#.#...#.#.#...#...#.#.#.#...#...#.#.#.#.....#.#.#.....#.#.#.....#.......#...#.#.....#.....#.#.#.#.#...#...#.#
|
|
||||||
#.#.#.###.###.#.#.#.###.#.#####.#.#####.#.#.###.###.#.#.###.#####.#.#.#.###.#.#.#####.#.#.#.#####.#.###.###.#.#.###########.###.#.#.#####.#.#
|
|
||||||
#.#.#.#.#.....#...#...#.#.......#.......#...#...#...#.#...#.....#.#.#...#...#.#...#...#.#.#.#...#.#...#...#.#.#.#.#.......#.................#
|
|
||||||
#.###.#.#.###########.#.#######################.#.###.#.#.#####.#.#.#####.#.#.#.###.###.#.#.#.#.#.###.###.#.#.#.#.#.###.#.#######.#####.#.#.#
|
|
||||||
#...#.#...#...#.....#.#.#.............#.......#.#.#.....#.....#.#...........#...#...#...#.#...#.#...#.#...#.#.#.....#.#.#.#.....#.....#.#.#.#
|
|
||||||
###.#.#####.#.#.#.#.#.#.#######.#####.#.#####.###.#########.#.#.#.###.#####.#.###.###.###.#.#.###.###.#####.#.#####.#.#.###.#.###.#.###.#.#.#
|
|
||||||
#...#.......#.....#.#.#...#.....#...#.#.#...#...#...#.....#...#...#.........#.#...#.....#...#.#...#...#.....#.........#.#...#.....#...#...#.#
|
|
||||||
#.#.#######.#####.#.#.###.#.#######.#.#.###.###.#.#.#.###.#.#######.###.#####.#.###.#######.###.###.###.#####.#########.#.#########.#.###.#.#
|
|
||||||
#.#...#.#.........#...#.#.....#...#.#.#...#.#...#.#.....#.....#.....#...#.....#.#.....#...#.......#.........#.......#...#.#.................#
|
|
||||||
#.###.#.#.#.#####.#####.#.#.#.#.#.#.#.#.#.#.#.#######.###.###.#.###.#####.#####.#.#####.#.###########.#####.#.#####.#.#.#.###.#.###.#######.#
|
|
||||||
#.#.....#...#.#...#.....#.#.#.#.#...#.#.#.#.#.......#.#...#...#.....#.....#...#...#.....#...........#.#...#.#.#...#.#.#.#.................#.#
|
|
||||||
#.###.#.###.#.#.#.#.#.#.#.###.#.###.#.###.#.#####.#.#.#.###.###.#.###.#.###.#######.#####.###.#####.###.#.###.#.#.#.#.#############.#.###.#.#
|
|
||||||
#.....#...#...#.#.#.#.#.......#...#.#.....#.......#.#.#...#.#...#.#...#...........#.#.....#.......#.....#.....#.#.....#...........#.#.#...#.#
|
|
||||||
#.###.###.#.#.#.###.#.#.#######.#.#########.#####.#.#####.#.#.#.###.###.#######.#.#.#######.#####.###.#.#####.#########.#.#####.###.#.#.###.#
|
|
||||||
#.#...#...#.#.#.....#.#.#.......#.#...........#...#.....#.#.#...#...#.#...#...#.#.#.#.......#...#.#.#...#...#.#.........#.....#.#...#.#...#.#
|
|
||||||
###.#.#.###.#.#######.###.#######.#.###.###.#.#.#######.#.###.#.#.###.#.###.#.#.#.#.#.#####.#.###.#.#####.#.#.#.#########.#.#.#.#.#.#####.#.#
|
|
||||||
#...#.#.....#.#.....#.#...#.#.....#.#.#.....#.#.#...#...#...#.#.#.#.....#...#.#.#.#.#.#.........#.#.......#.#.....#.....#.#.#.#.#.#.......#.#
|
|
||||||
#.###.#####.#.#.#####.#.###.#.#####.#.#######.###.#.#.#####.#.#.#.###.###.###.#.#.#.#.#########.#.#######.#.#.###.###.#.#.###.#.#.#.#.###.#.#
|
|
||||||
#.#.........#.#...#...#.....#.....#.#.......#.....#.........#.#.#...#.#...#.#...#.#...#.........#.......#.#.#.#.#...#.#.#...#.#.#.....#...#.#
|
|
||||||
#.#########.#.###.#.#######.#####.#.#######.#######.#########.#.###.#.#.###.#####.#.#.#.#######.#######.#.#.#.#.###.###.###.#.#.###.###.###.#
|
|
||||||
#...#.........#...#.....#...#...#...#.....#...#.........#.....#.#...#.#.#...#.....#.#...#...#.#.......#.#.#...#...#.#...#...#.#.....#.....#.#
|
|
||||||
#.#.#.#####.###.#.###.###.#####.#####.###.#.###.#######.#.#.#####.#####.#.#.#.#####.#####.#.#.#######.#.#####.###.#.#.###.###.###.#.#.#####.#
|
|
||||||
#.#...#.........#.#.....#.#.......#...#...#.#...#.........#.#.....#.....#.#.......#...#...#...#...#...#.#...#.....#...#...#.......#...#.#...#
|
|
||||||
#.#######.#.#####.#.###.#.#.#.###.#.#####.#.#.#####.#######.#.#####.#####.#######.###.#.#.###.#.#.#.###.#.#.#####.###.#.#######.###.###.#.#.#
|
|
||||||
#.........#.....#.#...#...#.#.#.#.#.....#.#.#.#...#.#.......#.#.....#.......#...#...#...#.#...#.#.....#...#.#...#...#.#.......#.#.......#.#.#
|
|
||||||
###########.###.#.#.#########.#.#.#####.#.#.#.#.#.###.#.###.#.###.###.#######.#.###.#####.#####.#####.#####.#.#.#####.#.#.###.###.#######.#.#
|
|
||||||
#.....#.....#.#...#...........#.........#.#.#...#.....#.#...#...#.#.#.#.....#.#.#...#...#.#...#.#...........#.#.......#.#.#.#.....#.......#.#
|
|
||||||
#.###.#.###.#.#######.###################.#.###########.#.#.#.#.#.#.#.#.###.#.#.#####.#.#.#.#.#.#.#.#######.#.#########.#.#.#.#####.###.###.#
|
|
||||||
#.#...#.#.#...........#.....#...#...#.........#.......#...#...#.#.#.#.#...#...#.......#.#...#...#.#.#.......#...#...#...#.#.......#.......#.#
|
|
||||||
###.###.#.#.#####.#####.###.#.#.#.#.#########.#####.#.#######.#.#.#.#.###.#############.#.#######.#.#.#.###.###.#.###.###.#.#####.#######.#.#
|
|
||||||
#.................#...#.#.#.#...#.#.......#.#.#.....#.....#...#...#...#.#...#.........#.#.#.#.....#.#.#.......#.#...#.....#.....#.......#.#.#
|
|
||||||
#.#.#.###.###.###.#.#.#.#.#.#.#.#.#######.#.#.#.###########.#.#.#.#####.###.###.#.#####.#.#.#.#######.#.#.###.#.###.###########.#########.#.#
|
|
||||||
#.#.#...#...#...#.#.#...#.#...#...#.....#...#.#...#.........#.#.#.#...#...#...#.#.#.....#.#.#.........#...#.#...#.........#.....#...........#
|
|
||||||
#.#.###.###.###.###.#####.#########.###.#.#.#.###.#.#.#.#######.#.#.#.###.#.#.#.###.#####.#.###############.#####.#######.#.#.#.#.#####.#.###
|
|
||||||
#.#...#...#...#.#...#.......#.......#...#.#...#...#.#.#...#.....#...#...#.#.#.#.....#.............#...................#.....#.....#.....#...#
|
|
||||||
#.#.#.###.#####.#.###.#.#####.#######.#.#.#.###.###.###.#.#.#########.#.#.#.#.#.#####.#########.#.#.###.###.#####.###.#######.###.#.###.###.#
|
|
||||||
#...#...#...#...#...#.#.......#.#.....#.#.#...#.#...#...#...#...#.....#.#.#.#.#.....#.#.......#.#...#...#.#.....#.#...#.....#...#.#...#.#.#.#
|
|
||||||
#.#.#######.#.#.###.#######.###.#.#######.###.#.#.###.#######.#.#.#####.#.###.#####.###.#####.#.#####.###.#####.#.#.#.#.###.###.#####.#.#.#.#
|
|
||||||
#.#.......#.#.#...#.......#.#...#.......#...#...#.#...#.......#.#.#.....#.....#...#.....#...#.#.......#.....#...#.#.#.#.#.....#...#...#...#.#
|
|
||||||
#.#.#####.#.#.###.#######.#.###.#######.###.#####.#.#######.###.#.#.###########.#.#########.#.#########.###.#.#####.#.#.#####.###.#.#######.#
|
|
||||||
#.#.....#...#.#.........#.#...#.......#...#.......#.......#.#.....#...#.......#.#.#.........#...#.......#.....#.....#.......#...#...#.......#
|
|
||||||
#.#.#.#######.###.#######.###.#.#####.###.#######.#######.#.#########.#####.#.#.#.#.#.#.#######.#.#######.###.#.###########.###.#####.#######
|
|
||||||
#.#.#.#...................#.#...#.....#...#.....#.#...#...#...#.#.....#...#.#.#.#...#.#.#.......#.......#...#.#...#.....#...#.#.......#.....#
|
|
||||||
#.#.#.#.#######.#.#######.#.#####.#####.#.#####.#.###.#.###.#.#.#.#####.#.#.###.#####.#.#.#################.#.#.#.#.#.###.#.#.#########.#.#.#
|
|
||||||
#...#.#.#...#...#.#.#...........#.#.....#.......#...#.#.#...#.#...#.....#...#.....#...#.#.................#...#.#...#...#.#.#.....#.....#.#.#
|
|
||||||
###.#.#.#.#.#.#.#.#.#.#######.###.#.#####.#########.#.#.#.###.#.###.###.###.#.###.#.###.#################.#.#######.###.#.#.#.#.#.#####.#.#.#
|
|
||||||
#...#.....#.#.#.#.#.#.#.....#.....#.....#.#.......#...#.#...#.#...#...#...#.#.#...#...#.#...#...........#.#.#.......#...#.#.#.#.#.........#.#
|
|
||||||
#.###########.###.#.#.#.###.###.#######.#.#.#####.###.#.#.#.#.###.#######.###.#.#.###.#.#.#.#.#######.#.#.#.#.#####.#.###.#.#.#.#####.#.#.#.#
|
|
||||||
#.#...............#.#.#.#.#.........#.#...#.#...#.....#.#.#...#.#.......#.....#.#...#.#.#.#...#.#.....#.#.#...#.......#...#...#...#.#.....#.#
|
|
||||||
#.#.#.#########.###.#.#.#.#####.#.#.#.###.#.#.#.#######.#.#####.#######.#.#######.#.#.#.#.#####.#.#######.###########.#.#####.###.#.#.#.###.#
|
|
||||||
#.#.#.....#...#.#...#...#.....#...#...#.#...#.#.......#...#...........#.#.........#...#.......#.#.......#...........#.#.#...#...#.#...#...#.#
|
|
||||||
#.#######.#.#.#.#.#######.###.#######.#.#####.###.#######.###.#########.#.#.###.###.###.#####.#.#######.#.#.#######.#.#.#.#.#.#.#.#####.#.###
|
|
||||||
#...#.....#.#.#.#.........#...#.....#.....#.....#.............#.........#.......#...#.......#.....#.#...#.#...#...#.#.#...#...#.#.#.....#...#
|
|
||||||
###.#.#####.#.#.###.#####.#####.###.#####.###############.###.#.#######.#####.#.#.###############.#.#.###.#.#.###.#.###########.#.#.###.###.#
|
|
||||||
#.#...#...#.#.#.........#.........#.....#...#...#...#.....#...#.#...#...#.....#.#.............#...#.#.....#.#.#...#.#...........#...#.....#.#
|
|
||||||
#.###.#.#.#.#.#########.#.#.#######.###.###.#.#.#.#.#.#######.#.#.#.#.###.#####.###########.#.#.###.###.###.#.#.###.#.#####.#.###.###.#.#.#.#
|
|
||||||
#.....#.#...#.....#.....#.#.....#...#.....#...#.#.#...#.....#.#.#.#...#...#.....#...........#.#...#.......#.#.#...#.#.#...#.#.#.............#
|
|
||||||
#######.###.#####.#.#####.#####.#.#############.#.#####.###.###.#.#####.#####.#.#.#####.#####.###.#.#####.###.#.#.#.#.#.###.#.#.###.###.#####
|
|
||||||
#.....#.........#...#.........#.#.............#.#.#.....#.#.....#.....#.#.....#.#.#.#.......#.#...#.#...#.#...#.#...#.#...#.#.#...#.#...#...#
|
|
||||||
#.###.#.###.###.#####.#####.#.#.#########.###.#.#.#.#.###.#####.###.#.#.#.#######.#.#.#.#####.#.###.###.#.#.###.#####.#.#.#.#.###.#.#.###.#.#
|
|
||||||
#...............#...#.#...#.#.#.....#.#...#...#...#.........#.....#.#.....#.......#...#.......#.#...#...#...#.#.......#.#.#...#.....#.#...#.#
|
|
||||||
#.#.#.#.#.#.#####.###.#.#.###.#####.#.#.#########.###.#####.#.###.#########.#######.###########.###.#.#.#####.#########.#.###.#######.#.###.#
|
|
||||||
#.#.....#.#...#.......#.#...#.....#.#.#.......#...#.#.....#...#.#...........#.....#.#.........#.....#.#.#.....#...#.....#...........#...#...#
|
|
||||||
#.#####.#.#.#.#.#######.###.#.###.#.#.###.#.#.#.###.#.###.#####.###############.#.#.#.#.#.#.#########.#.###.#.#.#.###########.#####.#.###.#.#
|
|
||||||
#.............#.....#...#...#...#.#...#.#.........#.....#.....#.........#.......#.#.#.#.#.#...........#.....#...#...#.......#.#.....#...#...#
|
|
||||||
#.#.#.#.#.#.#########.###.###.#.#.###.#.#########.###########.#.###.#####.###.#####.#.#.###.###.###################.#.#####.#.#.#####.###.#.#
|
|
||||||
#.#.#.#.#...#.........#.#.#...#.#...#.....#.#...#.........#.......#.....#.#.#.......#.#.......#...#.....#.........#.#.#...#.#.#.#.......#.#.#
|
|
||||||
#.#.#.#.###.#.#####.###.#.#.###.###.#####.#.#.#.#########.#.#.###.#####.#.#.###############.#####.###.#.###.#.#.#.#.#.#.#.#.#.#.#####.#.###.#
|
|
||||||
#.#...#.....#.#.....#...#.#.#.#...#.#...#.#.#.#...#.....#.#.#...#.....#.........#.........#.#.....#...#...#.#.#...#...#.#.#...#.......#.....#
|
|
||||||
#.#####.###.#.#.###.#.###.#.#.###.###.#.#.#.#.###.###.#.#.#.###.#####.#.#######.#####.###.#.#.#####.#####.###.#.#######.#.#####.#####.###.#.#
|
|
||||||
#.#.....#.#.#.#.......#...#.....#.#...#.#...#.#.#...#.#.#.#...........#.#.....#.....#.#...#.#...#...#...#.....#.........#.#.........#...#...#
|
|
||||||
#.###.#.#.#.#.###.#.###.#####.#.#.#.###.###.#.#.###.#.###.###.###.#####.#.#.#######.#.#.#######.###.#.#.#################.###.#.###.#.#.###.#
|
|
||||||
#.....#.#.........#.#...#...#.#...#...#.....#...#...#...........#.#.....#.#.....#...#.#.........#...#.#.....#.....#.....#...#...#...#.#...#.#
|
|
||||||
#######.#.#.#.#.###.#.###.#.#.#.###.#.###.#####.#.###.#########.###.###.#.###.###.###.###########.#####.#####.#.###.###.###.###.#.###.#.#.#.#
|
|
||||||
#.....#.#.#.....#...#...#.#.#.#.....#...#...#.........#.....#.#.........#...#.......#...#...#.........#.......#.....#...#.........#...#.....#
|
|
||||||
#.#.#.#.#.#############.#.#.#########.#.#####.###.###.#.###.#.#######.#.###.###.###.###.#.#.#.#######.#.###.#########.###.#####.###.###.#.###
|
|
||||||
#...#.#...#...#.........#.#.........#.#.#.....#.#...#.#.#.#.#...........#...#.#.........#.#.#...#...#.#.........#...#.............#...#.....#
|
|
||||||
###.###.#.###.#.#######.#.#####.###.#.#.#.#####.###.###.#.#.###########.#.###.#######.#####.###.#.#.#.#########.###.#######.#####.###.#.#.###
|
|
||||||
#...#.........#.#.#.....#.......#...#.#...........#.....#.#...#.....#...#.........#...#...#.....#.#.#...#.....#...........#.#.....#...#.#...#
|
|
||||||
#.###.#.#######.#.#.#####.#.#.###.###.#####.#.#########.#.###.#.###.#############.#.#.#.#.#.#####.#.###.###.#########.#####.#.#####.###.#.#.#
|
|
||||||
#.....#.........#.......#.#.#...#...#...#...#.....#...........#...#.........#.....#.#...#.#.......#...#...#.....#.....#.....#.....#.........#
|
|
||||||
#.#####.#########.###.###.#.###.###.###.#.#######.#.#.#.###.#.###.#.#####.###.#.#########.#####.#########.#.###.#.#####.#########.#.###.###.#
|
|
||||||
#.....#...#.........#...#.#.#.#...#...#.#.......#.....#.#...#...#.....#...#...#...........#.#...#.............#.........#.......#.#...#...#.#
|
|
||||||
#####.###.#.#######.#.#.#.#.#.#.#.#.#.#.#####.#########.#.###########.#.###.#####.#########.#.###.###########.#########.#.#.###.#.###.#.#.#.#
|
|
||||||
#...#...#.#.#.....#.#.#...#...#.#.#.#.#...#...#.....#...#.......#.....#.....#.....#.......#.#...#.#.......#...#.#.......#.#.................#
|
|
||||||
#.###.#.#.#.#.###.#.#.#########.###.#####.###.#.###.#.#########.#.###########.#.###.#####.#.###.#.#####.#.#.###.#.###########.###.###.#.###.#
|
|
||||||
#.......#.#.#...........#.....#...#.....#...#.#.#...#.........#.#.#...#.....#.#...#.#...#.#.#...#.....#.#.#.....#.#.........#.#...#...#.....#
|
|
||||||
#.#.#####.#.###.#.#####.#.###.#.#.#####.###.###.#.#######.#####.#.#.###.###.#.###.#.#.#.#.#.#.#####.#.#.#.#####.#.#####.###.#.#.#.#.###.#.###
|
|
||||||
#...#.#.......#.#...#...#.#...#.#.....#...#.....#.....#...#...#...#.....#.#...#.#.#...#.#...#...#...#.#.......#.#.......#...#.#.#.#.....#.#.#
|
|
||||||
#.#.#.#.#.#####.###.#.###.#.###.###.#.###.###########.#.###.#.#.#.#.#####.###.#.#.#####.#######.#.#.#.#.###.###.#########.###.#.#######.#.#.#
|
|
||||||
#.......#.#.....#.#...#...#.#.#.#.#.#.#.#...#.....#.............................#.#...#.......#.#.#.#.#.#.#.#.....#.......#...#.........#...#
|
|
||||||
#####.#.#.#.#####.#######.#.#.#.#.#.#.#.###.#.###.#.#########.#####.#.#########.#.#.#.#.###.###.###.#.#.#.#.#.#####.#######.#.#######.#.###.#
|
|
||||||
#.....#...........................#.#.#...#.#.#.#.#.........#...#...#...#.....#.#...#.#.#...#...#...#.#...#...#.#...#.......#.....#...#...#.#
|
|
||||||
#.#####.#.#.#####.#.#.###.#.#.###.#.#.#.###.#.#.#.#########.#.###.#.#.#.#####.#.#####.#.#.#.#.###.#.#.###.#####.#.#####.#.#######.#.###.#.#.#
|
|
||||||
#.#.....#.#.#...#.#...#.....#.....#.#.#.#...#.#.#...................#.......#.#.#.....#.#.#.#...#.#...#.....#...#.....#.#.....#.#.#...#...#.#
|
|
||||||
###.#####.#.#.#.#.#####.#.#######.#.#.#.#.###.#.###.###.###########.###.###.#.#.#.#.###.#.#####.#.#.#######.#.#######.#######.#.#.###.#.###.#
|
|
||||||
#...#.....#...#.#...#...#.......#.#.#.#...........................#.........#...#.#.#...#.....#.#.#...#...#...#.....#...#.....#...#.#.#...#.#
|
|
||||||
#.#############.###.#.###.###.#.###.#.#.#########.#.#.#####.#####.#.###.#########.#.#.#####.###.#.###.#.#.#####.#.#####.#.#####.###.#.#####.#
|
|
||||||
#S..................#.........#.....#.............#.........#.....................#.......#.........#...#.......#.........#.........#.......#
|
|
||||||
#############################################################################################################################################
|
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
Register A: 53437164
|
|
||||||
Register B: 0
|
|
||||||
Register C: 0
|
|
||||||
|
|
||||||
Program: 2,4,1,7,7,5,4,1,1,4,5,5,0,3,3,0
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user