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
|
||||
.vscode
|
||||
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" }]
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.12"
|
||||
python = "^3.10"
|
||||
numpy = "^2.1.3"
|
||||
tqdm = "^4.67.1"
|
||||
parse = "^1.20.2"
|
||||
scipy = "^1.14.1"
|
||||
sympy = "^1.13.3"
|
||||
networkx = "^3.4.2"
|
||||
pillow = "^11.0.0"
|
||||
imageio = "^2.36.1"
|
||||
pygifsicle = "^1.1.0"
|
||||
opencv-python = "^4.10.0.84"
|
||||
pandas = "^2.2.3"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
pyright = "^1.1.389"
|
||||
@@ -27,13 +25,6 @@ ipykernel = "^6.29.5"
|
||||
networkx-stubs = "^0.0.1"
|
||||
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]
|
||||
holt59-aoc = "holt59.aoc.__main__:main"
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ class Solver(BaseSolver):
|
||||
m2 += molecule[i]
|
||||
i += 1
|
||||
|
||||
# print(m2)
|
||||
molecule = m2
|
||||
|
||||
yield count
|
||||
|
||||
@@ -173,6 +173,7 @@ class Solver(BaseSolver):
|
||||
)
|
||||
)
|
||||
|
||||
# 1242 (not working)
|
||||
yield sum(
|
||||
c
|
||||
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):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = input.splitlines()
|
||||
# part 1
|
||||
answer_1 = sum(v2 > v1 for v1, v2 in zip(values[:-1], values[1:]))
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
values = [int(line) for line in lines]
|
||||
|
||||
# part 1
|
||||
yield sum(v2 > v1 for v1, v2 in zip(values[:-1], values[1:]))
|
||||
|
||||
# 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:]))
|
||||
# part 2
|
||||
runnings = [sum(values[i : i + 3]) for i in range(len(values) - 2)]
|
||||
answer_2 = sum(v2 > v1 for v1, v2 in zip(runnings[:-1], runnings[1:]))
|
||||
print(f"answer 2 is {answer_2}")
|
||||
|
||||
@@ -1,47 +1,11 @@
|
||||
from functools import reduce
|
||||
from typing import Any, Iterator
|
||||
import sys
|
||||
|
||||
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}
|
||||
COMPLETE_SCORES = {")": 1, "]": 2, "}": 3, ">": 4}
|
||||
|
||||
|
||||
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]
|
||||
# part 2
|
||||
answer_2 = ...
|
||||
print(f"answer 2 is {answer_2}")
|
||||
|
||||
@@ -1,66 +1,11 @@
|
||||
import itertools as it
|
||||
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}")
|
||||
|
||||
def do_step(values: list[list[int]]) -> tuple[list[list[int]], set[tuple[int, int]]]:
|
||||
values = [[c + 1 for c in r] for r in values]
|
||||
flashed: set[tuple[int, int]] = set()
|
||||
|
||||
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
|
||||
# part 2
|
||||
answer_2 = ...
|
||||
print(f"answer 2 is {answer_2}")
|
||||
|
||||
@@ -1,64 +1,11 @@
|
||||
import string
|
||||
from collections import defaultdict
|
||||
from functools import cache
|
||||
from typing import Any, Iterator, Mapping, Sequence
|
||||
import sys
|
||||
|
||||
from ..base import BaseSolver
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
# part 1
|
||||
answer_1 = ...
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
@cache
|
||||
def is_small(node: str):
|
||||
return all(c in string.ascii_lowercase for c in node)
|
||||
|
||||
|
||||
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)))
|
||||
# part 2
|
||||
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):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
# part 2
|
||||
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):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
# part 2
|
||||
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):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
# part 2
|
||||
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):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
# part 2
|
||||
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):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
# part 2
|
||||
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):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
# part 2
|
||||
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):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
# part 2
|
||||
answer_2 = ...
|
||||
print(f"answer 2 is {answer_2}")
|
||||
|
||||
@@ -1,38 +1,41 @@
|
||||
import sys
|
||||
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"]
|
||||
|
||||
commands: list[tuple[Command, int]] = [
|
||||
(cast(Command, (p := line.split())[0]), int(p[1])) for line in lines
|
||||
]
|
||||
|
||||
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
|
||||
]
|
||||
def depth_and_position(use_aim: bool):
|
||||
aim, pos, depth = 0, 0, 0
|
||||
for command, value in commands:
|
||||
d_depth = 0
|
||||
match command:
|
||||
case "forward":
|
||||
pos += value
|
||||
depth += value * aim
|
||||
case "up":
|
||||
d_depth = -value
|
||||
case "down":
|
||||
d_depth = value
|
||||
|
||||
def depth_and_position(use_aim: bool):
|
||||
aim, pos, depth = 0, 0, 0
|
||||
for command, value in commands:
|
||||
d_depth = 0
|
||||
match command:
|
||||
case "forward":
|
||||
pos += value
|
||||
depth += value * aim
|
||||
case "up":
|
||||
d_depth = -value
|
||||
case "down":
|
||||
d_depth = value
|
||||
if use_aim:
|
||||
aim += d_depth
|
||||
else:
|
||||
depth += value
|
||||
|
||||
if use_aim:
|
||||
aim += d_depth
|
||||
else:
|
||||
depth += value
|
||||
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):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
# part 2
|
||||
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):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
# part 2
|
||||
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):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
# part 2
|
||||
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):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
# part 2
|
||||
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):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
# part 2
|
||||
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):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
# part 2
|
||||
answer_2 = ...
|
||||
print(f"answer 2 is {answer_2}")
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import sys
|
||||
from collections import Counter
|
||||
from typing import Any, Iterator, Literal
|
||||
|
||||
from ..base import BaseSolver
|
||||
from typing import Literal
|
||||
|
||||
|
||||
def generator_rating(
|
||||
@@ -21,23 +20,20 @@ def generator_rating(
|
||||
return values[0]
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = input.splitlines()
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
# part 1
|
||||
most_and_least_common = [
|
||||
tuple(
|
||||
Counter(line[col] for line in lines).most_common(2)[m][0]
|
||||
for m in range(2)
|
||||
)
|
||||
for col in range(len(lines[0]))
|
||||
]
|
||||
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)
|
||||
yield gamma_rate * epsilon_rate
|
||||
|
||||
# part 2
|
||||
oxygen_generator_rating = int(generator_rating(lines, True, "1"), base=2)
|
||||
co2_scrubber_rating = int(generator_rating(lines, False, "0"), base=2)
|
||||
yield oxygen_generator_rating * co2_scrubber_rating
|
||||
# part 1
|
||||
most_and_least_common = [
|
||||
tuple(Counter(line[col] for line in lines).most_common(2)[m][0] for m in range(2))
|
||||
for col in range(len(lines[0]))
|
||||
]
|
||||
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)
|
||||
print(f"answer 1 is {gamma_rate * epsilon_rate}")
|
||||
|
||||
# part 2
|
||||
oxygen_generator_rating = int(generator_rating(lines, True, "1"), base=2)
|
||||
co2_scrubber_rating = int(generator_rating(lines, False, "0"), base=2)
|
||||
answer_2 = oxygen_generator_rating * co2_scrubber_rating
|
||||
print(f"answer 2 is {answer_2}")
|
||||
|
||||
@@ -1,52 +1,45 @@
|
||||
from typing import Any, Iterator
|
||||
import sys
|
||||
|
||||
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):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = input.splitlines()
|
||||
boards = np.asarray(
|
||||
[
|
||||
[[int(c) for c in line.split()] for line in lines[start : start + 5]]
|
||||
for start in range(2, len(lines), 6)
|
||||
]
|
||||
)
|
||||
|
||||
numbers = [int(c) for c in lines[0].split(",")]
|
||||
# (round, score) for each board (-1 when not found)
|
||||
winning_rounds: list[tuple[int, int]] = [(-1, -1) for _ in range(len(boards))]
|
||||
marked = np.zeros_like(boards, dtype=bool)
|
||||
|
||||
boards = np.asarray(
|
||||
[
|
||||
[[int(c) for c in line.split()] for line in lines[start : start + 5]]
|
||||
for start in range(2, len(lines), 6)
|
||||
]
|
||||
)
|
||||
for round, number in enumerate(numbers):
|
||||
# mark boards
|
||||
marked[boards == number] = True
|
||||
|
||||
# (round, score) for each board (-1 when not found)
|
||||
winning_rounds: list[tuple[int, int]] = [(-1, -1) for _ in range(len(boards))]
|
||||
marked = np.zeros_like(boards, dtype=bool)
|
||||
# check each board for winning
|
||||
for index in range(len(boards)):
|
||||
if winning_rounds[index][0] > 0:
|
||||
continue
|
||||
|
||||
for round, number in enumerate(numbers):
|
||||
# mark boards
|
||||
marked[boards == number] = True
|
||||
if np.any(np.all(marked[index], axis=0) | np.all(marked[index], axis=1)):
|
||||
winning_rounds[index] = (
|
||||
round,
|
||||
number * int(np.sum(boards[index][~marked[index]])),
|
||||
)
|
||||
|
||||
# check each board for winning
|
||||
for index in range(len(boards)):
|
||||
if winning_rounds[index][0] > 0:
|
||||
continue
|
||||
# all boards are winning - break
|
||||
if np.all(marked.all(axis=1) | marked.all(axis=2)):
|
||||
break
|
||||
|
||||
if np.any(
|
||||
np.all(marked[index], axis=0) | np.all(marked[index], axis=1)
|
||||
):
|
||||
winning_rounds[index] = (
|
||||
round,
|
||||
number * int(np.sum(boards[index][~marked[index]])),
|
||||
)
|
||||
# part 1
|
||||
(_, score) = min(winning_rounds, key=lambda w: w[0])
|
||||
print(f"answer 1 is {score}")
|
||||
|
||||
# all boards are winning - break
|
||||
if np.all(marked.all(axis=1) | marked.all(axis=2)):
|
||||
break
|
||||
|
||||
# part 1
|
||||
(_, score) = min(winning_rounds, key=lambda w: w[0])
|
||||
yield score
|
||||
|
||||
# part 2
|
||||
(_, score) = max(winning_rounds, key=lambda w: w[0])
|
||||
yield score
|
||||
# part 2
|
||||
(_, score) = max(winning_rounds, key=lambda w: w[0])
|
||||
print(f"answer 2 is {score}")
|
||||
|
||||
@@ -1,48 +1,48 @@
|
||||
from typing import Any, Iterator
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
|
||||
from ..base import BaseSolver
|
||||
lines: list[str] = sys.stdin.read().splitlines()
|
||||
|
||||
sections: list[tuple[tuple[int, int], tuple[int, int]]] = [
|
||||
(
|
||||
(
|
||||
int(line.split(" -> ")[0].split(",")[0]),
|
||||
int(line.split(" -> ")[0].split(",")[1]),
|
||||
),
|
||||
(
|
||||
int(line.split(" -> ")[1].split(",")[0]),
|
||||
int(line.split(" -> ")[1].split(",")[1]),
|
||||
),
|
||||
)
|
||||
for line in lines
|
||||
]
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = input.splitlines()
|
||||
np_sections = np.array(sections).reshape(-1, 4)
|
||||
|
||||
sections: list[tuple[tuple[int, int], tuple[int, int]]] = [
|
||||
(
|
||||
(
|
||||
int(line.split(" -> ")[0].split(",")[0]),
|
||||
int(line.split(" -> ")[0].split(",")[1]),
|
||||
),
|
||||
(
|
||||
int(line.split(" -> ")[1].split(",")[0]),
|
||||
int(line.split(" -> ")[1].split(",")[1]),
|
||||
),
|
||||
)
|
||||
for line in lines
|
||||
]
|
||||
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()),
|
||||
min(np_sections[:, 1].min(), np_sections[:, 3].min()),
|
||||
max(np_sections[:, 1].max(), np_sections[:, 3].max()),
|
||||
)
|
||||
|
||||
np_sections = np.array(sections).reshape(-1, 4)
|
||||
counts_1 = np.zeros((y_max + 1, x_max + 1), dtype=int)
|
||||
counts_2 = counts_1.copy()
|
||||
|
||||
x_max, y_max = (
|
||||
max(np_sections[:, 0].max(), np_sections[:, 2].max()),
|
||||
max(np_sections[:, 1].max(), np_sections[:, 3].max()),
|
||||
)
|
||||
for (x1, y1), (x2, y2) in sections:
|
||||
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)
|
||||
|
||||
counts_1 = np.zeros((y_max + 1, x_max + 1), dtype=int)
|
||||
counts_2 = counts_1.copy()
|
||||
if x1 == x2 or y1 == y2:
|
||||
counts_1[list(y_rng), list(x_rng)] += 1
|
||||
counts_2[list(y_rng), list(x_rng)] += 1
|
||||
elif abs(x2 - x1) == abs(y2 - y1):
|
||||
for i, j in zip(y_rng, x_rng):
|
||||
counts_2[i, j] += 1
|
||||
|
||||
for (x1, y1), (x2, y2) in sections:
|
||||
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)
|
||||
answer_1 = (counts_1 >= 2).sum()
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
if x1 == x2 or y1 == y2:
|
||||
counts_1[list(y_rng), list(x_rng)] += 1
|
||||
counts_2[list(y_rng), list(x_rng)] += 1
|
||||
elif abs(x2 - x1) == abs(y2 - y1):
|
||||
for i, j in zip(y_rng, x_rng):
|
||||
counts_2[i, j] += 1
|
||||
|
||||
yield (counts_1 >= 2).sum()
|
||||
yield (counts_2 >= 2).sum()
|
||||
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
|
||||
lanterns = {day: 0 for day in range(days)}
|
||||
for value in values:
|
||||
for day in range(value, days, 7):
|
||||
lanterns[day] += 1
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
values = [int(c) for c in input.split(",")]
|
||||
for day in range(days):
|
||||
for day2 in range(day + 9, days, 7):
|
||||
lanterns[day2] += lanterns[day]
|
||||
|
||||
days = 256
|
||||
lanterns = {day: 0 for day in range(days)}
|
||||
for value in values:
|
||||
for day in range(value, days, 7):
|
||||
lanterns[day] += 1
|
||||
# part 1
|
||||
answer_1 = sum(v for k, v in lanterns.items() if k < 80) + len(values)
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
for day in range(days):
|
||||
for day2 in range(day + 9, days, 7):
|
||||
lanterns[day2] += lanterns[day]
|
||||
|
||||
yield sum(v for k, v in lanterns.items() if k < 80) + len(values)
|
||||
yield sum(lanterns.values()) + len(values)
|
||||
# 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):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
positions = [int(c) for c in input.split(",")]
|
||||
# part 1
|
||||
answer_1 = min(
|
||||
sum(abs(p - position) for p in positions)
|
||||
for position in range(min_position, max_position + 1)
|
||||
)
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
min_position, max_position = min(positions), max(positions)
|
||||
|
||||
# part 1
|
||||
yield min(
|
||||
sum(abs(p - position) for p in positions)
|
||||
for position in range(min_position, max_position + 1)
|
||||
)
|
||||
|
||||
# part 2
|
||||
yield min(
|
||||
sum(abs(p - position) * (abs(p - position) + 1) // 2 for p in positions)
|
||||
for position in range(min_position, max_position + 1)
|
||||
)
|
||||
# part 2
|
||||
answer_2 = min(
|
||||
sum(abs(p - position) * (abs(p - position) + 1) // 2 for p in positions)
|
||||
for position in range(min_position, max_position + 1)
|
||||
)
|
||||
print(f"answer 2 is {answer_2}")
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import itertools
|
||||
from typing import Any, Iterator
|
||||
import os
|
||||
import sys
|
||||
|
||||
from ..base import BaseSolver
|
||||
VERBOSE = os.getenv("AOC_VERBOSE") == "True"
|
||||
|
||||
digits = {
|
||||
"abcefg": 0,
|
||||
@@ -16,74 +17,71 @@ digits = {
|
||||
"abcdfg": 9,
|
||||
}
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = input.splitlines()
|
||||
# part 1
|
||||
lengths = {len(k) for k, v in digits.items() if v in (1, 4, 7, 8)}
|
||||
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
|
||||
lengths = {len(k) for k, v in digits.items() if v in (1, 4, 7, 8)}
|
||||
yield sum(
|
||||
len(p) in lengths
|
||||
for line in lines
|
||||
for p in line.split("|")[1].strip().split()
|
||||
)
|
||||
# part 2
|
||||
values: list[int] = []
|
||||
|
||||
# part 2
|
||||
values: list[int] = []
|
||||
for line in lines:
|
||||
parts = line.split("|")
|
||||
broken_digits = sorted(parts[0].strip().split(), key=len)
|
||||
|
||||
for line in lines:
|
||||
parts = line.split("|")
|
||||
broken_digits = sorted(parts[0].strip().split(), key=len)
|
||||
per_length = {
|
||||
k: list(v)
|
||||
for k, v in itertools.groupby(sorted(broken_digits, key=len), key=len)
|
||||
}
|
||||
|
||||
per_length = {
|
||||
k: list(v)
|
||||
for k, v in itertools.groupby(sorted(broken_digits, key=len), key=len)
|
||||
}
|
||||
# a can be found immediately
|
||||
a = next(u for u in per_length[3][0] if u not in per_length[2][0])
|
||||
|
||||
# a can be found immediately
|
||||
a = next(u for u in per_length[3][0] if u not in per_length[2][0])
|
||||
# c and f have only two possible values corresponding to the single entry of
|
||||
# length 2
|
||||
cf = list(per_length[2][0])
|
||||
|
||||
# c and f have only two possible values corresponding to the single entry of
|
||||
# length 2
|
||||
cf = list(per_length[2][0])
|
||||
# the only digit of length 4 contains bcdf, so we can deduce bd by removing cf
|
||||
bd = [u for u in per_length[4][0] if u not in cf]
|
||||
|
||||
# the only digit of length 4 contains bcdf, so we can deduce bd by removing 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
|
||||
adg = [u for u in per_length[5][0] if all(u in pe for pe in per_length[5][1:])]
|
||||
|
||||
# the 3 digits of length 5 have a, d and g in common
|
||||
adg = [
|
||||
u for u in per_length[5][0] if all(u in pe for pe in per_length[5][1:])
|
||||
]
|
||||
# we can remove a
|
||||
dg = [u for u in adg if u != a]
|
||||
|
||||
# we can remove a
|
||||
dg = [u for u in adg if u != a]
|
||||
# we can deduce d and g
|
||||
d = next(u for u in dg if u in bd)
|
||||
g = next(u for u in dg if u != d)
|
||||
|
||||
# we can deduce d and g
|
||||
d = next(u for u in dg if u in bd)
|
||||
g = next(u for u in dg if u != d)
|
||||
# then b
|
||||
b = next(u for u in bd if u != d)
|
||||
|
||||
# then b
|
||||
b = next(u for u in bd if u != d)
|
||||
# f is in the three 6-length digits, while c is only in 2
|
||||
f = next(u for u in cf if all(u in p for p in per_length[6]))
|
||||
|
||||
# f is in the three 6-length digits, while c is only in 2
|
||||
f = next(u for u in cf if all(u in p for p in per_length[6]))
|
||||
# c is not f
|
||||
c = next(u for u in cf if u != f)
|
||||
|
||||
# c is not f
|
||||
c = next(u for u in cf if u != f)
|
||||
# e is the last one
|
||||
e = next(u for u in "abcdefg" if u not in {a, b, c, d, f, g})
|
||||
|
||||
# e is the last one
|
||||
e = next(u for u in "abcdefg" if u not in {a, b, c, d, f, g})
|
||||
mapping = dict(zip((a, b, c, d, e, f, g), "abcdefg"))
|
||||
|
||||
mapping = dict(zip((a, b, c, d, e, f, g), "abcdefg"))
|
||||
value = 0
|
||||
for number in parts[1].strip().split():
|
||||
digit = "".join(sorted(mapping[c] for c in number))
|
||||
value = 10 * value + digits[digit]
|
||||
|
||||
value = 0
|
||||
for number in parts[1].strip().split():
|
||||
digit = "".join(sorted(mapping[c] for c in number))
|
||||
value = 10 * value + digits[digit]
|
||||
if VERBOSE:
|
||||
print(value)
|
||||
|
||||
self.logger.info(f"value for '{line}' is {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 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
|
||||
for di, dj in ((-1, 0), (+1, 0), (0, -1), (0, +1)):
|
||||
if 0 <= i + di < n_rows and 0 <= j + dj < n_cols:
|
||||
yield (i + di, j + dj)
|
||||
|
||||
|
||||
def basin(values: list[list[int]], start: tuple[int, int]) -> set[tuple[int, int]]:
|
||||
n_rows, n_cols = len(values), len(values[0])
|
||||
def basin(start: tuple[int, int]) -> set[tuple[int, int]]:
|
||||
visited: set[tuple[int, int]] = set()
|
||||
queue = [start]
|
||||
|
||||
@@ -23,25 +23,22 @@ def basin(values: list[list[int]], start: tuple[int, int]) -> set[tuple[int, int
|
||||
continue
|
||||
|
||||
visited.add((i, j))
|
||||
queue.extend(neighbors((i, j), n_rows, n_cols))
|
||||
queue.extend(neighbors((i, j)))
|
||||
|
||||
return visited
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
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)
|
||||
for i in range(n_rows)
|
||||
for j in range(n_cols)
|
||||
if all(values[ti][tj] > values[i][j] for ti, tj in neighbors((i, j)))
|
||||
]
|
||||
|
||||
low_points = [
|
||||
(i, j)
|
||||
for i in range(n_rows)
|
||||
for j in range(n_cols)
|
||||
if all(
|
||||
values[ti][tj] > values[i][j]
|
||||
for ti, tj in neighbors((i, j), n_rows, n_cols)
|
||||
)
|
||||
]
|
||||
# part 1
|
||||
answer_1 = sum(values[i][j] + 1 for i, j in low_points)
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
yield sum(values[i][j] + 1 for i, j in low_points)
|
||||
yield prod(sorted(len(basin(values, point)) for point in low_points)[-3:])
|
||||
# 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)
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
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:])
|
||||
print(f"answer 1 is {values[-1]}")
|
||||
print(f"answer 2 is {sum(values[-3:])}")
|
||||
|
||||
@@ -1,43 +1,38 @@
|
||||
from typing import Any, Iterator
|
||||
import sys
|
||||
|
||||
from ..base import BaseSolver
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
cycle = 1
|
||||
x = 1
|
||||
|
||||
values = {cycle: x}
|
||||
|
||||
for line in lines:
|
||||
cycle += 1
|
||||
|
||||
if line == "noop":
|
||||
pass
|
||||
else:
|
||||
r = int(line.split()[1])
|
||||
|
||||
values[cycle] = x
|
||||
|
||||
cycle += 1
|
||||
x += r
|
||||
|
||||
values[cycle] = x
|
||||
|
||||
answer_1 = sum(c * values[c] for c in range(20, max(values.keys()) + 1, 40))
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = [line.strip() for line in input.splitlines()]
|
||||
for i in range(6):
|
||||
for j in range(40):
|
||||
v = values[1 + i * 40 + j]
|
||||
|
||||
cycle, x = 1, 1
|
||||
values = {cycle: x}
|
||||
if j >= v - 1 and j <= v + 1:
|
||||
print("#", end="")
|
||||
else:
|
||||
print(".", end="")
|
||||
|
||||
for line in lines:
|
||||
cycle += 1
|
||||
|
||||
if line == "noop":
|
||||
pass
|
||||
else:
|
||||
r = int(line.split()[1])
|
||||
|
||||
values[cycle] = x
|
||||
|
||||
cycle += 1
|
||||
x += r
|
||||
|
||||
values[cycle] = x
|
||||
|
||||
answer_1 = sum(c * values[c] for c in range(20, max(values.keys()) + 1, 40))
|
||||
yield answer_1
|
||||
|
||||
yield (
|
||||
"\n"
|
||||
+ "\n".join(
|
||||
"".join(
|
||||
"#"
|
||||
if j >= (v := values[1 + i * 40 + j]) - 1 and j <= v + 1
|
||||
else "."
|
||||
for j in range(40)
|
||||
)
|
||||
for i in range(6)
|
||||
)
|
||||
+ "\n"
|
||||
)
|
||||
print()
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import copy
|
||||
import sys
|
||||
from functools import reduce
|
||||
from typing import Any, Callable, Final, Iterator, Mapping, Sequence
|
||||
|
||||
from ..base import BaseSolver
|
||||
from typing import Callable, Final, Mapping, Sequence
|
||||
|
||||
|
||||
class Monkey:
|
||||
@@ -120,28 +119,24 @@ def monkey_business(inspects: dict[Monkey, int]) -> int:
|
||||
return sorted_levels[-2] * sorted_levels[-1]
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
monkeys = [parse_monkey(block.splitlines()) for block in input.split("\n\n")]
|
||||
monkeys = [parse_monkey(block.splitlines()) for block in sys.stdin.read().split("\n\n")]
|
||||
|
||||
# case 1: we simply divide the worry by 3 after applying the monkey worry operation
|
||||
yield monkey_business(
|
||||
run(copy.deepcopy(monkeys), 20, me_worry_fn=lambda w: w // 3)
|
||||
)
|
||||
# case 1: we simply divide the worry by 3 after applying the monkey worry operation
|
||||
answer_1 = monkey_business(
|
||||
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
|
||||
# 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 % d) + (b % d)) % c --- if d is a multiple of c, which is why here
|
||||
# we use the product of all test value
|
||||
#
|
||||
total_test_value = reduce(lambda w, m: w * m.test_value, monkeys, 1)
|
||||
yield monkey_business(
|
||||
run(
|
||||
copy.deepcopy(monkeys),
|
||||
10_000,
|
||||
me_worry_fn=lambda w: w % total_test_value,
|
||||
)
|
||||
)
|
||||
# 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
|
||||
#
|
||||
# (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
|
||||
# we use the product of all test value
|
||||
#
|
||||
total_test_value = reduce(lambda w, m: w * m.test_value, monkeys, 1)
|
||||
answer_2 = monkey_business(
|
||||
run(copy.deepcopy(monkeys), 10_000, me_worry_fn=lambda w: w % total_test_value)
|
||||
)
|
||||
print(f"answer 2 is {answer_2}")
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import heapq
|
||||
from typing import Any, Callable, Iterator, TypeVar
|
||||
|
||||
from ..base import BaseSolver
|
||||
import sys
|
||||
from typing import Callable, Iterator, TypeVar
|
||||
|
||||
Node = TypeVar("Node")
|
||||
|
||||
@@ -69,6 +68,30 @@ def make_path(parents: dict[Node, Node], start: Node, end: Node) -> list[Node] |
|
||||
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(
|
||||
grid: list[list[int]], node: tuple[int, int], up: bool
|
||||
) -> Iterator[tuple[int, int]]:
|
||||
@@ -95,82 +118,46 @@ def neighbors(
|
||||
|
||||
# === main code ===
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def print_path(
|
||||
self, name: str, path: list[tuple[int, int]], n_rows: int, n_cols: int
|
||||
) -> None:
|
||||
if not self.files:
|
||||
return
|
||||
grid = [[ord(cell) - ord("a") for cell in line] for line in lines]
|
||||
|
||||
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)]
|
||||
graph[end[0]][end[1]] = "E"
|
||||
# for part 2
|
||||
start_s: list[tuple[int, int]] = []
|
||||
|
||||
for i in range(0, len(path) - 1):
|
||||
cr, cc = path[i]
|
||||
nr, nc = path[i + 1]
|
||||
for i_row, row in enumerate(grid):
|
||||
for i_col, col in enumerate(row):
|
||||
if chr(col + ord("a")) == "S":
|
||||
start = (i_row, i_col)
|
||||
start_s.append(start)
|
||||
elif chr(col + ord("a")) == "E":
|
||||
end = (i_row, i_col)
|
||||
elif col == 0:
|
||||
start_s.append((i_row, i_col))
|
||||
|
||||
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])
|
||||
assert start is not None
|
||||
assert end is not None
|
||||
|
||||
self.files.create(
|
||||
f"graph_{name}.txt",
|
||||
"\n".join("".join(row) for row in graph).encode(),
|
||||
text=True,
|
||||
)
|
||||
# fix values
|
||||
grid[start[0]][start[1]] = 0
|
||||
grid[end[0]][end[1]] = ord("z") - ord("a")
|
||||
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = input.splitlines()
|
||||
|
||||
grid = [[ord(cell) - ord("a") for cell in line] for line in lines]
|
||||
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
|
||||
|
||||
start: tuple[int, int] | None = None
|
||||
end: tuple[int, int] | None = None
|
||||
print_path(path_1, n_rows=len(grid), n_cols=len(grid[0]))
|
||||
|
||||
# for part 2
|
||||
start_s: list[tuple[int, int]] = []
|
||||
print(f"answer 1 is {lengths_1[end] - 1}")
|
||||
|
||||
for i_row, row in enumerate(grid):
|
||||
for i_col, col in enumerate(row):
|
||||
if chr(col + ord("a")) == "S":
|
||||
start = (i_row, i_col)
|
||||
start_s.append(start)
|
||||
elif chr(col + ord("a")) == "E":
|
||||
end = (i_row, i_col)
|
||||
elif col == 0:
|
||||
start_s.append((i_row, i_col))
|
||||
|
||||
assert start is not None
|
||||
assert end is not None
|
||||
|
||||
# fix values
|
||||
grid[start[0]][start[1]] = 0
|
||||
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]))
|
||||
yield lengths_1[end] - 1
|
||||
|
||||
lengths_2, _ = dijkstra(
|
||||
start=end,
|
||||
neighbors=lambda n: neighbors(grid, n, False),
|
||||
cost=lambda lhs, rhs: 1,
|
||||
)
|
||||
yield min(lengths_2.get(start, float("inf")) for start in start_s)
|
||||
lengths_2, parents_2 = dijkstra(
|
||||
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 sys
|
||||
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"]]
|
||||
|
||||
@@ -25,18 +28,14 @@ def compare(lhs: Packet, rhs: Packet) -> int:
|
||||
return len(rhs) - len(lhs)
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
blocks = input.split("\n\n")
|
||||
pairs = [tuple(json.loads(p) for p in block.split("\n")) for block in blocks]
|
||||
answer_1 = sum(i + 1 for i, (lhs, rhs) in enumerate(pairs) if compare(lhs, rhs) > 0)
|
||||
print(f"answer_1 is {answer_1}")
|
||||
|
||||
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]
|
||||
packets.extend(dividers)
|
||||
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]
|
||||
d_index = [packets.index(d) + 1 for d in dividers]
|
||||
print(f"answer 2 is {d_index[0] * d_index[1]}")
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import sys
|
||||
from enum import Enum, auto
|
||||
from typing import Any, Callable, Iterator, cast
|
||||
|
||||
from ..base import BaseSolver
|
||||
from typing import Callable, cast
|
||||
|
||||
|
||||
class Cell(Enum):
|
||||
@@ -13,6 +12,26 @@ class Cell(Enum):
|
||||
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(
|
||||
blocks: dict[tuple[int, int], Cell],
|
||||
stop_fn: Callable[[int, int], bool],
|
||||
@@ -65,82 +84,57 @@ def flow(
|
||||
|
||||
# === inputs ===
|
||||
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def print_blocks(self, name: str, blocks: dict[tuple[int, int], Cell]):
|
||||
"""
|
||||
Print the given set of blocks on a grid.
|
||||
paths: list[list[tuple[int, int]]] = []
|
||||
for line in lines:
|
||||
parts = line.split(" -> ")
|
||||
paths.append(
|
||||
[
|
||||
cast(tuple[int, int], tuple(int(c.strip()) for c in part.split(",")))
|
||||
for part in parts
|
||||
]
|
||||
)
|
||||
|
||||
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),
|
||||
)
|
||||
blocks: dict[tuple[int, int], Cell] = {}
|
||||
for path in paths:
|
||||
for start, end in zip(path[:-1], path[1:]):
|
||||
x_start = min(start[0], end[0])
|
||||
x_end = max(start[0], end[0]) + 1
|
||||
y_start = min(start[1], end[1])
|
||||
y_end = max(start[1], end[1]) + 1
|
||||
|
||||
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,
|
||||
)
|
||||
for x in range(x_start, x_end):
|
||||
for y in range(y_start, y_end):
|
||||
blocks[x, y] = Cell.ROCK
|
||||
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = [line.strip() for line in input.splitlines()]
|
||||
print_blocks(blocks)
|
||||
print()
|
||||
|
||||
paths: list[list[tuple[int, int]]] = []
|
||||
for line in lines:
|
||||
parts = line.split(" -> ")
|
||||
paths.append(
|
||||
[
|
||||
cast(
|
||||
tuple[int, int], tuple(int(c.strip()) for c in part.split(","))
|
||||
)
|
||||
for part in parts
|
||||
]
|
||||
)
|
||||
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),
|
||||
)
|
||||
|
||||
blocks: dict[tuple[int, int], Cell] = {}
|
||||
for path in paths:
|
||||
for start, end in zip(path[:-1], path[1:]):
|
||||
x_start = min(start[0], end[0])
|
||||
x_end = max(start[0], end[0]) + 1
|
||||
y_start = min(start[1], end[1])
|
||||
y_end = max(start[1], end[1]) + 1
|
||||
# === part 1 ===
|
||||
|
||||
for x in range(x_start, x_end):
|
||||
for y in range(y_start, y_end):
|
||||
blocks[x, y] = Cell.ROCK
|
||||
blocks_1 = flow(
|
||||
blocks.copy(), stop_fn=lambda x, y: y > y_max, fill_fn=lambda x, y: Cell.AIR
|
||||
)
|
||||
print_blocks(blocks_1)
|
||||
print(f"answer 1 is {sum(v == Cell.SAND for v in blocks_1.values())}")
|
||||
print()
|
||||
|
||||
self.print_blocks("start", blocks)
|
||||
# === part 2 ===
|
||||
|
||||
y_max = max(y for _, y in blocks)
|
||||
|
||||
# === part 1 ===
|
||||
|
||||
blocks_1 = flow(
|
||||
blocks.copy(), stop_fn=lambda x, y: y > y_max, fill_fn=lambda x, y: Cell.AIR
|
||||
)
|
||||
self.print_blocks("part1", blocks_1)
|
||||
yield sum(v == Cell.SAND for v in blocks_1.values())
|
||||
|
||||
# === part 2 ===
|
||||
|
||||
blocks_2 = flow(
|
||||
blocks.copy(),
|
||||
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,
|
||||
)
|
||||
blocks_2[500, 0] = Cell.SAND
|
||||
self.print_blocks("part2", blocks_2)
|
||||
yield sum(v == Cell.SAND for v in blocks_2.values())
|
||||
blocks_2 = flow(
|
||||
blocks.copy(),
|
||||
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,
|
||||
)
|
||||
blocks_2[500, 0] = Cell.SAND
|
||||
print_blocks(blocks_2)
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
@@ -60,9 +62,8 @@ class Solver(BaseSolver):
|
||||
for (sx, sy), (bx, by) in sensor_to_beacon.items():
|
||||
d = abs(sx - bx) + abs(sy - by)
|
||||
m.add_constraint(
|
||||
m.abs(x - sx) + m.abs(y - sy) >= d + 1, # type: ignore
|
||||
ctname=f"ct_{sx}_{sy}",
|
||||
)
|
||||
m.abs(x - sx) + m.abs(y - sy) >= d + 1, ctname=f"ct_{sx}_{sy}"
|
||||
) # type: ignore
|
||||
|
||||
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 = 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
|
||||
|
||||
@@ -3,10 +3,11 @@ from __future__ import annotations
|
||||
import heapq
|
||||
import itertools
|
||||
import re
|
||||
import sys
|
||||
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):
|
||||
@@ -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)
|
||||
to all other pipes.
|
||||
"""
|
||||
queue = [(0, pipe)]
|
||||
visited: set[Pipe] = set()
|
||||
queue = [(0, pipe_1)]
|
||||
visited = set()
|
||||
distances: dict[Pipe, int] = {}
|
||||
|
||||
while len(distances) < len(pipes):
|
||||
@@ -60,100 +61,98 @@ def update_with_better(
|
||||
node_at_times[flowing] = max(node_at_times[flowing], flow)
|
||||
|
||||
|
||||
def part_1(
|
||||
start_pipe: Pipe,
|
||||
max_time: int,
|
||||
distances: dict[tuple[Pipe, Pipe], int],
|
||||
relevant_pipes: FrozenSet[Pipe],
|
||||
):
|
||||
node_at_times: dict[int, dict[Pipe, dict[FrozenSet[Pipe], int]]] = defaultdict(
|
||||
lambda: defaultdict(lambda: defaultdict(lambda: 0))
|
||||
)
|
||||
node_at_times[0] = {start_pipe: {frozenset(): 0}}
|
||||
|
||||
for time in range(max_time):
|
||||
for c_pipe, nodes in node_at_times[time].items():
|
||||
for flowing, flow in nodes.items():
|
||||
for target in relevant_pipes:
|
||||
distance = distances[c_pipe, target] + 1
|
||||
if time + distance >= max_time or target in flowing:
|
||||
continue
|
||||
|
||||
update_with_better(
|
||||
node_at_times[time + distance][target],
|
||||
flow + sum(pipe.flow for pipe in flowing) * distance,
|
||||
flowing | {target},
|
||||
)
|
||||
|
||||
update_with_better(
|
||||
node_at_times[max_time][c_pipe],
|
||||
flow + sum(pipe.flow for pipe in flowing) * (max_time - time),
|
||||
flowing,
|
||||
)
|
||||
|
||||
return max(
|
||||
flow
|
||||
for nodes_of_pipe in node_at_times[max_time].values()
|
||||
for flow in nodes_of_pipe.values()
|
||||
)
|
||||
|
||||
|
||||
def part_2(
|
||||
start_pipe: Pipe,
|
||||
max_time: int,
|
||||
distances: dict[tuple[Pipe, Pipe], int],
|
||||
relevant_pipes: FrozenSet[Pipe],
|
||||
):
|
||||
def compute(pipes_for_me: FrozenSet[Pipe]) -> int:
|
||||
return part_1(start_pipe, max_time, distances, pipes_for_me) + part_1(
|
||||
start_pipe, max_time, distances, relevant_pipes - pipes_for_me
|
||||
)
|
||||
|
||||
combs = [
|
||||
frozenset(relevant_pipes_1)
|
||||
for r in range(2, len(relevant_pipes) // 2 + 1)
|
||||
for relevant_pipes_1 in itertools.combinations(relevant_pipes, r)
|
||||
]
|
||||
|
||||
return max(compute(comb) for comb in tqdm(combs))
|
||||
|
||||
|
||||
# === MAIN ===
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def part_1(
|
||||
self,
|
||||
start_pipe: Pipe,
|
||||
max_time: int,
|
||||
distances: dict[tuple[Pipe, Pipe], int],
|
||||
relevant_pipes: FrozenSet[Pipe],
|
||||
):
|
||||
node_at_times: dict[int, dict[Pipe, dict[FrozenSet[Pipe], int]]] = defaultdict(
|
||||
lambda: defaultdict(lambda: defaultdict(lambda: 0))
|
||||
)
|
||||
node_at_times[0] = {start_pipe: {frozenset(): 0}}
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
for time in range(max_time):
|
||||
for c_pipe, nodes in node_at_times[time].items():
|
||||
for flowing, flow in nodes.items():
|
||||
for target in relevant_pipes:
|
||||
distance = distances[c_pipe, target] + 1
|
||||
if time + distance >= max_time or target in flowing:
|
||||
continue
|
||||
|
||||
update_with_better(
|
||||
node_at_times[time + distance][target],
|
||||
flow + sum(pipe.flow for pipe in flowing) * distance,
|
||||
flowing | {target},
|
||||
)
|
||||
pipes: dict[str, Pipe] = {}
|
||||
for line in lines:
|
||||
r = re.match(
|
||||
R"Valve ([A-Z]+) has flow rate=([0-9]+); tunnels? leads? to valves? (.+)",
|
||||
line,
|
||||
)
|
||||
assert r
|
||||
|
||||
update_with_better(
|
||||
node_at_times[max_time][c_pipe],
|
||||
flow + sum(pipe.flow for pipe in flowing) * (max_time - time),
|
||||
flowing,
|
||||
)
|
||||
g = r.groups()
|
||||
|
||||
return max(
|
||||
flow
|
||||
for nodes_of_pipe in node_at_times[max_time].values()
|
||||
for flow in nodes_of_pipe.values()
|
||||
)
|
||||
pipes[g[0]] = Pipe(g[0], int(g[1]), g[2].split(", "))
|
||||
|
||||
def part_2(
|
||||
self,
|
||||
start_pipe: Pipe,
|
||||
max_time: int,
|
||||
distances: dict[tuple[Pipe, Pipe], int],
|
||||
relevant_pipes: FrozenSet[Pipe],
|
||||
):
|
||||
def compute(pipes_for_me: FrozenSet[Pipe]) -> int:
|
||||
return self.part_1(
|
||||
start_pipe, max_time, distances, pipes_for_me
|
||||
) + self.part_1(
|
||||
start_pipe, max_time, distances, relevant_pipes - pipes_for_me
|
||||
)
|
||||
# compute distances from one valve to any other
|
||||
distances: dict[tuple[Pipe, Pipe], int] = {}
|
||||
for pipe_1 in pipes.values():
|
||||
distances.update(
|
||||
{
|
||||
(pipe_1, pipe_2): distance
|
||||
for pipe_2, distance in breadth_first_search(pipes, pipe_1).items()
|
||||
}
|
||||
)
|
||||
|
||||
combs = [
|
||||
frozenset(relevant_pipes_1)
|
||||
for r in range(2, len(relevant_pipes) // 2 + 1)
|
||||
for relevant_pipes_1 in itertools.combinations(relevant_pipes, r)
|
||||
]
|
||||
# valves with flow
|
||||
relevant_pipes = frozenset(pipe for pipe in pipes.values() if pipe.flow > 0)
|
||||
|
||||
return max(compute(comb) for comb in self.progress.wrap(combs))
|
||||
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = [line.strip() for line in input.splitlines()]
|
||||
# 1651, 1653
|
||||
print(part_1(pipes["AA"], 30, distances, relevant_pipes))
|
||||
|
||||
pipes: dict[str, Pipe] = {}
|
||||
for line in lines:
|
||||
r = re.match(
|
||||
R"Valve ([A-Z]+) has flow rate=([0-9]+); tunnels? leads? to valves? (.+)",
|
||||
line,
|
||||
)
|
||||
assert r
|
||||
|
||||
g = r.groups()
|
||||
|
||||
pipes[g[0]] = Pipe(g[0], int(g[1]), g[2].split(", "))
|
||||
|
||||
# compute distances from one valve to any other
|
||||
distances: dict[tuple[Pipe, Pipe], int] = {}
|
||||
for pipe_1 in pipes.values():
|
||||
distances.update(
|
||||
{
|
||||
(pipe_1, pipe_2): distance
|
||||
for pipe_2, distance in breadth_first_search(pipes, pipe_1).items()
|
||||
}
|
||||
)
|
||||
|
||||
# valves with flow
|
||||
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
|
||||
yield self.part_2(pipes["AA"], 26, 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
|
||||
from numpy.typing import NDArray
|
||||
|
||||
from ..base import BaseSolver
|
||||
|
||||
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)
|
||||
|
||||
|
||||
@@ -38,8 +45,8 @@ def build_tower(
|
||||
n_rocks: int,
|
||||
jets: str,
|
||||
early_stop: bool = False,
|
||||
init: Tower = np.ones(WIDTH, dtype=bool),
|
||||
) -> tuple[Tower, int, int, dict[int, int]]:
|
||||
init: np.ndarray = np.ones(WIDTH, dtype=bool),
|
||||
) -> tuple[np.ndarray, int, int, dict[int, int]]:
|
||||
tower = EMPTY_BLOCKS.copy()
|
||||
tower[0, :] = init
|
||||
|
||||
@@ -88,24 +95,26 @@ def build_tower(
|
||||
return tower, rock_count, done_at.get((i_rock, i_jet), -1), heights
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
tower, *_ = build_tower(2022, input)
|
||||
yield tower_height(tower)
|
||||
line = sys.stdin.read().strip()
|
||||
|
||||
TOTAL_ROCKS = 1_000_000_000_000
|
||||
_tower_1, n_rocks_1, prev_1, heights_1 = build_tower(TOTAL_ROCKS, input, True)
|
||||
assert prev_1 > 0
|
||||
tower, *_ = build_tower(2022, line)
|
||||
answer_1 = tower_height(tower)
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
# 2767 1513
|
||||
remaining_rocks = TOTAL_ROCKS - n_rocks_1
|
||||
n_repeat_rocks = n_rocks_1 - prev_1
|
||||
n_repeat_towers = remaining_rocks // n_repeat_rocks
|
||||
TOTAL_ROCKS = 1_000_000_000_000
|
||||
tower_1, n_rocks_1, prev_1, heights_1 = build_tower(TOTAL_ROCKS, line, True)
|
||||
assert prev_1 > 0
|
||||
|
||||
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]
|
||||
)
|
||||
# 2767 1513
|
||||
remaining_rocks = TOTAL_ROCKS - n_rocks_1
|
||||
n_repeat_rocks = n_rocks_1 - prev_1
|
||||
n_repeat_towers = remaining_rocks // n_repeat_rocks
|
||||
|
||||
yield base_height + (n_repeat_towers + 1) * repeat_height + remaining_height
|
||||
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]
|
||||
)
|
||||
|
||||
answer_2 = base_height + (n_repeat_towers + 1) * repeat_height + remaining_height
|
||||
print(f"answer 2 is {answer_2}")
|
||||
|
||||
@@ -1,58 +1,50 @@
|
||||
from typing import Any, Iterator
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
|
||||
from ..base import BaseSolver
|
||||
xyz = np.asarray(
|
||||
[
|
||||
tuple(int(x) for x in row.split(",")) # type: ignore
|
||||
for row in sys.stdin.read().splitlines()
|
||||
]
|
||||
)
|
||||
|
||||
xyz = xyz - xyz.min(axis=0) + 1
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
xyz = np.asarray(
|
||||
[
|
||||
tuple(int(x) for x in row.split(",")) # type: ignore
|
||||
for row in input.splitlines()
|
||||
]
|
||||
)
|
||||
cubes = np.zeros(xyz.max(axis=0) + 3, dtype=bool)
|
||||
cubes[xyz[:, 0], xyz[:, 1], xyz[:, 2]] = True
|
||||
|
||||
xyz = xyz - xyz.min(axis=0) + 1
|
||||
n_dims = len(cubes.shape)
|
||||
|
||||
cubes = np.zeros(xyz.max(axis=0) + 3, dtype=bool)
|
||||
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)]
|
||||
|
||||
faces = [(-1, 0, 0), (1, 0, 0), (0, -1, 0), (0, 1, 0), (0, 0, -1), (0, 0, 1)]
|
||||
answer_1 = sum(
|
||||
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}")
|
||||
|
||||
yield sum(
|
||||
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)
|
||||
queue = [(0, 0, 0)]
|
||||
|
||||
visited = np.zeros_like(cubes, dtype=bool)
|
||||
queue = [(0, 0, 0)]
|
||||
n_faces = 0
|
||||
while queue:
|
||||
x, y, z = queue.pop(0)
|
||||
|
||||
n_faces = 0
|
||||
while queue:
|
||||
x, y, z = queue.pop(0)
|
||||
if visited[x, y, z]:
|
||||
continue
|
||||
|
||||
if visited[x, y, z]:
|
||||
continue
|
||||
visited[x, y, z] = True
|
||||
|
||||
visited[x, y, z] = True
|
||||
for dx, dy, dz in faces:
|
||||
nx, ny, nz = x + dx, y + dy, z + dz
|
||||
if not all(n >= 0 and n < cubes.shape[i] for i, n in enumerate((nx, ny, nz))):
|
||||
continue
|
||||
|
||||
for dx, dy, dz in faces:
|
||||
nx, ny, nz = x + dx, y + dy, z + dz
|
||||
if not all(
|
||||
n >= 0 and n < cubes.shape[i] for i, n in enumerate((nx, ny, nz))
|
||||
):
|
||||
continue
|
||||
if visited[nx, ny, nz]:
|
||||
continue
|
||||
|
||||
if visited[nx, ny, nz]:
|
||||
continue
|
||||
|
||||
if cubes[nx, ny, nz]:
|
||||
n_faces += 1
|
||||
else:
|
||||
queue.append((nx, ny, nz))
|
||||
|
||||
yield n_faces
|
||||
if cubes[nx, ny, nz]:
|
||||
n_faces += 1
|
||||
else:
|
||||
queue.append((nx, ny, nz))
|
||||
print(f"answer 2 is {n_faces}")
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
from typing import Any, Iterator, Literal
|
||||
import sys
|
||||
from typing import Any, Literal
|
||||
|
||||
import numpy as np
|
||||
import parse # pyright: ignore[reportMissingTypeStubs]
|
||||
from numpy.typing import NDArray
|
||||
|
||||
from ..base import BaseSolver
|
||||
|
||||
Reagent = Literal["ore", "clay", "obsidian", "geode"]
|
||||
REAGENTS: tuple[Reagent, ...] = (
|
||||
"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:
|
||||
# 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.,
|
||||
@@ -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])
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
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,
|
||||
)
|
||||
answer_1 = sum(
|
||||
(i_blueprint + 1) * run(blueprint, 24)
|
||||
for i_blueprint, blueprint in enumerate(blueprints)
|
||||
)
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
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)
|
||||
for i_blueprint, blueprint in enumerate(blueprints)
|
||||
)
|
||||
|
||||
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
|
||||
|
||||
from ..base import BaseSolver
|
||||
import sys
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = input.splitlines()
|
||||
lines = sys.stdin.readlines()
|
||||
|
||||
# the solution relies on replacing rock / paper / scissor by values 0 / 1 / 2 and using
|
||||
# modulo-3 arithmetic
|
||||
#
|
||||
# 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)))
|
||||
#
|
||||
# the solution relies on replacing rock / paper / scissor by values 0 / 1 / 2 and using
|
||||
# modulo-3 arithmetic
|
||||
#
|
||||
# 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)))
|
||||
#
|
||||
|
||||
# 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
|
||||
values = [(ord(row[0]) - ord("A"), ord(row[2]) - ord("X")) for row in lines]
|
||||
# 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
|
||||
values = [(ord(row[0]) - ord("A"), ord(row[2]) - ord("X")) for row in lines]
|
||||
|
||||
# part 1 - 13526
|
||||
yield sum(score_1(*v) for v in values)
|
||||
# part 1 - 13526
|
||||
print(f"answer 1 is {sum(score_1(*v) for v in values)}")
|
||||
|
||||
# part 2 - 14204
|
||||
yield sum(score_2(*v) for v in values)
|
||||
# part 2 - 14204
|
||||
print(f"answer 2 is {sum(score_2(*v) for v in values)}")
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Iterator
|
||||
|
||||
from ..base import BaseSolver
|
||||
import sys
|
||||
|
||||
|
||||
class Number:
|
||||
@@ -67,9 +65,10 @@ def decrypt(numbers: list[Number], key: int, rounds: int) -> int:
|
||||
)
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
numbers = [Number(int(x)) for x in input.splitlines()]
|
||||
numbers = [Number(int(x)) for i, x in enumerate(sys.stdin.readlines())]
|
||||
|
||||
yield decrypt(numbers, 1, 1)
|
||||
yield decrypt(numbers, 811589153, 10)
|
||||
answer_1 = decrypt(numbers, 1, 1)
|
||||
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
|
||||
from typing import Any, Callable, Iterator
|
||||
|
||||
from ..base import BaseSolver
|
||||
import sys
|
||||
from typing import Callable
|
||||
|
||||
|
||||
def compute(monkeys: dict[str, int | tuple[str, str, str]], monkey: str) -> int:
|
||||
@@ -78,31 +77,31 @@ def invert(
|
||||
return monkeys
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = [line.strip() for line in input.splitlines()]
|
||||
lines = sys.stdin.read().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:
|
||||
parts = line.split(":")
|
||||
name = parts[0].strip()
|
||||
for line in lines:
|
||||
parts = line.split(":")
|
||||
name = parts[0].strip()
|
||||
|
||||
try:
|
||||
value = int(parts[1].strip())
|
||||
monkeys[name] = value
|
||||
except ValueError:
|
||||
op1, ope, op2 = parts[1].strip().split()
|
||||
monkeys[name] = (op1, ope, op2)
|
||||
try:
|
||||
value = int(parts[1].strip())
|
||||
monkeys[name] = value
|
||||
except ValueError:
|
||||
op1, ope, op2 = parts[1].strip().split()
|
||||
monkeys[name] = (op1, ope, op2)
|
||||
|
||||
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
|
||||
# humn, which is the case is my input and the test input
|
||||
assert isinstance(monkeys["root"], tuple)
|
||||
p1, _, p2 = monkeys["root"] # type: ignore
|
||||
yield compute(invert(monkeys, "humn", compute(monkeys.copy(), p2)), "humn")
|
||||
answer_1 = compute(monkeys.copy(), "root")
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
# assume the second operand of 'root' can be computed, and the first one depends on
|
||||
# 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,243 +1,223 @@
|
||||
import re
|
||||
from typing import Any, Callable, Iterator
|
||||
import sys
|
||||
from typing import Callable
|
||||
|
||||
import numpy as np
|
||||
|
||||
from ..base import BaseSolver
|
||||
|
||||
VOID, EMPTY, WALL = 0, 1, 2
|
||||
TILE_FROM_CHAR = {" ": VOID, ".": EMPTY, "#": WALL}
|
||||
|
||||
SCORES = {"E": 0, "S": 1, "W": 2, "N": 3}
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
board_map_s, direction_s = input.split("\n\n")
|
||||
board_map_s, direction_s = sys.stdin.read().split("\n\n")
|
||||
|
||||
# board
|
||||
board_lines = board_map_s.splitlines()
|
||||
max_line = max(len(line) for line in board_lines)
|
||||
board = np.array(
|
||||
[
|
||||
[TILE_FROM_CHAR[c] for c in row] + [VOID] * (max_line - len(row))
|
||||
for row in board_map_s.splitlines()
|
||||
]
|
||||
)
|
||||
# board
|
||||
board_lines = board_map_s.splitlines()
|
||||
max_line = max(len(line) for line in board_lines)
|
||||
board = np.array(
|
||||
[
|
||||
[TILE_FROM_CHAR[c] for c in row] + [VOID] * (max_line - len(row))
|
||||
for row in board_map_s.splitlines()
|
||||
]
|
||||
)
|
||||
|
||||
directions = [
|
||||
int(p1) if p2 else p1
|
||||
for p1, p2 in re.findall(R"(([0-9])+|L|R)", direction_s)
|
||||
]
|
||||
directions = [
|
||||
int(p1) if p2 else p1 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)
|
||||
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):
|
||||
faces[row : row + size, col : col + size] = faces.max() + 1
|
||||
# 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
|
||||
|
||||
SIZE = np.gcd(*board.shape)
|
||||
|
||||
# TODO: deduce this from the actual cube...
|
||||
faces_wrap: dict[int, dict[str, Callable[[int, int], tuple[int, int, str]]]]
|
||||
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):
|
||||
faces[row : row + size, col : col + size] = faces.max() + 1
|
||||
|
||||
if board.shape == (12, 16): # example
|
||||
faces_wrap = {
|
||||
1: {
|
||||
"W": lambda y, x: (4, 4 + y, "S"), # 3N
|
||||
"N": lambda y, x: (4, 11 - x, "S"), # 2N
|
||||
"E": lambda y, x: (11 - y, 15, "W"), # 6E
|
||||
},
|
||||
2: {
|
||||
"W": lambda y, x: (11, 19 - y, "N"), # 6S
|
||||
"N": lambda y, x: (0, 11 - y, "S"), # 1N
|
||||
"S": lambda y, x: (11, 11 - x, "N"), # 5S
|
||||
},
|
||||
3: {
|
||||
"N": lambda y, x: (x - 4, 8, "E"), # 1W
|
||||
"S": lambda y, x: (15 - x, 8, "E"), # 5W
|
||||
},
|
||||
4: {"E": lambda y, x: (8, 19 - y, "S")}, # 6N
|
||||
5: {
|
||||
"W": lambda y, x: (7, 15 - y, "N"), # 3S
|
||||
"S": lambda y, x: (7, 11 - x, "N"), # 2S
|
||||
},
|
||||
6: {
|
||||
"N": lambda y, x: (19 - x, 11, "W"), # 4E
|
||||
"E": lambda y, x: (11 - y, 11, "W"), # 1E
|
||||
"S": lambda y, x: (19 - x, 0, "E"), # 2W
|
||||
},
|
||||
}
|
||||
SIZE = np.gcd(*board.shape)
|
||||
|
||||
# TODO: deduce this from the actual cube...
|
||||
faces_wrap: dict[int, dict[str, Callable[[int, int], tuple[int, int, str]]]]
|
||||
|
||||
if board.shape == (12, 16): # example
|
||||
faces_wrap = {
|
||||
1: {
|
||||
"W": lambda y, x: (4, 4 + y, "S"), # 3N
|
||||
"N": lambda y, x: (4, 11 - x, "S"), # 2N
|
||||
"E": lambda y, x: (11 - y, 15, "W"), # 6E
|
||||
},
|
||||
2: {
|
||||
"W": lambda y, x: (11, 19 - y, "N"), # 6S
|
||||
"N": lambda y, x: (0, 11 - y, "S"), # 1N
|
||||
"S": lambda y, x: (11, 11 - x, "N"), # 5S
|
||||
},
|
||||
3: {
|
||||
"N": lambda y, x: (x - 4, 8, "E"), # 1W
|
||||
"S": lambda y, x: (15 - x, 8, "E"), # 5W
|
||||
},
|
||||
4: {"E": lambda y, x: (8, 19 - y, "S")}, # 6N
|
||||
5: {
|
||||
"W": lambda y, x: (7, 15 - y, "N"), # 3S
|
||||
"S": lambda y, x: (7, 11 - x, "N"), # 2S
|
||||
},
|
||||
6: {
|
||||
"N": lambda y, x: (19 - x, 11, "W"), # 4E
|
||||
"E": lambda y, x: (11 - y, 11, "W"), # 1E
|
||||
"S": lambda y, x: (19 - x, 0, "E"), # 2W
|
||||
},
|
||||
}
|
||||
|
||||
else:
|
||||
faces_wrap = {
|
||||
1: {
|
||||
"W": lambda y, x: (3 * SIZE - y - 1, 0, "E"), # 4W
|
||||
"N": lambda y, x: (2 * SIZE + x, 0, "E"), # 6W
|
||||
},
|
||||
2: {
|
||||
"N": lambda y, x: (4 * SIZE - 1, x - 2 * SIZE, "N"), # 6S
|
||||
"E": lambda y, x: (3 * SIZE - y - 1, 2 * SIZE - 1, "W"), # 5E
|
||||
"S": lambda y, x: (x - SIZE, 2 * SIZE - 1, "W"), # 3E
|
||||
},
|
||||
3: {
|
||||
"W": lambda y, x: (2 * SIZE, y - SIZE, "S"), # 4N
|
||||
"E": lambda y, x: (SIZE - 1, SIZE + y, "N"), # 2S
|
||||
},
|
||||
4: {
|
||||
"W": lambda y, x: (3 * SIZE - y - 1, SIZE, "E"), # 1W
|
||||
"N": lambda y, x: (SIZE + x, SIZE, "E"), # 3W
|
||||
},
|
||||
5: {
|
||||
"E": lambda y, x: (3 * SIZE - y - 1, 3 * SIZE - 1, "W"), # 2E
|
||||
"S": lambda y, x: (2 * SIZE + x, SIZE - 1, "W"), # 6E
|
||||
},
|
||||
6: {
|
||||
"W": lambda y, x: (0, y - 2 * SIZE, "S"), # 1N
|
||||
"E": lambda y, x: (3 * SIZE - 1, y - 2 * SIZE, "N"), # 5S
|
||||
"S": lambda y, x: (0, x + 2 * SIZE, "S"), # 2N
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def wrap_part_1(y0: int, x0: int, r0: str) -> tuple[int, int, str]:
|
||||
if r0 == "E":
|
||||
return y0, row_first_non_void[y0], r0
|
||||
elif r0 == "S":
|
||||
return col_first_non_void[x0], x0, r0
|
||||
elif r0 == "W":
|
||||
return y0, row_last_non_void[y0], r0
|
||||
elif r0 == "N":
|
||||
return col_last_non_void[x0], x0, r0
|
||||
|
||||
assert False
|
||||
|
||||
|
||||
def wrap_part_2(y0: int, x0: int, r0: str) -> tuple[int, int, str]:
|
||||
cube = faces[y0, x0]
|
||||
assert r0 in faces_wrap[cube]
|
||||
return faces_wrap[cube][r0](y0, x0)
|
||||
|
||||
|
||||
def run(wrap: Callable[[int, int, str], tuple[int, int, str]]) -> tuple[int, int, str]:
|
||||
y0 = 0
|
||||
x0 = np.where(board[0] == EMPTY)[0][0]
|
||||
r0 = "E"
|
||||
|
||||
for direction in directions:
|
||||
if isinstance(direction, int):
|
||||
while direction > 0:
|
||||
if r0 == "E":
|
||||
xi = np.where(board[y0, x0 + 1 : x0 + direction + 1] == WALL)[0]
|
||||
if len(xi):
|
||||
x0 = x0 + xi[0]
|
||||
direction = 0
|
||||
elif (
|
||||
x0 + direction < board.shape[1]
|
||||
and board[y0, x0 + direction] == EMPTY
|
||||
):
|
||||
x0 = x0 + direction
|
||||
direction = 0
|
||||
else:
|
||||
y0_t, x0_t, r0_t = wrap(y0, x0, r0)
|
||||
if board[y0_t, x0_t] == WALL:
|
||||
x0 = row_last_non_void[y0]
|
||||
direction = 0
|
||||
else:
|
||||
direction = direction - (row_last_non_void[y0] - x0) - 1
|
||||
y0, x0, r0 = y0_t, x0_t, r0_t
|
||||
elif r0 == "S":
|
||||
yi = np.where(board[y0 + 1 : y0 + direction + 1, x0] == WALL)[0]
|
||||
if len(yi):
|
||||
y0 = y0 + yi[0]
|
||||
direction = 0
|
||||
elif (
|
||||
y0 + direction < board.shape[0]
|
||||
and board[y0 + direction, x0] == EMPTY
|
||||
):
|
||||
y0 = y0 + direction
|
||||
direction = 0
|
||||
else:
|
||||
y0_t, x0_t, r0_t = wrap(y0, x0, r0)
|
||||
if board[y0_t, x0_t] == WALL:
|
||||
y0 = col_last_non_void[x0]
|
||||
direction = 0
|
||||
else:
|
||||
direction = direction - (col_last_non_void[x0] - y0) - 1
|
||||
y0, x0, r0 = y0_t, x0_t, r0_t
|
||||
elif r0 == "W":
|
||||
left = max(x0 - direction - 1, 0)
|
||||
xi = np.where(board[y0, left:x0] == WALL)[0]
|
||||
if len(xi):
|
||||
x0 = left + xi[-1] + 1
|
||||
direction = 0
|
||||
elif x0 - direction >= 0 and board[y0, x0 - direction] == EMPTY:
|
||||
x0 = x0 - direction
|
||||
direction = 0
|
||||
else:
|
||||
y0_t, x0_t, r0_t = wrap(y0, x0, r0)
|
||||
if board[y0_t, x0_t] == WALL:
|
||||
x0 = row_first_non_void[y0]
|
||||
direction = 0
|
||||
else:
|
||||
direction = direction - (x0 - row_first_non_void[y0]) - 1
|
||||
y0, x0, r0 = y0_t, x0_t, r0_t
|
||||
elif r0 == "N":
|
||||
top = max(y0 - direction - 1, 0)
|
||||
yi = np.where(board[top:y0, x0] == WALL)[0]
|
||||
if len(yi):
|
||||
y0 = top + yi[-1] + 1
|
||||
direction = 0
|
||||
elif y0 - direction >= 0 and board[y0 - direction, x0] == EMPTY:
|
||||
y0 = y0 - direction
|
||||
direction = 0
|
||||
else:
|
||||
y0_t, x0_t, r0_t = wrap(y0, x0, r0)
|
||||
if board[y0_t, x0_t] == WALL:
|
||||
y0 = col_first_non_void[x0]
|
||||
direction = 0
|
||||
else:
|
||||
direction = direction - (y0 - col_first_non_void[x0]) - 1
|
||||
y0, x0, r0 = y0_t, x0_t, r0_t
|
||||
else:
|
||||
faces_wrap = {
|
||||
1: {
|
||||
"W": lambda y, x: (3 * SIZE - y - 1, 0, "E"), # 4W
|
||||
"N": lambda y, x: (2 * SIZE + x, 0, "E"), # 6W
|
||||
},
|
||||
2: {
|
||||
"N": lambda y, x: (4 * SIZE - 1, x - 2 * SIZE, "N"), # 6S
|
||||
"E": lambda y, x: (3 * SIZE - y - 1, 2 * SIZE - 1, "W"), # 5E
|
||||
"S": lambda y, x: (x - SIZE, 2 * SIZE - 1, "W"), # 3E
|
||||
},
|
||||
3: {
|
||||
"W": lambda y, x: (2 * SIZE, y - SIZE, "S"), # 4N
|
||||
"E": lambda y, x: (SIZE - 1, SIZE + y, "N"), # 2S
|
||||
},
|
||||
4: {
|
||||
"W": lambda y, x: (3 * SIZE - y - 1, SIZE, "E"), # 1W
|
||||
"N": lambda y, x: (SIZE + x, SIZE, "E"), # 3W
|
||||
},
|
||||
5: {
|
||||
"E": lambda y, x: (3 * SIZE - y - 1, 3 * SIZE - 1, "W"), # 2E
|
||||
"S": lambda y, x: (2 * SIZE + x, SIZE - 1, "W"), # 6E
|
||||
},
|
||||
6: {
|
||||
"W": lambda y, x: (0, y - 2 * SIZE, "S"), # 1N
|
||||
"E": lambda y, x: (3 * SIZE - 1, y - 2 * SIZE, "N"), # 5S
|
||||
"S": lambda y, x: (0, x + 2 * SIZE, "S"), # 2N
|
||||
},
|
||||
}
|
||||
r0 = {
|
||||
"E": {"L": "N", "R": "S"},
|
||||
"N": {"L": "W", "R": "E"},
|
||||
"W": {"L": "S", "R": "N"},
|
||||
"S": {"L": "E", "R": "W"},
|
||||
}[r0][direction]
|
||||
|
||||
def wrap_part_1(y0: int, x0: int, r0: str) -> tuple[int, int, str]:
|
||||
if r0 == "E":
|
||||
return y0, row_first_non_void[y0], r0
|
||||
elif r0 == "S":
|
||||
return col_first_non_void[x0], x0, r0
|
||||
elif r0 == "W":
|
||||
return y0, row_last_non_void[y0], r0
|
||||
elif r0 == "N":
|
||||
return col_last_non_void[x0], x0, r0
|
||||
return y0, x0, r0
|
||||
|
||||
assert False
|
||||
|
||||
def wrap_part_2(y0: int, x0: int, r0: str) -> tuple[int, int, str]:
|
||||
cube = faces[y0, x0]
|
||||
assert r0 in faces_wrap[cube]
|
||||
return faces_wrap[cube][r0](y0, x0)
|
||||
y1, x1, r1 = run(wrap_part_1)
|
||||
answer_1 = 1000 * (1 + y1) + 4 * (1 + x1) + SCORES[r1]
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
def run(
|
||||
wrap: Callable[[int, int, str], tuple[int, int, str]],
|
||||
) -> tuple[int, int, str]:
|
||||
y0 = 0
|
||||
x0 = np.where(board[0] == EMPTY)[0][0]
|
||||
r0 = "E"
|
||||
|
||||
for direction in directions:
|
||||
if isinstance(direction, int):
|
||||
while direction > 0:
|
||||
if r0 == "E":
|
||||
xi = np.where(
|
||||
board[y0, x0 + 1 : x0 + direction + 1] == WALL
|
||||
)[0]
|
||||
if len(xi):
|
||||
x0 = x0 + xi[0]
|
||||
direction = 0
|
||||
elif (
|
||||
x0 + direction < board.shape[1]
|
||||
and board[y0, x0 + direction] == EMPTY
|
||||
):
|
||||
x0 = x0 + direction
|
||||
direction = 0
|
||||
else:
|
||||
y0_t, x0_t, r0_t = wrap(y0, x0, r0)
|
||||
if board[y0_t, x0_t] == WALL:
|
||||
x0 = row_last_non_void[y0]
|
||||
direction = 0
|
||||
else:
|
||||
direction = (
|
||||
direction - (row_last_non_void[y0] - x0) - 1
|
||||
)
|
||||
y0, x0, r0 = y0_t, x0_t, r0_t
|
||||
elif r0 == "S":
|
||||
yi = np.where(
|
||||
board[y0 + 1 : y0 + direction + 1, x0] == WALL
|
||||
)[0]
|
||||
if len(yi):
|
||||
y0 = y0 + yi[0]
|
||||
direction = 0
|
||||
elif (
|
||||
y0 + direction < board.shape[0]
|
||||
and board[y0 + direction, x0] == EMPTY
|
||||
):
|
||||
y0 = y0 + direction
|
||||
direction = 0
|
||||
else:
|
||||
y0_t, x0_t, r0_t = wrap(y0, x0, r0)
|
||||
if board[y0_t, x0_t] == WALL:
|
||||
y0 = col_last_non_void[x0]
|
||||
direction = 0
|
||||
else:
|
||||
direction = (
|
||||
direction - (col_last_non_void[x0] - y0) - 1
|
||||
)
|
||||
y0, x0, r0 = y0_t, x0_t, r0_t
|
||||
elif r0 == "W":
|
||||
left = max(x0 - direction - 1, 0)
|
||||
xi = np.where(board[y0, left:x0] == WALL)[0]
|
||||
if len(xi):
|
||||
x0 = left + xi[-1] + 1
|
||||
direction = 0
|
||||
elif (
|
||||
x0 - direction >= 0
|
||||
and board[y0, x0 - direction] == EMPTY
|
||||
):
|
||||
x0 = x0 - direction
|
||||
direction = 0
|
||||
else:
|
||||
y0_t, x0_t, r0_t = wrap(y0, x0, r0)
|
||||
if board[y0_t, x0_t] == WALL:
|
||||
x0 = row_first_non_void[y0]
|
||||
direction = 0
|
||||
else:
|
||||
direction = (
|
||||
direction - (x0 - row_first_non_void[y0]) - 1
|
||||
)
|
||||
y0, x0, r0 = y0_t, x0_t, r0_t
|
||||
elif r0 == "N":
|
||||
top = max(y0 - direction - 1, 0)
|
||||
yi = np.where(board[top:y0, x0] == WALL)[0]
|
||||
if len(yi):
|
||||
y0 = top + yi[-1] + 1
|
||||
direction = 0
|
||||
elif (
|
||||
y0 - direction >= 0
|
||||
and board[y0 - direction, x0] == EMPTY
|
||||
):
|
||||
y0 = y0 - direction
|
||||
direction = 0
|
||||
else:
|
||||
y0_t, x0_t, r0_t = wrap(y0, x0, r0)
|
||||
if board[y0_t, x0_t] == WALL:
|
||||
y0 = col_first_non_void[x0]
|
||||
direction = 0
|
||||
else:
|
||||
direction = (
|
||||
direction - (y0 - col_first_non_void[x0]) - 1
|
||||
)
|
||||
y0, x0, r0 = y0_t, x0_t, r0_t
|
||||
else:
|
||||
r0 = {
|
||||
"E": {"L": "N", "R": "S"},
|
||||
"N": {"L": "W", "R": "E"},
|
||||
"W": {"L": "S", "R": "N"},
|
||||
"S": {"L": "E", "R": "W"},
|
||||
}[r0][direction]
|
||||
|
||||
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)
|
||||
yield 1000 * (1 + y2) + 4 * (1 + x2) + SCORES[r2]
|
||||
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 sys
|
||||
from collections import defaultdict
|
||||
from typing import Any, Iterator
|
||||
|
||||
from ..base import BaseSolver
|
||||
|
||||
Directions = list[
|
||||
tuple[
|
||||
@@ -20,10 +18,22 @@ DIRECTIONS: Directions = [
|
||||
|
||||
|
||||
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)
|
||||
|
||||
|
||||
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(
|
||||
positions: set[tuple[int, int]],
|
||||
directions: Directions,
|
||||
@@ -59,38 +69,35 @@ def round(
|
||||
directions.append(directions.pop(0))
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
POSITIONS = {
|
||||
(i, j)
|
||||
for i, row in enumerate(input.splitlines())
|
||||
for j, col in enumerate(row)
|
||||
if col == "#"
|
||||
}
|
||||
POSITIONS = {
|
||||
(i, j)
|
||||
for i, row in enumerate(sys.stdin.read().splitlines())
|
||||
for j, col in enumerate(row)
|
||||
if col == "#"
|
||||
}
|
||||
|
||||
# === part 1 ===
|
||||
# === part 1 ===
|
||||
|
||||
p1, d1 = POSITIONS.copy(), DIRECTIONS.copy()
|
||||
for _ in range(10):
|
||||
round(p1, d1)
|
||||
p1, d1 = POSITIONS.copy(), DIRECTIONS.copy()
|
||||
for r in range(10):
|
||||
round(p1, d1)
|
||||
|
||||
min_y, min_x, max_y, max_x = min_max_yx(p1)
|
||||
yield sum(
|
||||
(y, x) not in p1
|
||||
for y in range(min_y, max_y + 1)
|
||||
for x in range(min_x, max_x + 1)
|
||||
)
|
||||
min_y, min_x, max_y, max_x = min_max_yx(p1)
|
||||
answer_1 = sum(
|
||||
(y, x) not in p1 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()
|
||||
answer_2 = 0
|
||||
while True:
|
||||
answer_2 += 1
|
||||
backup = p2.copy()
|
||||
round(p2, d2)
|
||||
p2, d2 = POSITIONS.copy(), DIRECTIONS.copy()
|
||||
answer_2 = 0
|
||||
while True:
|
||||
answer_2 += 1
|
||||
backup = p2.copy()
|
||||
round(p2, d2)
|
||||
|
||||
if backup == p2:
|
||||
break
|
||||
if backup == p2:
|
||||
break
|
||||
|
||||
yield answer_2
|
||||
print(f"answer 2 is {answer_2}")
|
||||
|
||||
@@ -1,117 +1,98 @@
|
||||
import heapq
|
||||
import math
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from typing import Any, Iterator
|
||||
|
||||
from ..base import BaseSolver
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
winds = {
|
||||
(i - 1, j - 1, lines[i][j])
|
||||
for i in range(1, len(lines) - 1)
|
||||
for j in range(1, len(lines[i]) - 1)
|
||||
if lines[i][j] != "."
|
||||
}
|
||||
|
||||
n_rows, n_cols = len(lines) - 2, len(lines[0]) - 2
|
||||
CYCLE = math.lcm(n_rows, n_cols)
|
||||
|
||||
east_winds = [{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 = [
|
||||
{i for i in range(n_rows) if (i, j, "^") in winds} for j in range(n_cols)
|
||||
]
|
||||
south_winds = [
|
||||
{i for i in range(n_rows) if (i, j, "v") in winds} for j in range(n_cols)
|
||||
]
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = [line.strip() for line in input.splitlines()]
|
||||
def run(start: tuple[int, int], start_cycle: int, end: tuple[int, int]):
|
||||
def heuristic(y: int, x: int) -> int:
|
||||
return abs(end[0] - y) + abs(end[1] - x)
|
||||
|
||||
winds = {
|
||||
(i - 1, j - 1, lines[i][j])
|
||||
for i in range(1, len(lines) - 1)
|
||||
for j in range(1, len(lines[i]) - 1)
|
||||
if lines[i][j] != "."
|
||||
}
|
||||
# (distance + heuristic, distance, (start_pos, cycle))
|
||||
queue = [(heuristic(start[0], start[1]), 0, ((start[0], start[1]), start_cycle))]
|
||||
visited: set[tuple[tuple[int, int], int]] = set()
|
||||
distances: dict[tuple[int, int], dict[int, int]] = defaultdict(lambda: {})
|
||||
|
||||
n_rows, n_cols = len(lines) - 2, len(lines[0]) - 2
|
||||
CYCLE = math.lcm(n_rows, n_cols)
|
||||
while queue:
|
||||
_, distance, ((y, x), cycle) = heapq.heappop(queue)
|
||||
|
||||
east_winds = [
|
||||
{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 = [
|
||||
{i for i in range(n_rows) if (i, j, "^") in winds} for j in range(n_cols)
|
||||
]
|
||||
south_winds = [
|
||||
{i for i in range(n_rows) if (i, j, "v") in winds} for j in range(n_cols)
|
||||
]
|
||||
if ((y, x), cycle) in visited:
|
||||
continue
|
||||
|
||||
def run(start: tuple[int, int], start_cycle: int, end: tuple[int, int]):
|
||||
def heuristic(y: int, x: int) -> int:
|
||||
return abs(end[0] - y) + abs(end[1] - x)
|
||||
distances[y, x][cycle] = distance
|
||||
|
||||
# (distance + heuristic, distance, (start_pos, cycle))
|
||||
queue = [
|
||||
(heuristic(start[0], start[1]), 0, ((start[0], start[1]), start_cycle))
|
||||
]
|
||||
visited: set[tuple[tuple[int, int], int]] = set()
|
||||
distances: dict[tuple[int, int], dict[int, int]] = defaultdict(lambda: {})
|
||||
visited.add(((y, x), cycle))
|
||||
|
||||
while queue:
|
||||
_, distance, ((y, x), cycle) = heapq.heappop(queue)
|
||||
if (y, x) == (end[0], end[1]):
|
||||
break
|
||||
|
||||
if ((y, x), cycle) in visited:
|
||||
for dy, dx in (0, 0), (-1, 0), (1, 0), (0, -1), (0, 1):
|
||||
ty = y + dy
|
||||
tx = x + dx
|
||||
|
||||
n_cycle = (cycle + 1) % CYCLE
|
||||
|
||||
if (ty, tx) == end:
|
||||
heapq.heappush(queue, (distance + 1, distance + 1, ((ty, tx), n_cycle)))
|
||||
break
|
||||
|
||||
if ((ty, tx), n_cycle) in visited:
|
||||
continue
|
||||
|
||||
if (ty, tx) != start and (ty < 0 or tx < 0 or ty >= n_rows or tx >= n_cols):
|
||||
continue
|
||||
|
||||
if (ty, tx) != start:
|
||||
if (ty - n_cycle) % n_rows in south_winds[tx]:
|
||||
continue
|
||||
if (ty + n_cycle) % n_rows in north_winds[tx]:
|
||||
continue
|
||||
if (tx + n_cycle) % n_cols in west_winds[ty]:
|
||||
continue
|
||||
if (tx - n_cycle) % n_cols in east_winds[ty]:
|
||||
continue
|
||||
|
||||
distances[y, x][cycle] = distance
|
||||
heapq.heappush(
|
||||
queue,
|
||||
((heuristic(ty, tx) + distance + 1, distance + 1, ((ty, tx), n_cycle))),
|
||||
)
|
||||
|
||||
visited.add(((y, x), cycle))
|
||||
return distances, next(iter(distances[end].values()))
|
||||
|
||||
if (y, x) == (end[0], end[1]):
|
||||
break
|
||||
|
||||
for dy, dx in (0, 0), (-1, 0), (1, 0), (0, -1), (0, 1):
|
||||
ty = y + dy
|
||||
tx = x + dx
|
||||
start = (
|
||||
-1,
|
||||
next(j for j in range(1, len(lines[0]) - 1) if lines[0][j] == ".") - 1,
|
||||
)
|
||||
end = (
|
||||
n_rows,
|
||||
next(j for j in range(1, len(lines[-1]) - 1) if lines[-1][j] == ".") - 1,
|
||||
)
|
||||
|
||||
n_cycle = (cycle + 1) % CYCLE
|
||||
distances_1, forward_1 = run(start, 0, end)
|
||||
print(f"answer 1 is {forward_1}")
|
||||
|
||||
if (ty, tx) == end:
|
||||
heapq.heappush(
|
||||
queue, (distance + 1, distance + 1, ((ty, tx), n_cycle))
|
||||
)
|
||||
break
|
||||
|
||||
if ((ty, tx), n_cycle) in visited:
|
||||
continue
|
||||
|
||||
if (ty, tx) != start and (
|
||||
ty < 0 or tx < 0 or ty >= n_rows or tx >= n_cols
|
||||
):
|
||||
continue
|
||||
|
||||
if (ty, tx) != start:
|
||||
if (ty - n_cycle) % n_rows in south_winds[tx]:
|
||||
continue
|
||||
if (ty + n_cycle) % n_rows in north_winds[tx]:
|
||||
continue
|
||||
if (tx + n_cycle) % n_cols in west_winds[ty]:
|
||||
continue
|
||||
if (tx - n_cycle) % n_cols in east_winds[ty]:
|
||||
continue
|
||||
|
||||
heapq.heappush(
|
||||
queue,
|
||||
(
|
||||
(
|
||||
heuristic(ty, tx) + distance + 1,
|
||||
distance + 1,
|
||||
((ty, tx), n_cycle),
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
return distances, next(iter(distances[end].values()))
|
||||
|
||||
start = (
|
||||
-1,
|
||||
next(j for j in range(1, len(lines[0]) - 1) if lines[0][j] == ".") - 1,
|
||||
)
|
||||
end = (
|
||||
n_rows,
|
||||
next(j for j in range(1, len(lines[-1]) - 1) if lines[-1][j] == ".") - 1,
|
||||
)
|
||||
|
||||
distances_1, forward_1 = run(start, 0, end)
|
||||
yield forward_1
|
||||
|
||||
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)
|
||||
yield forward_1 + return_1 + forward_2
|
||||
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)
|
||||
print(f"answer 2 is {forward_1 + return_1 + forward_2}")
|
||||
|
||||
@@ -1,28 +1,27 @@
|
||||
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 solve(self, input: str) -> Iterator[Any]:
|
||||
lines = [line.strip() for line in input.splitlines()]
|
||||
def snafu2number(number: str) -> int:
|
||||
value = 0
|
||||
for c in number:
|
||||
value *= 5
|
||||
value += coeffs[c]
|
||||
return value
|
||||
|
||||
coeffs = {"2": 2, "1": 1, "0": 0, "-": -1, "=": -2}
|
||||
|
||||
def snafu2number(number: str) -> int:
|
||||
value = 0
|
||||
for c in number:
|
||||
value *= 5
|
||||
value += coeffs[c]
|
||||
return value
|
||||
def number2snafu(number: int) -> str:
|
||||
values = ["0", "1", "2", "=", "-"]
|
||||
res = ""
|
||||
while number > 0:
|
||||
mod = number % 5
|
||||
res = res + values[mod]
|
||||
number = number // 5 + int(mod >= 3)
|
||||
return "".join(reversed(res))
|
||||
|
||||
def number2snafu(number: int) -> str:
|
||||
values = ["0", "1", "2", "=", "-"]
|
||||
res = ""
|
||||
while number > 0:
|
||||
mod = number % 5
|
||||
res = res + values[mod]
|
||||
number = number // 5 + int(mod >= 3)
|
||||
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
|
||||
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):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = [line.strip() for line in input.splitlines()]
|
||||
# priorities
|
||||
priorities = {c: i + 1 for i, c in enumerate(string.ascii_letters)}
|
||||
|
||||
# extract content of each part
|
||||
parts = [
|
||||
(set(line[: len(line) // 2]), set(line[len(line) // 2 :])) for line in lines
|
||||
]
|
||||
# part 1
|
||||
part1 = sum(priorities[c] for p1, p2 in parts for c in p1.intersection(p2))
|
||||
print(f"answer 1 is {part1}")
|
||||
|
||||
# priorities
|
||||
priorities = {c: i + 1 for i, c in enumerate(string.ascii_letters)}
|
||||
|
||||
# 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]
|
||||
for i in range(0, len(lines), n_per_group)
|
||||
for c in set(lines[i]).intersection(*lines[i + 1 : i + n_per_group])
|
||||
)
|
||||
# part 2
|
||||
n_per_group = 3
|
||||
part2 = sum(
|
||||
priorities[c]
|
||||
for i in range(0, len(lines), 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]:
|
||||
@@ -8,13 +8,10 @@ def make_range(value: str) -> set[int]:
|
||||
return set(range(int(parts[0]), int(parts[1]) + 1))
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = [line.strip() for line in input.splitlines()]
|
||||
sections = [tuple(make_range(part) for part in line.split(",")) for line in lines]
|
||||
|
||||
sections = [
|
||||
tuple(make_range(part) for part in line.split(",")) for line in lines
|
||||
]
|
||||
answer_1 = sum(s1.issubset(s2) or s2.issubset(s1) for s1, s2 in sections)
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
yield sum(s1.issubset(s2) or s2.issubset(s1) for s1, s2 in sections)
|
||||
yield sum(bool(s1.intersection(s2)) for s1, s2 in sections)
|
||||
answer_2 = sum(bool(s1.intersection(s2)) for s1, s2 in sections)
|
||||
print(f"answer 1 is {answer_2}")
|
||||
|
||||
@@ -1,43 +1,41 @@
|
||||
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):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
blocks_s, moves_s = (part.splitlines() for part in input.split("\n\n"))
|
||||
# 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)):
|
||||
crate = block[index + 1 : index + 2].strip()
|
||||
|
||||
blocks: dict[str, list[str]] = {stack: [] for stack in blocks_s[-1].split()}
|
||||
if crate:
|
||||
blocks[stack].append(crate)
|
||||
|
||||
# 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)):
|
||||
crate = block[index + 1 : index + 2].strip()
|
||||
# part 1 - deep copy for part 2
|
||||
blocks_1 = copy.deepcopy(blocks)
|
||||
|
||||
if crate:
|
||||
blocks[stack].append(crate)
|
||||
for move in moves_s:
|
||||
_, count_s, _, from_, _, to_ = move.strip().split()
|
||||
|
||||
# part 1 - deep copy for part 2
|
||||
blocks_1 = copy.deepcopy(blocks)
|
||||
for _i in range(int(count_s)):
|
||||
blocks_1[to_].append(blocks_1[from_].pop())
|
||||
|
||||
for move in moves_s:
|
||||
_, count_s, _, from_, _, to_ = move.strip().split()
|
||||
# part 2
|
||||
blocks_2 = copy.deepcopy(blocks)
|
||||
|
||||
for _i in range(int(count_s)):
|
||||
blocks_1[to_].append(blocks_1[from_].pop())
|
||||
for move in moves_s:
|
||||
_, count_s, _, from_, _, to_ = move.strip().split()
|
||||
count = int(count_s)
|
||||
|
||||
# part 2
|
||||
blocks_2 = copy.deepcopy(blocks)
|
||||
blocks_2[to_].extend(blocks_2[from_][-count:])
|
||||
del blocks_2[from_][-count:]
|
||||
|
||||
for move in moves_s:
|
||||
_, count_s, _, from_, _, to_ = move.strip().split()
|
||||
count = int(count_s)
|
||||
answer_1 = "".join(s[-1] for s in blocks_1.values())
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
blocks_2[to_].extend(blocks_2[from_][-count:])
|
||||
del blocks_2[from_][-count:]
|
||||
|
||||
yield "".join(s[-1] for s in blocks_1.values())
|
||||
yield "".join(s[-1] for s in blocks_2.values())
|
||||
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
|
||||
|
||||
from ..base import BaseSolver
|
||||
import sys
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
yield index_of_first_n_differents(input, 4)
|
||||
yield index_of_first_n_differents(input, 14)
|
||||
data = sys.stdin.read().strip()
|
||||
|
||||
|
||||
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,81 +1,80 @@
|
||||
import sys
|
||||
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
|
||||
#
|
||||
|
||||
# mapping from path to list of files or directories
|
||||
trees: dict[Path, list[Path]] = {}
|
||||
|
||||
# mapping from paths to either size (for file) or -1 for directory
|
||||
sizes: dict[Path, int] = {}
|
||||
|
||||
# first line must be a cd otherwise we have no idea where we are
|
||||
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
|
||||
if line.startswith("$"):
|
||||
parts = line.strip("$").strip().split()
|
||||
command = parts[0]
|
||||
|
||||
if command == "cd":
|
||||
cur_path = cur_path.joinpath(parts[1]).resolve()
|
||||
|
||||
# just initialize the lis of files if not already done
|
||||
if cur_path not in trees:
|
||||
trees[cur_path] = []
|
||||
else:
|
||||
# nothing to do here
|
||||
pass
|
||||
|
||||
# fill the current path
|
||||
else:
|
||||
parts = line.split()
|
||||
name: str = parts[1]
|
||||
if line.startswith("dir"):
|
||||
size = -1
|
||||
else:
|
||||
size = int(parts[0])
|
||||
|
||||
path = cur_path.joinpath(name)
|
||||
trees[cur_path].append(path)
|
||||
sizes[path] = size
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = [line.strip() for line in input.splitlines()]
|
||||
def compute_size(path: Path) -> int:
|
||||
size = sizes[path]
|
||||
|
||||
# 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
|
||||
#
|
||||
if size >= 0:
|
||||
return size
|
||||
|
||||
# mapping from path to list of files or directories
|
||||
trees: dict[Path, list[Path]] = {}
|
||||
return sum(compute_size(sub) for sub in trees[path])
|
||||
|
||||
# mapping from paths to either size (for file) or -1 for directory
|
||||
sizes: dict[Path, int] = {}
|
||||
|
||||
# first line must be a cd otherwise we have no idea where we are
|
||||
assert lines[0].startswith("$ cd")
|
||||
base_path = Path(lines[0].strip("$").split()[1]).resolve()
|
||||
cur_path = base_path
|
||||
acc_sizes = {path: compute_size(path) for path in trees}
|
||||
|
||||
trees[cur_path] = []
|
||||
sizes[cur_path] = -1
|
||||
# part 1
|
||||
answer_1 = sum(size for size in acc_sizes.values() if size <= 100_000)
|
||||
print(f"answer 1 is {answer_1}")
|
||||
|
||||
for line in lines[1:]:
|
||||
# command
|
||||
if line.startswith("$"):
|
||||
parts = line.strip("$").strip().split()
|
||||
command = parts[0]
|
||||
# part 2
|
||||
total_space = 70_000_000
|
||||
update_space = 30_000_000
|
||||
free_space = total_space - acc_sizes[base_path]
|
||||
|
||||
if command == "cd":
|
||||
cur_path = cur_path.joinpath(parts[1]).resolve()
|
||||
to_free_space = update_space - free_space
|
||||
|
||||
# just initialize the lis of files if not already done
|
||||
if cur_path not in trees:
|
||||
trees[cur_path] = []
|
||||
else:
|
||||
# nothing to do here
|
||||
pass
|
||||
|
||||
# fill the current path
|
||||
else:
|
||||
parts = line.split()
|
||||
name: str = parts[1]
|
||||
if line.startswith("dir"):
|
||||
size = -1
|
||||
else:
|
||||
size = int(parts[0])
|
||||
|
||||
path = cur_path.joinpath(name)
|
||||
trees[cur_path].append(path)
|
||||
sizes[path] = size
|
||||
|
||||
def compute_size(path: Path) -> int:
|
||||
size = sizes[path]
|
||||
|
||||
if size >= 0:
|
||||
return size
|
||||
|
||||
return sum(compute_size(sub) for sub in trees[path])
|
||||
|
||||
acc_sizes = {path: compute_size(path) for path in trees}
|
||||
|
||||
# part 1
|
||||
yield sum(size for size in acc_sizes.values() if size <= 100_000)
|
||||
|
||||
# part 2
|
||||
total_space = 70_000_000
|
||||
update_space = 30_000_000
|
||||
free_space = total_space - acc_sizes[base_path]
|
||||
|
||||
to_free_space = update_space - free_space
|
||||
|
||||
yield min(size for size in acc_sizes.values() if size >= to_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,54 +1,53 @@
|
||||
from typing import Any, Iterator
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
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):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = [line.strip() for line in input.splitlines()]
|
||||
|
||||
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 + 1 :, j].max(),
|
||||
trees[i, :j].max(),
|
||||
trees[i, j + 1 :].max(),
|
||||
]
|
||||
for j in range(1, trees.shape[1] - 1)
|
||||
]
|
||||
for i in range(1, trees.shape[0] - 1)
|
||||
# answer 1
|
||||
highest_trees = np.ones(trees.shape + (4,), dtype=int) * -1
|
||||
highest_trees[1:-1, 1:-1] = [
|
||||
[
|
||||
[
|
||||
trees[:i, j].max(),
|
||||
trees[i + 1 :, j].max(),
|
||||
trees[i, :j].max(),
|
||||
trees[i, j + 1 :].max(),
|
||||
]
|
||||
for j in range(1, trees.shape[1] - 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:
|
||||
w = np.where(row_of_trees >= value)[0]
|
||||
|
||||
if not w.size:
|
||||
return len(row_of_trees)
|
||||
def viewing_distance(row_of_trees: NDArray[np.int_], value: int) -> int:
|
||||
w = np.where(row_of_trees >= value)[0]
|
||||
|
||||
return w[0] + 1
|
||||
if not w.size:
|
||||
return len(row_of_trees)
|
||||
|
||||
# answer 2
|
||||
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, j - 1 :: -1], trees[i, j]),
|
||||
viewing_distance(trees[i, j + 1 :], trees[i, j]),
|
||||
viewing_distance(trees[i + 1 :, j], trees[i, j]),
|
||||
]
|
||||
for j in range(1, trees.shape[1] - 1)
|
||||
]
|
||||
for i in range(1, trees.shape[0] - 1)
|
||||
return w[0] + 1
|
||||
|
||||
|
||||
# answer 2
|
||||
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, j - 1 :: -1], trees[i, j]),
|
||||
viewing_distance(trees[i, j + 1 :], trees[i, j]),
|
||||
viewing_distance(trees[i + 1 :, j], trees[i, j]),
|
||||
]
|
||||
yield np.prod(v_distances, axis=2).max()
|
||||
for j in range(1, trees.shape[1] - 1)
|
||||
]
|
||||
for i in range(1, trees.shape[0] - 1)
|
||||
]
|
||||
answer_2 = np.prod(v_distances, axis=2).max()
|
||||
print(f"answer 2 is {answer_2}")
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import itertools as it
|
||||
from typing import Any, Iterator
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
|
||||
from ..base import BaseSolver
|
||||
|
||||
|
||||
def move(head: tuple[int, int], command: str) -> tuple[int, int]:
|
||||
h_col, h_row = head
|
||||
@@ -46,14 +43,17 @@ def run(commands: list[str], n_blocks: int) -> list[tuple[int, int]]:
|
||||
return visited
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
lines = [line.strip() for line in input.splitlines()]
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
# flatten the commands
|
||||
commands = list(
|
||||
it.chain(*(p[0] * int(p[1]) for line in lines if (p := line.split())))
|
||||
)
|
||||
# flatten the commands
|
||||
commands: list[str] = []
|
||||
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":
|
||||
cnt += 1
|
||||
|
||||
if self.files:
|
||||
rows = [["." for _j in range(len(lines[0]))] for _i in range(len(lines))]
|
||||
rows[si][sj] = "\033[91mS\033[0m"
|
||||
|
||||
for i, j in loop:
|
||||
rows[i][j] = lines[i][j]
|
||||
for i, j in inside:
|
||||
rows[i][j] = "\033[92mI\033[0m"
|
||||
|
||||
self.files.create(
|
||||
"output.txt", "\n".join("".join(row) for row in rows).encode(), True
|
||||
)
|
||||
if self.verbose:
|
||||
for i in range(len(lines)):
|
||||
s = ""
|
||||
for j in range(len(lines[0])):
|
||||
if (i, j) == (si, sj):
|
||||
s += "\033[91mS\033[0m"
|
||||
elif (i, j) in loop:
|
||||
s += lines[i][j]
|
||||
elif (i, j) in inside:
|
||||
s += "\033[92mI\033[0m"
|
||||
else:
|
||||
s += "."
|
||||
self.logger.info(s)
|
||||
|
||||
yield len(inside)
|
||||
|
||||
@@ -84,14 +84,9 @@ class Solver(BaseSolver):
|
||||
|
||||
beams = propagate(layout, (0, 0), "R")
|
||||
|
||||
if self.files:
|
||||
self.files.create(
|
||||
"beams.txt",
|
||||
"\n".join(
|
||||
"".join("#" if col else "." for col in row) for row in beams
|
||||
).encode(),
|
||||
True,
|
||||
)
|
||||
if self.verbose:
|
||||
for row in beams:
|
||||
self.logger.info("".join("#" if col else "." for col in row))
|
||||
|
||||
# part 1
|
||||
yield sum(sum(map(bool, row)) for row in beams)
|
||||
|
||||
@@ -33,14 +33,10 @@ MAPPINGS: dict[Direction, tuple[int, int, Direction]] = {
|
||||
class Solver(BaseSolver):
|
||||
def print_shortest_path(
|
||||
self,
|
||||
name: str,
|
||||
grid: list[list[int]],
|
||||
target: tuple[int, int],
|
||||
per_cell: dict[tuple[int, int], list[tuple[Label, int]]],
|
||||
):
|
||||
if not self.files:
|
||||
return
|
||||
|
||||
assert len(per_cell[target]) == 1
|
||||
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"
|
||||
|
||||
self.files.create(
|
||||
name, "\n".join("".join(row) for row in p_grid).encode(), True
|
||||
)
|
||||
for row in p_grid:
|
||||
self.logger.info("".join(row))
|
||||
|
||||
def shortest_many_paths(self, grid: list[list[int]]) -> dict[tuple[int, int], int]:
|
||||
n_rows, n_cols = len(grid), len(grid[0])
|
||||
@@ -134,7 +129,6 @@ class Solver(BaseSolver):
|
||||
|
||||
def shortest_path(
|
||||
self,
|
||||
name: str,
|
||||
grid: list[list[int]],
|
||||
min_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]
|
||||
|
||||
@@ -232,7 +227,7 @@ class Solver(BaseSolver):
|
||||
estimates = self.shortest_many_paths(data)
|
||||
|
||||
# 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
|
||||
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 math import lcm
|
||||
from typing import Any, Iterator, Literal, TypeAlias
|
||||
@@ -66,7 +67,7 @@ class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
self._modules = {}
|
||||
|
||||
lines = input.splitlines()
|
||||
lines = sys.stdin.read().splitlines()
|
||||
|
||||
for line in lines:
|
||||
name, outputs_s = line.split(" -> ")
|
||||
@@ -79,23 +80,22 @@ class Solver(BaseSolver):
|
||||
outputs,
|
||||
)
|
||||
|
||||
if self.files:
|
||||
contents = "digraph G {\n"
|
||||
contents += "rx [shape=circle, color=red, style=filled];\n"
|
||||
for name, (type, outputs) in self._modules.items():
|
||||
if type == "conjunction":
|
||||
shape = "diamond"
|
||||
elif type == "flip-flop":
|
||||
shape = "box"
|
||||
else:
|
||||
shape = "circle"
|
||||
contents += f"{name} [shape={shape}];\n"
|
||||
for name, (type, outputs) in self._modules.items():
|
||||
for output in outputs:
|
||||
contents += f"{name} -> {output};\n"
|
||||
contents += "}\n"
|
||||
|
||||
self.files.create("day20.dot", contents.encode(), False)
|
||||
if self.outputs:
|
||||
with open("./day20.dot", "w") as fp:
|
||||
fp.write("digraph G {\n")
|
||||
fp.write("rx [shape=circle, color=red, style=filled];\n")
|
||||
for name, (type, outputs) in self._modules.items():
|
||||
if type == "conjunction":
|
||||
shape = "diamond"
|
||||
elif type == "flip-flop":
|
||||
shape = "box"
|
||||
else:
|
||||
shape = "circle"
|
||||
fp.write(f"{name} [shape={shape}];\n")
|
||||
for name, (type, outputs) in self._modules.items():
|
||||
for output in outputs:
|
||||
fp.write(f"{name} -> {output};\n")
|
||||
fp.write("}\n")
|
||||
|
||||
# part 1
|
||||
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)))
|
||||
|
||||
if self.files:
|
||||
if self.verbose:
|
||||
n_rows, n_cols = len(map), len(map[0])
|
||||
|
||||
rows = [
|
||||
@@ -66,9 +66,8 @@ class Solver(BaseSolver):
|
||||
if (i // cycle) % 2 == (j // cycle) % 2:
|
||||
rows[i][j] = f"\033[91m{rows[i][j]}\033[0m"
|
||||
|
||||
self.files.create(
|
||||
"cycle.txt", "\n".join("".join(row) for row in rows).encode(), True
|
||||
)
|
||||
for row in rows:
|
||||
self.logger.info("".join(row))
|
||||
|
||||
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
|
||||
#
|
||||
|
||||
# counts = [
|
||||
# [
|
||||
# sum(
|
||||
# (i, j) in tiles
|
||||
# for i in range(ci * cycle, (ci + 1) * cycle)
|
||||
# for j in range(cj * cycle, (cj + 1) * cycle)
|
||||
# )
|
||||
# for cj in range(-2, 3)
|
||||
# ]
|
||||
# for ci in range(-2, 3)
|
||||
# ]
|
||||
counts = [
|
||||
[
|
||||
sum(
|
||||
(i, j) in tiles
|
||||
for i in range(ci * cycle, (ci + 1) * cycle)
|
||||
for j in range(cj * cycle, (cj + 1) * cycle)
|
||||
)
|
||||
for cj in range(-2, 3)
|
||||
]
|
||||
for ci in range(-2, 3)
|
||||
]
|
||||
|
||||
# radius = (26501365 - rhombus) // cycle - 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]
|
||||
# answer_2 = (
|
||||
# (radius + 1) * A
|
||||
# + radius * B
|
||||
# + 2 * radius * (radius + 1) // 2 * A
|
||||
# + 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, 1), (0, 3), (-1, 1), (-1, 3)))
|
||||
# * (radius + 1)
|
||||
# + sum(counts[i][j] for i, j in ((1, 1), (1, 3), (-2, 1), (-2, 3))) * radius
|
||||
# )
|
||||
radius = (26501365 - rhombus) // cycle - 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]
|
||||
answer_2 = (
|
||||
(radius + 1) * A
|
||||
+ radius * B
|
||||
+ 2 * radius * (radius + 1) // 2 * A
|
||||
+ 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, 1), (0, 3), (-1, 1), (-1, 3)))
|
||||
* (radius + 1)
|
||||
+ 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
|
||||
#
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
# pyright: reportUnknownMemberType=false
|
||||
|
||||
from typing import Any, Iterator
|
||||
|
||||
import networkx as nx
|
||||
|
||||
@@ -1,35 +1,7 @@
|
||||
import itertools as it
|
||||
from typing import Any, Iterator
|
||||
|
||||
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):
|
||||
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())
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
||||
@@ -1,36 +1,7 @@
|
||||
from functools import cache
|
||||
from typing import Any, Iterator
|
||||
|
||||
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):
|
||||
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)
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
||||
@@ -1,101 +1,7 @@
|
||||
import itertools as it
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Iterator, TypeAlias
|
||||
from typing import Any, Iterator
|
||||
|
||||
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):
|
||||
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)
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
||||
@@ -1,79 +1,7 @@
|
||||
import math
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Iterator
|
||||
|
||||
import parse # pyright: ignore[reportMissingTypeStubs]
|
||||
|
||||
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):
|
||||
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))
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
||||
@@ -1,74 +1,7 @@
|
||||
import itertools as it
|
||||
import operator as op
|
||||
from math import prod
|
||||
from typing import Any, Iterator
|
||||
|
||||
import numpy as np
|
||||
import parse # pyright: ignore[reportMissingTypeStubs]
|
||||
|
||||
from ..base import BaseSolver
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
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
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
||||
@@ -1,282 +1,7 @@
|
||||
from typing import Any, Callable, Final, Iterator, TypeAlias
|
||||
|
||||
import numpy as np
|
||||
from numpy.typing import NDArray
|
||||
from typing import Any, Iterator
|
||||
|
||||
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):
|
||||
def save_grid(self, name: str, grid: Grid):
|
||||
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)
|
||||
)
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
||||
@@ -1,62 +1,7 @@
|
||||
import heapq
|
||||
from collections import defaultdict
|
||||
from typing import Any, Iterator, TypeAlias
|
||||
from typing import Any, Iterator
|
||||
|
||||
from ..base import BaseSolver
|
||||
|
||||
Position: TypeAlias = tuple[int, int]
|
||||
Direction: TypeAlias = tuple[int, int]
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
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)
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
||||
@@ -3,128 +3,5 @@ from typing import Any, Iterator
|
||||
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):
|
||||
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)
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
||||
@@ -1,58 +1,7 @@
|
||||
from typing import Any, Iterator
|
||||
|
||||
from ..base import BaseSolver
|
||||
from ..tools import graphs
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def print_grid(self, grid: list[tuple[int, int]], n_rows: int, n_cols: int):
|
||||
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
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
||||
@@ -1,42 +1,7 @@
|
||||
from functools import cache
|
||||
from typing import Any, Iterator
|
||||
|
||||
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):
|
||||
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))
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
||||
@@ -1,95 +1,7 @@
|
||||
import itertools
|
||||
from collections import Counter
|
||||
from typing import Any, Callable, Iterable, Iterator, Sequence, TypeAlias
|
||||
from typing import Any, Iterator
|
||||
|
||||
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):
|
||||
def find_cheats(
|
||||
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())
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
||||
@@ -1,85 +1,7 @@
|
||||
import itertools
|
||||
from functools import cache
|
||||
from typing import Any, Iterator, Literal
|
||||
from typing import Any, Iterator
|
||||
|
||||
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):
|
||||
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()
|
||||
)
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
||||
@@ -3,57 +3,5 @@ from typing import Any, Iterator
|
||||
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):
|
||||
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)
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
||||
@@ -1,36 +1,7 @@
|
||||
from collections import defaultdict
|
||||
from typing import Any, Iterator
|
||||
|
||||
from ..base import BaseSolver
|
||||
from ..tools.graphs import iter_max_cliques
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
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))
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
||||
@@ -1,170 +1,7 @@
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Iterator, Literal, TypeAlias, cast
|
||||
from typing import Any, Iterator
|
||||
|
||||
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):
|
||||
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))
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
||||
@@ -1,40 +1,7 @@
|
||||
import itertools as it
|
||||
from typing import Any, Iterator
|
||||
|
||||
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):
|
||||
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)
|
||||
)
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
||||
@@ -4,64 +4,4 @@ from ..base import BaseSolver
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
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)
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
|
||||
@@ -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 importlib
|
||||
import json
|
||||
import logging
|
||||
import logging.handlers
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
from pathlib import Path
|
||||
from typing import Any, Iterable, Iterator, Literal, Sequence, TextIO, TypeVar
|
||||
|
||||
from tqdm import tqdm
|
||||
|
||||
from .base import BaseSolver
|
||||
from .utils.api import FileHandlerAPI, LoggerAPIHandler, ProgressAPI, dump_answer
|
||||
from .utils.files import SimpleFileHandler
|
||||
from .utils.progress import ProgressNone, ProgressTQDM
|
||||
|
||||
_T = TypeVar("_T")
|
||||
|
||||
|
||||
def find_input_file(folder: Path, day: int, target: Path | None):
|
||||
if (path := folder.joinpath(f"day{day}.txt")).exists():
|
||||
return path
|
||||
def dump_api_message(
|
||||
type: Literal["log", "answer", "progress-start", "progress-step", "progress-end"],
|
||||
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
|
||||
and (path := folder.joinpath(f"day{day}_v{target}.txt")).exists()
|
||||
|
||||
class LoggerAPIHandler(logging.Handler):
|
||||
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__()
|
||||
|
||||
try:
|
||||
return next(path for path in sorted(folder.glob(f"day{day}*.txt")))
|
||||
except StopIteration:
|
||||
...
|
||||
self.counter = 0
|
||||
self.output = output
|
||||
self.min_step = min_step
|
||||
self.min_time = min_time
|
||||
|
||||
return folder.joinpath(f"day{day}.txt")
|
||||
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:
|
||||
percent = 0
|
||||
time = datetime.now()
|
||||
|
||||
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():
|
||||
parser = argparse.ArgumentParser("Holt59 Advent-Of-Code Runner")
|
||||
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("-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(
|
||||
"-u", "--user", type=str, default="holt59", help="user input to use"
|
||||
)
|
||||
@@ -58,7 +125,7 @@ def main():
|
||||
default=None,
|
||||
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")
|
||||
|
||||
args = parser.parse_args()
|
||||
@@ -68,24 +135,20 @@ def main():
|
||||
test: bool = args.test
|
||||
stdin: bool = args.stdin
|
||||
user: str = args.user
|
||||
files_output: Path = args.output
|
||||
input_path: Path | None = args.input
|
||||
|
||||
year: int = args.year
|
||||
day: int = args.day
|
||||
|
||||
# TODO: change this
|
||||
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,
|
||||
)
|
||||
|
||||
if input_path is None or not input_path.exists():
|
||||
input_path = find_input_file(
|
||||
Path(__file__).parent.joinpath(
|
||||
"inputs", "tests" if test else user, str(year)
|
||||
),
|
||||
day,
|
||||
input_path,
|
||||
if input_path is None:
|
||||
input_path = Path(__file__).parent.joinpath(
|
||||
"inputs", "tests" if test else user, str(year), f"day{day}.txt"
|
||||
)
|
||||
assert input_path.exists(), f"{input_path} missing"
|
||||
|
||||
@@ -103,11 +166,7 @@ def main():
|
||||
else ProgressTQDM()
|
||||
if verbose
|
||||
else ProgressNone(), # type: ignore
|
||||
files=FileHandlerAPI(files_output)
|
||||
if api and verbose
|
||||
else SimpleFileHandler(logging.getLogger("AOC"), files_output)
|
||||
if verbose
|
||||
else None,
|
||||
outputs=not api,
|
||||
)
|
||||
|
||||
data: str
|
||||
@@ -120,7 +179,7 @@ def main():
|
||||
start = datetime.now()
|
||||
last = start
|
||||
|
||||
it = solver.solve(data.rstrip())
|
||||
it = solver.solve(data.strip())
|
||||
|
||||
if it is None:
|
||||
solver.logger.error(f"no implementation for {year} day {day}")
|
||||
@@ -130,11 +189,14 @@ def main():
|
||||
current = datetime.now()
|
||||
|
||||
if api:
|
||||
dump_answer(
|
||||
part=i_answer + 1,
|
||||
answer=answer,
|
||||
answer_time=current - last,
|
||||
total_time=current - start,
|
||||
dump_api_message(
|
||||
"answer",
|
||||
{
|
||||
"answer": i_answer + 1,
|
||||
"value": answer,
|
||||
"answerTime_s": (current - last).total_seconds(),
|
||||
"totalTime_s": (current - start).total_seconds(),
|
||||
},
|
||||
)
|
||||
else:
|
||||
print(
|
||||
|
||||
@@ -1,78 +1,18 @@
|
||||
from abc import abstractmethod
|
||||
from logging import Logger
|
||||
from pathlib import Path
|
||||
from typing import (
|
||||
Any,
|
||||
Final,
|
||||
Iterable,
|
||||
Iterator,
|
||||
Protocol,
|
||||
Sequence,
|
||||
TypeVar,
|
||||
overload,
|
||||
)
|
||||
|
||||
from numpy.typing import NDArray
|
||||
from typing import Any, Final, Iterable, Iterator, Protocol, Sequence, TypeVar, overload
|
||||
|
||||
_T = TypeVar("_T")
|
||||
|
||||
|
||||
class ProgressHandler(Protocol):
|
||||
@overload
|
||||
def wrap(self, values: Sequence[_T]) -> Iterator[_T]: ...
|
||||
def wrap(self, values: Sequence[_T]) -> Iterator[_T]:
|
||||
...
|
||||
|
||||
@overload
|
||||
def wrap(self, values: Iterable[_T], total: int) -> Iterator[_T]: ...
|
||||
|
||||
|
||||
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)
|
||||
def wrap(self, values: Iterable[_T], total: int) -> Iterator[_T]:
|
||||
...
|
||||
|
||||
|
||||
class BaseSolver:
|
||||
@@ -83,14 +23,15 @@ class BaseSolver:
|
||||
year: int,
|
||||
day: int,
|
||||
progress: ProgressHandler,
|
||||
files: FileHandler | None = None,
|
||||
outputs: bool = False,
|
||||
):
|
||||
self.logger: Final = logger
|
||||
self.verbose: Final = verbose
|
||||
self.year: Final = year
|
||||
self.day: Final = day
|
||||
self.progress: Final = progress
|
||||
self.files: Final = files
|
||||
self.outputs = outputs
|
||||
|
||||
@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