135 Commits

Author SHA1 Message Date
Mikaël Capelle
377e501d34 Start fixing 2015 for new API.
Some checks failed
continuous-integration/drone/pr Build is failing
continuous-integration/drone/push Build is failing
2024-12-08 12:13:41 +01:00
Mikaël Capelle
d1f4f5bed0 2024 day 8.
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2024-12-08 08:53:36 +01:00
Mikaël Capelle
03a950c485 Force flush API message.
Some checks failed
continuous-integration/drone/push Build is failing
2024-12-07 12:38:02 +01:00
Mikaël Capelle
22b1513271 Fix answer API model.
Some checks failed
continuous-integration/drone/push Build is failing
2024-12-07 12:21:57 +01:00
Mikaël Capelle
1f5b21a13a 2024 day 7.
Some checks failed
continuous-integration/drone/push Build is failing
2024-12-07 09:39:17 +01:00
Mikaël Capelle
8c707c00ba 2024 day 6 new API.
Some checks failed
continuous-integration/drone/push Build is failing
2024-12-06 21:15:18 +01:00
Mikael CAPELLE
ae4f42517c Start adding progress.
Some checks failed
continuous-integration/drone/push Build is failing
2024-12-06 14:39:23 +01:00
Mikael CAPELLE
17432f7ac6 Refactor main entrypoint for UI. 2024-12-06 14:11:35 +01:00
Mikael CAPELLE
664dcfe7ba Refactor 2023 for new system. 2024-12-06 14:11:35 +01:00
Mikael CAPELLE
a9bcf9ef8f Start refactoring code better flexibility. 2024-12-06 14:11:32 +01:00
Mikael CAPELLE
1caf93b38b Refactor 2024 day 6 to be a little bit faster.
All checks were successful
continuous-integration/drone/push Build is passing
2024-12-06 14:10:51 +01:00
Mikaël Capelle
f9a3dee20b 2024 day 6, brute force.
Some checks failed
continuous-integration/drone/push Build is failing
2024-12-06 06:50:35 +01:00
Mikael CAPELLE
1a1ff0c64d Refactor 2024 day 5 without networkx.
All checks were successful
continuous-integration/drone/push Build is passing
2024-12-05 08:28:55 +01:00
Mikaël Capelle
d7621d09b5 2024 day 5.
Some checks failed
continuous-integration/drone/push Build is failing
2024-12-05 07:25:55 +01:00
Mikael CAPELLE
b89d29e880 Refactor 2024 day 4.
All checks were successful
continuous-integration/drone/push Build is passing
2024-12-04 09:31:47 +01:00
Mikaël Capelle
f1cd7e6c85 2024 day 4.
All checks were successful
continuous-integration/drone/push Build is passing
2024-12-04 07:35:22 +01:00
Mikael CAPELLE
d16ee7f9ad Refactor 2024 day 3.
All checks were successful
continuous-integration/drone/push Build is passing
2024-12-03 15:22:54 +01:00
0c46d3ed18 Add .drone.yml for CI. (#2)
All checks were successful
continuous-integration/drone/push Build is passing
2024-12-03 13:38:03 +00:00
Mikael CAPELLE
acb767184e Fix linting. 2024-12-03 14:11:29 +01:00
Mikael CAPELLE
cb0145baa2 2024 day 3. 2024-12-03 08:29:25 +01:00
Mikaël Capelle
a4ad0259a9 Fix 2024 day 2. 2024-12-02 18:44:50 +01:00
Mikael CAPELLE
82452c0751 Update Python dependencies. 2024-12-02 17:08:50 +01:00
Mikael CAPELLE
79cc208875 2024 day 2. 2024-12-02 15:42:56 +01:00
Mikaël Capelle
4dd2d5d9c9 2024 day 1. 2024-12-01 10:26:02 +01:00
Mikaël Capelle
def4305c1c 2015 day 22, part 1. 2024-12-01 10:25:49 +01:00
Mikaël Capelle
3edaa249fc 2015 day 21. 2024-01-20 17:57:37 +01:00
Mikaël Capelle
57fcb47fe9 2015 day 20. 2024-01-06 22:07:34 +01:00
Mikaël Capelle
cfa7718475 2015 day 19. 2024-01-06 21:35:48 +01:00
Mikaël Capelle
2d23e355b2 2015 day 18. 2024-01-06 16:43:35 +01:00
Mikaël Capelle
fab4899715 2015 day 17. 2024-01-06 15:46:43 +01:00
Mikaël Capelle
b6e20eefa3 2015 day 16. 2024-01-06 15:27:45 +01:00
Mikaël Capelle
872fd72dcd 2015 day 15. 2024-01-06 15:11:47 +01:00
Mikaël Capelle
98f28e96f8 2015 day 12, 13 & 14. 2024-01-06 14:56:30 +01:00
Mikaël Capelle
ed7aba80ad 2015 day 11. 2024-01-06 11:46:59 +01:00
Mikaël Capelle
e507dad5e0 2015 day 10. 2024-01-06 11:30:10 +01:00
Mikael CAPELLE
04172beb5a 2015 day 9. 2024-01-05 14:46:05 +01:00
Mikael CAPELLE
15ef67e757 2015 day 8. 2024-01-05 10:01:02 +01:00
Mikaël Capelle
cd0ada785c 2015 day 4, 5, 6, 7. 2024-01-04 21:05:42 +01:00
Mikael CAPELLE
42bd8d6983 2015 day 3. 2024-01-04 18:36:30 +01:00
Mikael CAPELLE
0567ab7440 2015 day 1 & 2. 2024-01-04 18:27:17 +01:00
Mikaël Capelle
7d2eb6b5ec Faster 2023 day 24 (part 1). 2024-01-01 18:44:13 +01:00
Mikaël Capelle
3a9c7e728b Minor cleaning 2023. 2023-12-30 19:35:06 +01:00
Mikaël Capelle
d002e419c3 2023 day 25. 2023-12-25 10:36:36 +01:00
Mikaël Capelle
19d93e0c1d 2023 day 24. 2023-12-25 10:36:29 +01:00
Mikaël Capelle
5c05ee5c85 2023 day 23. 2023-12-23 11:05:35 +01:00
Mikaël Capelle
103af21915 2021 day 9. 2023-12-22 21:26:13 +01:00
Mikaël Capelle
af2fbf2da1 2023 day 22. 2023-12-22 14:49:31 +01:00
Mikaël Capelle
c496ea25c9 2023 day 21, version 2. 2023-12-21 21:56:38 +01:00
Mikael CAPELLE
5f8c74fd1c 2023 day 21. 2023-12-21 16:47:43 +01:00
Mikael CAPELLE
dda2be2505 2023 day 20. 2023-12-20 14:27:25 +01:00
Mikael CAPELLE
12891194bb Poetry stuff. 2023-12-19 17:45:33 +01:00
Mikaël Capelle
f15908876d 2023 day 19. 2023-12-19 10:41:53 +01:00
Mikael CAPELLE
5f5ebda674 2023 day 18. 2023-12-18 11:40:32 +01:00
Mikaël Capelle
5b30cc00d5 2023 day 17. 2023-12-17 18:19:49 +01:00
Mikaël Capelle
3a7f8e83dc 2023 day 16. 2023-12-16 18:33:11 +01:00
Mikaël Capelle
ba5b01c594 2023 day 15. 2023-12-15 16:18:21 +01:00
Mikaël Capelle
d0970c090b 2023 day 14. 2023-12-14 19:34:38 +01:00
Mikaël Capelle
8e90bf7002 2023 day 13. 2023-12-13 20:05:05 +01:00
9698dfcdac 2023 day 12. 2023-12-12 20:20:26 +00:00
Mikaël Capelle
1a6ab1cc0e 2023 day 11. 2023-12-11 10:25:56 +01:00
Mikaël Capelle
f5aabbee8f 2021 day 8. 2023-12-10 20:23:22 +01:00
Mikaël Capelle
6c00341ab0 2023 day 10. 2023-12-10 10:09:12 +01:00
Mikaël Capelle
755e0bd4b3 2021 day 7. 2023-12-09 12:52:46 +01:00
Mikaël Capelle
a52d077a40 2021 day 6. 2023-12-09 12:36:10 +01:00
Mikaël Capelle
3fc0f94b1c 2021 day 1-5. 2023-12-09 11:01:28 +01:00
Mikaël Capelle
8a0412f926 Clean 2022. 2023-12-09 09:54:53 +01:00
Mikaël Capelle
855efeb0aa 2023 day 9. 2023-12-09 08:08:46 +01:00
Mikaël Capelle
f2a65e03e5 2023 day 8. 2023-12-08 08:44:03 +01:00
Mikaël Capelle
759f47bfab 2023 day 7. 2023-12-08 08:38:08 +01:00
Mikael CAPELLE
999207b007 Clean 2023. 2023-12-06 08:47:59 +01:00
Mikaël Capelle
d92e4744a4 2023 day 6. 2023-12-06 07:14:26 +01:00
Mikael CAPELLE
8dbf0f101c 2023 day 5. 2023-12-05 13:41:17 +01:00
Mikaël Capelle
b8d8df06d6 2023 day 5 part 1. 2023-12-05 07:22:56 +01:00
Mikaël Capelle
825ebea299 Prepare 2023 days. 2023-12-04 19:32:41 +01:00
Mikaël Capelle
869cd4477f 2023 day 4. 2023-12-04 19:30:44 +01:00
Mikaël Capelle
fd777627d6 2023 day 3. 2023-12-03 09:09:25 +01:00
Mikaël Capelle
98f605f30e 2023 day 2. 2023-12-02 09:47:52 +01:00
Mikaël Capelle
d51fed283c Fix 2023 day 1. 2023-12-01 20:27:42 +01:00
Mikael CAPELLE
e991cd8b04 2023: Day 1. 2023-12-01 10:41:13 +01:00
Mikael CAPELLE
10f67e6bfd Post-christmas cleaning. 2023-01-06 13:48:18 +01:00
Mikaël Capelle
f291b0aa3f Day 25. 2022-12-25 11:34:49 +01:00
Mikaël Capelle
0eb5b5a88f Faster day 24. 2022-12-24 23:00:14 +01:00
Mikaël Capelle
2ec0a3d5f9 Day 24. 2022-12-24 20:50:37 +01:00
Mikael CAPELLE
0327a3f36a Add day 23. 2022-12-23 13:25:22 +01:00
Mikaël Capelle
3732e70ef7 Ugly day 22. 2022-12-22 23:00:36 +01:00
Mikaël Capelle
b0cc6b4a46 Update day 22. 2022-12-22 18:46:59 +01:00
Mikael CAPELLE
8c24b9f9e2 Update day 22. 2022-12-22 17:22:56 +01:00
Mikael CAPELLE
dca6f6a08f Update day 22. 2022-12-22 17:00:09 +01:00
Mikael CAPELLE
8d7a20f575 Day 22 part 1. 2022-12-22 14:10:30 +01:00
Mikael CAPELLE
3934dfd152 Start day 22. 2022-12-22 08:20:09 +01:00
Mikael CAPELLE
b656e8929e Remove tqdm from day 19. 2022-12-21 17:39:43 +01:00
Mikael CAPELLE
c9c69f479b Day 21. 2022-12-21 09:44:05 +01:00
Mikaël Capelle
72ebcfff1f Clean day 20. 2022-12-20 23:39:26 +01:00
Mikaël Capelle
dd72bb3238 Add empty files for following days. 2022-12-20 21:51:38 +01:00
Mikael CAPELLE
c1dd74c57d Faster day 20. 2022-12-20 18:27:09 +01:00
Mikael CAPELLE
1bf2de62c7 Day 20, slow. 2022-12-20 13:39:36 +01:00
Mikael CAPELLE
df808bc98a Start day 20. 2022-12-20 12:35:01 +01:00
Mikaël Capelle
f46e190e98 Add all tests from previous days. 2022-12-19 22:32:15 +01:00
Mikaël Capelle
7f4a34b2d7 Day 19. 2022-12-19 22:09:20 +01:00
Mikael CAPELLE
ddebd26db2 Tmp 2022-12-19 18:46:16 +01:00
Mikael CAPELLE
01300e23b2 Start working on day 19. 2022-12-19 13:51:32 +01:00
Mikaël Capelle
b8e2faa8c9 Clean day 17. 2022-12-18 16:46:00 +01:00
Mikaël Capelle
ea5b757180 Day 18. 2022-12-18 09:57:35 +01:00
Mikaël Capelle
89a71c175f Day 17. 2022-12-17 12:27:05 +01:00
Mikaël Capelle
9ffb332dea Day 17. 2022-12-17 12:25:48 +01:00
Mikaël Capelle
8167ab34c7 Less BFS for day 16. 2022-12-16 22:56:34 +01:00
Mikaël Capelle
100df02a09 Better day 16. 2022-12-16 22:52:03 +01:00
Mikael CAPELLE
15b987a590 Update ugly day 16. 2022-12-16 18:40:21 +01:00
Mikael CAPELLE
b1578f5709 Add ugly day 16, to be improved... 2022-12-16 09:21:54 +01:00
Mikael CAPELLE
d80dbb6c7c Update day 15. 2022-12-15 14:17:04 +01:00
Mikael CAPELLE
b679c1f895 Add day 15. 2022-12-15 09:36:19 +01:00
Mikael CAPELLE
e9d5f9747b Add day 14. 2022-12-14 09:29:56 +01:00
Mikael CAPELLE
fe3aad7ddd Clean day 9. 2022-12-13 11:18:31 +01:00
Mikael CAPELLE
7ac9981ae5 Clean day 13. 2022-12-13 08:59:53 +01:00
Mikael CAPELLE
652756a341 Add day 13. 2022-12-13 08:54:15 +01:00
Mikael CAPELLE
c7ef505f1b Clean day 12. 2022-12-12 17:55:24 +01:00
Mikael CAPELLE
c55f6ac8e1 One to many Dijkstra. 2022-12-12 17:50:48 +01:00
Mikael CAPELLE
726a6aecac Generic Dijkstra for day 12. 2022-12-12 15:59:19 +01:00
Mikael CAPELLE
291b188238 Clean day 12. 2022-12-12 10:48:37 +01:00
Mikael CAPELLE
289e3b7d02 Add day 12. 2022-12-12 09:35:12 +01:00
Mikaël Capelle
9820765e9c Clean monkey code. 2022-12-11 11:50:23 +01:00
Mikaël Capelle
c6522de8a2 Add day 11. 2022-12-11 11:42:47 +01:00
Mikaël Capelle
80465e5e53 Add day 10. 2022-12-10 10:24:23 +01:00
Mikaël Capelle
af1428b5e1 Add day 9. 2022-12-09 10:45:00 +01:00
Mikael CAPELLE
fca283527d Add 2022 day 8. 2022-12-08 08:59:25 +01:00
Mikael CAPELLE
0d37458ec5 Add 2021 day 5. 2022-12-07 18:41:39 +01:00
Mikael CAPELLE
198927e4a3 Add day 7. 2022-12-07 09:28:06 +01:00
Mikael CAPELLE
4192c98bba Cleaning. 2022-12-06 15:28:46 +01:00
Mikael CAPELLE
7cb8317659 Add day 6. 2022-12-06 09:03:22 +01:00
Mikaël Capelle
f46cb51c60 Add day 4. 2022-12-05 19:09:55 +01:00
Mikael CAPELLE
261a396ae7 Add day 5. 2022-12-05 08:58:25 +01:00
Mikaël Capelle
4b3af377ab Day 3. 2022-12-03 11:42:09 +01:00
Mikael CAPELLE
f697415ef2 More comments. 2022-12-02 15:06:37 +01:00
Mikael CAPELLE
ac2806b0fb Comments. 2022-12-02 09:21:38 +01:00
Mikael CAPELLE
c62b8abfd0 Day 2. 2022-12-02 09:12:49 +01:00
152 changed files with 1653 additions and 20841 deletions

1
.gitignore vendored
View File

@@ -4,4 +4,3 @@ __pycache__
.ruff_cache .ruff_cache
.vscode .vscode
build build
files

504
poetry.lock generated
View File

@@ -1,15 +1,4 @@
# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. # This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand.
[[package]]
name = "absl-py"
version = "2.1.0"
description = "Abseil Python Common Libraries, see https://github.com/abseil/abseil-py."
optional = false
python-versions = ">=3.7"
files = [
{file = "absl-py-2.1.0.tar.gz", hash = "sha256:7820790efbb316739cde8b4e19357243fc3608a152024288513dd968d7d959ff"},
{file = "absl_py-2.1.0-py3-none-any.whl", hash = "sha256:526a04eadab8b4ee719ce68f204172ead1027549089702d99b9059f129ff1308"},
]
[[package]] [[package]]
name = "appnope" name = "appnope"
@@ -144,30 +133,6 @@ traitlets = ">=4"
[package.extras] [package.extras]
test = ["pytest"] test = ["pytest"]
[[package]]
name = "cplex"
version = "22.1.1.2"
description = "A Python interface to the CPLEX Callable Library, Community Edition."
optional = false
python-versions = "*"
files = [
{file = "cplex-22.1.1.2-cp310-cp310-macosx_10_6_x86_64.whl", hash = "sha256:d74a91f6e9c6f4ad4c7c69f7ab937ea9e91178a556f6f105c87eef9e434ea42e"},
{file = "cplex-22.1.1.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b066b5aa01fcf7cb471ad41920b3fecdd87dc95686e9a7031ff470873f0db10f"},
{file = "cplex-22.1.1.2-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:a7230032928b1a657c384d3f49c04d8b80d0ab8134a2f4c0b26ff50e71ec767a"},
{file = "cplex-22.1.1.2-cp310-cp310-manylinux2014_ppc64le.whl", hash = "sha256:dd81e8ee7a7f1fb5769bcbb1349b084b37c495cbd0db1a095d774f97d790ee3c"},
{file = "cplex-22.1.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:68b33bb9ff84be3442a6f71000e7214781c6aa8674143a9aa79cb9a84e697dfd"},
{file = "cplex-22.1.1.2-cp311-cp311-macosx_10_6_x86_64.whl", hash = "sha256:cda2f59af50d6c3d6476b2e38aba1e947f9bd72591d71961a9d53b5582062ba9"},
{file = "cplex-22.1.1.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0f69a539ed50994e26e32c3d2b203eb5f112d1ba64400241614e1a91c0933974"},
{file = "cplex-22.1.1.2-cp311-cp311-manylinux1_x86_64.whl", hash = "sha256:2a0f6984980779e6878a6cded52ee08806bae49af6bd209c7740549417e69e96"},
{file = "cplex-22.1.1.2-cp311-cp311-manylinux2014_ppc64le.whl", hash = "sha256:0ac0005414a09facbeaa976a89b3153d4ed15f23a89bf5d283f65d4e951f63be"},
{file = "cplex-22.1.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:46550cac476d74cc95dc3abf6f9bfe08c9fd61d889e20f2028f754b9fe503b88"},
{file = "cplex-22.1.1.2-cp39-cp39-macosx_10_6_x86_64.whl", hash = "sha256:21f6fd1ad4876a7775e64fe8a1fb43f6bb7a010c5e099abdb8c01887a8cc1d84"},
{file = "cplex-22.1.1.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d6acbf74c3fe32f2138a98730d1ebe3fa275c8c3fdcd8b1f68d312bfe9ef6899"},
{file = "cplex-22.1.1.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:3211f9c84f44c6317ea1e83a6c2ff1cfdc08532f421987b7faa8c07a018dfae5"},
{file = "cplex-22.1.1.2-cp39-cp39-manylinux2014_ppc64le.whl", hash = "sha256:648ad8c1c83ea30b0802c571a0dbf7fac23dcb9dc121ea0768c1794313aec2a7"},
{file = "cplex-22.1.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:285b26008a77942c6c9c29bff91e1658c1beed2aa520e1a8b26137d81abf81dc"},
]
[[package]] [[package]]
name = "debugpy" name = "debugpy"
version = "1.8.9" version = "1.8.9"
@@ -214,19 +179,6 @@ files = [
{file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"},
] ]
[[package]]
name = "docplex"
version = "2.28.240"
description = "The IBM Decision Optimization CPLEX Modeling for Python"
optional = false
python-versions = "*"
files = [
{file = "docplex-2.28.240.tar.gz", hash = "sha256:c0de407e33f8709bb4cd91b6efeb96fd88bfecbdce2caec51afb79253bde6ff5"},
]
[package.dependencies]
six = "*"
[[package]] [[package]]
name = "exceptiongroup" name = "exceptiongroup"
version = "1.2.2" version = "1.2.2"
@@ -255,50 +207,6 @@ files = [
[package.extras] [package.extras]
tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"] tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"]
[[package]]
name = "imageio"
version = "2.36.1"
description = "Library for reading and writing a wide range of image, video, scientific, and volumetric data formats."
optional = false
python-versions = ">=3.9"
files = [
{file = "imageio-2.36.1-py3-none-any.whl", hash = "sha256:20abd2cae58e55ca1af8a8dcf43293336a59adf0391f1917bf8518633cfc2cdf"},
{file = "imageio-2.36.1.tar.gz", hash = "sha256:e4e1d231f47f9a9e16100b0f7ce1a86e8856fb4d1c0fa2c4365a316f1746be62"},
]
[package.dependencies]
numpy = "*"
pillow = ">=8.3.2"
[package.extras]
all-plugins = ["astropy", "av", "imageio-ffmpeg", "numpy (>2)", "pillow-heif", "psutil", "rawpy", "tifffile"]
all-plugins-pypy = ["av", "imageio-ffmpeg", "pillow-heif", "psutil", "tifffile"]
build = ["wheel"]
dev = ["black", "flake8", "fsspec[github]", "pytest", "pytest-cov"]
docs = ["numpydoc", "pydata-sphinx-theme", "sphinx (<6)"]
ffmpeg = ["imageio-ffmpeg", "psutil"]
fits = ["astropy"]
full = ["astropy", "av", "black", "flake8", "fsspec[github]", "gdal", "imageio-ffmpeg", "itk", "numpy (>2)", "numpydoc", "pillow-heif", "psutil", "pydata-sphinx-theme", "pytest", "pytest-cov", "rawpy", "sphinx (<6)", "tifffile", "wheel"]
gdal = ["gdal"]
itk = ["itk"]
linting = ["black", "flake8"]
pillow-heif = ["pillow-heif"]
pyav = ["av"]
rawpy = ["numpy (>2)", "rawpy"]
test = ["fsspec[github]", "pytest", "pytest-cov"]
tifffile = ["tifffile"]
[[package]]
name = "immutabledict"
version = "4.2.1"
description = "Immutable wrapper around dictionaries (a fork of frozendict)"
optional = false
python-versions = ">=3.8"
files = [
{file = "immutabledict-4.2.1-py3-none-any.whl", hash = "sha256:c56a26ced38c236f79e74af3ccce53772827cef5c3bce7cab33ff2060f756373"},
{file = "immutabledict-4.2.1.tar.gz", hash = "sha256:d91017248981c72eb66c8ff9834e99c2f53562346f23e7f51e7a5ebcf66a3bcc"},
]
[[package]] [[package]]
name = "ipykernel" name = "ipykernel"
version = "6.29.5" version = "6.29.5"
@@ -522,133 +430,68 @@ files = [
[[package]] [[package]]
name = "numpy" name = "numpy"
version = "2.2.0" version = "2.1.3"
description = "Fundamental package for array computing in Python" description = "Fundamental package for array computing in Python"
optional = false optional = false
python-versions = ">=3.10" python-versions = ">=3.10"
files = [ files = [
{file = "numpy-2.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1e25507d85da11ff5066269d0bd25d06e0a0f2e908415534f3e603d2a78e4ffa"}, {file = "numpy-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c894b4305373b9c5576d7a12b473702afdf48ce5369c074ba304cc5ad8730dff"},
{file = "numpy-2.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a62eb442011776e4036af5c8b1a00b706c5bc02dc15eb5344b0c750428c94219"}, {file = "numpy-2.1.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b47fbb433d3260adcd51eb54f92a2ffbc90a4595f8970ee00e064c644ac788f5"},
{file = "numpy-2.2.0-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:b606b1aaf802e6468c2608c65ff7ece53eae1a6874b3765f69b8ceb20c5fa78e"}, {file = "numpy-2.1.3-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:825656d0743699c529c5943554d223c021ff0494ff1442152ce887ef4f7561a1"},
{file = "numpy-2.2.0-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:36b2b43146f646642b425dd2027730f99bac962618ec2052932157e213a040e9"}, {file = "numpy-2.1.3-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:6a4825252fcc430a182ac4dee5a505053d262c807f8a924603d411f6718b88fd"},
{file = "numpy-2.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fe8f3583e0607ad4e43a954e35c1748b553bfe9fdac8635c02058023277d1b3"}, {file = "numpy-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e711e02f49e176a01d0349d82cb5f05ba4db7d5e7e0defd026328e5cfb3226d3"},
{file = "numpy-2.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:122fd2fcfafdefc889c64ad99c228d5a1f9692c3a83f56c292618a59aa60ae83"}, {file = "numpy-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78574ac2d1a4a02421f25da9559850d59457bac82f2b8d7a44fe83a64f770098"},
{file = "numpy-2.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3f2f5cddeaa4424a0a118924b988746db6ffa8565e5829b1841a8a3bd73eb59a"}, {file = "numpy-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c7662f0e3673fe4e832fe07b65c50342ea27d989f92c80355658c7f888fcc83c"},
{file = "numpy-2.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7fe4bb0695fe986a9e4deec3b6857003b4cfe5c5e4aac0b95f6a658c14635e31"}, {file = "numpy-2.1.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:fa2d1337dc61c8dc417fbccf20f6d1e139896a30721b7f1e832b2bb6ef4eb6c4"},
{file = "numpy-2.2.0-cp310-cp310-win32.whl", hash = "sha256:b30042fe92dbd79f1ba7f6898fada10bdaad1847c44f2dff9a16147e00a93661"}, {file = "numpy-2.1.3-cp310-cp310-win32.whl", hash = "sha256:72dcc4a35a8515d83e76b58fdf8113a5c969ccd505c8a946759b24e3182d1f23"},
{file = "numpy-2.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:54dc1d6d66f8d37843ed281773c7174f03bf7ad826523f73435deb88ba60d2d4"}, {file = "numpy-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:ecc76a9ba2911d8d37ac01de72834d8849e55473457558e12995f4cd53e778e0"},
{file = "numpy-2.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9874bc2ff574c40ab7a5cbb7464bf9b045d617e36754a7bc93f933d52bd9ffc6"}, {file = "numpy-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4d1167c53b93f1f5d8a139a742b3c6f4d429b54e74e6b57d0eff40045187b15d"},
{file = "numpy-2.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0da8495970f6b101ddd0c38ace92edea30e7e12b9a926b57f5fabb1ecc25bb90"}, {file = "numpy-2.1.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c80e4a09b3d95b4e1cac08643f1152fa71a0a821a2d4277334c88d54b2219a41"},
{file = "numpy-2.2.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:0557eebc699c1c34cccdd8c3778c9294e8196df27d713706895edc6f57d29608"}, {file = "numpy-2.1.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:576a1c1d25e9e02ed7fa5477f30a127fe56debd53b8d2c89d5578f9857d03ca9"},
{file = "numpy-2.2.0-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:3579eaeb5e07f3ded59298ce22b65f877a86ba8e9fe701f5576c99bb17c283da"}, {file = "numpy-2.1.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:973faafebaae4c0aaa1a1ca1ce02434554d67e628b8d805e61f874b84e136b09"},
{file = "numpy-2.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40deb10198bbaa531509aad0cd2f9fadb26c8b94070831e2208e7df543562b74"}, {file = "numpy-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:762479be47a4863e261a840e8e01608d124ee1361e48b96916f38b119cfda04a"},
{file = "numpy-2.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2aed8fcf8abc3020d6a9ccb31dbc9e7d7819c56a348cc88fd44be269b37427e"}, {file = "numpy-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc6f24b3d1ecc1eebfbf5d6051faa49af40b03be1aaa781ebdadcbc090b4539b"},
{file = "numpy-2.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a222d764352c773aa5ebde02dd84dba3279c81c6db2e482d62a3fa54e5ece69b"}, {file = "numpy-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:17ee83a1f4fef3c94d16dc1802b998668b5419362c8a4f4e8a491de1b41cc3ee"},
{file = "numpy-2.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4e58666988605e251d42c2818c7d3d8991555381be26399303053b58a5bbf30d"}, {file = "numpy-2.1.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:15cb89f39fa6d0bdfb600ea24b250e5f1a3df23f901f51c8debaa6a5d122b2f0"},
{file = "numpy-2.2.0-cp311-cp311-win32.whl", hash = "sha256:4723a50e1523e1de4fccd1b9a6dcea750c2102461e9a02b2ac55ffeae09a4410"}, {file = "numpy-2.1.3-cp311-cp311-win32.whl", hash = "sha256:d9beb777a78c331580705326d2367488d5bc473b49a9bc3036c154832520aca9"},
{file = "numpy-2.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:16757cf28621e43e252c560d25b15f18a2f11da94fea344bf26c599b9cf54b73"}, {file = "numpy-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:d89dd2b6da69c4fff5e39c28a382199ddedc3a5be5390115608345dec660b9e2"},
{file = "numpy-2.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cff210198bb4cae3f3c100444c5eaa573a823f05c253e7188e1362a5555235b3"}, {file = "numpy-2.1.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f55ba01150f52b1027829b50d70ef1dafd9821ea82905b63936668403c3b471e"},
{file = "numpy-2.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:58b92a5828bd4d9aa0952492b7de803135038de47343b2aa3cc23f3b71a3dc4e"}, {file = "numpy-2.1.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:13138eadd4f4da03074851a698ffa7e405f41a0845a6b1ad135b81596e4e9958"},
{file = "numpy-2.2.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:ebe5e59545401fbb1b24da76f006ab19734ae71e703cdb4a8b347e84a0cece67"}, {file = "numpy-2.1.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:a6b46587b14b888e95e4a24d7b13ae91fa22386c199ee7b418f449032b2fa3b8"},
{file = "numpy-2.2.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:e2b8cd48a9942ed3f85b95ca4105c45758438c7ed28fff1e4ce3e57c3b589d8e"}, {file = "numpy-2.1.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:0fa14563cc46422e99daef53d725d0c326e99e468a9320a240affffe87852564"},
{file = "numpy-2.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57fcc997ffc0bef234b8875a54d4058afa92b0b0c4223fc1f62f24b3b5e86038"}, {file = "numpy-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8637dcd2caa676e475503d1f8fdb327bc495554e10838019651b76d17b98e512"},
{file = "numpy-2.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85ad7d11b309bd132d74397fcf2920933c9d1dc865487128f5c03d580f2c3d03"}, {file = "numpy-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2312b2aa89e1f43ecea6da6ea9a810d06aae08321609d8dc0d0eda6d946a541b"},
{file = "numpy-2.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cb24cca1968b21355cc6f3da1a20cd1cebd8a023e3c5b09b432444617949085a"}, {file = "numpy-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a38c19106902bb19351b83802531fea19dee18e5b37b36454f27f11ff956f7fc"},
{file = "numpy-2.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0798b138c291d792f8ea40fe3768610f3c7dd2574389e37c3f26573757c8f7ef"}, {file = "numpy-2.1.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:02135ade8b8a84011cbb67dc44e07c58f28575cf9ecf8ab304e51c05528c19f0"},
{file = "numpy-2.2.0-cp312-cp312-win32.whl", hash = "sha256:afe8fb968743d40435c3827632fd36c5fbde633b0423da7692e426529b1759b1"}, {file = "numpy-2.1.3-cp312-cp312-win32.whl", hash = "sha256:e6988e90fcf617da2b5c78902fe8e668361b43b4fe26dbf2d7b0f8034d4cafb9"},
{file = "numpy-2.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:3a4199f519e57d517ebd48cb76b36c82da0360781c6a0353e64c0cac30ecaad3"}, {file = "numpy-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:0d30c543f02e84e92c4b1f415b7c6b5326cbe45ee7882b6b77db7195fb971e3a"},
{file = "numpy-2.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f8c8b141ef9699ae777c6278b52c706b653bf15d135d302754f6b2e90eb30367"}, {file = "numpy-2.1.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:96fe52fcdb9345b7cd82ecd34547fca4321f7656d500eca497eb7ea5a926692f"},
{file = "numpy-2.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0f0986e917aca18f7a567b812ef7ca9391288e2acb7a4308aa9d265bd724bdae"}, {file = "numpy-2.1.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f653490b33e9c3a4c1c01d41bc2aef08f9475af51146e4a7710c450cf9761598"},
{file = "numpy-2.2.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:1c92113619f7b272838b8d6702a7f8ebe5edea0df48166c47929611d0b4dea69"}, {file = "numpy-2.1.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:dc258a761a16daa791081d026f0ed4399b582712e6fc887a95af09df10c5ca57"},
{file = "numpy-2.2.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:5a145e956b374e72ad1dff82779177d4a3c62bc8248f41b80cb5122e68f22d13"}, {file = "numpy-2.1.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:016d0f6f5e77b0f0d45d77387ffa4bb89816b57c835580c3ce8e099ef830befe"},
{file = "numpy-2.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18142b497d70a34b01642b9feabb70156311b326fdddd875a9981f34a369b671"}, {file = "numpy-2.1.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c181ba05ce8299c7aa3125c27b9c2167bca4a4445b7ce73d5febc411ca692e43"},
{file = "numpy-2.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a7d41d1612c1a82b64697e894b75db6758d4f21c3ec069d841e60ebe54b5b571"}, {file = "numpy-2.1.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5641516794ca9e5f8a4d17bb45446998c6554704d888f86df9b200e66bdcce56"},
{file = "numpy-2.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a98f6f20465e7618c83252c02041517bd2f7ea29be5378f09667a8f654a5918d"}, {file = "numpy-2.1.3-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ea4dedd6e394a9c180b33c2c872b92f7ce0f8e7ad93e9585312b0c5a04777a4a"},
{file = "numpy-2.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e09d40edfdb4e260cb1567d8ae770ccf3b8b7e9f0d9b5c2a9992696b30ce2742"}, {file = "numpy-2.1.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0df3635b9c8ef48bd3be5f862cf71b0a4716fa0e702155c45067c6b711ddcef"},
{file = "numpy-2.2.0-cp313-cp313-win32.whl", hash = "sha256:3905a5fffcc23e597ee4d9fb3fcd209bd658c352657548db7316e810ca80458e"}, {file = "numpy-2.1.3-cp313-cp313-win32.whl", hash = "sha256:50ca6aba6e163363f132b5c101ba078b8cbd3fa92c7865fd7d4d62d9779ac29f"},
{file = "numpy-2.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:a184288538e6ad699cbe6b24859206e38ce5fba28f3bcfa51c90d0502c1582b2"}, {file = "numpy-2.1.3-cp313-cp313-win_amd64.whl", hash = "sha256:747641635d3d44bcb380d950679462fae44f54b131be347d5ec2bce47d3df9ed"},
{file = "numpy-2.2.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:7832f9e8eb00be32f15fdfb9a981d6955ea9adc8574c521d48710171b6c55e95"}, {file = "numpy-2.1.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:996bb9399059c5b82f76b53ff8bb686069c05acc94656bb259b1d63d04a9506f"},
{file = "numpy-2.2.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f0dd071b95bbca244f4cb7f70b77d2ff3aaaba7fa16dc41f58d14854a6204e6c"}, {file = "numpy-2.1.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:45966d859916ad02b779706bb43b954281db43e185015df6eb3323120188f9e4"},
{file = "numpy-2.2.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:b0b227dcff8cdc3efbce66d4e50891f04d0a387cce282fe1e66199146a6a8fca"}, {file = "numpy-2.1.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:baed7e8d7481bfe0874b566850cb0b85243e982388b7b23348c6db2ee2b2ae8e"},
{file = "numpy-2.2.0-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:6ab153263a7c5ccaf6dfe7e53447b74f77789f28ecb278c3b5d49db7ece10d6d"}, {file = "numpy-2.1.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:a9f7f672a3388133335589cfca93ed468509cb7b93ba3105fce780d04a6576a0"},
{file = "numpy-2.2.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e500aba968a48e9019e42c0c199b7ec0696a97fa69037bea163b55398e390529"}, {file = "numpy-2.1.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7aac50327da5d208db2eec22eb11e491e3fe13d22653dce51b0f4109101b408"},
{file = "numpy-2.2.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:440cfb3db4c5029775803794f8638fbdbf71ec702caf32735f53b008e1eaece3"}, {file = "numpy-2.1.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4394bc0dbd074b7f9b52024832d16e019decebf86caf909d94f6b3f77a8ee3b6"},
{file = "numpy-2.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a55dc7a7f0b6198b07ec0cd445fbb98b05234e8b00c5ac4874a63372ba98d4ab"}, {file = "numpy-2.1.3-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:50d18c4358a0a8a53f12a8ba9d772ab2d460321e6a93d6064fc22443d189853f"},
{file = "numpy-2.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4bddbaa30d78c86329b26bd6aaaea06b1e47444da99eddac7bf1e2fab717bd72"}, {file = "numpy-2.1.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:14e253bd43fc6b37af4921b10f6add6925878a42a0c5fe83daee390bca80bc17"},
{file = "numpy-2.2.0-cp313-cp313t-win32.whl", hash = "sha256:30bf971c12e4365153afb31fc73f441d4da157153f3400b82db32d04de1e4066"}, {file = "numpy-2.1.3-cp313-cp313t-win32.whl", hash = "sha256:08788d27a5fd867a663f6fc753fd7c3ad7e92747efc73c53bca2f19f8bc06f48"},
{file = "numpy-2.2.0-cp313-cp313t-win_amd64.whl", hash = "sha256:d35717333b39d1b6bb8433fa758a55f1081543de527171543a2b710551d40881"}, {file = "numpy-2.1.3-cp313-cp313t-win_amd64.whl", hash = "sha256:2564fbdf2b99b3f815f2107c1bbc93e2de8ee655a69c261363a1172a79a257d4"},
{file = "numpy-2.2.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:e12c6c1ce84628c52d6367863773f7c8c8241be554e8b79686e91a43f1733773"}, {file = "numpy-2.1.3-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4f2015dfe437dfebbfce7c85c7b53d81ba49e71ba7eadbf1df40c915af75979f"},
{file = "numpy-2.2.0-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:b6207dc8fb3c8cb5668e885cef9ec7f70189bec4e276f0ff70d5aa078d32c88e"}, {file = "numpy-2.1.3-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:3522b0dfe983a575e6a9ab3a4a4dfe156c3e428468ff08ce582b9bb6bd1d71d4"},
{file = "numpy-2.2.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a50aeff71d0f97b6450d33940c7181b08be1441c6c193e678211bff11aa725e7"}, {file = "numpy-2.1.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c006b607a865b07cd981ccb218a04fc86b600411d83d6fc261357f1c0966755d"},
{file = "numpy-2.2.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:df12a1f99b99f569a7c2ae59aa2d31724e8d835fc7f33e14f4792e3071d11221"}, {file = "numpy-2.1.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e14e26956e6f1696070788252dcdff11b4aca4c3e8bd166e0df1bb8f315a67cb"},
{file = "numpy-2.2.0.tar.gz", hash = "sha256:140dd80ff8981a583a60980be1a655068f8adebf7a45a06a6858c873fcdcd4a0"}, {file = "numpy-2.1.3.tar.gz", hash = "sha256:aa08e04e08aaf974d4458def539dece0d28146d866a39da5639596f4921fd761"},
] ]
[[package]]
name = "opencv-python"
version = "4.10.0.84"
description = "Wrapper package for OpenCV python bindings."
optional = false
python-versions = ">=3.6"
files = [
{file = "opencv-python-4.10.0.84.tar.gz", hash = "sha256:72d234e4582e9658ffea8e9cae5b63d488ad06994ef12d81dc303b17472f3526"},
{file = "opencv_python-4.10.0.84-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:fc182f8f4cda51b45f01c64e4cbedfc2f00aff799debebc305d8d0210c43f251"},
{file = "opencv_python-4.10.0.84-cp37-abi3-macosx_12_0_x86_64.whl", hash = "sha256:71e575744f1d23f79741450254660442785f45a0797212852ee5199ef12eed98"},
{file = "opencv_python-4.10.0.84-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09a332b50488e2dda866a6c5573ee192fe3583239fb26ff2f7f9ceb0bc119ea6"},
{file = "opencv_python-4.10.0.84-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ace140fc6d647fbe1c692bcb2abce768973491222c067c131d80957c595b71f"},
{file = "opencv_python-4.10.0.84-cp37-abi3-win32.whl", hash = "sha256:2db02bb7e50b703f0a2d50c50ced72e95c574e1e5a0bb35a8a86d0b35c98c236"},
{file = "opencv_python-4.10.0.84-cp37-abi3-win_amd64.whl", hash = "sha256:32dbbd94c26f611dc5cc6979e6b7aa1f55a64d6b463cc1dcd3c95505a63e48fe"},
]
[package.dependencies]
numpy = [
{version = ">=1.26.0", markers = "python_version >= \"3.12\""},
{version = ">=1.23.5", markers = "python_version >= \"3.11\" and python_version < \"3.12\""},
{version = ">=1.21.4", markers = "python_version >= \"3.10\" and platform_system == \"Darwin\" and python_version < \"3.11\""},
{version = ">=1.21.2", markers = "platform_system != \"Darwin\" and python_version >= \"3.10\" and python_version < \"3.11\""},
]
[[package]]
name = "ortools"
version = "9.11.4210"
description = "Google OR-Tools python libraries and modules"
optional = false
python-versions = ">=3.8"
files = [
{file = "ortools-9.11.4210-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:127f20f03ce04c28f979eac635d1cacdc01597c9e035a1981070506294d7db9c"},
{file = "ortools-9.11.4210-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:250c62ba9e5fcaf18ada449bc0128c71bb0dbea83ddec5559cc506cff920235c"},
{file = "ortools-9.11.4210-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7c15cefc7bc71aa2f70bee157aaa7e51ed8cb74c3edd499d15b6f5cd79cdf5b"},
{file = "ortools-9.11.4210-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c3693f0cb07ee0b5d36c4817bcfe05a745e3a613798a2ed62eb998d7fff979c"},
{file = "ortools-9.11.4210-cp310-cp310-win_amd64.whl", hash = "sha256:6b9d4ae6c7e9efac7cbef8a6289e97e238c2f0a8ef587b3e56b71af14c2f04e6"},
{file = "ortools-9.11.4210-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:0f902caa1576d737714f6a4fa165db62469bce82115e250409607197b3b6b434"},
{file = "ortools-9.11.4210-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c6f3e2869396dc6d8ee2d11b65d6f88f6386bb3ad64212c0ad7a6d32ddcb48ca"},
{file = "ortools-9.11.4210-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a56c5844ff927ce3c5428159cdd01b7fdbe243e8062bf1dfdb2e0eb305a55a30"},
{file = "ortools-9.11.4210-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5a17a37aeaa7d149e2fe8c8dfd5f09630ae28ad734a109ad55536605f8059df"},
{file = "ortools-9.11.4210-cp311-cp311-win_amd64.whl", hash = "sha256:d9b858f0273e19f81555428d54d407428d0a70a8cb5df2c320935bb735f2c6bb"},
{file = "ortools-9.11.4210-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:079bea08c6341dcfe3fb9586eb6edec6ae80f4ed16ed366fd7a46ef4b5709009"},
{file = "ortools-9.11.4210-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7f55124f9d1afa6434d0d6de07c6a4eb836f29b00b3413d27138634d5d79b606"},
{file = "ortools-9.11.4210-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f48e3d4053a169440608d881c1abd2a706db885d9b0af85bf45b444a1fec244"},
{file = "ortools-9.11.4210-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03ecd32e5d760d48e59832ef6bf724f8cac95e4e40db72a7fb912abf7adcf931"},
{file = "ortools-9.11.4210-cp312-cp312-win_amd64.whl", hash = "sha256:bc1b6e4cc0a121ef888481a99194765e6df72d4d3da81f928543171a2bac8cbb"},
{file = "ortools-9.11.4210-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:a503291dc12dc44da48567c5e1f79c77cd054fb86176f2c99d2860bc5a57e03d"},
{file = "ortools-9.11.4210-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2fd0aa0b4edfb3088f086bc05d42a381cc3d03da4b8ad18ce18ba213ab2c719f"},
{file = "ortools-9.11.4210-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c242738a49279c3a58b4611a64dd24634f1638f4dbb435163e3f9308e7c84c9"},
{file = "ortools-9.11.4210-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db9186bbc7a30538f277e704e9e77ff52bc75aa2c17095a125b2dc212a75cf8e"},
{file = "ortools-9.11.4210-cp38-cp38-win_amd64.whl", hash = "sha256:afcca4919e1095a79af0375276c5377a2d75794ebd592c4cc841d9979e0526e7"},
{file = "ortools-9.11.4210-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:a2828e91960c4e4fcf27bc6e200e2cd61ce1c42d4a3b95481a842a58c8315345"},
{file = "ortools-9.11.4210-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8d7d1a105f105502cf2f785816b09b796e5845fd47efac0dc0e3c0476b4c961a"},
{file = "ortools-9.11.4210-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f250641d7b822be25237fb78aed0878b07e8afdefddb700bafcc52f32ad520a"},
{file = "ortools-9.11.4210-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd2c0b319f4c0999360ab45a85d5764838c9dd0fd33437d12e32b2c07cbe04e4"},
{file = "ortools-9.11.4210-cp39-cp39-win_amd64.whl", hash = "sha256:219ffa56e8e4f52561586cea3dd55eb0f5d174a84c83a819d71debad766338e3"},
]
[package.dependencies]
absl-py = ">=2.0.0"
immutabledict = ">=3.0.0"
numpy = ">=1.13.3"
pandas = ">=2.0.0"
protobuf = ">=5.26.1,<5.27"
[[package]] [[package]]
name = "packaging" name = "packaging"
version = "24.2" version = "24.2"
@@ -713,9 +556,9 @@ files = [
[package.dependencies] [package.dependencies]
numpy = [ numpy = [
{version = ">=1.26.0", markers = "python_version >= \"3.12\""},
{version = ">=1.23.2", markers = "python_version == \"3.11\""},
{version = ">=1.22.4", markers = "python_version < \"3.11\""}, {version = ">=1.22.4", markers = "python_version < \"3.11\""},
{version = ">=1.23.2", markers = "python_version == \"3.11\""},
{version = ">=1.26.0", markers = "python_version >= \"3.12\""},
] ]
python-dateutil = ">=2.8.2" python-dateutil = ">=2.8.2"
pytz = ">=2020.1" pytz = ">=2020.1"
@@ -797,98 +640,6 @@ files = [
[package.dependencies] [package.dependencies]
ptyprocess = ">=0.5" ptyprocess = ">=0.5"
[[package]]
name = "pillow"
version = "11.0.0"
description = "Python Imaging Library (Fork)"
optional = false
python-versions = ">=3.9"
files = [
{file = "pillow-11.0.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:6619654954dc4936fcff82db8eb6401d3159ec6be81e33c6000dfd76ae189947"},
{file = "pillow-11.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b3c5ac4bed7519088103d9450a1107f76308ecf91d6dabc8a33a2fcfb18d0fba"},
{file = "pillow-11.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a65149d8ada1055029fcb665452b2814fe7d7082fcb0c5bed6db851cb69b2086"},
{file = "pillow-11.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88a58d8ac0cc0e7f3a014509f0455248a76629ca9b604eca7dc5927cc593c5e9"},
{file = "pillow-11.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:c26845094b1af3c91852745ae78e3ea47abf3dbcd1cf962f16b9a5fbe3ee8488"},
{file = "pillow-11.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:1a61b54f87ab5786b8479f81c4b11f4d61702830354520837f8cc791ebba0f5f"},
{file = "pillow-11.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:674629ff60030d144b7bca2b8330225a9b11c482ed408813924619c6f302fdbb"},
{file = "pillow-11.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:598b4e238f13276e0008299bd2482003f48158e2b11826862b1eb2ad7c768b97"},
{file = "pillow-11.0.0-cp310-cp310-win32.whl", hash = "sha256:9a0f748eaa434a41fccf8e1ee7a3eed68af1b690e75328fd7a60af123c193b50"},
{file = "pillow-11.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:a5629742881bcbc1f42e840af185fd4d83a5edeb96475a575f4da50d6ede337c"},
{file = "pillow-11.0.0-cp310-cp310-win_arm64.whl", hash = "sha256:ee217c198f2e41f184f3869f3e485557296d505b5195c513b2bfe0062dc537f1"},
{file = "pillow-11.0.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:1c1d72714f429a521d8d2d018badc42414c3077eb187a59579f28e4270b4b0fc"},
{file = "pillow-11.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:499c3a1b0d6fc8213519e193796eb1a86a1be4b1877d678b30f83fd979811d1a"},
{file = "pillow-11.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8b2351c85d855293a299038e1f89db92a2f35e8d2f783489c6f0b2b5f3fe8a3"},
{file = "pillow-11.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f4dba50cfa56f910241eb7f883c20f1e7b1d8f7d91c750cd0b318bad443f4d5"},
{file = "pillow-11.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:5ddbfd761ee00c12ee1be86c9c0683ecf5bb14c9772ddbd782085779a63dd55b"},
{file = "pillow-11.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:45c566eb10b8967d71bf1ab8e4a525e5a93519e29ea071459ce517f6b903d7fa"},
{file = "pillow-11.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b4fd7bd29610a83a8c9b564d457cf5bd92b4e11e79a4ee4716a63c959699b306"},
{file = "pillow-11.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:cb929ca942d0ec4fac404cbf520ee6cac37bf35be479b970c4ffadf2b6a1cad9"},
{file = "pillow-11.0.0-cp311-cp311-win32.whl", hash = "sha256:006bcdd307cc47ba43e924099a038cbf9591062e6c50e570819743f5607404f5"},
{file = "pillow-11.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:52a2d8323a465f84faaba5236567d212c3668f2ab53e1c74c15583cf507a0291"},
{file = "pillow-11.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:16095692a253047fe3ec028e951fa4221a1f3ed3d80c397e83541a3037ff67c9"},
{file = "pillow-11.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d2c0a187a92a1cb5ef2c8ed5412dd8d4334272617f532d4ad4de31e0495bd923"},
{file = "pillow-11.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:084a07ef0821cfe4858fe86652fffac8e187b6ae677e9906e192aafcc1b69903"},
{file = "pillow-11.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8069c5179902dcdce0be9bfc8235347fdbac249d23bd90514b7a47a72d9fecf4"},
{file = "pillow-11.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f02541ef64077f22bf4924f225c0fd1248c168f86e4b7abdedd87d6ebaceab0f"},
{file = "pillow-11.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:fcb4621042ac4b7865c179bb972ed0da0218a076dc1820ffc48b1d74c1e37fe9"},
{file = "pillow-11.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:00177a63030d612148e659b55ba99527803288cea7c75fb05766ab7981a8c1b7"},
{file = "pillow-11.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8853a3bf12afddfdf15f57c4b02d7ded92c7a75a5d7331d19f4f9572a89c17e6"},
{file = "pillow-11.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3107c66e43bda25359d5ef446f59c497de2b5ed4c7fdba0894f8d6cf3822dafc"},
{file = "pillow-11.0.0-cp312-cp312-win32.whl", hash = "sha256:86510e3f5eca0ab87429dd77fafc04693195eec7fd6a137c389c3eeb4cfb77c6"},
{file = "pillow-11.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:8ec4a89295cd6cd4d1058a5e6aec6bf51e0eaaf9714774e1bfac7cfc9051db47"},
{file = "pillow-11.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:27a7860107500d813fcd203b4ea19b04babe79448268403172782754870dac25"},
{file = "pillow-11.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:bcd1fb5bb7b07f64c15618c89efcc2cfa3e95f0e3bcdbaf4642509de1942a699"},
{file = "pillow-11.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0e038b0745997c7dcaae350d35859c9715c71e92ffb7e0f4a8e8a16732150f38"},
{file = "pillow-11.0.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ae08bd8ffc41aebf578c2af2f9d8749d91f448b3bfd41d7d9ff573d74f2a6b2"},
{file = "pillow-11.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d69bfd8ec3219ae71bcde1f942b728903cad25fafe3100ba2258b973bd2bc1b2"},
{file = "pillow-11.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:61b887f9ddba63ddf62fd02a3ba7add935d053b6dd7d58998c630e6dbade8527"},
{file = "pillow-11.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:c6a660307ca9d4867caa8d9ca2c2658ab685de83792d1876274991adec7b93fa"},
{file = "pillow-11.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:73e3a0200cdda995c7e43dd47436c1548f87a30bb27fb871f352a22ab8dcf45f"},
{file = "pillow-11.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fba162b8872d30fea8c52b258a542c5dfd7b235fb5cb352240c8d63b414013eb"},
{file = "pillow-11.0.0-cp313-cp313-win32.whl", hash = "sha256:f1b82c27e89fffc6da125d5eb0ca6e68017faf5efc078128cfaa42cf5cb38798"},
{file = "pillow-11.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:8ba470552b48e5835f1d23ecb936bb7f71d206f9dfeee64245f30c3270b994de"},
{file = "pillow-11.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:846e193e103b41e984ac921b335df59195356ce3f71dcfd155aa79c603873b84"},
{file = "pillow-11.0.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4ad70c4214f67d7466bea6a08061eba35c01b1b89eaa098040a35272a8efb22b"},
{file = "pillow-11.0.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:6ec0d5af64f2e3d64a165f490d96368bb5dea8b8f9ad04487f9ab60dc4bb6003"},
{file = "pillow-11.0.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c809a70e43c7977c4a42aefd62f0131823ebf7dd73556fa5d5950f5b354087e2"},
{file = "pillow-11.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:4b60c9520f7207aaf2e1d94de026682fc227806c6e1f55bba7606d1c94dd623a"},
{file = "pillow-11.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:1e2688958a840c822279fda0086fec1fdab2f95bf2b717b66871c4ad9859d7e8"},
{file = "pillow-11.0.0-cp313-cp313t-win32.whl", hash = "sha256:607bbe123c74e272e381a8d1957083a9463401f7bd01287f50521ecb05a313f8"},
{file = "pillow-11.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5c39ed17edea3bc69c743a8dd3e9853b7509625c2462532e62baa0732163a904"},
{file = "pillow-11.0.0-cp313-cp313t-win_arm64.whl", hash = "sha256:75acbbeb05b86bc53cbe7b7e6fe00fbcf82ad7c684b3ad82e3d711da9ba287d3"},
{file = "pillow-11.0.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:2e46773dc9f35a1dd28bd6981332fd7f27bec001a918a72a79b4133cf5291dba"},
{file = "pillow-11.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2679d2258b7f1192b378e2893a8a0a0ca472234d4c2c0e6bdd3380e8dfa21b6a"},
{file = "pillow-11.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eda2616eb2313cbb3eebbe51f19362eb434b18e3bb599466a1ffa76a033fb916"},
{file = "pillow-11.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20ec184af98a121fb2da42642dea8a29ec80fc3efbaefb86d8fdd2606619045d"},
{file = "pillow-11.0.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:8594f42df584e5b4bb9281799698403f7af489fba84c34d53d1c4bfb71b7c4e7"},
{file = "pillow-11.0.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:c12b5ae868897c7338519c03049a806af85b9b8c237b7d675b8c5e089e4a618e"},
{file = "pillow-11.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:70fbbdacd1d271b77b7721fe3cdd2d537bbbd75d29e6300c672ec6bb38d9672f"},
{file = "pillow-11.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5178952973e588b3f1360868847334e9e3bf49d19e169bbbdfaf8398002419ae"},
{file = "pillow-11.0.0-cp39-cp39-win32.whl", hash = "sha256:8c676b587da5673d3c75bd67dd2a8cdfeb282ca38a30f37950511766b26858c4"},
{file = "pillow-11.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:94f3e1780abb45062287b4614a5bc0874519c86a777d4a7ad34978e86428b8dd"},
{file = "pillow-11.0.0-cp39-cp39-win_arm64.whl", hash = "sha256:290f2cc809f9da7d6d622550bbf4c1e57518212da51b6a30fe8e0a270a5b78bd"},
{file = "pillow-11.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1187739620f2b365de756ce086fdb3604573337cc28a0d3ac4a01ab6b2d2a6d2"},
{file = "pillow-11.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:fbbcb7b57dc9c794843e3d1258c0fbf0f48656d46ffe9e09b63bbd6e8cd5d0a2"},
{file = "pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d203af30149ae339ad1b4f710d9844ed8796e97fda23ffbc4cc472968a47d0b"},
{file = "pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21a0d3b115009ebb8ac3d2ebec5c2982cc693da935f4ab7bb5c8ebe2f47d36f2"},
{file = "pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:73853108f56df97baf2bb8b522f3578221e56f646ba345a372c78326710d3830"},
{file = "pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e58876c91f97b0952eb766123bfef372792ab3f4e3e1f1a2267834c2ab131734"},
{file = "pillow-11.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:224aaa38177597bb179f3ec87eeefcce8e4f85e608025e9cfac60de237ba6316"},
{file = "pillow-11.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5bd2d3bdb846d757055910f0a59792d33b555800813c3b39ada1829c372ccb06"},
{file = "pillow-11.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:375b8dd15a1f5d2feafff536d47e22f69625c1aa92f12b339ec0b2ca40263273"},
{file = "pillow-11.0.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:daffdf51ee5db69a82dd127eabecce20729e21f7a3680cf7cbb23f0829189790"},
{file = "pillow-11.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7326a1787e3c7b0429659e0a944725e1b03eeaa10edd945a86dead1913383944"},
{file = "pillow-11.0.0.tar.gz", hash = "sha256:72bacbaf24ac003fea9bff9837d1eedb6088758d41e100c1552930151f677739"},
]
[package.extras]
docs = ["furo", "olefile", "sphinx (>=8.1)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"]
fpx = ["olefile"]
mic = ["olefile"]
tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"]
typing = ["typing-extensions"]
xmp = ["defusedxml"]
[[package]] [[package]]
name = "platformdirs" name = "platformdirs"
version = "4.3.6" version = "4.3.6"
@@ -938,26 +689,6 @@ files = [
[package.dependencies] [package.dependencies]
wcwidth = "*" wcwidth = "*"
[[package]]
name = "protobuf"
version = "5.26.1"
description = ""
optional = false
python-versions = ">=3.8"
files = [
{file = "protobuf-5.26.1-cp310-abi3-win32.whl", hash = "sha256:3c388ea6ddfe735f8cf69e3f7dc7611e73107b60bdfcf5d0f024c3ccd3794e23"},
{file = "protobuf-5.26.1-cp310-abi3-win_amd64.whl", hash = "sha256:e6039957449cb918f331d32ffafa8eb9255769c96aa0560d9a5bf0b4e00a2a33"},
{file = "protobuf-5.26.1-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:38aa5f535721d5bb99861166c445c4105c4e285c765fbb2ac10f116e32dcd46d"},
{file = "protobuf-5.26.1-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:fbfe61e7ee8c1860855696e3ac6cfd1b01af5498facc6834fcc345c9684fb2ca"},
{file = "protobuf-5.26.1-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:f7417703f841167e5a27d48be13389d52ad705ec09eade63dfc3180a959215d7"},
{file = "protobuf-5.26.1-cp38-cp38-win32.whl", hash = "sha256:d693d2504ca96750d92d9de8a103102dd648fda04540495535f0fec7577ed8fc"},
{file = "protobuf-5.26.1-cp38-cp38-win_amd64.whl", hash = "sha256:9b557c317ebe6836835ec4ef74ec3e994ad0894ea424314ad3552bc6e8835b4e"},
{file = "protobuf-5.26.1-cp39-cp39-win32.whl", hash = "sha256:b9ba3ca83c2e31219ffbeb9d76b63aad35a3eb1544170c55336993d7a18ae72c"},
{file = "protobuf-5.26.1-cp39-cp39-win_amd64.whl", hash = "sha256:7ee014c2c87582e101d6b54260af03b6596728505c79f17c8586e7523aaa8f8c"},
{file = "protobuf-5.26.1-py3-none-any.whl", hash = "sha256:da612f2720c0183417194eeaa2523215c4fcc1a1949772dc65f05047e08d5932"},
{file = "protobuf-5.26.1.tar.gz", hash = "sha256:8ca2a1d97c290ec7b16e4e5dff2e5ae150cc1582f55b5ab300d45cb0dfa90e51"},
]
[[package]] [[package]]
name = "psutil" name = "psutil"
version = "6.1.0" version = "6.1.0"
@@ -1024,19 +755,6 @@ files = [
{file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"},
] ]
[[package]]
name = "pygifsicle"
version = "1.1.0"
description = "Python package wrapping the gifsicle library for editing and optimizing gifs."
optional = false
python-versions = "*"
files = [
{file = "pygifsicle-1.1.0.tar.gz", hash = "sha256:dcef433520ace4c1136dfc7060e77042142a3dbd6bdb6a19bd9149ef5cbe7441"},
]
[package.extras]
test = ["pytest", "pytest-cov", "touch", "validate_version_code"]
[[package]] [[package]]
name = "pygments" name = "pygments"
version = "2.18.0" version = "2.18.0"
@@ -1053,13 +771,13 @@ windows-terminal = ["colorama (>=0.4.6)"]
[[package]] [[package]]
name = "pyright" name = "pyright"
version = "1.1.390" version = "1.1.389"
description = "Command line wrapper for pyright" description = "Command line wrapper for pyright"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "pyright-1.1.390-py3-none-any.whl", hash = "sha256:ecebfba5b6b50af7c1a44c2ba144ba2ab542c227eb49bc1f16984ff714e0e110"}, {file = "pyright-1.1.389-py3-none-any.whl", hash = "sha256:41e9620bba9254406dc1f621a88ceab5a88af4c826feb4f614d95691ed243a60"},
{file = "pyright-1.1.390.tar.gz", hash = "sha256:aad7f160c49e0fbf8209507a15e17b781f63a86a1facb69ca877c71ef2e9538d"}, {file = "pyright-1.1.389.tar.gz", hash = "sha256:716bf8cc174ab8b4dcf6828c3298cac05c5ed775dda9910106a5dcfe4c7fe220"},
] ]
[package.dependencies] [package.dependencies]
@@ -1308,40 +1026,90 @@ cffi = {version = "*", markers = "implementation_name == \"pypy\""}
[[package]] [[package]]
name = "ruff" name = "ruff"
version = "0.8.3" version = "0.8.1"
description = "An extremely fast Python linter and code formatter, written in Rust." description = "An extremely fast Python linter and code formatter, written in Rust."
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "ruff-0.8.3-py3-none-linux_armv6l.whl", hash = "sha256:8d5d273ffffff0acd3db5bf626d4b131aa5a5ada1276126231c4174543ce20d6"}, {file = "ruff-0.8.1-py3-none-linux_armv6l.whl", hash = "sha256:fae0805bd514066f20309f6742f6ee7904a773eb9e6c17c45d6b1600ca65c9b5"},
{file = "ruff-0.8.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:e4d66a21de39f15c9757d00c50c8cdd20ac84f55684ca56def7891a025d7e939"}, {file = "ruff-0.8.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b8a4f7385c2285c30f34b200ca5511fcc865f17578383db154e098150ce0a087"},
{file = "ruff-0.8.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c356e770811858bd20832af696ff6c7e884701115094f427b64b25093d6d932d"}, {file = "ruff-0.8.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:cd054486da0c53e41e0086e1730eb77d1f698154f910e0cd9e0d64274979a209"},
{file = "ruff-0.8.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c0a60a825e3e177116c84009d5ebaa90cf40dfab56e1358d1df4e29a9a14b13"}, {file = "ruff-0.8.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2029b8c22da147c50ae577e621a5bfbc5d1fed75d86af53643d7a7aee1d23871"},
{file = "ruff-0.8.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:75fb782f4db39501210ac093c79c3de581d306624575eddd7e4e13747e61ba18"}, {file = "ruff-0.8.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2666520828dee7dfc7e47ee4ea0d928f40de72056d929a7c5292d95071d881d1"},
{file = "ruff-0.8.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f26bc76a133ecb09a38b7868737eded6941b70a6d34ef53a4027e83913b6502"}, {file = "ruff-0.8.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:333c57013ef8c97a53892aa56042831c372e0bb1785ab7026187b7abd0135ad5"},
{file = "ruff-0.8.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:01b14b2f72a37390c1b13477c1c02d53184f728be2f3ffc3ace5b44e9e87b90d"}, {file = "ruff-0.8.1-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:288326162804f34088ac007139488dcb43de590a5ccfec3166396530b58fb89d"},
{file = "ruff-0.8.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:53babd6e63e31f4e96ec95ea0d962298f9f0d9cc5990a1bbb023a6baf2503a82"}, {file = "ruff-0.8.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b12c39b9448632284561cbf4191aa1b005882acbc81900ffa9f9f471c8ff7e26"},
{file = "ruff-0.8.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1ae441ce4cf925b7f363d33cd6570c51435972d697e3e58928973994e56e1452"}, {file = "ruff-0.8.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:364e6674450cbac8e998f7b30639040c99d81dfb5bbc6dfad69bc7a8f916b3d1"},
{file = "ruff-0.8.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7c65bc0cadce32255e93c57d57ecc2cca23149edd52714c0c5d6fa11ec328cd"}, {file = "ruff-0.8.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b22346f845fec132aa39cd29acb94451d030c10874408dbf776af3aaeb53284c"},
{file = "ruff-0.8.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:5be450bb18f23f0edc5a4e5585c17a56ba88920d598f04a06bd9fd76d324cb20"}, {file = "ruff-0.8.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b2f2f7a7e7648a2bfe6ead4e0a16745db956da0e3a231ad443d2a66a105c04fa"},
{file = "ruff-0.8.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8faeae3827eaa77f5721f09b9472a18c749139c891dbc17f45e72d8f2ca1f8fc"}, {file = "ruff-0.8.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:adf314fc458374c25c5c4a4a9270c3e8a6a807b1bec018cfa2813d6546215540"},
{file = "ruff-0.8.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:db503486e1cf074b9808403991663e4277f5c664d3fe237ee0d994d1305bb060"}, {file = "ruff-0.8.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a885d68342a231b5ba4d30b8c6e1b1ee3a65cf37e3d29b3c74069cdf1ee1e3c9"},
{file = "ruff-0.8.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:6567be9fb62fbd7a099209257fef4ad2c3153b60579818b31a23c886ed4147ea"}, {file = "ruff-0.8.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:d2c16e3508c8cc73e96aa5127d0df8913d2290098f776416a4b157657bee44c5"},
{file = "ruff-0.8.3-py3-none-win32.whl", hash = "sha256:19048f2f878f3ee4583fc6cb23fb636e48c2635e30fb2022b3a1cd293402f964"}, {file = "ruff-0.8.1-py3-none-win32.whl", hash = "sha256:93335cd7c0eaedb44882d75a7acb7df4b77cd7cd0d2255c93b28791716e81790"},
{file = "ruff-0.8.3-py3-none-win_amd64.whl", hash = "sha256:f7df94f57d7418fa7c3ffb650757e0c2b96cf2501a0b192c18e4fb5571dfada9"}, {file = "ruff-0.8.1-py3-none-win_amd64.whl", hash = "sha256:2954cdbe8dfd8ab359d4a30cd971b589d335a44d444b6ca2cb3d1da21b75e4b6"},
{file = "ruff-0.8.3-py3-none-win_arm64.whl", hash = "sha256:fe2756edf68ea79707c8d68b78ca9a58ed9af22e430430491ee03e718b5e4936"}, {file = "ruff-0.8.1-py3-none-win_arm64.whl", hash = "sha256:55873cc1a473e5ac129d15eccb3c008c096b94809d693fc7053f588b67822737"},
{file = "ruff-0.8.3.tar.gz", hash = "sha256:5e7558304353b84279042fc584a4f4cb8a07ae79b2bf3da1a7551d960b5626d3"}, {file = "ruff-0.8.1.tar.gz", hash = "sha256:3583db9a6450364ed5ca3f3b4225958b24f78178908d5c4bc0f46251ccca898f"},
] ]
[[package]]
name = "scipy"
version = "1.14.1"
description = "Fundamental algorithms for scientific computing in Python"
optional = false
python-versions = ">=3.10"
files = [
{file = "scipy-1.14.1-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:b28d2ca4add7ac16ae8bb6632a3c86e4b9e4d52d3e34267f6e1b0c1f8d87e389"},
{file = "scipy-1.14.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:d0d2821003174de06b69e58cef2316a6622b60ee613121199cb2852a873f8cf3"},
{file = "scipy-1.14.1-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:8bddf15838ba768bb5f5083c1ea012d64c9a444e16192762bd858f1e126196d0"},
{file = "scipy-1.14.1-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:97c5dddd5932bd2a1a31c927ba5e1463a53b87ca96b5c9bdf5dfd6096e27efc3"},
{file = "scipy-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ff0a7e01e422c15739ecd64432743cf7aae2b03f3084288f399affcefe5222d"},
{file = "scipy-1.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e32dced201274bf96899e6491d9ba3e9a5f6b336708656466ad0522d8528f69"},
{file = "scipy-1.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8426251ad1e4ad903a4514712d2fa8fdd5382c978010d1c6f5f37ef286a713ad"},
{file = "scipy-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:a49f6ed96f83966f576b33a44257d869756df6cf1ef4934f59dd58b25e0327e5"},
{file = "scipy-1.14.1-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:2da0469a4ef0ecd3693761acbdc20f2fdeafb69e6819cc081308cc978153c675"},
{file = "scipy-1.14.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:c0ee987efa6737242745f347835da2cc5bb9f1b42996a4d97d5c7ff7928cb6f2"},
{file = "scipy-1.14.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3a1b111fac6baec1c1d92f27e76511c9e7218f1695d61b59e05e0fe04dc59617"},
{file = "scipy-1.14.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:8475230e55549ab3f207bff11ebfc91c805dc3463ef62eda3ccf593254524ce8"},
{file = "scipy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:278266012eb69f4a720827bdd2dc54b2271c97d84255b2faaa8f161a158c3b37"},
{file = "scipy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fef8c87f8abfb884dac04e97824b61299880c43f4ce675dd2cbeadd3c9b466d2"},
{file = "scipy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b05d43735bb2f07d689f56f7b474788a13ed8adc484a85aa65c0fd931cf9ccd2"},
{file = "scipy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:716e389b694c4bb564b4fc0c51bc84d381735e0d39d3f26ec1af2556ec6aad94"},
{file = "scipy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:631f07b3734d34aced009aaf6fedfd0eb3498a97e581c3b1e5f14a04164a456d"},
{file = "scipy-1.14.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:af29a935803cc707ab2ed7791c44288a682f9c8107bc00f0eccc4f92c08d6e07"},
{file = "scipy-1.14.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:2843f2d527d9eebec9a43e6b406fb7266f3af25a751aa91d62ff416f54170bc5"},
{file = "scipy-1.14.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:eb58ca0abd96911932f688528977858681a59d61a7ce908ffd355957f7025cfc"},
{file = "scipy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30ac8812c1d2aab7131a79ba62933a2a76f582d5dbbc695192453dae67ad6310"},
{file = "scipy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f9ea80f2e65bdaa0b7627fb00cbeb2daf163caa015e59b7516395fe3bd1e066"},
{file = "scipy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:edaf02b82cd7639db00dbff629995ef185c8df4c3ffa71a5562a595765a06ce1"},
{file = "scipy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:2ff38e22128e6c03ff73b6bb0f85f897d2362f8c052e3b8ad00532198fbdae3f"},
{file = "scipy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1729560c906963fc8389f6aac023739ff3983e727b1a4d87696b7bf108316a79"},
{file = "scipy-1.14.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:4079b90df244709e675cdc8b93bfd8a395d59af40b72e339c2287c91860deb8e"},
{file = "scipy-1.14.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:e0cf28db0f24a38b2a0ca33a85a54852586e43cf6fd876365c86e0657cfe7d73"},
{file = "scipy-1.14.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:0c2f95de3b04e26f5f3ad5bb05e74ba7f68b837133a4492414b3afd79dfe540e"},
{file = "scipy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b99722ea48b7ea25e8e015e8341ae74624f72e5f21fc2abd45f3a93266de4c5d"},
{file = "scipy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5149e3fd2d686e42144a093b206aef01932a0059c2a33ddfa67f5f035bdfe13e"},
{file = "scipy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4f5a7c49323533f9103d4dacf4e4f07078f360743dec7f7596949149efeec06"},
{file = "scipy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:baff393942b550823bfce952bb62270ee17504d02a1801d7fd0719534dfb9c84"},
{file = "scipy-1.14.1.tar.gz", hash = "sha256:5a275584e726026a5699459aa72f828a610821006228e841b94275c4a7c08417"},
]
[package.dependencies]
numpy = ">=1.23.5,<2.3"
[package.extras]
dev = ["cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy (==1.10.0)", "pycodestyle", "pydevtool", "rich-click", "ruff (>=0.0.292)", "types-psutil", "typing_extensions"]
doc = ["jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.13.1)", "jupytext", "matplotlib (>=3.5)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<=7.3.7)", "sphinx-design (>=0.4.0)"]
test = ["Cython", "array-api-strict (>=2.0)", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"]
[[package]] [[package]]
name = "six" name = "six"
version = "1.17.0" version = "1.16.0"
description = "Python 2 and 3 compatibility utilities" description = "Python 2 and 3 compatibility utilities"
optional = false optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
files = [ files = [
{file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
{file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
] ]
[[package]] [[package]]
@@ -1527,4 +1295,4 @@ files = [
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = "^3.10" python-versions = "^3.10"
content-hash = "5b57bccd8dc65a9acecbe187939bae625ef6a259f4188c6587907245bcfa604f" content-hash = "c91bc307ff4a5b3e8cd1976ebea211c9749fe09d563dd80861f70ce26826cda9"

View File

@@ -12,12 +12,10 @@ python = "^3.10"
numpy = "^2.1.3" numpy = "^2.1.3"
tqdm = "^4.67.1" tqdm = "^4.67.1"
parse = "^1.20.2" parse = "^1.20.2"
scipy = "^1.14.1"
sympy = "^1.13.3" sympy = "^1.13.3"
networkx = "^3.4.2" networkx = "^3.4.2"
pillow = "^11.0.0" pandas = "^2.2.3"
imageio = "^2.36.1"
pygifsicle = "^1.1.0"
opencv-python = "^4.10.0.84"
[tool.poetry.group.dev.dependencies] [tool.poetry.group.dev.dependencies]
pyright = "^1.1.389" pyright = "^1.1.389"
@@ -27,13 +25,6 @@ ipykernel = "^6.29.5"
networkx-stubs = "^0.0.1" networkx-stubs = "^0.0.1"
types-networkx = "^3.4.2.20241115" types-networkx = "^3.4.2.20241115"
[tool.poetry.group.cplex.dependencies]
docplex = "^2.28.240"
cplex = "^22.1.1.2"
[tool.poetry.group.ortools.dependencies]
ortools = "^9.11.4210"
[tool.poetry.scripts] [tool.poetry.scripts]
holt59-aoc = "holt59.aoc.__main__:main" holt59-aoc = "holt59.aoc.__main__:main"

View File

@@ -52,6 +52,7 @@ class Solver(BaseSolver):
m2 += molecule[i] m2 += molecule[i]
i += 1 i += 1
# print(m2)
molecule = m2 molecule = m2
yield count yield count

View File

@@ -173,6 +173,7 @@ class Solver(BaseSolver):
) )
) )
# 1242 (not working)
yield sum( yield sum(
c c
for _, c in play( for _, c in play(

View File

@@ -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"]

View File

@@ -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)

View File

@@ -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

View File

@@ -1,17 +1,14 @@
from typing import Any, Iterator import sys
from ..base import BaseSolver lines = sys.stdin.read().splitlines()
class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]:
lines = input.splitlines()
values = [int(line) for line in lines] values = [int(line) for line in lines]
# part 1 # part 1
yield sum(v2 > v1 for v1, v2 in zip(values[:-1], values[1:])) answer_1 = sum(v2 > v1 for v1, v2 in zip(values[:-1], values[1:]))
print(f"answer 1 is {answer_1}")
# part 2 # part 2
runnings = [sum(values[i : i + 3]) for i in range(len(values) - 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:])) answer_2 = sum(v2 > v1 for v1, v2 in zip(runnings[:-1], runnings[1:]))
print(f"answer 2 is {answer_2}")

View File

@@ -1,47 +1,11 @@
from functools import reduce import sys
from typing import Any, Iterator
from ..base import BaseSolver lines = sys.stdin.read().splitlines()
BRACKETS = {"{": "}", "[": "]", "<": ">", "(": ")"} # part 1
answer_1 = ...
print(f"answer 1 is {answer_1}")
CORRUPT_SCORES = {")": 3, "]": 57, "}": 1197, ">": 25137} # part 2
COMPLETE_SCORES = {")": 1, "]": 2, "}": 3, ">": 4} answer_2 = ...
print(f"answer 2 is {answer_2}")
def corrupted_or_incomplete(line: str) -> tuple[bool, str]:
opens: list[str] = []
for c in line:
if c in BRACKETS:
opens.append(c)
elif BRACKETS[opens[-1]] != c:
return True, c
else:
opens.pop()
return (False, "".join(opens))
class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]:
lines = input.splitlines()
answer_1: int = 0
incomplete_scores: list[int] = []
for line in lines:
c, r = corrupted_or_incomplete(line)
if c:
answer_1 += CORRUPT_SCORES[r]
else:
incomplete_scores.append(
reduce(
lambda s, c: s * 5 + COMPLETE_SCORES[BRACKETS[c]],
reversed(r),
0,
),
)
yield answer_1
yield sorted(incomplete_scores)[len(incomplete_scores) // 2]

View File

@@ -1,66 +1,11 @@
import itertools as it import sys
from typing import Any, Iterator
from ..base import BaseSolver lines = sys.stdin.read().splitlines()
# part 1
answer_1 = ...
print(f"answer 1 is {answer_1}")
def do_step(values: list[list[int]]) -> tuple[list[list[int]], set[tuple[int, int]]]: # part 2
values = [[c + 1 for c in r] for r in values] answer_2 = ...
flashed: set[tuple[int, int]] = set() print(f"answer 2 is {answer_2}")
while True:
found = False
for i_row, row in enumerate(values):
for i_col, col in enumerate(row):
if col <= 9 or (i_row, i_col) in flashed:
continue
found = True
flashed.add((i_row, i_col))
for dr, dc in it.product((-1, 0, 1), repeat=2):
if 0 <= i_row + dr < len(values) and 0 <= i_col + dc < len(
values[0]
):
values[i_row + dr][i_col + dc] += 1
if not found:
break
for i, j in flashed:
values[i][j] = 0
return values, flashed
class Solver(BaseSolver):
def print_grid(self, values: list[list[int]], flashed: set[tuple[int, int]]):
for i_row, row in enumerate(values):
s_row = ""
for i_col, col in enumerate(row):
if (i_row, i_col) in flashed:
s_row += f"\033[0;31m{col}\033[0;00m"
else:
s_row += str(col)
self.logger.info(s_row)
self.logger.info("")
def solve(self, input: str) -> Iterator[Any]:
values_0 = [[int(c) for c in r] for r in input.splitlines()]
values = values_0
total_flashed: int = 0
for _ in range(100):
values, flashed = do_step(values)
total_flashed += len(flashed)
yield total_flashed
n_cells = len(values) * len(values[0])
flashed: set[tuple[int, int]] = set()
values, step = values_0, 0
while len(flashed) != n_cells:
values, flashed = do_step(values)
step += 1
yield step

View File

@@ -1,64 +1,11 @@
import string import sys
from collections import defaultdict
from functools import cache
from typing import Any, Iterator, Mapping, Sequence
from ..base import BaseSolver lines = sys.stdin.read().splitlines()
# part 1
answer_1 = ...
print(f"answer 1 is {answer_1}")
@cache # part 2
def is_small(node: str): answer_2 = ...
return all(c in string.ascii_lowercase for c in node) print(f"answer 2 is {answer_2}")
def enumerate_paths(
neighbors: Mapping[str, Sequence[str]],
duplicate_smalls: int = 0,
start: str = "start",
current: tuple[str, ...] = ("start",),
) -> Iterator[tuple[str, ...]]:
if start == "end":
yield current
for neighbor in neighbors[start]:
if not is_small(neighbor):
yield from enumerate_paths(
neighbors, duplicate_smalls, neighbor, current + (neighbor,)
)
elif neighbor not in current:
yield from enumerate_paths(
neighbors, duplicate_smalls, neighbor, current + (neighbor,)
)
elif duplicate_smalls > 0:
yield from enumerate_paths(
neighbors, duplicate_smalls - 1, neighbor, current + (neighbor,)
)
class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]:
neighbors: dict[str, list[str]] = defaultdict(list)
for row in input.splitlines():
a, b = row.split("-")
if a != "end" and b != "start":
neighbors[a].append(b)
if b != "end" and a != "start":
neighbors[b].append(a)
if self.files:
graph = "graph {\n"
for node, neighbors_of in neighbors.items():
graph += (
" ".join(
f"{node} -- {neighbor};"
for neighbor in neighbors_of
if node <= neighbor or node == "start" or neighbor == "end"
)
+ "\n"
)
graph += "}\n"
self.files.create("graph.dot", graph.encode(), False)
yield len(list(enumerate_paths(neighbors)))
yield len(list(enumerate_paths(neighbors, 1)))

View File

@@ -1,7 +1,11 @@
from typing import Any, Iterator import sys
from ..base import BaseSolver lines = sys.stdin.read().splitlines()
# part 1
answer_1 = ...
print(f"answer 1 is {answer_1}")
class Solver(BaseSolver): # part 2
def solve(self, input: str) -> Iterator[Any]: ... answer_2 = ...
print(f"answer 2 is {answer_2}")

View File

@@ -1,7 +1,11 @@
from typing import Any, Iterator import sys
from ..base import BaseSolver lines = sys.stdin.read().splitlines()
# part 1
answer_1 = ...
print(f"answer 1 is {answer_1}")
class Solver(BaseSolver): # part 2
def solve(self, input: str) -> Iterator[Any]: ... answer_2 = ...
print(f"answer 2 is {answer_2}")

View File

@@ -1,7 +1,11 @@
from typing import Any, Iterator import sys
from ..base import BaseSolver lines = sys.stdin.read().splitlines()
# part 1
answer_1 = ...
print(f"answer 1 is {answer_1}")
class Solver(BaseSolver): # part 2
def solve(self, input: str) -> Iterator[Any]: ... answer_2 = ...
print(f"answer 2 is {answer_2}")

View File

@@ -1,7 +1,11 @@
from typing import Any, Iterator import sys
from ..base import BaseSolver lines = sys.stdin.read().splitlines()
# part 1
answer_1 = ...
print(f"answer 1 is {answer_1}")
class Solver(BaseSolver): # part 2
def solve(self, input: str) -> Iterator[Any]: ... answer_2 = ...
print(f"answer 2 is {answer_2}")

View File

@@ -1,7 +1,11 @@
from typing import Any, Iterator import sys
from ..base import BaseSolver lines = sys.stdin.read().splitlines()
# part 1
answer_1 = ...
print(f"answer 1 is {answer_1}")
class Solver(BaseSolver): # part 2
def solve(self, input: str) -> Iterator[Any]: ... answer_2 = ...
print(f"answer 2 is {answer_2}")

View File

@@ -1,7 +1,11 @@
from typing import Any, Iterator import sys
from ..base import BaseSolver lines = sys.stdin.read().splitlines()
# part 1
answer_1 = ...
print(f"answer 1 is {answer_1}")
class Solver(BaseSolver): # part 2
def solve(self, input: str) -> Iterator[Any]: ... answer_2 = ...
print(f"answer 2 is {answer_2}")

View File

@@ -1,7 +1,11 @@
from typing import Any, Iterator import sys
from ..base import BaseSolver lines = sys.stdin.read().splitlines()
# part 1
answer_1 = ...
print(f"answer 1 is {answer_1}")
class Solver(BaseSolver): # part 2
def solve(self, input: str) -> Iterator[Any]: ... answer_2 = ...
print(f"answer 2 is {answer_2}")

View File

@@ -1,19 +1,16 @@
import sys
from math import prod from math import prod
from typing import Any, Iterator, Literal, TypeAlias, cast from typing import Literal, TypeAlias, cast
from ..base import BaseSolver lines = sys.stdin.read().splitlines()
Command: TypeAlias = Literal["forward", "up", "down"] Command: TypeAlias = Literal["forward", "up", "down"]
class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]:
lines = input.splitlines()
commands: list[tuple[Command, int]] = [ commands: list[tuple[Command, int]] = [
(cast(Command, (p := line.split())[0]), int(p[1])) for line in lines (cast(Command, (p := line.split())[0]), int(p[1])) for line in lines
] ]
def depth_and_position(use_aim: bool): def depth_and_position(use_aim: bool):
aim, pos, depth = 0, 0, 0 aim, pos, depth = 0, 0, 0
for command, value in commands: for command, value in commands:
@@ -34,5 +31,11 @@ class Solver(BaseSolver):
return depth, pos return depth, pos
yield prod(depth_and_position(False))
yield prod(depth_and_position(True)) # part 1
answer_1 = prod(depth_and_position(False))
print(f"answer 1 is {answer_1}")
# part 2
answer_2 = prod(depth_and_position(True))
print(f"answer 2 is {answer_2}")

View File

@@ -1,7 +1,11 @@
from typing import Any, Iterator import sys
from ..base import BaseSolver lines = sys.stdin.read().splitlines()
# part 1
answer_1 = ...
print(f"answer 1 is {answer_1}")
class Solver(BaseSolver): # part 2
def solve(self, input: str) -> Iterator[Any]: ... answer_2 = ...
print(f"answer 2 is {answer_2}")

View File

@@ -1,7 +1,11 @@
from typing import Any, Iterator import sys
from ..base import BaseSolver lines = sys.stdin.read().splitlines()
# part 1
answer_1 = ...
print(f"answer 1 is {answer_1}")
class Solver(BaseSolver): # part 2
def solve(self, input: str) -> Iterator[Any]: ... answer_2 = ...
print(f"answer 2 is {answer_2}")

View File

@@ -1,7 +1,11 @@
from typing import Any, Iterator import sys
from ..base import BaseSolver lines = sys.stdin.read().splitlines()
# part 1
answer_1 = ...
print(f"answer 1 is {answer_1}")
class Solver(BaseSolver): # part 2
def solve(self, input: str) -> Iterator[Any]: ... answer_2 = ...
print(f"answer 2 is {answer_2}")

View File

@@ -1,7 +1,11 @@
from typing import Any, Iterator import sys
from ..base import BaseSolver lines = sys.stdin.read().splitlines()
# part 1
answer_1 = ...
print(f"answer 1 is {answer_1}")
class Solver(BaseSolver): # part 2
def solve(self, input: str) -> Iterator[Any]: ... answer_2 = ...
print(f"answer 2 is {answer_2}")

View File

@@ -1,7 +1,11 @@
from typing import Any, Iterator import sys
from ..base import BaseSolver lines = sys.stdin.read().splitlines()
# part 1
answer_1 = ...
print(f"answer 1 is {answer_1}")
class Solver(BaseSolver): # part 2
def solve(self, input: str) -> Iterator[Any]: ... answer_2 = ...
print(f"answer 2 is {answer_2}")

View File

@@ -1,7 +1,11 @@
from typing import Any, Iterator import sys
from ..base import BaseSolver lines = sys.stdin.read().splitlines()
# part 1
answer_1 = ...
print(f"answer 1 is {answer_1}")
class Solver(BaseSolver): # part 2
def solve(self, input: str) -> Iterator[Any]: ... answer_2 = ...
print(f"answer 2 is {answer_2}")

View File

@@ -1,7 +1,6 @@
import sys
from collections import Counter from collections import Counter
from typing import Any, Iterator, Literal from typing import Literal
from ..base import BaseSolver
def generator_rating( def generator_rating(
@@ -21,23 +20,20 @@ def generator_rating(
return values[0] return values[0]
class Solver(BaseSolver): lines = sys.stdin.read().splitlines()
def solve(self, input: str) -> Iterator[Any]:
lines = input.splitlines()
# part 1 # part 1
most_and_least_common = [ most_and_least_common = [
tuple( tuple(Counter(line[col] for line in lines).most_common(2)[m][0] for m in range(2))
Counter(line[col] for line in lines).most_common(2)[m][0]
for m in range(2)
)
for col in range(len(lines[0])) for col in range(len(lines[0]))
] ]
gamma_rate = int("".join(most for most, _ in most_and_least_common), base=2) gamma_rate = int("".join(most for most, _ in most_and_least_common), base=2)
epsilon_rate = int("".join(least for _, least in most_and_least_common), base=2) epsilon_rate = int("".join(least for _, least in most_and_least_common), base=2)
yield gamma_rate * epsilon_rate print(f"answer 1 is {gamma_rate * epsilon_rate}")
# part 2 # part 2
oxygen_generator_rating = int(generator_rating(lines, True, "1"), base=2) oxygen_generator_rating = int(generator_rating(lines, True, "1"), base=2)
co2_scrubber_rating = int(generator_rating(lines, False, "0"), base=2) co2_scrubber_rating = int(generator_rating(lines, False, "0"), base=2)
yield oxygen_generator_rating * co2_scrubber_rating answer_2 = oxygen_generator_rating * co2_scrubber_rating
print(f"answer 2 is {answer_2}")

View File

@@ -1,13 +1,8 @@
from typing import Any, Iterator import sys
import numpy as np import numpy as np
from ..base import BaseSolver lines = sys.stdin.read().splitlines()
class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]:
lines = input.splitlines()
numbers = [int(c) for c in lines[0].split(",")] numbers = [int(c) for c in lines[0].split(",")]
@@ -31,9 +26,7 @@ class Solver(BaseSolver):
if winning_rounds[index][0] > 0: if winning_rounds[index][0] > 0:
continue continue
if np.any( if np.any(np.all(marked[index], axis=0) | np.all(marked[index], axis=1)):
np.all(marked[index], axis=0) | np.all(marked[index], axis=1)
):
winning_rounds[index] = ( winning_rounds[index] = (
round, round,
number * int(np.sum(boards[index][~marked[index]])), number * int(np.sum(boards[index][~marked[index]])),
@@ -45,8 +38,8 @@ class Solver(BaseSolver):
# part 1 # part 1
(_, score) = min(winning_rounds, key=lambda w: w[0]) (_, score) = min(winning_rounds, key=lambda w: w[0])
yield score print(f"answer 1 is {score}")
# part 2 # part 2
(_, score) = max(winning_rounds, key=lambda w: w[0]) (_, score) = max(winning_rounds, key=lambda w: w[0])
yield score print(f"answer 2 is {score}")

View File

@@ -1,13 +1,8 @@
from typing import Any, Iterator import sys
import numpy as np import numpy as np
from ..base import BaseSolver lines: list[str] = sys.stdin.read().splitlines()
class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]:
lines = input.splitlines()
sections: list[tuple[tuple[int, int], tuple[int, int]]] = [ sections: list[tuple[tuple[int, int], tuple[int, int]]] = [
( (
@@ -25,8 +20,10 @@ class Solver(BaseSolver):
np_sections = np.array(sections).reshape(-1, 4) np_sections = np.array(sections).reshape(-1, 4)
x_max, y_max = ( x_min, x_max, y_min, y_max = (
min(np_sections[:, 0].min(), np_sections[:, 2].min()),
max(np_sections[:, 0].max(), np_sections[:, 2].max()), max(np_sections[:, 0].max(), np_sections[:, 2].max()),
min(np_sections[:, 1].min(), np_sections[:, 3].min()),
max(np_sections[:, 1].max(), np_sections[:, 3].max()), max(np_sections[:, 1].max(), np_sections[:, 3].max()),
) )
@@ -44,5 +41,8 @@ class Solver(BaseSolver):
for i, j in zip(y_rng, x_rng): for i, j in zip(y_rng, x_rng):
counts_2[i, j] += 1 counts_2[i, j] += 1
yield (counts_1 >= 2).sum() answer_1 = (counts_1 >= 2).sum()
yield (counts_2 >= 2).sum() print(f"answer 1 is {answer_1}")
answer_2 = (counts_2 >= 2).sum()
print(f"answer 2 is {answer_2}")

View File

@@ -1,11 +1,6 @@
from typing import Any, Iterator import sys
from ..base import BaseSolver values = [int(c) for c in sys.stdin.read().strip().split(",")]
class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]:
values = [int(c) for c in input.split(",")]
days = 256 days = 256
lanterns = {day: 0 for day in range(days)} lanterns = {day: 0 for day in range(days)}
@@ -17,5 +12,10 @@ class Solver(BaseSolver):
for day2 in range(day + 9, days, 7): for day2 in range(day + 9, days, 7):
lanterns[day2] += lanterns[day] lanterns[day2] += lanterns[day]
yield sum(v for k, v in lanterns.items() if k < 80) + len(values) # part 1
yield sum(lanterns.values()) + len(values) answer_1 = sum(v for k, v in lanterns.items() if k < 80) + len(values)
print(f"answer 1 is {answer_1}")
# part 2
answer_2 = sum(lanterns.values()) + len(values)
print(f"answer 2 is {answer_2}")

View File

@@ -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(",")]
class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]:
positions = [int(c) for c in input.split(",")]
min_position, max_position = min(positions), max(positions) min_position, max_position = min(positions), max(positions)
# part 1 # part 1
yield min( answer_1 = min(
sum(abs(p - position) for p in positions) sum(abs(p - position) for p in positions)
for position in range(min_position, max_position + 1) for position in range(min_position, max_position + 1)
) )
print(f"answer 1 is {answer_1}")
# part 2 # part 2
yield min( answer_2 = min(
sum(abs(p - position) * (abs(p - position) + 1) // 2 for p in positions) sum(abs(p - position) * (abs(p - position) + 1) // 2 for p in positions)
for position in range(min_position, max_position + 1) for position in range(min_position, max_position + 1)
) )
print(f"answer 2 is {answer_2}")

View File

@@ -1,7 +1,8 @@
import itertools import itertools
from typing import Any, Iterator import os
import sys
from ..base import BaseSolver VERBOSE = os.getenv("AOC_VERBOSE") == "True"
digits = { digits = {
"abcefg": 0, "abcefg": 0,
@@ -16,18 +17,14 @@ digits = {
"abcdfg": 9, "abcdfg": 9,
} }
lines = sys.stdin.read().splitlines()
class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]:
lines = input.splitlines()
# part 1 # part 1
lengths = {len(k) for k, v in digits.items() if v in (1, 4, 7, 8)} lengths = {len(k) for k, v in digits.items() if v in (1, 4, 7, 8)}
yield sum( answer_1 = sum(
len(p) in lengths len(p) in lengths for line in lines for p in line.split("|")[1].strip().split()
for line in lines
for p in line.split("|")[1].strip().split()
) )
print(f"answer 1 is {answer_1}")
# part 2 # part 2
values: list[int] = [] values: list[int] = []
@@ -52,9 +49,7 @@ class Solver(BaseSolver):
bd = [u for u in per_length[4][0] if u not in cf] bd = [u for u in per_length[4][0] if u not in cf]
# the 3 digits of length 5 have a, d and g in common # the 3 digits of length 5 have a, d and g in common
adg = [ adg = [u for u in per_length[5][0] if all(u in pe for pe in per_length[5][1:])]
u for u in per_length[5][0] if all(u in pe for pe in per_length[5][1:])
]
# we can remove a # we can remove a
dg = [u for u in adg if u != a] dg = [u for u in adg if u != a]
@@ -82,8 +77,11 @@ class Solver(BaseSolver):
digit = "".join(sorted(mapping[c] for c in number)) digit = "".join(sorted(mapping[c] for c in number))
value = 10 * value + digits[digit] value = 10 * value + digits[digit]
self.logger.info(f"value for '{line}' is {value}") if VERBOSE:
print(value)
values.append(value) values.append(value)
yield sum(values)
answer_2 = sum(values)
print(f"answer 2 is {answer_2}")

View File

@@ -1,18 +1,18 @@
import sys
from math import prod from math import prod
from typing import Any, Iterator
from ..base import BaseSolver values = [[int(c) for c in row] for row in sys.stdin.read().splitlines()]
n_rows, n_cols = len(values), len(values[0])
def neighbors(point: tuple[int, int], n_rows: int, n_cols: int): def neighbors(point: tuple[int, int]):
i, j = point i, j = point
for di, dj in ((-1, 0), (+1, 0), (0, -1), (0, +1)): for di, dj in ((-1, 0), (+1, 0), (0, -1), (0, +1)):
if 0 <= i + di < n_rows and 0 <= j + dj < n_cols: if 0 <= i + di < n_rows and 0 <= j + dj < n_cols:
yield (i + di, j + dj) yield (i + di, j + dj)
def basin(values: list[list[int]], start: tuple[int, int]) -> set[tuple[int, int]]: def basin(start: tuple[int, int]) -> set[tuple[int, int]]:
n_rows, n_cols = len(values), len(values[0])
visited: set[tuple[int, int]] = set() visited: set[tuple[int, int]] = set()
queue = [start] queue = [start]
@@ -23,25 +23,22 @@ def basin(values: list[list[int]], start: tuple[int, int]) -> set[tuple[int, int
continue continue
visited.add((i, j)) visited.add((i, j))
queue.extend(neighbors((i, j), n_rows, n_cols)) queue.extend(neighbors((i, j)))
return visited return visited
class Solver(BaseSolver):
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 = [ low_points = [
(i, j) (i, j)
for i in range(n_rows) for i in range(n_rows)
for j in range(n_cols) for j in range(n_cols)
if all( if all(values[ti][tj] > values[i][j] for ti, tj in neighbors((i, j)))
values[ti][tj] > values[i][j]
for ti, tj in neighbors((i, j), n_rows, n_cols)
)
] ]
yield sum(values[i][j] + 1 for i, j in low_points) # part 1
yield prod(sorted(len(basin(values, point)) for point in low_points)[-3:]) answer_1 = sum(values[i][j] + 1 for i, j in low_points)
print(f"answer 1 is {answer_1}")
# part 2
answer_2 = prod(sorted(len(basin(point)) for point in low_points)[-3:])
print(f"answer 2 is {answer_2}")

View File

@@ -1,12 +1,7 @@
from typing import Any, Iterator import sys
from ..base import BaseSolver blocks = sys.stdin.read().split("\n\n")
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) values = sorted(sum(map(int, block.split())) for block in blocks)
yield values[-1] print(f"answer 1 is {values[-1]}")
yield sum(values[-3:]) print(f"answer 2 is {sum(values[-3:])}")

View File

@@ -1,13 +1,10 @@
from typing import Any, Iterator import sys
from ..base import BaseSolver lines = sys.stdin.read().splitlines()
cycle = 1
x = 1
class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]:
lines = [line.strip() for line in input.splitlines()]
cycle, x = 1, 1
values = {cycle: x} values = {cycle: x}
for line in lines: for line in lines:
@@ -26,18 +23,16 @@ class Solver(BaseSolver):
values[cycle] = x values[cycle] = x
answer_1 = sum(c * values[c] for c in range(20, max(values.keys()) + 1, 40)) answer_1 = sum(c * values[c] for c in range(20, max(values.keys()) + 1, 40))
yield answer_1 print(f"answer 1 is {answer_1}")
yield (
"\n" for i in range(6):
+ "\n".join( for j in range(40):
"".join( v = values[1 + i * 40 + j]
"#"
if j >= (v := values[1 + i * 40 + j]) - 1 and j <= v + 1 if j >= v - 1 and j <= v + 1:
else "." print("#", end="")
for j in range(40) else:
) print(".", end="")
for i in range(6)
) print()
+ "\n"
)

View File

@@ -1,8 +1,7 @@
import copy import copy
import sys
from functools import reduce from functools import reduce
from typing import Any, Callable, Final, Iterator, Mapping, Sequence from typing import Callable, Final, Mapping, Sequence
from ..base import BaseSolver
class Monkey: class Monkey:
@@ -120,14 +119,13 @@ def monkey_business(inspects: dict[Monkey, int]) -> int:
return sorted_levels[-2] * sorted_levels[-1] return sorted_levels[-2] * sorted_levels[-1]
class Solver(BaseSolver): monkeys = [parse_monkey(block.splitlines()) for block in sys.stdin.read().split("\n\n")]
def solve(self, input: str) -> Iterator[Any]:
monkeys = [parse_monkey(block.splitlines()) for block in input.split("\n\n")]
# case 1: we simply divide the worry by 3 after applying the monkey worry operation # case 1: we simply divide the worry by 3 after applying the monkey worry operation
yield monkey_business( answer_1 = monkey_business(
run(copy.deepcopy(monkeys), 20, me_worry_fn=lambda w: w // 3) run(copy.deepcopy(monkeys), 20, me_worry_fn=lambda w: w // 3)
) )
print(f"answer 1 is {answer_1}")
# case 2: to keep reasonable level values, we can use a modulo operation, we need to # case 2: to keep reasonable level values, we can use a modulo operation, we need to
# use the product of all "divisible by" test so that the test remains valid # use the product of all "divisible by" test so that the test remains valid
@@ -138,10 +136,7 @@ class Solver(BaseSolver):
# we use the product of all test value # we use the product of all test value
# #
total_test_value = reduce(lambda w, m: w * m.test_value, monkeys, 1) total_test_value = reduce(lambda w, m: w * m.test_value, monkeys, 1)
yield monkey_business( answer_2 = monkey_business(
run( run(copy.deepcopy(monkeys), 10_000, me_worry_fn=lambda w: w % total_test_value)
copy.deepcopy(monkeys),
10_000,
me_worry_fn=lambda w: w % total_test_value,
)
) )
print(f"answer 2 is {answer_2}")

View File

@@ -1,7 +1,6 @@
import heapq import heapq
from typing import Any, Callable, Iterator, TypeVar import sys
from typing import Callable, Iterator, TypeVar
from ..base import BaseSolver
Node = TypeVar("Node") Node = TypeVar("Node")
@@ -69,6 +68,30 @@ def make_path(parents: dict[Node, Node], start: Node, end: Node) -> list[Node] |
return list(reversed(path)) return list(reversed(path))
def print_path(path: list[tuple[int, int]], n_rows: int, n_cols: int) -> None:
end = path[-1]
graph = [["." for _c in range(n_cols)] for _r in range(n_rows)]
graph[end[0]][end[1]] = "E"
for i in range(0, len(path) - 1):
cr, cc = path[i]
nr, nc = path[i + 1]
if cr == nr and nc == cc - 1:
graph[cr][cc] = "<"
elif cr == nr and nc == cc + 1:
graph[cr][cc] = ">"
elif cr == nr - 1 and nc == cc:
graph[cr][cc] = "v"
elif cr == nr + 1 and nc == cc:
graph[cr][cc] = "^"
else:
assert False, "{} -> {} infeasible".format(path[i], path[i + 1])
print("\n".join("".join(row) for row in graph))
def neighbors( def neighbors(
grid: list[list[int]], node: tuple[int, int], up: bool grid: list[list[int]], node: tuple[int, int], up: bool
) -> Iterator[tuple[int, int]]: ) -> Iterator[tuple[int, int]]:
@@ -95,42 +118,7 @@ def neighbors(
# === main code === # === 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
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])
self.files.create(
f"graph_{name}.txt",
"\n".join("".join(row) for row in graph).encode(),
text=True,
)
def solve(self, input: str) -> Iterator[Any]:
lines = input.splitlines()
grid = [[ord(cell) - ord("a") for cell in line] for line in lines] grid = [[ord(cell) - ord("a") for cell in line] for line in lines]
@@ -157,20 +145,19 @@ class Solver(BaseSolver):
grid[start[0]][start[1]] = 0 grid[start[0]][start[1]] = 0
grid[end[0]][end[1]] = ord("z") - ord("a") grid[end[0]][end[1]] = ord("z") - ord("a")
lengths_1, parents_1 = dijkstra( lengths_1, parents_1 = dijkstra(
start=start, start=start, neighbors=lambda n: neighbors(grid, n, True), cost=lambda lhs, rhs: 1
neighbors=lambda n: neighbors(grid, n, True),
cost=lambda lhs, rhs: 1,
) )
path_1 = make_path(parents_1, start, end) path_1 = make_path(parents_1, start, end)
assert path_1 is not None assert path_1 is not None
self.print_path("answer1", path_1, n_rows=len(grid), n_cols=len(grid[0])) print_path(path_1, n_rows=len(grid), n_cols=len(grid[0]))
yield lengths_1[end] - 1
lengths_2, _ = dijkstra( print(f"answer 1 is {lengths_1[end] - 1}")
start=end,
neighbors=lambda n: neighbors(grid, n, False), lengths_2, parents_2 = dijkstra(
cost=lambda lhs, rhs: 1, 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) answer_2 = min(lengths_2.get(start, float("inf")) for start in start_s)
print(f"answer 2 is {answer_2}")

View File

@@ -1,8 +1,11 @@
import json import json
import sys
from functools import cmp_to_key from functools import cmp_to_key
from typing import Any, Iterator, TypeAlias, cast from typing import TypeAlias, cast
from ..base import BaseSolver blocks = sys.stdin.read().strip().split("\n\n")
pairs = [tuple(json.loads(p) for p in block.split("\n")) for block in blocks]
Packet: TypeAlias = list[int | list["Packet"]] Packet: TypeAlias = list[int | list["Packet"]]
@@ -25,12 +28,8 @@ def compare(lhs: Packet, rhs: Packet) -> int:
return len(rhs) - len(lhs) return len(rhs) - len(lhs)
class Solver(BaseSolver): answer_1 = sum(i + 1 for i, (lhs, rhs) in enumerate(pairs) if compare(lhs, rhs) > 0)
def solve(self, input: str) -> Iterator[Any]: print(f"answer_1 is {answer_1}")
blocks = input.split("\n\n")
pairs = [tuple(json.loads(p) for p in block.split("\n")) for block in blocks]
yield sum(i + 1 for i, (lhs, rhs) in enumerate(pairs) if compare(lhs, rhs) > 0)
dividers = [[[2]], [[6]]] dividers = [[[2]], [[6]]]
@@ -39,4 +38,4 @@ class Solver(BaseSolver):
packets = list(reversed(sorted(packets, key=cmp_to_key(compare)))) packets = list(reversed(sorted(packets, key=cmp_to_key(compare))))
d_index = [packets.index(d) + 1 for d in dividers] d_index = [packets.index(d) + 1 for d in dividers]
yield d_index[0] * d_index[1] print(f"answer 2 is {d_index[0] * d_index[1]}")

View File

@@ -1,7 +1,6 @@
import sys
from enum import Enum, auto from enum import Enum, auto
from typing import Any, Callable, Iterator, cast from typing import Callable, cast
from ..base import BaseSolver
class Cell(Enum): class Cell(Enum):
@@ -13,6 +12,26 @@ class Cell(Enum):
return {Cell.AIR: ".", Cell.ROCK: "#", Cell.SAND: "O"}[self] return {Cell.AIR: ".", Cell.ROCK: "#", Cell.SAND: "O"}[self]
def print_blocks(blocks: dict[tuple[int, int], Cell]):
"""
Print the given set of blocks on a grid.
Args:
blocks: Set of blocks to print.
"""
x_min, y_min, x_max, y_max = (
min(x for x, _ in blocks),
0,
max(x for x, _ in blocks),
max(y for _, y in blocks),
)
for y in range(y_min, y_max + 1):
print(
"".join(str(blocks.get((x, y), Cell.AIR)) for x in range(x_min, x_max + 1))
)
def flow( def flow(
blocks: dict[tuple[int, int], Cell], blocks: dict[tuple[int, int], Cell],
stop_fn: Callable[[int, int], bool], stop_fn: Callable[[int, int], bool],
@@ -65,51 +84,19 @@ def flow(
# === inputs === # === 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.
Args:
blocks: Set of blocks to print.
"""
if not self.files:
return
x_min, y_min, x_max, y_max = (
min(x for x, _ in blocks),
0,
max(x for x, _ in blocks),
max(y for _, y in blocks),
)
self.files.create(
f"blocks_{name}.txt",
"\n".join(
"".join(
str(blocks.get((x, y), Cell.AIR)) for x in range(x_min, x_max + 1)
)
for y in range(y_min, y_max + 1)
).encode(),
True,
)
def solve(self, input: str) -> Iterator[Any]:
lines = [line.strip() for line in input.splitlines()]
paths: list[list[tuple[int, int]]] = [] paths: list[list[tuple[int, int]]] = []
for line in lines: for line in lines:
parts = line.split(" -> ") parts = line.split(" -> ")
paths.append( paths.append(
[ [
cast( cast(tuple[int, int], tuple(int(c.strip()) for c in part.split(",")))
tuple[int, int], tuple(int(c.strip()) for c in part.split(","))
)
for part in parts for part in parts
] ]
) )
blocks: dict[tuple[int, int], Cell] = {} blocks: dict[tuple[int, int], Cell] = {}
for path in paths: for path in paths:
for start, end in zip(path[:-1], path[1:]): for start, end in zip(path[:-1], path[1:]):
@@ -122,17 +109,24 @@ class Solver(BaseSolver):
for y in range(y_start, y_end): for y in range(y_start, y_end):
blocks[x, y] = Cell.ROCK blocks[x, y] = Cell.ROCK
self.print_blocks("start", blocks) print_blocks(blocks)
print()
y_max = max(y for _, y in blocks) x_min, y_min, x_max, y_max = (
min(x for x, _ in blocks),
0,
max(x for x, _ in blocks),
max(y for _, y in blocks),
)
# === part 1 === # === part 1 ===
blocks_1 = flow( blocks_1 = flow(
blocks.copy(), stop_fn=lambda x, y: y > y_max, fill_fn=lambda x, y: Cell.AIR blocks.copy(), stop_fn=lambda x, y: y > y_max, fill_fn=lambda x, y: Cell.AIR
) )
self.print_blocks("part1", blocks_1) print_blocks(blocks_1)
yield sum(v == Cell.SAND for v in blocks_1.values()) print(f"answer 1 is {sum(v == Cell.SAND for v in blocks_1.values())}")
print()
# === part 2 === # === part 2 ===
@@ -142,5 +136,5 @@ class Solver(BaseSolver):
fill_fn=lambda x, y: Cell.AIR if y < y_max + 2 else Cell.ROCK, fill_fn=lambda x, y: Cell.AIR if y < y_max + 2 else Cell.ROCK,
) )
blocks_2[500, 0] = Cell.SAND blocks_2[500, 0] = Cell.SAND
self.print_blocks("part2", blocks_2) print_blocks(blocks_2)
yield sum(v == Cell.SAND for v in blocks_2.values()) print(f"answer 2 is {sum(v == Cell.SAND for v in blocks_2.values())}")

View File

@@ -1,4 +1,4 @@
import itertools as it import sys
from typing import Any, Iterator from typing import Any, Iterator
import numpy as np import numpy as np
@@ -21,7 +21,9 @@ class Solver(BaseSolver):
no_beacons_row_l.append(sx + np.arange(0, d - abs(sy - row) + 1)) # type: ignore no_beacons_row_l.append(sx + np.arange(0, d - abs(sy - row) + 1)) # type: ignore
beacons_at_row = set(bx for (bx, by) in sensor_to_beacon.values() if by == row) beacons_at_row = set(bx for (bx, by) in sensor_to_beacon.values() if by == row)
no_beacons_row = set(it.chain(*no_beacons_row_l)).difference(beacons_at_row) # type: ignore no_beacons_row = set(np.concatenate(no_beacons_row_l)).difference(
beacons_at_row
) # type: ignore
return len(no_beacons_row) return len(no_beacons_row)
@@ -60,9 +62,8 @@ class Solver(BaseSolver):
for (sx, sy), (bx, by) in sensor_to_beacon.items(): for (sx, sy), (bx, by) in sensor_to_beacon.items():
d = abs(sx - bx) + abs(sy - by) d = abs(sx - bx) + abs(sy - by)
m.add_constraint( m.add_constraint(
m.abs(x - sx) + m.abs(y - sy) >= d + 1, # type: ignore m.abs(x - sx) + m.abs(y - sy) >= d + 1, ctname=f"ct_{sx}_{sy}"
ctname=f"ct_{sx}_{sy}", ) # type: ignore
)
m.set_objective("min", x + y) m.set_objective("min", x + y)
@@ -91,5 +92,5 @@ class Solver(BaseSolver):
# x, y, a2 = part2_cplex(sensor_to_beacon, xy_max) # x, y, a2 = part2_cplex(sensor_to_beacon, xy_max)
x, y, a2 = self.part2_intervals(sensor_to_beacon, xy_max) x, y, a2 = self.part2_intervals(sensor_to_beacon, xy_max)
self.logger.info(f"answer 2 is {a2} (x={x}, y={y})") self.logger.info("answer 2 is {at} (x={x}, y={y})")
yield a2 yield a2

View File

@@ -3,10 +3,11 @@ from __future__ import annotations
import heapq import heapq
import itertools import itertools
import re import re
import sys
from collections import defaultdict from collections import defaultdict
from typing import Any, FrozenSet, Iterator, NamedTuple from typing import FrozenSet, NamedTuple
from ..base import BaseSolver from tqdm import tqdm
class Pipe(NamedTuple): class Pipe(NamedTuple):
@@ -35,8 +36,8 @@ def breadth_first_search(pipes: dict[str, Pipe], pipe: Pipe) -> dict[Pipe, int]:
Runs a BFS from the given pipe and return the shortest distance (in term of hops) Runs a BFS from the given pipe and return the shortest distance (in term of hops)
to all other pipes. to all other pipes.
""" """
queue = [(0, pipe)] queue = [(0, pipe_1)]
visited: set[Pipe] = set() visited = set()
distances: dict[Pipe, int] = {} distances: dict[Pipe, int] = {}
while len(distances) < len(pipes): while len(distances) < len(pipes):
@@ -60,12 +61,7 @@ def update_with_better(
node_at_times[flowing] = max(node_at_times[flowing], flow) node_at_times[flowing] = max(node_at_times[flowing], flow)
# === MAIN ===
class Solver(BaseSolver):
def part_1( def part_1(
self,
start_pipe: Pipe, start_pipe: Pipe,
max_time: int, max_time: int,
distances: dict[tuple[Pipe, Pipe], int], distances: dict[tuple[Pipe, Pipe], int],
@@ -102,17 +98,15 @@ class Solver(BaseSolver):
for flow in nodes_of_pipe.values() for flow in nodes_of_pipe.values()
) )
def part_2( def part_2(
self,
start_pipe: Pipe, start_pipe: Pipe,
max_time: int, max_time: int,
distances: dict[tuple[Pipe, Pipe], int], distances: dict[tuple[Pipe, Pipe], int],
relevant_pipes: FrozenSet[Pipe], relevant_pipes: FrozenSet[Pipe],
): ):
def compute(pipes_for_me: FrozenSet[Pipe]) -> int: def compute(pipes_for_me: FrozenSet[Pipe]) -> int:
return self.part_1( return part_1(start_pipe, max_time, distances, pipes_for_me) + part_1(
start_pipe, max_time, distances, pipes_for_me
) + self.part_1(
start_pipe, max_time, distances, relevant_pipes - pipes_for_me start_pipe, max_time, distances, relevant_pipes - pipes_for_me
) )
@@ -122,10 +116,14 @@ class Solver(BaseSolver):
for relevant_pipes_1 in itertools.combinations(relevant_pipes, r) for relevant_pipes_1 in itertools.combinations(relevant_pipes, r)
] ]
return max(compute(comb) for comb in self.progress.wrap(combs)) return max(compute(comb) for comb in tqdm(combs))
# === MAIN ===
lines = sys.stdin.read().splitlines()
def solve(self, input: str) -> Iterator[Any]:
lines = [line.strip() for line in input.splitlines()]
pipes: dict[str, Pipe] = {} pipes: dict[str, Pipe] = {}
for line in lines: for line in lines:
@@ -152,8 +150,9 @@ class Solver(BaseSolver):
# valves with flow # valves with flow
relevant_pipes = frozenset(pipe for pipe in pipes.values() if pipe.flow > 0) relevant_pipes = frozenset(pipe for pipe in pipes.values() if pipe.flow > 0)
# 1651, 1653 # 1651, 1653
yield self.part_1(pipes["AA"], 30, distances, relevant_pipes) print(part_1(pipes["AA"], 30, distances, relevant_pipes))
# 1707, 2223 # 1707, 2223
yield self.part_2(pipes["AA"], 26, distances, relevant_pipes) print(part_2(pipes["AA"], 26, distances, relevant_pipes))

View File

@@ -1,16 +1,23 @@
from typing import Any, Iterator, Sequence, TypeAlias, TypeVar import sys
from typing import Sequence, TypeVar
import numpy as np import numpy as np
from numpy.typing import NDArray
from ..base import BaseSolver
T = TypeVar("T") T = TypeVar("T")
Tower: TypeAlias = NDArray[np.bool]
def print_tower(tower: np.ndarray, out: str = "#"):
print("-" * (tower.shape[1] + 2))
non_empty = False
for row in reversed(range(1, tower.shape[0])):
if not non_empty and not tower[row, :].any():
continue
non_empty = True
print("|" + "".join(out if c else "." for c in tower[row, :]) + "|")
print("+" + "-" * tower.shape[1] + "+")
def tower_height(tower: Tower) -> int: def tower_height(tower: np.ndarray) -> int:
return int(tower.shape[0] - tower[::-1, :].argmax(axis=0).min() - 1) return int(tower.shape[0] - tower[::-1, :].argmax(axis=0).min() - 1)
@@ -38,8 +45,8 @@ def build_tower(
n_rocks: int, n_rocks: int,
jets: str, jets: str,
early_stop: bool = False, early_stop: bool = False,
init: Tower = np.ones(WIDTH, dtype=bool), init: np.ndarray = np.ones(WIDTH, dtype=bool),
) -> tuple[Tower, int, int, dict[int, int]]: ) -> tuple[np.ndarray, int, int, dict[int, int]]:
tower = EMPTY_BLOCKS.copy() tower = EMPTY_BLOCKS.copy()
tower[0, :] = init tower[0, :] = init
@@ -88,13 +95,14 @@ def build_tower(
return tower, rock_count, done_at.get((i_rock, i_jet), -1), heights return tower, rock_count, done_at.get((i_rock, i_jet), -1), heights
class Solver(BaseSolver): line = sys.stdin.read().strip()
def solve(self, input: str) -> Iterator[Any]:
tower, *_ = build_tower(2022, input) tower, *_ = build_tower(2022, line)
yield tower_height(tower) answer_1 = tower_height(tower)
print(f"answer 1 is {answer_1}")
TOTAL_ROCKS = 1_000_000_000_000 TOTAL_ROCKS = 1_000_000_000_000
_tower_1, n_rocks_1, prev_1, heights_1 = build_tower(TOTAL_ROCKS, input, True) tower_1, n_rocks_1, prev_1, heights_1 = build_tower(TOTAL_ROCKS, line, True)
assert prev_1 > 0 assert prev_1 > 0
# 2767 1513 # 2767 1513
@@ -108,4 +116,5 @@ class Solver(BaseSolver):
heights_1[prev_1 + remaining_rocks % n_repeat_rocks] - heights_1[prev_1] heights_1[prev_1 + remaining_rocks % n_repeat_rocks] - heights_1[prev_1]
) )
yield base_height + (n_repeat_towers + 1) * repeat_height + remaining_height answer_2 = base_height + (n_repeat_towers + 1) * repeat_height + remaining_height
print(f"answer 2 is {answer_2}")

View File

@@ -1,16 +1,11 @@
from typing import Any, Iterator import sys
import numpy as np import numpy as np
from ..base import BaseSolver
class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]:
xyz = np.asarray( xyz = np.asarray(
[ [
tuple(int(x) for x in row.split(",")) # type: ignore tuple(int(x) for x in row.split(",")) # type: ignore
for row in input.splitlines() for row in sys.stdin.read().splitlines()
] ]
) )
@@ -19,14 +14,14 @@ class Solver(BaseSolver):
cubes = np.zeros(xyz.max(axis=0) + 3, dtype=bool) cubes = np.zeros(xyz.max(axis=0) + 3, dtype=bool)
cubes[xyz[:, 0], xyz[:, 1], xyz[:, 2]] = True cubes[xyz[:, 0], xyz[:, 1], xyz[:, 2]] = True
n_dims = len(cubes.shape)
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)]
yield sum( answer_1 = sum(
1 1 for x, y, z in xyz for dx, dy, dz in faces if not cubes[x + dx, y + dy, z + dz]
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}")
visited = np.zeros_like(cubes, dtype=bool) visited = np.zeros_like(cubes, dtype=bool)
queue = [(0, 0, 0)] queue = [(0, 0, 0)]
@@ -42,9 +37,7 @@ class Solver(BaseSolver):
for dx, dy, dz in faces: for dx, dy, dz in faces:
nx, ny, nz = x + dx, y + dy, z + dz nx, ny, nz = x + dx, y + dy, z + dz
if not all( if not all(n >= 0 and n < cubes.shape[i] for i, n in enumerate((nx, ny, nz))):
n >= 0 and n < cubes.shape[i] for i, n in enumerate((nx, ny, nz))
):
continue continue
if visited[nx, ny, nz]: if visited[nx, ny, nz]:
@@ -54,5 +47,4 @@ class Solver(BaseSolver):
n_faces += 1 n_faces += 1
else: else:
queue.append((nx, ny, nz)) queue.append((nx, ny, nz))
print(f"answer 2 is {n_faces}")
yield n_faces

View File

@@ -1,11 +1,10 @@
from typing import Any, Iterator, Literal import sys
from typing import Any, Literal
import numpy as np import numpy as np
import parse # pyright: ignore[reportMissingTypeStubs] import parse # pyright: ignore[reportMissingTypeStubs]
from numpy.typing import NDArray from numpy.typing import NDArray
from ..base import BaseSolver
Reagent = Literal["ore", "clay", "obsidian", "geode"] Reagent = Literal["ore", "clay", "obsidian", "geode"]
REAGENTS: tuple[Reagent, ...] = ( REAGENTS: tuple[Reagent, ...] = (
"ore", "ore",
@@ -63,6 +62,29 @@ def dominates(lhs: State, rhs: State):
) )
lines = sys.stdin.read().splitlines()
blueprints: list[dict[Reagent, IntOfReagent]] = []
for line in lines:
r: list[int] = parse.parse( # type: ignore
"Blueprint {}: "
"Each ore robot costs {:d} ore. "
"Each clay robot costs {:d} ore. "
"Each obsidian robot costs {:d} ore and {:d} clay. "
"Each geode robot costs {:d} ore and {:d} obsidian.",
line,
)
blueprints.append(
{
"ore": {"ore": r[1]},
"clay": {"ore": r[2]},
"obsidian": {"ore": r[3], "clay": r[4]},
"geode": {"ore": r[5], "obsidian": r[6]},
}
)
def run(blueprint: dict[Reagent, dict[Reagent, int]], max_time: int) -> int: def run(blueprint: dict[Reagent, dict[Reagent, int]], max_time: int) -> int:
# since we can only build one robot per time, we do not need more than X robots # since we can only build one robot per time, we do not need more than X robots
# of type K where X is the maximum number of K required among all robots, e.g., # of type K where X is the maximum number of K required among all robots, e.g.,
@@ -151,31 +173,11 @@ def run(blueprint: dict[Reagent, dict[Reagent, int]], max_time: int) -> int:
return max(state.reagents["geode"] for state in state_after_t[max_time]) return max(state.reagents["geode"] for state in state_after_t[max_time])
class Solver(BaseSolver): answer_1 = sum(
def solve(self, input: str) -> Iterator[Any]:
blueprints: list[dict[Reagent, IntOfReagent]] = []
for line in input.splitlines():
r: list[int] = parse.parse( # type: ignore
"Blueprint {}: "
"Each ore robot costs {:d} ore. "
"Each clay robot costs {:d} ore. "
"Each obsidian robot costs {:d} ore and {:d} clay. "
"Each geode robot costs {:d} ore and {:d} obsidian.",
line,
)
blueprints.append(
{
"ore": {"ore": r[1]},
"clay": {"ore": r[2]},
"obsidian": {"ore": r[3], "clay": r[4]},
"geode": {"ore": r[5], "obsidian": r[6]},
}
)
yield sum(
(i_blueprint + 1) * run(blueprint, 24) (i_blueprint + 1) * run(blueprint, 24)
for i_blueprint, blueprint in enumerate(blueprints) for i_blueprint, blueprint in enumerate(blueprints)
) )
print(f"answer 1 is {answer_1}")
yield (run(blueprints[0], 32) * run(blueprints[1], 32) * run(blueprints[2], 32)) answer_2 = run(blueprints[0], 32) * run(blueprints[1], 32) * run(blueprints[2], 32)
print(f"answer 2 is {answer_2}")

View File

@@ -1,6 +1,4 @@
from typing import Any, Iterator import sys
from ..base import BaseSolver
def score_1(ux: int, vx: int) -> int: def score_1(ux: int, vx: int) -> int:
@@ -35,9 +33,7 @@ def score_2(ux: int, vx: int) -> int:
return (ux + vx - 1) % 3 + 1 + vx * 3 return (ux + vx - 1) % 3 + 1 + vx * 3
class Solver(BaseSolver): lines = sys.stdin.readlines()
def solve(self, input: str) -> Iterator[Any]:
lines = input.splitlines()
# the solution relies on replacing rock / paper / scissor by values 0 / 1 / 2 and using # the solution relies on replacing rock / paper / scissor by values 0 / 1 / 2 and using
# modulo-3 arithmetic # modulo-3 arithmetic
@@ -51,7 +47,7 @@ class Solver(BaseSolver):
values = [(ord(row[0]) - ord("A"), ord(row[2]) - ord("X")) for row in lines] values = [(ord(row[0]) - ord("A"), ord(row[2]) - ord("X")) for row in lines]
# part 1 - 13526 # part 1 - 13526
yield sum(score_1(*v) for v in values) print(f"answer 1 is {sum(score_1(*v) for v in values)}")
# part 2 - 14204 # part 2 - 14204
yield sum(score_2(*v) for v in values) print(f"answer 2 is {sum(score_2(*v) for v in values)}")

View File

@@ -1,8 +1,6 @@
from __future__ import annotations from __future__ import annotations
from typing import Any, Iterator import sys
from ..base import BaseSolver
class Number: class Number:
@@ -67,9 +65,10 @@ def decrypt(numbers: list[Number], key: int, rounds: int) -> int:
) )
class Solver(BaseSolver): numbers = [Number(int(x)) for i, x in enumerate(sys.stdin.readlines())]
def solve(self, input: str) -> Iterator[Any]:
numbers = [Number(int(x)) for x in input.splitlines()]
yield decrypt(numbers, 1, 1) answer_1 = decrypt(numbers, 1, 1)
yield decrypt(numbers, 811589153, 10) print(f"answer 1 is {answer_1}")
answer_2 = decrypt(numbers, 811589153, 10)
print(f"answer 2 is {answer_2}")

View File

@@ -1,7 +1,6 @@
import operator import operator
from typing import Any, Callable, Iterator import sys
from typing import Callable
from ..base import BaseSolver
def compute(monkeys: dict[str, int | tuple[str, str, str]], monkey: str) -> int: def compute(monkeys: dict[str, int | tuple[str, str, str]], monkey: str) -> int:
@@ -78,9 +77,7 @@ def invert(
return monkeys return monkeys
class Solver(BaseSolver): lines = sys.stdin.read().splitlines()
def solve(self, input: str) -> Iterator[Any]:
lines = [line.strip() for line in input.splitlines()]
monkeys: dict[str, int | tuple[str, str, str]] = {} monkeys: dict[str, int | tuple[str, str, str]] = {}
@@ -99,10 +96,12 @@ class Solver(BaseSolver):
op_monkeys.add(name) op_monkeys.add(name)
yield compute(monkeys.copy(), "root")
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 # 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 # humn, which is the case is my input and the test input
assert isinstance(monkeys["root"], tuple)
p1, _, p2 = monkeys["root"] # type: ignore p1, _, p2 = monkeys["root"] # type: ignore
yield compute(invert(monkeys, "humn", compute(monkeys.copy(), p2)), "humn") answer_2 = compute(invert(monkeys, "humn", compute(monkeys.copy(), p2)), "humn")
print(f"answer 2 is {answer_2}")

View File

@@ -1,19 +1,16 @@
import re import re
from typing import Any, Callable, Iterator import sys
from typing import Callable
import numpy as np import numpy as np
from ..base import BaseSolver
VOID, EMPTY, WALL = 0, 1, 2 VOID, EMPTY, WALL = 0, 1, 2
TILE_FROM_CHAR = {" ": VOID, ".": EMPTY, "#": WALL} TILE_FROM_CHAR = {" ": VOID, ".": EMPTY, "#": WALL}
SCORES = {"E": 0, "S": 1, "W": 2, "N": 3} SCORES = {"E": 0, "S": 1, "W": 2, "N": 3}
class Solver(BaseSolver): board_map_s, direction_s = sys.stdin.read().split("\n\n")
def solve(self, input: str) -> Iterator[Any]:
board_map_s, direction_s = input.split("\n\n")
# board # board
board_lines = board_map_s.splitlines() board_lines = board_map_s.splitlines()
@@ -26,19 +23,16 @@ class Solver(BaseSolver):
) )
directions = [ directions = [
int(p1) if p2 else p1 int(p1) if p2 else p1 for p1, p2 in re.findall(R"(([0-9])+|L|R)", direction_s)
for p1, p2 in re.findall(R"(([0-9])+|L|R)", direction_s)
] ]
# find on each row and column the first and last non-void # find on each row and column the first and last non-void
row_first_non_void = np.argmax(board != VOID, axis=1) row_first_non_void = np.argmax(board != VOID, axis=1)
row_last_non_void = ( row_last_non_void = board.shape[1] - np.argmax(board[:, ::-1] != VOID, axis=1) - 1
board.shape[1] - np.argmax(board[:, ::-1] != VOID, axis=1) - 1
)
col_first_non_void = np.argmax(board != VOID, axis=0) col_first_non_void = np.argmax(board != VOID, axis=0)
col_last_non_void = ( col_last_non_void = board.shape[0] - np.argmax(board[::-1, :] != VOID, axis=0) - 1
board.shape[0] - np.argmax(board[::-1, :] != VOID, axis=0) - 1
)
faces = np.zeros_like(board) faces = np.zeros_like(board)
size = np.gcd(board.shape[0], board.shape[1]) size = np.gcd(board.shape[0], board.shape[1])
@@ -109,6 +103,7 @@ class Solver(BaseSolver):
}, },
} }
def wrap_part_1(y0: int, x0: int, r0: str) -> tuple[int, int, str]: def wrap_part_1(y0: int, x0: int, r0: str) -> tuple[int, int, str]:
if r0 == "E": if r0 == "E":
return y0, row_first_non_void[y0], r0 return y0, row_first_non_void[y0], r0
@@ -121,14 +116,14 @@ class Solver(BaseSolver):
assert False assert False
def wrap_part_2(y0: int, x0: int, r0: str) -> tuple[int, int, str]: def wrap_part_2(y0: int, x0: int, r0: str) -> tuple[int, int, str]:
cube = faces[y0, x0] cube = faces[y0, x0]
assert r0 in faces_wrap[cube] assert r0 in faces_wrap[cube]
return faces_wrap[cube][r0](y0, x0) return faces_wrap[cube][r0](y0, x0)
def run(
wrap: Callable[[int, int, str], tuple[int, int, str]], def run(wrap: Callable[[int, int, str], tuple[int, int, str]]) -> tuple[int, int, str]:
) -> tuple[int, int, str]:
y0 = 0 y0 = 0
x0 = np.where(board[0] == EMPTY)[0][0] x0 = np.where(board[0] == EMPTY)[0][0]
r0 = "E" r0 = "E"
@@ -137,9 +132,7 @@ class Solver(BaseSolver):
if isinstance(direction, int): if isinstance(direction, int):
while direction > 0: while direction > 0:
if r0 == "E": if r0 == "E":
xi = np.where( xi = np.where(board[y0, x0 + 1 : x0 + direction + 1] == WALL)[0]
board[y0, x0 + 1 : x0 + direction + 1] == WALL
)[0]
if len(xi): if len(xi):
x0 = x0 + xi[0] x0 = x0 + xi[0]
direction = 0 direction = 0
@@ -155,14 +148,10 @@ class Solver(BaseSolver):
x0 = row_last_non_void[y0] x0 = row_last_non_void[y0]
direction = 0 direction = 0
else: else:
direction = ( direction = direction - (row_last_non_void[y0] - x0) - 1
direction - (row_last_non_void[y0] - x0) - 1
)
y0, x0, r0 = y0_t, x0_t, r0_t y0, x0, r0 = y0_t, x0_t, r0_t
elif r0 == "S": elif r0 == "S":
yi = np.where( yi = np.where(board[y0 + 1 : y0 + direction + 1, x0] == WALL)[0]
board[y0 + 1 : y0 + direction + 1, x0] == WALL
)[0]
if len(yi): if len(yi):
y0 = y0 + yi[0] y0 = y0 + yi[0]
direction = 0 direction = 0
@@ -178,9 +167,7 @@ class Solver(BaseSolver):
y0 = col_last_non_void[x0] y0 = col_last_non_void[x0]
direction = 0 direction = 0
else: else:
direction = ( direction = direction - (col_last_non_void[x0] - y0) - 1
direction - (col_last_non_void[x0] - y0) - 1
)
y0, x0, r0 = y0_t, x0_t, r0_t y0, x0, r0 = y0_t, x0_t, r0_t
elif r0 == "W": elif r0 == "W":
left = max(x0 - direction - 1, 0) left = max(x0 - direction - 1, 0)
@@ -188,10 +175,7 @@ class Solver(BaseSolver):
if len(xi): if len(xi):
x0 = left + xi[-1] + 1 x0 = left + xi[-1] + 1
direction = 0 direction = 0
elif ( elif x0 - direction >= 0 and board[y0, x0 - direction] == EMPTY:
x0 - direction >= 0
and board[y0, x0 - direction] == EMPTY
):
x0 = x0 - direction x0 = x0 - direction
direction = 0 direction = 0
else: else:
@@ -200,9 +184,7 @@ class Solver(BaseSolver):
x0 = row_first_non_void[y0] x0 = row_first_non_void[y0]
direction = 0 direction = 0
else: else:
direction = ( direction = direction - (x0 - row_first_non_void[y0]) - 1
direction - (x0 - row_first_non_void[y0]) - 1
)
y0, x0, r0 = y0_t, x0_t, r0_t y0, x0, r0 = y0_t, x0_t, r0_t
elif r0 == "N": elif r0 == "N":
top = max(y0 - direction - 1, 0) top = max(y0 - direction - 1, 0)
@@ -210,10 +192,7 @@ class Solver(BaseSolver):
if len(yi): if len(yi):
y0 = top + yi[-1] + 1 y0 = top + yi[-1] + 1
direction = 0 direction = 0
elif ( elif y0 - direction >= 0 and board[y0 - direction, x0] == EMPTY:
y0 - direction >= 0
and board[y0 - direction, x0] == EMPTY
):
y0 = y0 - direction y0 = y0 - direction
direction = 0 direction = 0
else: else:
@@ -222,9 +201,7 @@ class Solver(BaseSolver):
y0 = col_first_non_void[x0] y0 = col_first_non_void[x0]
direction = 0 direction = 0
else: else:
direction = ( direction = direction - (y0 - col_first_non_void[x0]) - 1
direction - (y0 - col_first_non_void[x0]) - 1
)
y0, x0, r0 = y0_t, x0_t, r0_t y0, x0, r0 = y0_t, x0_t, r0_t
else: else:
r0 = { r0 = {
@@ -236,8 +213,11 @@ class Solver(BaseSolver):
return y0, x0, r0 return y0, x0, r0
y1, x1, r1 = run(wrap_part_1) y1, x1, r1 = run(wrap_part_1)
yield 1000 * (1 + y1) + 4 * (1 + x1) + SCORES[r1] answer_1 = 1000 * (1 + y1) + 4 * (1 + x1) + SCORES[r1]
print(f"answer 1 is {answer_1}")
y2, x2, r2 = run(wrap_part_2) y2, x2, r2 = run(wrap_part_2)
yield 1000 * (1 + y2) + 4 * (1 + x2) + SCORES[r2] answer_2 = 1000 * (1 + y2) + 4 * (1 + x2) + SCORES[r2]
print(f"answer 2 is {answer_2}")

View File

@@ -1,8 +1,6 @@
import itertools import itertools
import sys
from collections import defaultdict from collections import defaultdict
from typing import Any, Iterator
from ..base import BaseSolver
Directions = list[ Directions = list[
tuple[ tuple[
@@ -20,10 +18,22 @@ DIRECTIONS: Directions = [
def min_max_yx(positions: set[tuple[int, int]]) -> tuple[int, int, int, int]: def min_max_yx(positions: set[tuple[int, int]]) -> tuple[int, int, int, int]:
ys, xs = {y for y, _x in positions}, {x for _y, x in positions} ys, xs = {y for y, x in positions}, {x for y, x in positions}
return min(ys), min(xs), max(ys), max(xs) return min(ys), min(xs), max(ys), max(xs)
def print_positions(positions: set[tuple[int, int]]):
min_y, min_x, max_y, max_x = min_max_yx(positions)
print(
"\n".join(
"".join(
"#" if (y, x) in positions else "." for x in range(min_x - 1, max_x + 2)
)
for y in range(min_y - 1, max_y + 2)
)
)
def round( def round(
positions: set[tuple[int, int]], positions: set[tuple[int, int]],
directions: Directions, directions: Directions,
@@ -59,11 +69,9 @@ def round(
directions.append(directions.pop(0)) directions.append(directions.pop(0))
class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]:
POSITIONS = { POSITIONS = {
(i, j) (i, j)
for i, row in enumerate(input.splitlines()) for i, row in enumerate(sys.stdin.read().splitlines())
for j, col in enumerate(row) for j, col in enumerate(row)
if col == "#" if col == "#"
} }
@@ -71,15 +79,14 @@ class Solver(BaseSolver):
# === part 1 === # === part 1 ===
p1, d1 = POSITIONS.copy(), DIRECTIONS.copy() p1, d1 = POSITIONS.copy(), DIRECTIONS.copy()
for _ in range(10): for r in range(10):
round(p1, d1) round(p1, d1)
min_y, min_x, max_y, max_x = min_max_yx(p1) min_y, min_x, max_y, max_x = min_max_yx(p1)
yield sum( answer_1 = sum(
(y, x) not in p1 (y, x) not in p1 for y in range(min_y, max_y + 1) for x in range(min_x, max_x + 1)
for y in range(min_y, max_y + 1)
for x in range(min_x, max_x + 1)
) )
print(f"answer 1 is {answer_1}")
# === part 2 === # === part 2 ===
@@ -93,4 +100,4 @@ class Solver(BaseSolver):
if backup == p2: if backup == p2:
break break
yield answer_2 print(f"answer 2 is {answer_2}")

View File

@@ -1,14 +1,9 @@
import heapq import heapq
import math import math
import sys
from collections import defaultdict from collections import defaultdict
from typing import Any, Iterator
from ..base import BaseSolver lines = sys.stdin.read().splitlines()
class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]:
lines = [line.strip() for line in input.splitlines()]
winds = { winds = {
(i - 1, j - 1, lines[i][j]) (i - 1, j - 1, lines[i][j])
@@ -20,12 +15,8 @@ class Solver(BaseSolver):
n_rows, n_cols = len(lines) - 2, len(lines[0]) - 2 n_rows, n_cols = len(lines) - 2, len(lines[0]) - 2
CYCLE = math.lcm(n_rows, n_cols) CYCLE = math.lcm(n_rows, n_cols)
east_winds = [ east_winds = [{j for j in range(n_cols) if (i, j, ">") in winds} for i in range(n_rows)]
{j for j in range(n_cols) if (i, j, ">") in winds} for i in range(n_rows) west_winds = [{j for j in range(n_cols) if (i, j, "<") in winds} for i in range(n_rows)]
]
west_winds = [
{j for j in range(n_cols) if (i, j, "<") in winds} for i in range(n_rows)
]
north_winds = [ north_winds = [
{i for i in range(n_rows) if (i, j, "^") in winds} for j in range(n_cols) {i for i in range(n_rows) if (i, j, "^") in winds} for j in range(n_cols)
] ]
@@ -33,14 +24,13 @@ class Solver(BaseSolver):
{i for i in range(n_rows) if (i, j, "v") in winds} for j in range(n_cols) {i for i in range(n_rows) if (i, j, "v") in winds} for j in range(n_cols)
] ]
def run(start: tuple[int, int], start_cycle: int, end: tuple[int, int]): def run(start: tuple[int, int], start_cycle: int, end: tuple[int, int]):
def heuristic(y: int, x: int) -> int: def heuristic(y: int, x: int) -> int:
return abs(end[0] - y) + abs(end[1] - x) return abs(end[0] - y) + abs(end[1] - x)
# (distance + heuristic, distance, (start_pos, cycle)) # (distance + heuristic, distance, (start_pos, cycle))
queue = [ queue = [(heuristic(start[0], start[1]), 0, ((start[0], start[1]), start_cycle))]
(heuristic(start[0], start[1]), 0, ((start[0], start[1]), start_cycle))
]
visited: set[tuple[tuple[int, int], int]] = set() visited: set[tuple[tuple[int, int], int]] = set()
distances: dict[tuple[int, int], dict[int, int]] = defaultdict(lambda: {}) distances: dict[tuple[int, int], dict[int, int]] = defaultdict(lambda: {})
@@ -64,17 +54,13 @@ class Solver(BaseSolver):
n_cycle = (cycle + 1) % CYCLE n_cycle = (cycle + 1) % CYCLE
if (ty, tx) == end: if (ty, tx) == end:
heapq.heappush( heapq.heappush(queue, (distance + 1, distance + 1, ((ty, tx), n_cycle)))
queue, (distance + 1, distance + 1, ((ty, tx), n_cycle))
)
break break
if ((ty, tx), n_cycle) in visited: if ((ty, tx), n_cycle) in visited:
continue continue
if (ty, tx) != start and ( if (ty, tx) != start and (ty < 0 or tx < 0 or ty >= n_rows or tx >= n_cols):
ty < 0 or tx < 0 or ty >= n_rows or tx >= n_cols
):
continue continue
if (ty, tx) != start: if (ty, tx) != start:
@@ -89,17 +75,12 @@ class Solver(BaseSolver):
heapq.heappush( heapq.heappush(
queue, queue,
( ((heuristic(ty, tx) + distance + 1, distance + 1, ((ty, tx), n_cycle))),
(
heuristic(ty, tx) + distance + 1,
distance + 1,
((ty, tx), n_cycle),
)
),
) )
return distances, next(iter(distances[end].values())) return distances, next(iter(distances[end].values()))
start = ( start = (
-1, -1,
next(j for j in range(1, len(lines[0]) - 1) if lines[0][j] == ".") - 1, next(j for j in range(1, len(lines[0]) - 1) if lines[0][j] == ".") - 1,
@@ -110,8 +91,8 @@ class Solver(BaseSolver):
) )
distances_1, forward_1 = run(start, 0, end) distances_1, forward_1 = run(start, 0, end)
yield forward_1 print(f"answer 1 is {forward_1}")
distances_2, return_1 = run(end, next(iter(distances_1[end].keys())), start) distances_2, return_1 = run(end, next(iter(distances_1[end].keys())), start)
_distances_3, forward_2 = run(start, next(iter(distances_2[start].keys())), end) distances_3, forward_2 = run(start, next(iter(distances_2[start].keys())), end)
yield forward_1 + return_1 + forward_2 print(f"answer 2 is {forward_1 + return_1 + forward_2}")

View File

@@ -1,14 +1,10 @@
from typing import Any, Iterator import sys
from ..base import BaseSolver lines = sys.stdin.read().splitlines()
class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]:
lines = [line.strip() for line in input.splitlines()]
coeffs = {"2": 2, "1": 1, "0": 0, "-": -1, "=": -2} coeffs = {"2": 2, "1": 1, "0": 0, "-": -1, "=": -2}
def snafu2number(number: str) -> int: def snafu2number(number: str) -> int:
value = 0 value = 0
for c in number: for c in number:
@@ -16,6 +12,7 @@ class Solver(BaseSolver):
value += coeffs[c] value += coeffs[c]
return value return value
def number2snafu(number: int) -> str: def number2snafu(number: int) -> str:
values = ["0", "1", "2", "=", "-"] values = ["0", "1", "2", "=", "-"]
res = "" res = ""
@@ -25,4 +22,6 @@ class Solver(BaseSolver):
number = number // 5 + int(mod >= 3) number = number // 5 + int(mod >= 3)
return "".join(reversed(res)) return "".join(reversed(res))
yield number2snafu(sum(map(snafu2number, lines)))
answer_1 = number2snafu(sum(map(snafu2number, lines)))
print(f"answer 1 is {answer_1}")

View File

@@ -1,28 +1,23 @@
import string import string
from typing import Any, Iterator import sys
from ..base import BaseSolver lines = [line.strip() for line in sys.stdin.readlines()]
class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]:
lines = [line.strip() for line in input.splitlines()]
# extract content of each part # extract content of each part
parts = [ parts = [(set(line[: len(line) // 2]), set(line[len(line) // 2 :])) for line in lines]
(set(line[: len(line) // 2]), set(line[len(line) // 2 :])) for line in lines
]
# priorities # priorities
priorities = {c: i + 1 for i, c in enumerate(string.ascii_letters)} priorities = {c: i + 1 for i, c in enumerate(string.ascii_letters)}
# part 1 # part 1
yield sum(priorities[c] for p1, p2 in parts for c in p1.intersection(p2)) part1 = sum(priorities[c] for p1, p2 in parts for c in p1.intersection(p2))
print(f"answer 1 is {part1}")
# part 2 # part 2
n_per_group = 3 n_per_group = 3
yield sum( part2 = sum(
priorities[c] priorities[c]
for i in range(0, len(lines), n_per_group) for i in range(0, len(lines), n_per_group)
for c in set(lines[i]).intersection(*lines[i + 1 : i + n_per_group]) for c in set(lines[i]).intersection(*lines[i + 1 : i + n_per_group])
) )
print(f"answer 2 is {part2}")

View File

@@ -1,6 +1,6 @@
from typing import Any, Iterator import sys
from ..base import BaseSolver lines = [line.strip() for line in sys.stdin.readlines()]
def make_range(value: str) -> set[int]: def make_range(value: str) -> set[int]:
@@ -8,13 +8,10 @@ def make_range(value: str) -> set[int]:
return set(range(int(parts[0]), int(parts[1]) + 1)) return set(range(int(parts[0]), int(parts[1]) + 1))
class Solver(BaseSolver): sections = [tuple(make_range(part) for part in line.split(",")) for line in lines]
def solve(self, input: str) -> Iterator[Any]:
lines = [line.strip() for line in input.splitlines()]
sections = [ answer_1 = sum(s1.issubset(s2) or s2.issubset(s1) for s1, s2 in sections)
tuple(make_range(part) for part in line.split(",")) for line in lines print(f"answer 1 is {answer_1}")
]
yield sum(s1.issubset(s2) or s2.issubset(s1) for s1, s2 in sections) answer_2 = sum(bool(s1.intersection(s2)) for s1, s2 in sections)
yield sum(bool(s1.intersection(s2)) for s1, s2 in sections) print(f"answer 1 is {answer_2}")

View File

@@ -1,12 +1,7 @@
import copy import copy
from typing import Any, Iterator import sys
from ..base import BaseSolver blocks_s, moves_s = (part.splitlines() for part in sys.stdin.read().split("\n\n"))
class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]:
blocks_s, moves_s = (part.splitlines() for part in input.split("\n\n"))
blocks: dict[str, list[str]] = {stack: [] for stack in blocks_s[-1].split()} blocks: dict[str, list[str]] = {stack: [] for stack in blocks_s[-1].split()}
@@ -39,5 +34,8 @@ class Solver(BaseSolver):
blocks_2[to_].extend(blocks_2[from_][-count:]) blocks_2[to_].extend(blocks_2[from_][-count:])
del blocks_2[from_][-count:] del blocks_2[from_][-count:]
yield "".join(s[-1] for s in blocks_1.values()) answer_1 = "".join(s[-1] for s in blocks_1.values())
yield "".join(s[-1] for s in blocks_2.values()) print(f"answer 1 is {answer_1}")
answer_2 = "".join(s[-1] for s in blocks_2.values())
print(f"answer 2 is {answer_2}")

View File

@@ -1,6 +1,4 @@
from typing import Any, Iterator import sys
from ..base import BaseSolver
def index_of_first_n_differents(data: str, n: int) -> int: def index_of_first_n_differents(data: str, n: int) -> int:
@@ -10,7 +8,8 @@ def index_of_first_n_differents(data: str, n: int) -> int:
return -1 return -1
class Solver(BaseSolver): data = sys.stdin.read().strip()
def solve(self, input: str) -> Iterator[Any]:
yield index_of_first_n_differents(input, 4)
yield index_of_first_n_differents(input, 14) print(f"answer 1 is {index_of_first_n_differents(data, 4)}")
print(f"answer 2 is {index_of_first_n_differents(data, 14)}")

View File

@@ -1,12 +1,7 @@
import sys
from pathlib import Path from pathlib import Path
from typing import Any, Iterator
from ..base import BaseSolver lines = sys.stdin.read().splitlines()
class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]:
lines = [line.strip() for line in input.splitlines()]
# we are going to use Path to create path and go up/down in the file tree since it # we are going to use Path to create path and go up/down in the file tree since it
# implements everything we need # implements everything we need
@@ -58,6 +53,7 @@ class Solver(BaseSolver):
trees[cur_path].append(path) trees[cur_path].append(path)
sizes[path] = size sizes[path] = size
def compute_size(path: Path) -> int: def compute_size(path: Path) -> int:
size = sizes[path] size = sizes[path]
@@ -66,10 +62,12 @@ class Solver(BaseSolver):
return sum(compute_size(sub) for sub in trees[path]) return sum(compute_size(sub) for sub in trees[path])
acc_sizes = {path: compute_size(path) for path in trees} acc_sizes = {path: compute_size(path) for path in trees}
# part 1 # part 1
yield sum(size for size in acc_sizes.values() if size <= 100_000) answer_1 = sum(size for size in acc_sizes.values() if size <= 100_000)
print(f"answer 1 is {answer_1}")
# part 2 # part 2
total_space = 70_000_000 total_space = 70_000_000
@@ -78,4 +76,5 @@ class Solver(BaseSolver):
to_free_space = update_space - free_space 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}")

View File

@@ -1,14 +1,9 @@
from typing import Any, Iterator import sys
import numpy as np import numpy as np
from numpy.typing import NDArray from numpy.typing import NDArray
from ..base import BaseSolver lines = sys.stdin.read().splitlines()
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]) trees = np.array([[int(x) for x in row] for row in lines])
@@ -27,7 +22,9 @@ class Solver(BaseSolver):
for i in range(1, trees.shape[0] - 1) for i in range(1, trees.shape[0] - 1)
] ]
yield (highest_trees.min(axis=2) < trees).sum() answer_1 = (highest_trees.min(axis=2) < trees).sum()
print(f"answer 1 is {answer_1}")
def viewing_distance(row_of_trees: NDArray[np.int_], value: int) -> int: def viewing_distance(row_of_trees: NDArray[np.int_], value: int) -> int:
w = np.where(row_of_trees >= value)[0] w = np.where(row_of_trees >= value)[0]
@@ -37,6 +34,7 @@ class Solver(BaseSolver):
return w[0] + 1 return w[0] + 1
# answer 2 # answer 2
v_distances = np.zeros(trees.shape + (4,), dtype=int) v_distances = np.zeros(trees.shape + (4,), dtype=int)
v_distances[1:-1, 1:-1, :] = [ v_distances[1:-1, 1:-1, :] = [
@@ -51,4 +49,5 @@ class Solver(BaseSolver):
] ]
for i in range(1, trees.shape[0] - 1) for i in range(1, trees.shape[0] - 1)
] ]
yield np.prod(v_distances, axis=2).max() answer_2 = np.prod(v_distances, axis=2).max()
print(f"answer 2 is {answer_2}")

View File

@@ -1,10 +1,7 @@
import itertools as it import sys
from typing import Any, Iterator
import numpy as np import numpy as np
from ..base import BaseSolver
def move(head: tuple[int, int], command: str) -> tuple[int, int]: def move(head: tuple[int, int], command: str) -> tuple[int, int]:
h_col, h_row = head h_col, h_row = head
@@ -46,14 +43,17 @@ def run(commands: list[str], n_blocks: int) -> list[tuple[int, int]]:
return visited return visited
class Solver(BaseSolver): lines = sys.stdin.read().splitlines()
def solve(self, input: str) -> Iterator[Any]:
lines = [line.strip() for line in input.splitlines()]
# flatten the commands # flatten the commands
commands = list( commands: list[str] = []
it.chain(*(p[0] * int(p[1]) for line in lines if (p := line.split()))) for line in lines:
) d, c = line.split()
commands.extend(d * int(c))
yield len(set(run(commands, n_blocks=2)))
yield len(set(run(commands, n_blocks=10))) visited_1 = run(commands, n_blocks=2)
print(f"answer 1 is {len(set(visited_1))}")
visited_2 = run(commands, n_blocks=10)
print(f"answer 2 is {len(set(visited_2))}")

View File

@@ -83,17 +83,18 @@ class Solver(BaseSolver):
if (i, j) in loop_s and lines[i][j] in "|LJ": if (i, j) in loop_s and lines[i][j] in "|LJ":
cnt += 1 cnt += 1
if self.files: if self.verbose:
rows = [["." for _j in range(len(lines[0]))] for _i in range(len(lines))] for i in range(len(lines)):
rows[si][sj] = "\033[91mS\033[0m" s = ""
for j in range(len(lines[0])):
for i, j in loop: if (i, j) == (si, sj):
rows[i][j] = lines[i][j] s += "\033[91mS\033[0m"
for i, j in inside: elif (i, j) in loop:
rows[i][j] = "\033[92mI\033[0m" s += lines[i][j]
elif (i, j) in inside:
self.files.create( s += "\033[92mI\033[0m"
"output.txt", "\n".join("".join(row) for row in rows).encode(), True else:
) s += "."
self.logger.info(s)
yield len(inside) yield len(inside)

View File

@@ -84,14 +84,9 @@ class Solver(BaseSolver):
beams = propagate(layout, (0, 0), "R") beams = propagate(layout, (0, 0), "R")
if self.files: if self.verbose:
self.files.create( for row in beams:
"beams.txt", self.logger.info("".join("#" if col else "." for col in row))
"\n".join(
"".join("#" if col else "." for col in row) for row in beams
).encode(),
True,
)
# part 1 # part 1
yield sum(sum(map(bool, row)) for row in beams) yield sum(sum(map(bool, row)) for row in beams)

View File

@@ -33,14 +33,10 @@ MAPPINGS: dict[Direction, tuple[int, int, Direction]] = {
class Solver(BaseSolver): class Solver(BaseSolver):
def print_shortest_path( def print_shortest_path(
self, self,
name: str,
grid: list[list[int]], grid: list[list[int]],
target: tuple[int, int], target: tuple[int, int],
per_cell: dict[tuple[int, int], list[tuple[Label, int]]], per_cell: dict[tuple[int, int], list[tuple[Label, int]]],
): ):
if not self.files:
return
assert len(per_cell[target]) == 1 assert len(per_cell[target]) == 1
label = per_cell[target][0][0] label = per_cell[target][0][0]
@@ -78,9 +74,8 @@ class Solver(BaseSolver):
p_grid[0][0] = f"\033[92m{grid[0][0]}\033[0m" p_grid[0][0] = f"\033[92m{grid[0][0]}\033[0m"
self.files.create( for row in p_grid:
name, "\n".join("".join(row) for row in p_grid).encode(), True self.logger.info("".join(row))
)
def shortest_many_paths(self, grid: list[list[int]]) -> dict[tuple[int, int], int]: def shortest_many_paths(self, grid: list[list[int]]) -> dict[tuple[int, int], int]:
n_rows, n_cols = len(grid), len(grid[0]) n_rows, n_cols = len(grid), len(grid[0])
@@ -134,7 +129,6 @@ class Solver(BaseSolver):
def shortest_path( def shortest_path(
self, self,
name: str,
grid: list[list[int]], grid: list[list[int]],
min_straight: int, min_straight: int,
max_straight: int, max_straight: int,
@@ -223,7 +217,8 @@ class Solver(BaseSolver):
), ),
) )
self.print_shortest_path(f"shortest-path_{name}.txt", grid, target, per_cell) if self.verbose:
self.print_shortest_path(grid, target, per_cell)
return per_cell[target][0][1] return per_cell[target][0][1]
@@ -232,7 +227,7 @@ class Solver(BaseSolver):
estimates = self.shortest_many_paths(data) estimates = self.shortest_many_paths(data)
# part 1 # part 1
yield self.shortest_path("answer_1", data, 1, 3, lower_bounds=estimates) yield self.shortest_path(data, 1, 3, lower_bounds=estimates)
# part 2 # part 2
yield self.shortest_path("answer_2", data, 4, 10, lower_bounds=estimates) yield self.shortest_path(data, 4, 10, lower_bounds=estimates)

View File

@@ -1,3 +1,4 @@
import sys
from collections import defaultdict from collections import defaultdict
from math import lcm from math import lcm
from typing import Any, Iterator, Literal, TypeAlias from typing import Any, Iterator, Literal, TypeAlias
@@ -66,7 +67,7 @@ class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]: def solve(self, input: str) -> Iterator[Any]:
self._modules = {} self._modules = {}
lines = input.splitlines() lines = sys.stdin.read().splitlines()
for line in lines: for line in lines:
name, outputs_s = line.split(" -> ") name, outputs_s = line.split(" -> ")
@@ -79,9 +80,10 @@ class Solver(BaseSolver):
outputs, outputs,
) )
if self.files: if self.outputs:
contents = "digraph G {\n" with open("./day20.dot", "w") as fp:
contents += "rx [shape=circle, color=red, style=filled];\n" fp.write("digraph G {\n")
fp.write("rx [shape=circle, color=red, style=filled];\n")
for name, (type, outputs) in self._modules.items(): for name, (type, outputs) in self._modules.items():
if type == "conjunction": if type == "conjunction":
shape = "diamond" shape = "diamond"
@@ -89,13 +91,11 @@ class Solver(BaseSolver):
shape = "box" shape = "box"
else: else:
shape = "circle" shape = "circle"
contents += f"{name} [shape={shape}];\n" fp.write(f"{name} [shape={shape}];\n")
for name, (type, outputs) in self._modules.items(): for name, (type, outputs) in self._modules.items():
for output in outputs: for output in outputs:
contents += f"{name} -> {output};\n" fp.write(f"{name} -> {output};\n")
contents += "}\n" fp.write("}\n")
self.files.create("day20.dot", contents.encode(), False)
# part 1 # part 1
flip_flop_states: dict[str, Literal["on", "off"]] = { flip_flop_states: dict[str, Literal["on", "off"]] = {

View File

@@ -50,7 +50,7 @@ class Solver(BaseSolver):
values.append(len(tiles := reachable(map, tiles, cycle))) values.append(len(tiles := reachable(map, tiles, cycle)))
values.append(len(tiles := reachable(map, tiles, cycle))) values.append(len(tiles := reachable(map, tiles, cycle)))
if self.files: if self.verbose:
n_rows, n_cols = len(map), len(map[0]) n_rows, n_cols = len(map), len(map[0])
rows = [ rows = [
@@ -66,9 +66,8 @@ class Solver(BaseSolver):
if (i // cycle) % 2 == (j // cycle) % 2: if (i // cycle) % 2 == (j // cycle) % 2:
rows[i][j] = f"\033[91m{rows[i][j]}\033[0m" rows[i][j] = f"\033[91m{rows[i][j]}\033[0m"
self.files.create( for row in rows:
"cycle.txt", "\n".join("".join(row) for row in rows).encode(), True self.logger.info("".join(row))
)
self.logger.info(f"values to fit: {values}") self.logger.info(f"values to fit: {values}")
@@ -102,31 +101,32 @@ class Solver(BaseSolver):
# depending on the number of cycles, either A or B will be in the center # depending on the number of cycles, either A or B will be in the center
# #
# counts = [ counts = [
# [ [
# sum( sum(
# (i, j) in tiles (i, j) in tiles
# for i in range(ci * cycle, (ci + 1) * cycle) for i in range(ci * cycle, (ci + 1) * cycle)
# for j in range(cj * cycle, (cj + 1) * cycle) for j in range(cj * cycle, (cj + 1) * cycle)
# ) )
# for cj in range(-2, 3) for cj in range(-2, 3)
# ] ]
# for ci in range(-2, 3) for ci in range(-2, 3)
# ] ]
# radius = (26501365 - rhombus) // cycle - 1 radius = (26501365 - rhombus) // cycle - 1
# A = counts[2][2] if radius % 2 == 0 else counts[2][1] A = counts[2][2] if radius % 2 == 0 else counts[2][1]
# B = counts[2][2] if radius % 2 == 1 else counts[2][1] B = counts[2][2] if radius % 2 == 1 else counts[2][1]
# answer_2 = ( answer_2 = (
# (radius + 1) * A (radius + 1) * A
# + radius * B + radius * B
# + 2 * radius * (radius + 1) // 2 * A + 2 * radius * (radius + 1) // 2 * A
# + 2 * radius * (radius - 1) // 2 * B + 2 * radius * (radius - 1) // 2 * B
# + sum(counts[i][j] for i, j in ((0, 2), (-1, 2), (2, 0), (2, -1))) + sum(counts[i][j] for i, j in ((0, 2), (-1, 2), (2, 0), (2, -1)))
# + sum(counts[i][j] for i, j in ((0, 1), (0, 3), (-1, 1), (-1, 3))) + sum(counts[i][j] for i, j in ((0, 1), (0, 3), (-1, 1), (-1, 3)))
# * (radius + 1) * (radius + 1)
# + sum(counts[i][j] for i, j in ((1, 1), (1, 3), (-2, 1), (-2, 3))) * radius + sum(counts[i][j] for i, j in ((1, 1), (1, 3), (-2, 1), (-2, 3))) * radius
# ) )
print(f"answer 2 (v1) is {answer_2}")
# version 2: fitting a polynomial # version 2: fitting a polynomial
# #

View File

@@ -1,5 +1,3 @@
# pyright: reportUnknownMemberType=false
from typing import Any, Iterator from typing import Any, Iterator
import networkx as nx import networkx as nx

View File

@@ -1,35 +1,7 @@
import itertools as it
from typing import Any, Iterator from typing import Any, Iterator
from ..base import BaseSolver from ..base import BaseSolver
def process(
grid: list[list[int]], current: tuple[int, int]
) -> set[tuple[tuple[int, int], ...]]:
row, col = current
value = grid[row][col] + 1
if grid[row][col] == 9:
return {((row, col),)}
return {
((row, col),) + path
for i, j in ((row - 1, col), (row, col + 1), (row + 1, col), (row, col - 1))
if 0 <= i < len(grid) and 0 <= j < len(grid[i]) and grid[i][j] == value
for path in process(grid, (i, j))
}
class Solver(BaseSolver): class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]: def solve(self, input: str) -> Iterator[Any]: ...
grid = [[int(col) for col in row] for row in input.splitlines()]
paths = {
(i, j): process(grid, (i, j))
for i, j in it.product(range(len(grid)), range(len(grid[0])))
if grid[i][j] == 0
}
yield sum(len({path[-1] for path in paths[head]}) for head in paths)
yield sum(len(paths_of) for paths_of in paths.values())

View File

@@ -1,36 +1,7 @@
from functools import cache
from typing import Any, Iterator from typing import Any, Iterator
from ..base import BaseSolver from ..base import BaseSolver
def n_digits(n: int) -> int:
c = int(n == 0)
while n > 0:
c, n = c + 1, n // 10
return c
@cache
def blink_one_stone(stone: int, round: int) -> int:
if round == 0:
return 1
if stone == 0:
return blink_one_stone(1, round - 1)
if (n := n_digits(stone)) % 2 == 0:
p = 10 ** (n // 2)
return blink_one_stone(stone // p, round - 1) + blink_one_stone(
stone % p, round - 1
)
return blink_one_stone(stone * 2024, round - 1)
class Solver(BaseSolver): class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]: def solve(self, input: str) -> Iterator[Any]: ...
stones = list(map(int, input.split()))
yield sum(blink_one_stone(stone, 25) for stone in stones)
yield sum(blink_one_stone(stone, 75) for stone in stones)

View File

@@ -1,101 +1,7 @@
import itertools as it from typing import Any, Iterator
from dataclasses import dataclass
from typing import Any, Iterator, TypeAlias
from ..base import BaseSolver from ..base import BaseSolver
Node: TypeAlias = tuple[int, int]
Edge: TypeAlias = tuple[Node, Node]
@dataclass(frozen=True)
class Region:
value: str
cells: set[tuple[int, int]]
edges: set[Edge]
sides: list[tuple[Edge, ...]]
def extract_region(grid: list[str], cell: tuple[int, int]):
n_rows, n_cols = len(grid), len(grid[0])
row, col = cell
value = grid[row][col]
cells: set[tuple[int, int]] = set()
edges: set[Edge] = set()
sides: list[tuple[Edge, ...]] = []
queue: list[tuple[int, int]] = [(row, col)]
while queue:
row, col = queue.pop(0)
if (row, col) in cells:
continue
cells.add((row, col))
for ur, uc in (
(row - 1, col),
(row, col + 1),
(row + 1, col),
(row, col - 1),
):
if 0 <= ur < n_rows and 0 <= uc < n_cols and grid[ur][uc] == value:
queue.append((ur, uc))
continue
if ((row, col), (ur, uc)) in edges:
continue
if col == uc:
mid, max = col, n_cols
def get(v: int):
return (row, v, ur, v)
else:
mid, max = row, n_rows
def get(v: int):
return (v, col, v, uc)
side: tuple[Edge, ...] = ((((row, col), (ur, uc))),)
for rng in (range(mid - 1, -1, -1), range(mid, max)):
for r2, c2, ur2, uc2 in map(get, rng):
if grid[r2][c2] != value or (
0 <= ur2 < n_rows
and 0 <= uc2 < n_cols
and grid[r2][c2] == grid[ur2][uc2]
):
break
side += ((((r2, c2), (ur2, uc2))),)
sides.append(side)
edges = edges.union(side)
return Region(value=value, cells=cells, edges=edges, sides=sides)
class Solver(BaseSolver): class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]: def solve(self, input: str) -> Iterator[Any]: ...
grid = input.splitlines()
regions: list[Region] = []
to_visit: set[tuple[int, int]] = set(
it.product(range(len(grid)), range(len(grid[0])))
)
while to_visit:
region = extract_region(grid, next(iter(to_visit)))
self.logger.info(
f"region with {region.value}: "
f"{len(region.cells)} * {len(region.edges)} = {len(region.cells) * len(region.edges)}, "
f"{len(region.cells)} * {len(region.sides)} = {len(region.cells) * len(region.sides)}"
)
to_visit.difference_update(region.cells)
regions.append(region)
yield sum(len(region.cells) * len(region.edges) for region in regions)
yield sum(len(region.cells) * len(region.sides) for region in regions)

View File

@@ -1,79 +1,7 @@
import math
from dataclasses import dataclass
from typing import Any, Iterator from typing import Any, Iterator
import parse # pyright: ignore[reportMissingTypeStubs]
from ..base import BaseSolver from ..base import BaseSolver
@dataclass(frozen=True)
class Machine:
prize: tuple[int, int]
button_a: tuple[int, int]
button_b: tuple[int, int]
def read_machine(block: str) -> Machine:
ba = parse.parse( # type: ignore
"""Button A: X{bax:d}, Y{bay:d}
Button B: X{bbx:d}, Y{bby:d}
Prize: X={px:d}, Y={py:d}""",
block,
)
return Machine(
prize=(ba["px"], ba["py"]), # type: ignore
button_a=(ba["bax"], ba["bay"]), # type: ignore
button_b=(ba["bbx"], ba["bby"]), # type: ignore
)
def diophantine(a: int, b: int, c: int) -> tuple[int, int]:
q, r = divmod(a, b)
if r == 0:
return (0, c // b)
else:
u, v = diophantine(b, r, c)
return (v, u - q * v)
def solve(machine: Machine) -> int:
(ax, ay), (bx, by), (px, py) = machine.button_a, machine.button_b, machine.prize
dx, dy = math.gcd(ax, bx), math.gcd(ay, by)
if px % dx != 0 or py % dy != 0:
return 0
xa, xb = diophantine(ax, bx, px)
ya, yb = diophantine(ay, by, py)
# expr (x): xa - kx * bx / dx, xb + kx * ax / dx
# expr (y): ya - ky * by / dy, yb + ky * ay / dy
num = ay * (ya - xa) + by * (yb - xb)
den = (ax * by - ay * bx) // dx
if num % den != 0:
return 0
kx = num // den
pa, pb = xa - kx * bx // dx, xb + kx * ax // dx
return 3 * pa + pb
class Solver(BaseSolver): class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]: def solve(self, input: str) -> Iterator[Any]: ...
machines = [read_machine(block) for block in input.split("\n\n")]
yield sum(map(solve, machines))
shift = 10000000000000
machines = [
Machine(
prize=(shift + m.prize[0], shift + m.prize[1]),
button_a=m.button_a,
button_b=m.button_b,
)
for m in machines
]
yield sum(map(solve, machines))

View File

@@ -1,74 +1,7 @@
import itertools as it
import operator as op
from math import prod
from typing import Any, Iterator from typing import Any, Iterator
import numpy as np
import parse # pyright: ignore[reportMissingTypeStubs]
from ..base import BaseSolver from ..base import BaseSolver
class Solver(BaseSolver): class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]: def solve(self, input: str) -> Iterator[Any]: ...
positions: list[tuple[int, int]] = []
velocities: list[tuple[int, int]] = []
for line in input.splitlines():
r = parse.parse("p={x:d},{y:d} v={vx:d},{vy:d}", line) # type: ignore
positions.append((r["y"], r["x"])) # type: ignore
velocities.append((r["vy"], r["vx"])) # type: ignore
n_rows, n_cols = 103, 101
if len(positions) < 20:
n_rows, n_cols = 7, 11
n_rounds = 100
new_positions = [
((row + v_row * n_rounds) % n_rows, (col + v_col * n_rounds) % n_cols)
for (row, col), (v_row, v_col) in zip(positions, velocities, strict=True)
]
midrow = n_rows // 2
midcol = n_cols // 2
yield prod(
(
sum(opr(row, midrow) and opc(col, midcol) for row, col in new_positions)
for opr, opc in it.product((op.gt, op.lt), repeat=2)
)
)
new_positions = positions.copy()
for rnd in self.progress.wrap(range(10000)):
new_positions = [
((row + v_row) % n_rows, (col + v_col) % n_cols)
for (row, col), (v_row, v_col) in zip(
new_positions, velocities, strict=True
)
]
m = [[False for _ in range(n_cols)] for _ in range(n_rows)]
for row, col in new_positions:
m[row][col] = True
found = False
for row in m:
if sum(row) <= 10:
continue
if any(all(row[i : i + 10]) for i in range(n_cols - 10)):
if self.files:
self.files.create(
f"result_{rnd+1}.txt",
"\n".join(
"".join("#" if m[i][j] else "." for j in range(n_cols))
for i in range(n_rows)
).encode(),
True,
)
self.files.image(f"result_{rnd+1}.png", np.array(m))
yield rnd + 1
# found = True
break
if found:
break

View File

@@ -1,282 +1,7 @@
from typing import Any, Callable, Final, Iterator, TypeAlias from typing import Any, Iterator
import numpy as np
from numpy.typing import NDArray
from ..base import BaseSolver from ..base import BaseSolver
ImageGrid: TypeAlias = NDArray[np.uint8]
class Grid:
FREE: Final = 0
BLOCK: Final = 1
ROBOT: Final = 2
robot: tuple[int, int]
def __init__(self, grid_s: list[str], large: bool):
grid: list[list[int]] = []
robot: tuple[int, int] | None = None
box_counter = 4 if not large else 5
for i_row, row in enumerate(grid_s):
row_u: list[int] = []
for i_col, col in enumerate(row):
if col in ".@":
row_u.extend((Grid.FREE, Grid.FREE) if large else (Grid.FREE,))
if col == "@":
robot = (i_row, i_col * 2 if large else i_col)
elif col == "#":
row_u.extend((Grid.BLOCK, Grid.BLOCK) if large else (Grid.BLOCK,))
else:
row_u.extend(
(box_counter, -box_counter) if large else (box_counter,)
)
box_counter += 2
grid.append(row_u)
self.grid = np.array(grid)
assert robot is not None
self.robot = robot
@property
def n_rows(self):
return len(self.grid)
@property
def n_columns(self):
return len(self.grid[0])
def __len__(self):
return self.n_rows
def __iter__(self):
return iter(self.grid)
def __getitem__(self, index: tuple[int, int]):
return self.grid[*index]
def __setitem__(self, index: tuple[int, int], value: int):
self.grid[*index] = value
def is_free(self, row: int, col: int):
return self[row, col] == Grid.FREE
def is_block(self, row: int, col: int):
return self[row, col] == Grid.BLOCK
def is_box(self, row: int, col: int):
return (c := self[row, col]) >= 4 and c % 2 == 0
def is_open_or_close_box(self, row: int, col: int):
return abs(c := self[row, col]) >= 4 and c % 2 == 1
def is_open_box(self, row: int, col: int):
return (c := self[row, col]) >= 4 and c % 2 == 1
def is_close_box(self, row: int, col: int):
return self[row, col] < 0
def _to_char(self, row: int, col: int):
if self.is_free(row, col):
return "."
elif self.is_block(row, col):
return "#"
elif self.is_box(row, col):
return "O"
elif self.is_open_box(row, col):
return "["
else:
return "]"
def as_numpy(self):
arr = self.grid.copy()
arr[*self.robot] = Grid.ROBOT
return arr
def as_printable(self):
grid_s = [
[self._to_char(row, col) for col in range(self.n_columns)]
for row in range(self.n_rows)
]
grid_s[self.robot[0]][self.robot[1]] = "\033[31;1m@\033[00m"
return "\n".join("".join(row) for row in grid_s)
def __str__(self):
return self.as_printable()
class Solver(BaseSolver): class Solver(BaseSolver):
def save_grid(self, name: str, grid: Grid): def solve(self, input: str) -> Iterator[Any]: ...
if self.files:
self.files.create(name, grid.as_printable().encode(), True)
def step_part1(self, grid: Grid, move: str):
match move:
case "^":
d_row, d_col = -1, 0
case ">":
d_row, d_col = 0, 1
case "v":
d_row, d_col = 1, 0
case "<":
d_row, d_col = 0, -1
case _:
assert False
row, col = grid.robot
if grid.is_free(row + d_row, col + d_col):
grid.robot = (row + d_row, col + d_col)
elif not grid.is_block(row + d_row, col + d_col):
n = 1
while grid.is_box(row + n * d_row, col + n * d_col):
n += 1
if grid.is_free(row + n * d_row, col + n * d_col):
grid.robot = (row + d_row, col + d_col)
for k in range(2, n + 1):
grid[row + k * d_row, col + k * d_col] = grid[
row + (k - 1) * d_row, col + (k - 1) * d_col
]
grid[row + d_row, col + d_col] = Grid.FREE
return grid
def step_part2(self, grid: Grid, move: str):
match move:
case "^":
d_row, d_col = -1, 0
case ">":
d_row, d_col = 0, 1
case "v":
d_row, d_col = 1, 0
case "<":
d_row, d_col = 0, -1
case _:
assert False
row, col = grid.robot
if grid.is_free(row + d_row, col + d_col):
grid.robot = (row + d_row, col + d_col)
elif grid.is_block(row + d_row, col + d_col):
...
elif move in "<>":
n = 1
while grid.is_open_or_close_box(row, col + n * d_col):
n += 1
if grid.is_free(row, col + n * d_col):
grid.robot = (row, col + d_col)
for k in range(n, 1, -1):
grid[row, col + k * d_col] = grid[row, col + (k - 1) * d_col]
grid[row + d_row, col + d_col] = Grid.FREE
elif move in "^v":
n = 1
boxes: list[set[int]] = [{col}]
while True:
to_move = boxes[-1]
if any(grid.is_block(row + n * d_row, c) for c in to_move):
break
if all(grid.is_free(row + n * d_row, c) for c in to_move):
break
as_move: set[int] = set()
for c in to_move:
if grid.is_close_box(row + n * d_row, c):
as_move.update({c - 1, c})
elif grid.is_open_box(row + n * d_row, c):
as_move.update({c, c + 1})
boxes.append(as_move)
n += 1
if all(grid.is_free(row + n * d_row, c) for c in boxes[-1]):
for k, to_move in zip(range(n, 1, -1), boxes[-1:0:-1], strict=True):
for c in to_move:
grid[row + k * d_row, c] = grid[row + (k - 1) * d_row, c]
grid[row + (k - 1) * d_row, c] = Grid.FREE
grid.robot = (row + d_row, col + d_col)
return grid
def run(
self,
name: str,
grid: Grid,
moves: str,
fn: Callable[[Grid, str], Grid],
generate: bool,
) -> tuple[Grid, list[ImageGrid]]:
# initialize
images: list[ImageGrid] = []
if generate:
images.append(grid.as_numpy())
self.save_grid(f"initial_grid_{name}.txt", grid)
for move in self.progress.wrap(moves):
self.logger.debug(f"Move '{move}'...")
grid = fn(grid, move)
if generate:
images.append(grid.as_numpy())
self.save_grid(f"final_grid_{name}.txt", grid)
return grid, images
def solve(self, input: str) -> Iterator[Any]:
grid_s, moves = input.split("\n\n")
moves = "".join(moves.split())
n_boxes = grid_s.count("O")
colors = np.concatenate(
[
np.array(
[[255, 255, 255], [64, 64, 64], [255, 0, 0]],
dtype=np.uint8,
),
np.random.randint(0, 256, size=(n_boxes, 3), dtype=np.uint8),
],
dtype=np.uint8,
)
grid, images = self.run(
"part1",
Grid(grid_s.splitlines(), False),
moves,
self.step_part1,
self.files is not None,
)
if self.files:
images = np.stack(images, axis=0)
images[images >= 2] = 1 + images[images >= 2] // 2
self.files.video("anim_part1.webm", colors[images])
yield sum(
100 * row + col
for row in range(grid.n_rows)
for col in range(grid.n_columns)
if grid.is_box(row, col)
)
grid, images = self.run(
"part2",
Grid(grid_s.splitlines(), True),
moves,
self.step_part2,
self.files is not None,
)
if self.files:
images = np.abs(np.stack(images, axis=0))
images[images >= 2] = 1 + images[images >= 2] // 2
self.files.video("anim_part2.webm", colors[images])
yield sum(
100 * row + col
for row in range(grid.n_rows)
for col in range(grid.n_columns)
if grid.is_open_box(row, col)
)

View File

@@ -1,62 +1,7 @@
import heapq from typing import Any, Iterator
from collections import defaultdict
from typing import Any, Iterator, TypeAlias
from ..base import BaseSolver from ..base import BaseSolver
Position: TypeAlias = tuple[int, int]
Direction: TypeAlias = tuple[int, int]
class Solver(BaseSolver): class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]: def solve(self, input: str) -> Iterator[Any]: ...
grid = [list(r) for r in input.splitlines()]
n_rows, n_cols = len(grid), len(grid[0])
rein = next(
(i, j) for i in range(n_rows) for j in range(n_cols) if grid[i][j] == "S"
)
target = next(
(i, j) for i in range(n_rows) for j in range(n_cols) if grid[i][j] == "E"
)
queue: list[tuple[int, Position, Direction, tuple[Position, ...]]] = [
(0, rein, (0, 1), (rein,))
]
max_score = n_rows * n_cols * 1000
target_score: int = max_score
scores: dict[tuple[Position, Direction], int] = defaultdict(lambda: max_score)
visited: set[Position] = set()
while queue:
score, pos, dir, path = heapq.heappop(queue)
if target_score < score:
break
if pos == target:
target_score = score
visited |= set(path)
continue
scores[pos, dir] = score
row, col = pos
d_row, d_col = dir
for cost, n_pos, n_dir in (
(1, (row + d_row, col + d_col), dir),
(1000, pos, (1, 0) if d_row == 0 else (0, 1)),
(1000, pos, (-1, 0) if d_row == 0 else (0, -1)),
):
n_row, n_col = n_pos
score_n = score + cost
if grid[n_row][n_col] != "#" and score_n < scores[n_pos, n_dir]:
heapq.heappush(
queue,
(score_n, n_pos, n_dir, path + (n_pos,)),
)
assert target_score is not None
yield target_score
yield len(visited)

View File

@@ -3,128 +3,5 @@ from typing import Any, Iterator
from ..base import BaseSolver from ..base import BaseSolver
def combo(registers: dict[str, int], operand: int):
if operand < 4:
return operand
assert operand < 7
return registers["ABC"[operand - 4]]
def adv(registers: dict[str, int], operand: int) -> int | None:
registers["A"] = registers["A"] >> combo(registers, operand)
def bxl(registers: dict[str, int], operand: int) -> int | None:
registers["B"] ^= operand
def bst(registers: dict[str, int], operand: int) -> int | None:
registers["B"] = combo(registers, operand) % 8
def jnz(registers: dict[str, int], operand: int) -> int | None:
if registers["A"] != 0:
return operand
def bxc(registers: dict[str, int], operand: int) -> int | None:
registers["B"] = registers["B"] ^ registers["C"]
def bdv(registers: dict[str, int], operand: int) -> int | None:
registers["B"] = registers["A"] >> combo(registers, operand)
def cdv(registers: dict[str, int], operand: int) -> int | None:
registers["C"] = registers["A"] >> combo(registers, operand)
def run(registers: dict[str, int], program: list[int]):
outputs: list[int] = []
def out(registers: dict[str, int], operand: int) -> int | None:
outputs.append(combo(registers, operand) % 8)
instructions = [adv, bxl, bst, jnz, bxc, out, bdv, cdv]
index = 0
while index < len(program):
instruction, operand = instructions[program[index]], program[index + 1]
ret = instruction(registers, operand)
if ret is None:
index += 2
else:
index = ret
return outputs
class Solver(BaseSolver): class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]: def solve(self, input: str) -> Iterator[Any]: ...
register_s, program_s = input.split("\n\n")
registers = {
p[0][-1]: int(p[1].strip())
for line in register_s.splitlines()
if (p := line.split(":"))
}
program = [int(c) for c in program_s.split(":")[1].strip().split(",")]
self.logger.info(f"program ({len(program)}): " + ",".join(map(str, program)))
instruction_s = [
"A = A >> {}",
"B = B ^ {}",
"B = {} % 8",
"JMP {}",
"B = B ^ C",
"OUT {} % 8",
"B = A >> {}",
"C = A >> {}",
]
self.logger.info("PROGRAM:")
for index in range(0, len(program), 2):
self.logger.info(
instruction_s[program[index]].format(
""
if program[index] == 4
else (
program[index + 1]
if program[index] in (1, 3) or program[index + 1] < 4
else "ABC"[program[index + 1] - 4]
)
),
)
yield ",".join(map(str, run(registers.copy(), program)))
# last instruction is JNZ 0 (jump at the beginning), and it is the only jump
# in the program
jnz_indices = [i for i in range(0, len(program), 2) if program[i] == 3]
assert jnz_indices == [len(program) - 2] and program[-1] == 0
# previous instruction is dividing A by 8, or A = A >> 3
assert program[-4:-2] == [0, 3]
# previous instruction is a OUT B % 8, and it is the only OUT in the program
out_indices = [i for i in range(0, len(program), 2) if program[i] == 5]
assert out_indices == [len(program) - 6] and program[len(program) - 5] == 5
valid: list[int] = [0]
for p in reversed(program):
new_valid: list[int] = []
for v in valid:
a_high = v << 3
for a_low in range(0, 2**3):
registers["A"] = a_high | a_low
run(registers, program[:-6])
if registers["B"] % 8 == p:
new_valid.append(a_high | a_low)
valid = new_valid
assert run(registers | {"A": min(valid)}, program) == program
yield min(valid)

View File

@@ -1,58 +1,7 @@
from typing import Any, Iterator from typing import Any, Iterator
from ..base import BaseSolver from ..base import BaseSolver
from ..tools import graphs
class Solver(BaseSolver): class Solver(BaseSolver):
def print_grid(self, grid: list[tuple[int, int]], n_rows: int, n_cols: int): def solve(self, input: str) -> Iterator[Any]: ...
values = set(grid)
if self.files:
self.files.create(
"graph.txt",
"\n".join(
"".join(
"#" if (row, col) in values else "." for col in range(n_cols)
)
for row in range(n_rows)
).encode(),
text=True,
)
else:
for row in range(n_rows):
self.logger.info(
"".join(
"#" if (row, col) in values else "." for col in range(n_cols)
)
)
def dijkstra(self, corrupted: list[tuple[int, int]], n_rows: int, n_cols: int):
return graphs.dijkstra(
(0, 0),
(n_rows - 1, n_cols - 1),
graphs.make_neighbors_grid_fn(n_rows, n_cols, set(corrupted)),
)
def solve(self, input: str) -> Iterator[Any]:
values = [
(int(p[0]), int(p[1])) for r in input.splitlines() if (p := r.split(","))
]
_is_test = len(values) < 100
n_rows, n_cols, n_bytes_p1 = (7, 7, 12) if _is_test else (71, 71, 1024)
bytes_p1 = values[:n_bytes_p1]
self.print_grid(bytes_p1, n_rows, n_cols)
path_p1, cost_p1 = self.dijkstra(bytes_p1, n_rows, n_cols) or ((), -1)
yield cost_p1
path = path_p1
for b in range(n_bytes_p1, len(values)):
if values[b] not in path:
continue
path, _ = self.dijkstra(values[: b + 1], n_rows, n_cols) or (None, -1)
if path is None:
yield ",".join(map(str, values[b]))
break

View File

@@ -1,42 +1,7 @@
from functools import cache
from typing import Any, Iterator from typing import Any, Iterator
from ..base import BaseSolver from ..base import BaseSolver
@cache
def is_valid(design: str, towels: tuple[str, ...]) -> bool:
if not design:
return True
return any(
design.startswith(towel) and is_valid(design[len(towel) :], towels)
for towel in towels
)
@cache
def count_valid(design: str, towels: tuple[str, ...]) -> int:
if not design:
return 1
return sum(
design.startswith(towel) and count_valid(design[len(towel) :], towels)
for towel in towels
)
class Solver(BaseSolver): class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]: def solve(self, input: str) -> Iterator[Any]: ...
towels_s, designs_s = input.split("\n\n")
towels = tuple(s.strip() for s in towels_s.split(","))
designs = [
design
for design in self.progress.wrap(designs_s.splitlines())
if is_valid(design, towels)
]
yield len(designs)
yield sum(count_valid(design, towels) for design in self.progress.wrap(designs))

View File

@@ -1,95 +1,7 @@
import itertools from typing import Any, Iterator
from collections import Counter
from typing import Any, Callable, Iterable, Iterator, Sequence, TypeAlias
from ..base import BaseSolver from ..base import BaseSolver
from ..tools.graphs import dijkstra, make_neighbors_grid_fn
Node: TypeAlias = tuple[int, int]
def make_neighbors_fn(grid: list[str], cheat_length: int):
n_rows, n_cols = len(grid), len(grid[0])
def _fn(node: Node):
row, col = node
return (
((row_n, col_n), abs(row_n - row) + abs(col_n - col))
for row_d in range(-cheat_length, cheat_length + 1)
for col_d in range(
-cheat_length + abs(row_d), cheat_length - abs(row_d) + 1
)
if 0 <= (row_n := row + row_d) < n_rows
and 0 <= (col_n := col + col_d) < n_cols
and grid[row_n][col_n] != "#"
)
return _fn
class Solver(BaseSolver): class Solver(BaseSolver):
def find_cheats( def solve(self, input: str) -> Iterator[Any]: ...
self,
path: Sequence[Node],
cost: float,
costs_to_target: dict[Node, float],
neighbors_fn: Callable[[Node], Iterable[tuple[Node, float]]],
):
cheats: dict[tuple[tuple[int, int], tuple[int, int]], float] = {}
for i_node, node in enumerate(self.progress.wrap(path)):
for reach_node, reach_cost in neighbors_fn(node):
n_cost = (
i_node + reach_cost + costs_to_target.get(reach_node, float("inf"))
)
if n_cost < cost:
cheats[node, reach_node] = cost - n_cost
return cheats
def solve(self, input: str) -> Iterator[Any]:
grid = input.splitlines()
n_rows, n_cols = len(grid), len(grid[0])
start = next(
(i, j) for i in range(n_rows) for j in range(n_cols) if grid[i][j] == "S"
)
target = next(
(i, j) for i in range(n_rows) for j in range(n_cols) if grid[i][j] == "E"
)
reachable = dijkstra(
target,
None,
make_neighbors_grid_fn(
n_rows,
n_cols,
excluded=(
(i, j)
for i in range(n_rows)
for j in range(n_cols)
if grid[i][j] == "#"
),
),
)
# note: path is inverted here
path, cost = reachable[start]
costs_to_target = {k: c for k, (_, c) in reachable.items()}
self.logger.info(f"found past from start to target with cost {cost}")
for cheat_length in (2, 20):
cheats = self.find_cheats(
list(reversed(path)),
cost,
costs_to_target,
make_neighbors_fn(grid, cheat_length),
)
for saving, count in sorted(Counter(cheats.values()).items()):
self.logger.debug(
f"There are {count} cheats that save {saving} picoseconds."
)
target_saving = 100 if len(grid) > 20 else 50
yield sum(saving >= target_saving for saving in cheats.values())

View File

@@ -1,85 +1,7 @@
import itertools from typing import Any, Iterator
from functools import cache
from typing import Any, Iterator, Literal
from ..base import BaseSolver from ..base import BaseSolver
NUM_PAD_P = {
v: (i, j)
for i, r in enumerate(("789", "456", "123", " 0A"))
for j, v in enumerate(r)
if v.strip()
}
MOV_PAD_P = {
v: (i, j)
for i, r in enumerate((" ^A", "<v>"))
for j, v in enumerate(r)
if v.strip()
}
def path(start: tuple[int, int], end: tuple[int, int], pad: Literal["num", "mov"]):
# a move in the grid is composed of at most two straight line: up/down and
# left/right, since doing some kind of diagonal moves would create long path for
# the robot above (since this involves going back-and-forth to the letter 'A')
#
row_s, col_s = start
row_e, col_e = end
le, de, ue, re = (
"<" * max(0, col_s - col_e),
"v" * max(0, row_e - row_s),
"^" * max(0, row_s - row_e),
">" * max(0, col_e - col_s),
)
# when the robot starts or ends on the row/column with the empty cell, there is
# only one way to move
#
if pad == "num" and (row_s, col_e) == (3, 0):
return ue + le
elif pad == "num" and (col_s, row_e) == (0, 3):
return re + de
elif pad == "mov" and col_s == 0:
return re + ue
elif pad == "mov" and col_e == 0:
return de + le
# otherwise, we need to decide if we want to go up/down first, or left/right, and
# apparently this is the best way to do it...
return le + de + ue + re
@cache
def v_clicks(clicks: str, depth: int) -> int:
if depth == 0:
return len(clicks)
n_clicks = 0
at = "A"
for _, group in itertools.groupby(clicks):
group = list(group)
n_clicks += v_clicks(
path(MOV_PAD_P[at], MOV_PAD_P[group[0]], "mov") + "A" * len(group),
depth - 1,
)
at = group[0]
return n_clicks
def path_length(code: str, depth: int):
return sum(
v_clicks(path(NUM_PAD_P[start], NUM_PAD_P[end], "num") + "A", depth)
for start, end in zip("A" + code[:-1], code, strict=True)
)
class Solver(BaseSolver): class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]: def solve(self, input: str) -> Iterator[Any]: ...
yield sum(
path_length(code, 2) * int(code[:-1], 10) for code in input.splitlines()
)
yield sum(
path_length(code, 25) * int(code[:-1], 10) for code in input.splitlines()
)

View File

@@ -3,57 +3,5 @@ from typing import Any, Iterator
from ..base import BaseSolver from ..base import BaseSolver
def mix(secret: int, value: int) -> int:
return secret ^ value
def prune(secret: int) -> int:
return secret % 16777216
def next_number(secret: int) -> int:
# Calculate the result of multiplying the secret number by 64. Then, mix this
# result into the secret number. Finally, prune the secret number.
secret = prune(mix(secret, secret * 64))
# Calculate the result of dividing the secret number by 32. Round the result down
# to the nearest integer. Then, mix this result into the secret number. Finally,
# prune the secret number.
secret = prune(mix(secret, secret // 32))
# Calculate the result of multiplying the secret number by 2048. Then, mix this
# result into the secret number. Finally, prune the secret number.
secret = prune(mix(secret, secret * 2048))
return secret
class Solver(BaseSolver): class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]: def solve(self, input: str) -> Iterator[Any]: ...
starts = [int(r) for r in input.splitlines()]
ends: list[int] = []
prices: list[int] = [0 for _ in range(2**16)]
for secret in self.progress.wrap(starts):
checked: list[bool] = [False] * len(prices)
hashed: int = 0
for i in range(2000):
last = secret % 10
secret = next_number(secret)
next = secret % 10
hashed = ((hashed << 4) & 0xFFFF) | ((last - next) & 0xF)
if i >= 3 and not checked[hashed]:
checked[hashed] = True
prices[hashed] += next
ends.append(secret)
for start, end in zip(starts, ends, strict=True):
self.logger.info(f"{start}: {end}")
yield sum(ends)
yield max(prices)

View File

@@ -1,36 +1,7 @@
from collections import defaultdict
from typing import Any, Iterator from typing import Any, Iterator
from ..base import BaseSolver from ..base import BaseSolver
from ..tools.graphs import iter_max_cliques
class Solver(BaseSolver): class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]: def solve(self, input: str) -> Iterator[Any]: ...
connections: dict[str, set[str]] = defaultdict(set)
for row in input.splitlines():
src, dst = row.split("-")
connections[src].add(dst)
connections[dst].add(src)
if self.files:
content = "graph G {\n"
for row in input.splitlines():
src, dst = row.split("-")
content += f"{src} -- {dst}\n"
content += "}"
self.files.create("graph.dot", content.encode(), False)
cliques: set[frozenset[str]] = set()
for node1, neighbors in connections.items():
for node2 in neighbors:
for node3 in connections[node2].intersection(neighbors):
cliques.add(frozenset({node1, node2, node3}))
self.logger.info(f"found {len(cliques)} cliques of size 3")
yield sum(any(node.startswith("t") for node in clique) for clique in cliques)
# clique = max(nx.algorithms.clique.find_cliques(G), key=len)
clique = max(iter_max_cliques(connections), key=len)
yield ",".join(sorted(clique))

View File

@@ -1,170 +1,7 @@
from dataclasses import dataclass from typing import Any, Iterator
from typing import Any, Iterator, Literal, TypeAlias, cast
from ..base import BaseSolver from ..base import BaseSolver
GateType: TypeAlias = Literal["and", "or", "xor"]
@dataclass(frozen=True, eq=True)
class Gate:
type: GateType
lhs: str
rhs: str
def __call__(self, lhs: int, rhs: int) -> Any:
match self.type:
case "or":
return int(lhs or rhs)
case "and":
return int(lhs and rhs)
case "xor":
return int(lhs != rhs)
class Solver(BaseSolver): class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]: def solve(self, input: str) -> Iterator[Any]: ...
inputs_s, gates_s = input.split("\n\n")
wires: dict[str, int | None] = {}
for row in inputs_s.splitlines():
parts = row.split(": ")
wires[parts[0]] = int(parts[1])
gates: dict[str, Gate] = {}
for row in gates_s.splitlines():
parts = row.split()
assert parts[4] not in gates
assert parts[4] not in wires
lhs, rhs = sorted([parts[0], parts[2]])
gates[parts[4]] = Gate(cast(GateType, parts[1].lower()), lhs, rhs)
wires[parts[4]] = None
if self.files:
content = "digraph G {\n"
for wire in wires:
content += f'{wire} [label="{wire}"]\n'
for wire, gate in gates.items():
gate_n = f"G_{wire}"
content += f'{gate_n} [label="{gate.type.upper()}"]\n'
content += f"{gate.lhs} -> {gate_n}\n"
content += f"{gate.rhs} -> {gate_n}\n"
content += f"{gate_n} -> {wire}\n"
content += "}\n"
self.files.create("gates.dot", content.encode(), text=False)
wires_to_find = set(gates)
while wires_to_find:
wires_found: list[str] = []
for wire in wires_to_find:
gate = gates[wire]
lhs, rhs = wires[gate.lhs], wires[gate.rhs]
if lhs is None or rhs is None:
continue
assert wires[wire] is None
wires[wire] = gate(lhs, rhs)
wires_found.append(wire)
wires_to_find.difference_update(wires_found)
z_wires = sorted((wire for wire in wires if wire.startswith("z")))
self.logger.info(
"binary value is '{}'".format(
"".join(str(wires[w]) for w in reversed(z_wires))
)
)
yield int("".join(str(wires[w]) for w in reversed(z_wires)), base=2)
# e00 = x00 ^ y00
# z00 = e00
# r00 = x00 & y00
# e01 = x01 ^ y01
# z01 = r00 ^ e01
# a01 = x01 & y01
# b01 = r00 & e01
# r01 = a01 | (r00 & e01)
assert gates["z00"] == Gate("xor", "x00", "y00")
# normalized names -> gate name
m_gates: dict[str, str] = {}
def find_gate(type: GateType, lhs: str, rhs: str):
try:
return next(
wire
for wire, gate in gates.items()
if gate.type == type
and {gate.lhs, gate.rhs}
== {m_gates.get(lhs, lhs), m_gates.get(rhs, rhs)}
)
except StopIteration as ex:
self.logger.info(
f"gate {lhs} [{m_gates.get(lhs, lhs)}] {type} {rhs} [{m_gates.get(rhs, rhs)}] not found"
)
raise ex
# find the r00 gate (= x00 & y00)
m_gates["r00"] = find_gate("and", "x00", "y00")
swapped: list[str] = []
for i_wire, z_wire in enumerate(z_wires[1:-1], start=1):
i2d = f"{i_wire:02d}"
r0n = f"r{i_wire - 1:02d}"
m_gates[f"e{i2d}"] = find_gate("xor", f"x{i2d}", f"y{i2d}")
try:
z_gate = find_gate("xor", r0n, f"e{i2d}")
except StopIteration:
# gate xor not found -> one of the input gate has been swapped
#
# assume there is a XOR gate with the remainder, so it is the other
# input that has been swapped
assert gates[z_wire].type == "xor"
assert m_gates.get(r0n, r0n) in (gates[z_wire].lhs, gates[z_wire].rhs)
wrong_wire_1 = (
gates[z_wire].lhs
if gates[z_wire].rhs == m_gates.get(r0n, r0n)
else gates[z_wire].rhs
)
wrong_wire_2 = m_gates[f"e{i2d}"]
# we are going to fix all the gates (there is probably only 2 but
# eh...) whose wires needs to be swapped
self.logger.info(f"swapping {wrong_wire_1} <> {wrong_wire_2}")
switch = {wrong_wire_1: wrong_wire_2, wrong_wire_2: wrong_wire_1}
for wire, gate in list(gates.items()):
lhs, rhs = (
switch.get(gate.lhs, gate.lhs),
switch.get(gate.rhs, gate.rhs),
)
if lhs != gate.lhs or rhs != gate.rhs:
gates[wire] = Gate(gate.type, lhs, rhs)
swapped.extend((wrong_wire_1, wrong_wire_2))
z_gate = find_gate("xor", r0n, f"e{i2d}")
if z_gate != z_wire:
self.logger.info(f"swapping {z_gate} <> {z_wire}")
gates[z_gate], gates[z_wire] = gates[z_wire], gates[z_gate]
swapped.extend((z_gate, z_wire))
m_gates[f"a{i2d}"] = find_gate("and", f"x{i2d}", f"y{i2d}")
m_gates[f"b{i2d}"] = find_gate("and", r0n, f"e{i2d}")
m_gates[f"r{i2d}"] = find_gate("or", f"a{i2d}", f"b{i2d}")
assert len(swapped) == 8
yield ",".join(sorted(swapped))

View File

@@ -1,40 +1,7 @@
import itertools as it
from typing import Any, Iterator from typing import Any, Iterator
from ..base import BaseSolver from ..base import BaseSolver
def read_locks_and_keys(input: str):
locks: list[tuple[int, ...]] = []
keys: list[tuple[int, ...]] = []
for block in map(str.splitlines, input.split("\n\n")):
n_rows, n_cols = len(block), len(block[0])
if block[0] == "#" * n_cols:
locks.append(
tuple(
next(i for i in range(n_rows) if block[i][j] == ".") - 1
for j in range(n_cols)
)
)
else:
keys.append(
tuple(
n_rows - next(i for i in range(n_rows) if block[i][j] == "#") - 1
for j in range(n_cols)
)
)
return locks, keys
class Solver(BaseSolver): class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]: def solve(self, input: str) -> Iterator[Any]: ...
locks, keys = read_locks_and_keys(input)
assert len(set(locks)) == len(locks)
assert len(set(keys)) == len(keys)
yield sum(
all(c1 + c2 <= 5 for c1, c2 in zip(lock, key, strict=True))
for lock, key in it.product(locks, keys)
)

View File

@@ -4,64 +4,4 @@ from ..base import BaseSolver
class Solver(BaseSolver): class Solver(BaseSolver):
def solve(self, input: str) -> Iterator[Any]: def solve(self, input: str) -> Iterator[Any]: ...
blocks: list[tuple[int, int]] = []
frees: list[tuple[int, int]] = []
contents_0: list[int | None] = [None for _ in range(sum(map(int, input)))]
acc = 0
for i, c in enumerate(input):
if i % 2 == 0:
for j in range(acc, acc + int(c)):
contents_0[j] = i // 2
blocks.append((acc, int(c)))
else:
frees.append((acc, int(c)))
acc += int(c)
assert contents_0[-1] is not None
contents = contents_0.copy()
free_0 = next(i for i, c in enumerate(contents) if c is None)
next_b = len(contents) - 1
while free_0 < next_b:
contents[free_0], contents[next_b] = contents[next_b], contents[free_0]
free_0 += 1
while free_0 < len(contents) and contents[free_0] is not None:
free_0 += 1
next_b -= 1
while next_b >= 0 and contents[next_b] is None:
next_b -= 1
yield sum(i * c for i, c in enumerate(contents) if c is not None)
contents = contents_0.copy()
for block_start, block_length in self.progress.wrap(blocks[::-1]):
try:
i_free = next(
i_free
for i_free, (free_start, free_length) in enumerate(frees)
if free_start < block_start and free_length >= block_length
)
except StopIteration:
continue
free_start, free_length = frees[i_free]
contents[free_start : free_start + block_length] = contents[
block_start : block_start + block_length
]
contents[block_start : block_start + block_length] = [None] * block_length
if free_length == block_length:
del frees[i_free]
else:
frees[i_free] = (free_start + block_length, free_length - block_length)
yield sum(i * c for i, c in enumerate(contents) if c is not None)

View File

@@ -1,48 +1,114 @@
import argparse import argparse
import importlib import importlib
import json
import logging import logging
import logging.handlers import logging.handlers
import sys import sys
from datetime import datetime from datetime import datetime, timedelta
from pathlib import Path from pathlib import Path
from typing import Any, Iterable, Iterator, Literal, Sequence, TextIO, TypeVar
from tqdm import tqdm
from .base import BaseSolver from .base import BaseSolver
from .utils.api import FileHandlerAPI, LoggerAPIHandler, ProgressAPI, dump_answer
from .utils.files import SimpleFileHandler _T = TypeVar("_T")
from .utils.progress import ProgressNone, ProgressTQDM
def find_input_file(folder: Path, day: int, target: Path | None): def dump_api_message(
if (path := folder.joinpath(f"day{day}.txt")).exists(): type: Literal["log", "answer", "progress-start", "progress-step", "progress-end"],
return path content: Any,
file: TextIO = sys.stdout,
if (
target is not None
and (path := folder.joinpath(f"day{day}_v{target}.txt")).exists()
): ):
return path print(
json.dumps(
{"type": type, "time": datetime.now().isoformat(), "content": content}
),
flush=True,
file=file,
)
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,
):
super().__init__()
self.counter = 0
self.output = output
self.min_step = min_step
self.min_time = min_time
def wrap(
self, values: Sequence[_T] | Iterable[_T], total: int | None = None
) -> Iterator[_T]:
total = total or len(values) # type: ignore
current = self.counter
self.counter += 1
dump_api_message("progress-start", {"counter": current, "total": total})
try: try:
return next(path for path in sorted(folder.glob(f"day{day}*.txt"))) percent = 0
except StopIteration: time = datetime.now()
...
return folder.joinpath(f"day{day}.txt") for i_value, value in enumerate(values):
yield value
if datetime.now() - time < self.min_time:
continue
time = datetime.now()
c_percent = round(i_value / total * 100)
if c_percent >= percent + self.min_step:
dump_api_message(
"progress-step", {"counter": current, "percent": c_percent}
)
percent = c_percent
finally:
dump_api_message(
"progress-end",
{"counter": current},
)
class ProgressTQDM:
def wrap(
self, values: Sequence[_T] | Iterable[_T], total: int | None = None
) -> Iterator[_T]:
return iter(tqdm(values, total=total))
class ProgressNone:
def wrap(
self, values: Sequence[_T] | Iterable[_T], total: int | None = None
) -> Iterator[_T]:
return iter(values)
def main(): def main():
parser = argparse.ArgumentParser("Holt59 Advent-Of-Code Runner") parser = argparse.ArgumentParser("Holt59 Advent-Of-Code Runner")
parser.add_argument("-v", "--verbose", action="store_true", help="verbose mode") parser.add_argument("-v", "--verbose", action="store_true", help="verbose mode")
parser.add_argument("-t", "--test", action="store_true", help="test mode") parser.add_argument("-t", "--test", action="store_true", help="test mode")
parser.add_argument("-a", "--api", action="store_true", help="API mode") parser.add_argument("-a", "--api", action="store_true", help="API mode")
parser.add_argument(
"-o",
"--output",
type=Path,
default=Path("files"),
help="output folder for created files",
)
parser.add_argument( parser.add_argument(
"-u", "--user", type=str, default="holt59", help="user input to use" "-u", "--user", type=str, default="holt59", help="user input to use"
) )
@@ -69,24 +135,20 @@ def main():
test: bool = args.test test: bool = args.test
stdin: bool = args.stdin stdin: bool = args.stdin
user: str = args.user user: str = args.user
files_output: Path = args.output
input_path: Path | None = args.input input_path: Path | None = args.input
year: int = args.year year: int = args.year
day: int = args.day day: int = args.day
# TODO: change this
logging.basicConfig( logging.basicConfig(
level=logging.INFO if verbose else logging.WARNING, level=logging.INFO if verbose or api else logging.WARNING,
handlers=[LoggerAPIHandler()] if api else None, handlers=[LoggerAPIHandler()] if api else None,
) )
if input_path is None or not input_path.exists(): if input_path is None:
input_path = find_input_file( input_path = Path(__file__).parent.joinpath(
Path(__file__).parent.joinpath( "inputs", "tests" if test else user, str(year), f"day{day}.txt"
"inputs", "tests" if test else user, str(year)
),
day,
input_path,
) )
assert input_path.exists(), f"{input_path} missing" assert input_path.exists(), f"{input_path} missing"
@@ -104,11 +166,7 @@ def main():
else ProgressTQDM() else ProgressTQDM()
if verbose if verbose
else ProgressNone(), # type: ignore else ProgressNone(), # type: ignore
files=FileHandlerAPI(files_output) outputs=not api,
if api and verbose
else SimpleFileHandler(logging.getLogger("AOC"), files_output)
if verbose
else None,
) )
data: str data: str
@@ -121,7 +179,7 @@ def main():
start = datetime.now() start = datetime.now()
last = start last = start
it = solver.solve(data.rstrip()) it = solver.solve(data.strip())
if it is None: if it is None:
solver.logger.error(f"no implementation for {year} day {day}") solver.logger.error(f"no implementation for {year} day {day}")
@@ -131,11 +189,14 @@ def main():
current = datetime.now() current = datetime.now()
if api: if api:
dump_answer( dump_api_message(
part=i_answer + 1, "answer",
answer=answer, {
answer_time=current - last, "answer": i_answer + 1,
total_time=current - start, "value": answer,
"answerTime_s": (current - last).total_seconds(),
"totalTime_s": (current - start).total_seconds(),
},
) )
else: else:
print( print(

View File

@@ -1,78 +1,18 @@
from abc import abstractmethod from abc import abstractmethod
from logging import Logger from logging import Logger
from pathlib import Path from typing import Any, Final, Iterable, Iterator, Protocol, Sequence, TypeVar, overload
from typing import (
Any,
Final,
Iterable,
Iterator,
Protocol,
Sequence,
TypeVar,
overload,
)
from numpy.typing import NDArray
_T = TypeVar("_T") _T = TypeVar("_T")
class ProgressHandler(Protocol): class ProgressHandler(Protocol):
@overload @overload
def wrap(self, values: Sequence[_T]) -> Iterator[_T]: ... def wrap(self, values: Sequence[_T]) -> Iterator[_T]:
...
@overload @overload
def wrap(self, values: Iterable[_T], total: int) -> Iterator[_T]: ... def wrap(self, values: Iterable[_T], total: int) -> Iterator[_T]:
...
class FileHandler:
@abstractmethod
def make_path(self, filename: str) -> Path: ...
@abstractmethod
def notify_created(self, path: Path): ...
@abstractmethod
def _create(
self, path: Path, content: bytes, text: bool = False
) -> Path | None: ...
def create(self, filename: str, content: bytes, text: bool = False):
path = self._create(self.make_path(filename), content, text)
if path is not None:
self.notify_created(path)
def image(self, filename: str, image: NDArray[Any]):
import imageio.v3 as iio
from pygifsicle import optimize # type: ignore
path = self.make_path(filename)
iio.imwrite(path, image) # type: ignore
optimize(path, options=["--no-warnings"])
self.notify_created(path)
def video(self, filename: str, video: NDArray[Any]):
import cv2
path = self.make_path(filename)
fps = 5
out = cv2.VideoWriter(
path.as_posix(),
cv2.VideoWriter_fourcc(*"vp80"), # type: ignore
fps,
(video.shape[2], video.shape[1]),
True,
)
for picture in video:
out.write(picture)
out.release()
self.notify_created(path)
class BaseSolver: class BaseSolver:
@@ -83,14 +23,15 @@ class BaseSolver:
year: int, year: int,
day: int, day: int,
progress: ProgressHandler, progress: ProgressHandler,
files: FileHandler | None = None, outputs: bool = False,
): ):
self.logger: Final = logger self.logger: Final = logger
self.verbose: Final = verbose self.verbose: Final = verbose
self.year: Final = year self.year: Final = year
self.day: Final = day self.day: Final = day
self.progress: Final = progress self.progress: Final = progress
self.files: Final = files self.outputs = outputs
@abstractmethod @abstractmethod
def solve(self, input: str) -> Iterator[Any] | None: ... def solve(self, input: str) -> Iterator[Any] | None:
...

View File

@@ -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

View File

@@ -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

View File

@@ -1 +0,0 @@
To continue, please consult the code grid in the manual. Enter the code at row 3010, column 3019.

View File

@@ -1,94 +0,0 @@
<[<<({{<{<[[([()][()()])<{[]<>}{<>}>><<<[]{}>>{<<><>>({}{})}>][<<<{}<>>([])>{<{}><()>}>]><(<{(()[]){[](
<{([({{[(<[({({}{})[()<>]}{{<>{}}[(){}]})]>({(<<<><>>{{}()}>)<<<[]><{}<>>><[{}[]]<<>[]>>>}))[{(<{([]
([<([({(<([<({()()}(<>[]))[<[]()>{<>{}}]>]<{{{{}{}}{()()})({[]}[<>{}])}>)>)}){<<{{(<<<()<>><<><>>>
[{{[<<[{([[{{[<>{}]<()<>>}[(()<>)[{}<>]]}<<[{}[]]([]<>)>{{[]{}}{()()}}>]][[{<({}{})<[]{}>>
<<{{<([(((([{<[]<>>{()<>}}(<<>[]>{(){}})]([{{}<>}<[]>](<[][]><{}()>)))))[({{{<[]{}>[()]}<<<><>>
<(<[{(<[{{{<{[[]<>]{<>()}}><[[{}()][(){}]]>}}<[<[<()()>({}<>)]><[{[]()}([][])](<(){}>[<><>])>]{
{[[<{{<<[[<<(({}<>){<><>})[[<>()][[]{})]>[[[{}[]]<<>>]{(<>[])}]>{{<<()[]>{<>{}}>[{[]<>}<[]{}>]
({[((((([{[({[{}[]]<[]()>}[({}{})<<>[]>])<[(()[])<{}()>]{[[]<>]{[]()})>](([({}<>)(()[])][<[]{}>])
{[[{[({(<<{<([{}<>])<({}<>)({}<>}>>[<[{}()]([]<>)>((<>())<[]{}>)]}<([(<>())[(){}]]{[{}<>]<[][]>}){<{<><
(<{<<[<<([[([<<><>>]<<{}()><[]<>>>)]][{(({<>{}}(()())))(<[()()]<[]()>>)}[[<<<>()><<>{}>>([{}<>][{}[]])]{<{(
<<[({{{{{[<([((){})([]())]<((){})({}[])>)[{[{}()]{[]<>}}]>([<{{}<>}><({}<>)({}[])>]<[{<>{}}
(([[{{({{{[<<{[]()}({})>{{{}()}[[]<>]}>{<([])>[[[]{}]]}](([<[]{}>]<<[]<>><{}[]>>))}}}(([[[{[<><>
<<[(<[{{<((<[<()>[<><>]][[<><>]([]())]>[({<>})<<()<>><{}[]>>])[[(<[]<>>([]())){{<>[]}(()())}]]){(<(<[]<>>
({[<<[[{<[[{{[()()]{()[]}}}]<{([{}{}]{[]()})[[()[]]<<>>]}>]>}[({((<{<><>)>{{[]()}{{}[]}}){([{}[]]<{}{}>)<
([{{<{[(<[<<[({}())({}())]>>[{[<<>[]>[<>()]]<(<>[]){()[]}>}(<<<>[]>[<>[]]>{<<>[]>{{}()}})]]{
<[{{<[((<([[{<<><>>{()}}{<{}[]><[]()]}]])<{({<()>{()[]}}(<(){}><[]<>>)){[({}[]){<>[]}]}}<<([()()]<()(
<{<{[(({(({({<[]>([])}<<()<>>{<>()}>){[[()[]]<{}()>]{({}[])[()<>]}}}<[<<{}()><[]{}>>({[][]}[()<>])}{<<[]
<[{{[<({(<[<[[()<>]({}[])]([{}[]]([]))>]{[{{<>[]}[[]{}]}(({}<>)<()[]>)]<<[()[]]>({(){}}<{}()>)>}>)}<<[[[[<<>(
{{<(<[((({(<[<[]{}>[(){}]](<{}<>>((){}))>){(({[]{}}<{}[]>){{<><>}[[]{}]}))}<([<(<>)>[<<>{}>[{}
<([({[<[(({[(({}))(<{}()><<>{}>)]<[{{}[]}{{}<>}]{[{}()]{{}()}}>})([[<(<>())({}{})>[<[]<>>[
{((<<<{<(<[[[<{}<>}]<(<><>)>]]<(([(){}]{[]()}))<({{}<>}<()<>>){<()<>>{(){}}}>>>{({({()[]}[<>
([<[[((<(<[<([{}[]])>{<(()<>)((){})>{<<>>(()<>)}}][{[(<>[])(<>[])]}[[{{}[]}[()()]]<<[]<>>{(){}}>]]><({(
[{<([[[{([{<<([]<>){<><>}>[<(){}>]><{[<>[]](()<>)}[{()()}]>}<({{{}{}}}{[{}{}]<<>()>})<(<[]<
(<({[{{[[(<[<(<>[])[[][]]>]{((<>[])({}<>))({[]<>})}>({<[()[]]]<{()[]}>})){(<(<<>[]>[<>{}])>{[({}<
(<{<(({[(({[[<<>{}>({}<>)]{({}{}){(){}}}]{(<(){}>[[][]])<{()<>}>}}[[[{[]{}}[()]]](([[]()][(){}]))])
([({<{[{<[{<({{}()}{{}()})>}]>}<<[[{{((){})<<>{}>}(({}[]){<>[]})}]]><[{{<({}<>)(()())>[{<>()}{{}()}]}{<{
<[{[({[<<[[<<{{}{}}<{}{}>>([<>][(){}])><<<{}{}>>>]]{([{[[]()][[][]]}<{[]<>}>]<<[<>[]][[]()]><<()[
[{({{{<<{[{([[()]({}[])]{[()()]})(((<>{})[[][]])<{{}{}}>)}]}>>}[((({{<([[]()][[]])}}{{<({}[])[{}
{[({<{<<{[(([<<>[]>({}{})>))]{(<{{{}<>}<<>{}>}>)}}><(<(({([]())(<>[])}{{[]()}{[][]}})<{(()[])[<>{}]}>){({
[<((<[<<(<<{<(<>)<[]{}>>[<[]{}><[]()>]}<((()[])((){}))[({}[]){[]{}}]>>([<[{}()][[]{}]>{{()[]}}][{[{}<>]<[]<
[<[({({[([{<(([]<>)({}[]))<{{}[]}[<>[]]>><[<{}[]>({}<>)]<(())>>]]([[[{[]<>}({}[])](<[]{}>{<>()
{[<<{(<[{(<[({[]{}}{[]{}}}]({<()[]><<>[]>}{<[]()>[{}{}]})>)}{[{(((<><>))(<[]<>>(()[])))[[<[]()>[{}()]](((
({[<<([[{(<<<{<>()}<{}<>>>[[[]{}){()}]><[[(){}]<[]<>>]({(){}}[[]{}])>>{[{[()<>][{}()]}][[[{}{}]<<>()
([(<((<{[[[[[{{}()}{()[]}]]<([[]<>])<[()<>][[][]]>>]][{([{()[]}(()[])]({<>{}}{[]()}))}({([[]
(({{[<<{(([{<{()()}[[]()]>{<()<>>[[]{}]}}{[<()()>[[]{}]]{([]())({}[])}}][(<{<>[]}[()()]><<()>(()())>)
[<(<{{{<{(<{(<<>[]><<>()>){<{}()><()<>>}}(<[<>{}]{<>{}}><[{}{}][<>()]>)>)}{{{(<(<><>)(<>())><{[]}([][
<<<{([[<[[[(([[]{}])<({}())(<>())>)({[<>{}]{[]()}}<<(){}>{(){}}>)]{([(()()>({}[])]((<><>)<
{{({<<<[[<(<{{{}<>}({}[])}{<{}<>><<>()>}>{({{}<>}({}()}){[[]<>]([]{})}}){{[[[][]](()())]}([<<>{}
<<[[<{{({<{[{<<>()><()()>}<[()<>]<()()>>]{(([]<>)[{}[]]){{{}<>}{[]<>})}}>{{<[<{}<>>({}())]
({[<[[{<<{{[{(<>{})}]{<[{}{}][[]()]>[[[]{}][()()]]}}[(<<{}[]>{<>[]}>{{{}<>}[(){}]}){{[<>{}]<{}{}>}{
(([<{<[[([[(((()<>))({{}[]}<()<>>))[[({}[])(())]<{(){})>]][{((()){[]()}){{()<>}{<><>}}}[{{()}{()[]}}]]]){{(({
{<[{(<[{[{{[<([]<>)<{}<>>>]}}]}]><{{<[[([{<>()}[[]{}]]({{}()}{<>{}}))]{([<[]{}>(()<>)]<[[]<>]([])
{[<<[<(<[{<<[{{}()}{<>{}}](<{}<>>({}<>))>><{<({}[])<()<>>>[[<>[]][<><>]]}[<(<><>){{}<>}>[<[]()>{[]}]]>}]{[<{<
(<({{[{<(<<<{[{}<>]({}[])}{[[]{}]<()[]>}>(<[[]()][()()]><[()[]][<>()]>)>>[(<<<{}()>{<><>}>>){<<{<><>}(
(<{[[{{<(<(<({{}<>}{{}()}){[()<>]<{}[]>}>[(<{}{}><[]()>)<({}<>){()()}>]){[[([]{}){{}[]}]<[{}{}]<[][]>>][{<()
[(<([({[[[<[[[[][]][{}{}]]([{}()]{<>{}})]{<{()()}<()<>>><{{}<>}<(){}>>}>]{{[([[][]]<()()>)
(<(<<({{(<[{{[()<>][<>{}]}[<[]<>>]}<<{[]{}}>[[{}()]{()()}]>]{[([()()]<<>>)({()<>}[<>[]])][{{[][]}(<>())}
[[((({(({{{[{{<>[]}[<>{}]}[[{}<>]([]())]][{(<><>)}]}][(<{{[][]}(<><>)}<[[]()]>>([[{}()]<[]<>>][<[][]>[()()]])
<{({(([((<[<{(()[])<[][]>}{<<><>><[]<>>}><<([]<>)([]<>)>>]{[<([]{}]{<>{}}>]}>[{[(([]{})[{}{}])[<<>{}
{(([<{(({<({{{{}{}}}[[[]]{[]()}]}{<[[]]<<>()>>(<()>[()<>])})>{{[(([]<>){{}()}){[{}]{{}<>}}]}([[([]{})]<[[](
<{[({<{[[[{{{[{}{}]}}([<[][]>[<>[]}][<<>()>{()}])}((<({}[])[<><>]>(((){})[{}()]))[[<{}[]>[(
{<[([(<((<<<<[{}[]]({}{})>((()())[(){}])><([[]{}][()<>])<<<>[]>([]<>)>>><[[((){}){[][]}}{[[]]
[{(<{<{<<({({(()<>){{}[]}}([[]()]{()<>}))(([[]<>](())))}<{({()[]}{[][]})}])>>}>(({[{[{{([]())(<><>)
<[[<([<<({[[(<[]()><<><>>)({<>})]{{<<><>>[()[]]}([()<>](()[]))}]((<{<>{}}<(){}>>))}<<[(<(){}><<>{}>)[[()[
<[{<<<{[{<{(<[<>{}][{}()]>((<>[])[<><>]))<[({}<>)<<>[]>]<(<><>)(<>{})>>}({<<[][]>([]<>)>([<>{}><<>[]>
[<<(<{((<([<({{}{}](<>[]))[[()<>]([][])]>((([])<(){}>))]){<{{<()[]>(()<>)}(<[]<>>([][]))}><[([(
{[[[{{<[[{<[<<<>[]>{<><>}>{<<>{}><[]<>>}]((<{}()>(<>[])))><<{<<>{}>{(){}}}([{}{}]<<>()>)><[{<>{}}]>>}]
((((([[(([{<({()[]}<()<>>)><<<<>()>({}{})>{{(){}}(<>[])}>}<<<{<><>}>><(((){})<[]()>){{()()}({}<>)}>
<<[<[{<[<[<{[[()[]]({}[])]{<{}<>>[{}{}]}}[([[][]])[([]())[[]<>]]]>[(<<{}()>(()<>)>{{[]{}}<{}{}>})({([
[{<(<{(<[<[[[{()<>}[[][]]][(()<>){{}[]}]](<{<>{}}[()[]]>(<[]>[{}()]))]([([<>{}]<()[]>){{<>{}}{()
<[<({<({[{({{(<>{}){[]()}}<{[]<>}[(){}]>}({[<>[]]{[]<>}}))<{([{}[]])(({}[]){(){}})}[{[[]<>]}[({}())[(){}]]]
[[[{<[((<[<{([[]<>]{<><>})<<{}[]>[[][]]>}{[[<>{}]]<<{}>([]<>)>}>{<{{<>[]}}[(<><>)[[]<>]])<{[(){}]<()()>}>}]{{
([(<({[[{<([{{<>{}}([]<>)}[[{}[]]{<>{}}]](<[{}<>]{[]()}><((){})[[][])>)){({{{}{}}{{}{}}}[<{}{}>({}<
<[{(((({[[{{({{}[]]<<>>)<{[]()}<()<>>>}((<(){}>([]{})))}{({[()()]([]<>)}<([]<>)[()()]>)<[{{}[
<[({[<<<<{[({{(){}}[{}<>}}(<<>[]>[[]()])){(<()[]><<>()>)}]}><({<[{()()}]({[]{}}<{}>)>[({[]
<<([[<{{([{<{([]{})[(){}]}{([]{})<{}[]>}><<(<>{})[<>()]>({{}<>})>}<[(<<>()><{}()>)<{()<>}<<>>
<[[[({[({<[{((<>[]]<{}<>>){<<>()>{[]()}}}<{<{}{}>[<>{}]}{{{}[]}{{}()}}>]{<{{()()}<[]<>>}((
[[({(([[(([<[([]<>){{}()}]>(<{{}{}}(()<>)>[{<><>}{{}<>}])]{{<[[]<>]>[[{}()]]}([<{}()>][([]{})<{}
<(([<{([[<[((([]<>)<<><>>){[[]()]({}{})})({{(){}}((){}]}({{}()}))]([<{<>()}<[]{}>><{[]{}}<(){}>>])>
<<[[{<<{[(<<{{[][]}[[]<>]}<<[][]><<>[]>]>([{<>}[<>[]]]{{[]()}<{}()>})>{({({}<>){[]<>}}[{<>{}}[<>[]]
((<<<<[[(({[[<()<>>[(){}]]{(<>()){<>{}}}]}{(([<>[]><<>()>)<<(){}><()()>>)[(<{}{}>((){}))[{[][]}(()<>)]]})){
[({(<{{<<<{<[{[]()}<<><>>][[()[]][<>[]]]>}>([([<[]<>>]{<<>()><()<>>})({<{}[]><()()>}[[[]()]])]<{<(()
([(<({[([{{{((()())[<>[]]){{[]<>}[{}{}]}}([{()<>}<{}()>])}}<{[({(){}}(<><>)}<(<>())>][<[(){}]{(){}}
{[[{((((([[{{[[]{}]({}{})}{[[]<>](()[])}}[{[()()]}((<>{})<(){}>)]]{(<{<>()}<(){}>>){(<{}()>{{}<>})({<>(
([[{<[<[[<<{<{()<>}[<>()]>[[[]{}]{{}{}}]}<[{{}[]}]>>{<{{<>{}}([]())}>[(<<>()>)(<{}()>[<>()])]}>{({<[()<>]
{(([{[{{(({(<[()[]][<>[]]>)<[(()<>){{}{}}]>}[(<<{}{}><{}<>>>){<[()()]<()()>>({[][]}<<><>>)}
<[{<(<<[{[({[({}<>)<<>[]>](<<>()>(<><>))})[([{<><>}<()()>])]]}]><<[<({{{<>}}<([]][<>{}]>}[<(())<<><>>>])
(<(({<[[{{[<[{<>[]}[()<>])((()()){{}[]})>]}}]]((<<<((({}{})<{}>){{{}<>}{<>}})[({{}()}{<>()}){{{}()}}]
{[<[{(([<[{{[([]{})<[][]>]{([][])[()<>]}}<<(()<>)>>}[[(({}{}){{}<>})]]]{{[(<{}{}>[{}()])({()()}
[{{((<<[[((<<{[]<>}<{}>>(<{}<>>{[]()})>({<()>([][])><[{}{}]{{}()}>))(({([]<>)([]())}<{[][]}<()>>)
({([{({[({[<({{}{}}([]()))(((){}){{}{}}>>({(()()){{}()}})]<[[{{}{}}<{}[]>]{<[][]><<>[]>}]({<<>[]>
{[({[{{[<[{([<{}{}>[(){}]](<{}<>>{{}()}))([([]()){()[]}]([{}<>]{<>{}}))}]>[{{[[{[][]}]]<((()[])([]{}))<[()
[[(({{{(([[[{[()()]([]())}((<>){{}{}])]]({<[<>]({}{})>([<>{}]{{}{}})})]))}[(<[[(([[][]]{<>{}}){{(){}}})
<(<({<{<[<(<{<()><<><>>}<<{}[]>([]<>)>>)<{<{[]{}}[{}()]>}([(()[]){[]<>}]{{<>()}{{}<>}})>}{[[{(()[]){(
[(<(<([{<[{<(<()>([]<>))[{()()}<{}<>>]><{([]())<<>()>}(<{}{}>[()[]])>}]<{<({[][]}<[]()>){{{}[
[<({<{(<<[[[<{()[]}{{}[]}>{[<><>]}]{[<()<>>({}<>)]}]][[{<[<>[]>([]())><{()()}{[]{}}>}([({}{})[[](
<<[[{{<<([[{[(()())[()]][[{}[]]{{}}]}[[({}<>){[]{}}]{{<><>}[()[]]}]]{<[(<>())]>{({{}()}(()<>))}}])
{<[{({[({{<({[{}()]([][])}([{}<>]{[]()}))[<(<><>)([]{})><{()()}(<>[])>]>{{(<[]<>>[{}])}[<{(){}}(<>
<{{(({([[<[{<(<>)([]{})>{<<>{}>{(){}}}}]{[<([]{})<{}{}>>[[<>{}]{()<>}]][{{<><>}([]())}({()<>}<()>)]}>]
{<{[{[({[(({<[{}()]({}[]}>[<()>]}{(<<>>)}))]})]{<{<{[[{(<>())[()[]]}[[{}{}][[]]]][([[]()]<{}<>>)[<[]{}>([]<>
((<{{<[[<{{([([]{})<<>()>]<(<>{})(()<>)))([{()()}(<><>)]<(<>)(<>{})>)}([<{(){}}<<>{}>>]<[([]<
[<<<{(((<<{([<()[]>({})]({<>()}(()())))({([])<<>>}((()[])[()[]]))}{<[<{}()>]<[{}{}]({}<>)>>{<<
[[[<<<<[{(<<[{{}[]}]<(<><>)(<>[])>><<<<><>][[][]]>(([]{}))>>([<[[]<>]<[]<>>><{()<>}([][])>]))}<(
<<{[[[{{{{[[(([]{}))([<>[]]<()>)][{(<>()){[]()}})]{(({<><>}{<>[]})[<<>[]>[()()]])}}}<{(<((<><>)(<>{}))<{

View File

@@ -1,10 +0,0 @@
4738615556
6744423741
2812868827
8844365624
4546674266
4518674278
7457237431
4524873247
3153341314
3721414667

View File

@@ -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

View File

@@ -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

View File

@@ -1 +0,0 @@
2 77706 5847 9258441 0 741 883933 12

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1,141 +0,0 @@
#############################################################################################################################################
#.................#.................#.............#.......#...................#.......#.............................#...#.......#.........#E#
#.#.###############.#####.#####.###.#.#########.###.#.###.#.#################.#.#####.#.#.#####.#################.#.###.#.###.#.#.#.#.###.#.#
#.#.#.....#.........#...#.#...#.#.#.#.........#.....#.#...#.....#...#.........#.#.......#.#.....#.....#.#.........#...#.......#.#.#.#...#.#.#
###.#.###.#.#########.#.###.#.#.#.#.###.#############.#.###.###.#.###.#########.#.#####.#.#######.###.#.#.#######.###.#######.#.#.#.#.#.#.#.#
#...#...#...#...#...#.#.#...#...#.....#.#...#.........#...#...#.#.#...#.......#.#...#.....#.......#...#.#.#.#.......#.#...#...#.#.#.#.#...#.#
#.#####.#####.###.#.#.#.#.###.#######.###.#.#.###########.#####.#.#.###.#####.#.###.#.#.###.#######.###.#.#.#.###.###.#.#.#.#.#.#.#.#####.#.#
#.......#...#...#.#.#.#...#...#...#.................................#...#...#...#...#.#.#.....#.............#...#.....#.#...#.#...#.....#...#
#.#######.#.#.#.#.#.#.#######.#.#.#.###.###.#.#.#.#####.###.#.###.#.#.#####.###.#.###.#.#.###.#.#.#.#.###.#####.#.#####.#####.###.#####.#.###
#.#.....#.....#.#.#...#.....#.#.#.#.....#.#.#.#.....#.#...#...#...#.#.....#.....#...#...#.#.....#...#.....#...#.......#.#...#...#.....#.....#
#.#.###.#####.#.#.#####.###.#.#.#.#######.#.#.#####.#.#.#######.#.#.#.###.#####.###.###.#.#.#.#############.#.###.###.#.###.#.#.#####.###.#.#
#.#...#.....#.#.#.#.....#...#.#.#.....#.....#...#.#...#...#.............#.....#...#...#...#.#.#.....#.....#.#.....#...#...#...#...#...#.....#
#.###.#####.###.#.#.#####.#####.#####.#.#####.#.#.#.#####.#.###########.#####.###.###.#####.#.#.###.#.###.#.#####.#.#####.#.#.###.###.#.#.###
#.....#.....#...#.#.#.....#.....#.....#.....#.#.#...#.....#.#.........#.....#...#...#.....#.......#.....#...#...#.#.......#.....#...#.#.....#
#######.#####.#.#.#.#.#####.#.###.#########.#.#.#.###.###.#.#####.###.#########.#######.#####.#########.#.###.#.#.#########.#.#.###.#######.#
#.....#.#.....#.#...#.......#...#.......#.#.#.#.#.#.#.#...#.#...#.#.......#.....#...#...#.....#.......#.#.....#...#.....#.....#...#...#.....#
#.###.#.#.###.#.###.#########.#.#####.#.#.#.###.#.#.#.#.###.#.#.#.#######.#.#####.#.#.###.###.#.#####.#.#.###########.#.#.###.#.#.###.#.###.#
#.#...#.#.#...#.#.............#.#.......#.#.....#.#.#.#...#...#.#...#.....#.#.....#.#...#.#...#...#...#.#.#.....#.....#.#...#...#...#.......#
#.#.###.###.###.###.#########.###.#######.#####.#.#.#.#########.#.#.#.#####.#.#####.#.#.#.#.#####.###.#.#.#.#.###.#.###.#####.#.#####.#.#.#.#
#.#.#...#...#.#...#.#.......#...#.#.............#...#.........#.#.#.#.#...#.......#...#.#.#.....#...#.....#.#.#...#...#.......#.#.......#...#
#.#.#.###.###.###.#.#####.#####.#.#.#.#############.#########.#.###.#.###.#.#######.#.#.#.#####.###.#########.#.#####.###########.#####.###.#
#.#...............#...#...#.....#...#.......#.......#.......#.....#.#...#...#.....#.#...#.#...#...#.........#...#...#.........#.............#
#.#.#.#.###.#.#######.#.#.#.###.###.#.#####.#.###########.#######.#.###.#####.###.#######.###.###.#.#######.#.#####.#########.#.###.#####.#.#
#.#...#...#.#.#.....#...#.#.#.....#.#...#.#.......#.......#...#.#...#.#.....#.#...#.......#.....#.#.......#.#.....#.......#...#...#...#.#.#.#
#.#######.#.#.#.###.#######.#.#####.###.#.#######.#.###.###.#.#.#####.#####.#.#.#.#.#######.#.###.#######.#.#####.#.###.#.#.#####.###.#.#.#.#
#.#.......#.#.#...#.......#.#.#.#...#.....#...#.#...#...#...#.#...........#.#.#...#.#...#...#.#...#...#...#.#...#.#.#...#.......#.#.....#.#.#
#.#####.###.#.###.#######.#.#.#.#.#########.#.#.#####.###.###.#.###.#.#.#.#.#.#.###.#.#.#.#.###.###.#.#.###.#.#.#.#.#.###.###.###.#.#####.###
#.......#.........#.....#...#...#.....#.....#.........#.......#...#...#.#.....#...#.#.#...#.....#...#.#...#.#.#...#.#.#...#...#...#.#...#...#
#########.#.#########.#.#.#####.#####.#.#####.#.###.###.###.#####.#####.#########.#.#.#.#.#########.#.#.###.#.#####.#.#.###.#.#.#####.#.###.#
#.#.......#...#.......#...#...#.#...#...#...#.#.......#.#.#.....#.#...#...#.......#.#...............#.#.#...#...#.#.#.#.#...#.#.......#.....#
#.#.#.#########.#.#########.#.#.#.#######.#.#.#####.###.#.#####.#.#.#####.#.#######.#.###############.#.#.#####.#.#.#.#.#.#.###.###########.#
#...#.......#...#.....#.....#...#.......#.#.#.#.........#.#.....#...#.....#.........#...#...........#.#.#.#...#.#.#.#.....#...#.#.......#...#
#.#########.#.#######.#.#############.#.#.#.#.#.#########.#.#####.###.#######.#########.#.#########.#.###.#.###.#.#.#.###.###.#.#.#####.###.#
#...#.....#...#.#.....#...#...#.....#.#.#.#.#...#.........#.....#.#...#.......#...#.....#.#.#.......#.....#...#.#...#.#.#...#.#.#.#...#...#.#
###.###.#######.#.###.###.#.#.#.#.#.#.#.#.#.#####.#######.#####.#.#.###.#####.#.#.#.#####.#.#.###.#########.#.#.#####.#.###.#.#.#.###.###.###
#.#...#.#.......#.#.#.#...#.#...#.#.#.#...#.....#...#.#...#...#.#.#.....#.#.....#.#.#...#...#.#.#.#.............#.....#.....#...#...#...#...#
#.###.#.#.#####.#.#.#.#.#########.#.###.#####.#####.#.#.#.#.#.#.#.#######.#.#####.#.#.#####.#.#.#.#.#.#####.#.###.###.#############.#.#####.#
#.....#.....#...#.#...#...........#.........#...#.....#.#...#.#.#.........#.#.#...#.........#.#...#.#.....#.#.....#...#.............#.#.....#
#.#########.#.###.#########################.###.#.#####.#####.#.#########.#.#.#.#####.#.#####.#.###.###.#.#.#######.###.#############.#.#####
#.......#.#.#...#.............#.......#.......#.#.#...#.#.......#.....#...#...#...#...#.#.....#...#.....#.#...#...#.#...#...#.........#.....#
#######.#.#.###.###########.#.#.#.###.#.#.###.#.#.#.#.#.#.#####.#.###.#######.###.#####.#.#####.#####.###.###.#.###.#.###.#.#.#.#####.#####.#
#...#...#.#...#.#.......#...#.#.#.#...#.#.#...#...#.#.#.#...#...#.#.#.#.....#.#.#.....#.#.#.....#.......#...#.#.....#.....#.#.#.#.#...#...#.#
#.#.#.###.###.#.#.#.###.#.#####.#.#####.#.#.###.###.#.#.###.#####.#.#.#.###.#.#.#####.#.#.#.#####.#.###.###.#.#.###########.###.#.#.#####.#.#
#.#.#.#.#.....#...#...#.#.......#.......#...#...#...#.#...#.....#.#.#...#...#.#...#...#.#.#.#...#.#...#...#.#.#.#.#.......#.................#
#.###.#.#.###########.#.#######################.#.###.#.#.#####.#.#.#####.#.#.#.###.###.#.#.#.#.#.###.###.#.#.#.#.#.###.#.#######.#####.#.#.#
#...#.#...#...#.....#.#.#.............#.......#.#.#.....#.....#.#...........#...#...#...#.#...#.#...#.#...#.#.#.....#.#.#.#.....#.....#.#.#.#
###.#.#####.#.#.#.#.#.#.#######.#####.#.#####.###.#########.#.#.#.###.#####.#.###.###.###.#.#.###.###.#####.#.#####.#.#.###.#.###.#.###.#.#.#
#...#.......#.....#.#.#...#.....#...#.#.#...#...#...#.....#...#...#.........#.#...#.....#...#.#...#...#.....#.........#.#...#.....#...#...#.#
#.#.#######.#####.#.#.###.#.#######.#.#.###.###.#.#.#.###.#.#######.###.#####.#.###.#######.###.###.###.#####.#########.#.#########.#.###.#.#
#.#...#.#.........#...#.#.....#...#.#.#...#.#...#.#.....#.....#.....#...#.....#.#.....#...#.......#.........#.......#...#.#.................#
#.###.#.#.#.#####.#####.#.#.#.#.#.#.#.#.#.#.#.#######.###.###.#.###.#####.#####.#.#####.#.###########.#####.#.#####.#.#.#.###.#.###.#######.#
#.#.....#...#.#...#.....#.#.#.#.#...#.#.#.#.#.......#.#...#...#.....#.....#...#...#.....#...........#.#...#.#.#...#.#.#.#.................#.#
#.###.#.###.#.#.#.#.#.#.#.###.#.###.#.###.#.#####.#.#.#.###.###.#.###.#.###.#######.#####.###.#####.###.#.###.#.#.#.#.#############.#.###.#.#
#.....#...#...#.#.#.#.#.......#...#.#.....#.......#.#.#...#.#...#.#...#...........#.#.....#.......#.....#.....#.#.....#...........#.#.#...#.#
#.###.###.#.#.#.###.#.#.#######.#.#########.#####.#.#####.#.#.#.###.###.#######.#.#.#######.#####.###.#.#####.#########.#.#####.###.#.#.###.#
#.#...#...#.#.#.....#.#.#.......#.#...........#...#.....#.#.#...#...#.#...#...#.#.#.#.......#...#.#.#...#...#.#.........#.....#.#...#.#...#.#
###.#.#.###.#.#######.###.#######.#.###.###.#.#.#######.#.###.#.#.###.#.###.#.#.#.#.#.#####.#.###.#.#####.#.#.#.#########.#.#.#.#.#.#####.#.#
#...#.#.....#.#.....#.#...#.#.....#.#.#.....#.#.#...#...#...#.#.#.#.....#...#.#.#.#.#.#.........#.#.......#.#.....#.....#.#.#.#.#.#.......#.#
#.###.#####.#.#.#####.#.###.#.#####.#.#######.###.#.#.#####.#.#.#.###.###.###.#.#.#.#.#########.#.#######.#.#.###.###.#.#.###.#.#.#.#.###.#.#
#.#.........#.#...#...#.....#.....#.#.......#.....#.........#.#.#...#.#...#.#...#.#...#.........#.......#.#.#.#.#...#.#.#...#.#.#.....#...#.#
#.#########.#.###.#.#######.#####.#.#######.#######.#########.#.###.#.#.###.#####.#.#.#.#######.#######.#.#.#.#.###.###.###.#.#.###.###.###.#
#...#.........#...#.....#...#...#...#.....#...#.........#.....#.#...#.#.#...#.....#.#...#...#.#.......#.#.#...#...#.#...#...#.#.....#.....#.#
#.#.#.#####.###.#.###.###.#####.#####.###.#.###.#######.#.#.#####.#####.#.#.#.#####.#####.#.#.#######.#.#####.###.#.#.###.###.###.#.#.#####.#
#.#...#.........#.#.....#.#.......#...#...#.#...#.........#.#.....#.....#.#.......#...#...#...#...#...#.#...#.....#...#...#.......#...#.#...#
#.#######.#.#####.#.###.#.#.#.###.#.#####.#.#.#####.#######.#.#####.#####.#######.###.#.#.###.#.#.#.###.#.#.#####.###.#.#######.###.###.#.#.#
#.........#.....#.#...#...#.#.#.#.#.....#.#.#.#...#.#.......#.#.....#.......#...#...#...#.#...#.#.....#...#.#...#...#.#.......#.#.......#.#.#
###########.###.#.#.#########.#.#.#####.#.#.#.#.#.###.#.###.#.###.###.#######.#.###.#####.#####.#####.#####.#.#.#####.#.#.###.###.#######.#.#
#.....#.....#.#...#...........#.........#.#.#...#.....#.#...#...#.#.#.#.....#.#.#...#...#.#...#.#...........#.#.......#.#.#.#.....#.......#.#
#.###.#.###.#.#######.###################.#.###########.#.#.#.#.#.#.#.#.###.#.#.#####.#.#.#.#.#.#.#.#######.#.#########.#.#.#.#####.###.###.#
#.#...#.#.#...........#.....#...#...#.........#.......#...#...#.#.#.#.#...#...#.......#.#...#...#.#.#.......#...#...#...#.#.......#.......#.#
###.###.#.#.#####.#####.###.#.#.#.#.#########.#####.#.#######.#.#.#.#.###.#############.#.#######.#.#.#.###.###.#.###.###.#.#####.#######.#.#
#.................#...#.#.#.#...#.#.......#.#.#.....#.....#...#...#...#.#...#.........#.#.#.#.....#.#.#.......#.#...#.....#.....#.......#.#.#
#.#.#.###.###.###.#.#.#.#.#.#.#.#.#######.#.#.#.###########.#.#.#.#####.###.###.#.#####.#.#.#.#######.#.#.###.#.###.###########.#########.#.#
#.#.#...#...#...#.#.#...#.#...#...#.....#...#.#...#.........#.#.#.#...#...#...#.#.#.....#.#.#.........#...#.#...#.........#.....#...........#
#.#.###.###.###.###.#####.#########.###.#.#.#.###.#.#.#.#######.#.#.#.###.#.#.#.###.#####.#.###############.#####.#######.#.#.#.#.#####.#.###
#.#...#...#...#.#...#.......#.......#...#.#...#...#.#.#...#.....#...#...#.#.#.#.....#.............#...................#.....#.....#.....#...#
#.#.#.###.#####.#.###.#.#####.#######.#.#.#.###.###.###.#.#.#########.#.#.#.#.#.#####.#########.#.#.###.###.#####.###.#######.###.#.###.###.#
#...#...#...#...#...#.#.......#.#.....#.#.#...#.#...#...#...#...#.....#.#.#.#.#.....#.#.......#.#...#...#.#.....#.#...#.....#...#.#...#.#.#.#
#.#.#######.#.#.###.#######.###.#.#######.###.#.#.###.#######.#.#.#####.#.###.#####.###.#####.#.#####.###.#####.#.#.#.#.###.###.#####.#.#.#.#
#.#.......#.#.#...#.......#.#...#.......#...#...#.#...#.......#.#.#.....#.....#...#.....#...#.#.......#.....#...#.#.#.#.#.....#...#...#...#.#
#.#.#####.#.#.###.#######.#.###.#######.###.#####.#.#######.###.#.#.###########.#.#########.#.#########.###.#.#####.#.#.#####.###.#.#######.#
#.#.....#...#.#.........#.#...#.......#...#.......#.......#.#.....#...#.......#.#.#.........#...#.......#.....#.....#.......#...#...#.......#
#.#.#.#######.###.#######.###.#.#####.###.#######.#######.#.#########.#####.#.#.#.#.#.#.#######.#.#######.###.#.###########.###.#####.#######
#.#.#.#...................#.#...#.....#...#.....#.#...#...#...#.#.....#...#.#.#.#...#.#.#.......#.......#...#.#...#.....#...#.#.......#.....#
#.#.#.#.#######.#.#######.#.#####.#####.#.#####.#.###.#.###.#.#.#.#####.#.#.###.#####.#.#.#################.#.#.#.#.#.###.#.#.#########.#.#.#
#...#.#.#...#...#.#.#...........#.#.....#.......#...#.#.#...#.#...#.....#...#.....#...#.#.................#...#.#...#...#.#.#.....#.....#.#.#
###.#.#.#.#.#.#.#.#.#.#######.###.#.#####.#########.#.#.#.###.#.###.###.###.#.###.#.###.#################.#.#######.###.#.#.#.#.#.#####.#.#.#
#...#.....#.#.#.#.#.#.#.....#.....#.....#.#.......#...#.#...#.#...#...#...#.#.#...#...#.#...#...........#.#.#.......#...#.#.#.#.#.........#.#
#.###########.###.#.#.#.###.###.#######.#.#.#####.###.#.#.#.#.###.#######.###.#.#.###.#.#.#.#.#######.#.#.#.#.#####.#.###.#.#.#.#####.#.#.#.#
#.#...............#.#.#.#.#.........#.#...#.#...#.....#.#.#...#.#.......#.....#.#...#.#.#.#...#.#.....#.#.#...#.......#...#...#...#.#.....#.#
#.#.#.#########.###.#.#.#.#####.#.#.#.###.#.#.#.#######.#.#####.#######.#.#######.#.#.#.#.#####.#.#######.###########.#.#####.###.#.#.#.###.#
#.#.#.....#...#.#...#...#.....#...#...#.#...#.#.......#...#...........#.#.........#...#.......#.#.......#...........#.#.#...#...#.#...#...#.#
#.#######.#.#.#.#.#######.###.#######.#.#####.###.#######.###.#########.#.#.###.###.###.#####.#.#######.#.#.#######.#.#.#.#.#.#.#.#####.#.###
#...#.....#.#.#.#.........#...#.....#.....#.....#.............#.........#.......#...#.......#.....#.#...#.#...#...#.#.#...#...#.#.#.....#...#
###.#.#####.#.#.###.#####.#####.###.#####.###############.###.#.#######.#####.#.#.###############.#.#.###.#.#.###.#.###########.#.#.###.###.#
#.#...#...#.#.#.........#.........#.....#...#...#...#.....#...#.#...#...#.....#.#.............#...#.#.....#.#.#...#.#...........#...#.....#.#
#.###.#.#.#.#.#########.#.#.#######.###.###.#.#.#.#.#.#######.#.#.#.#.###.#####.###########.#.#.###.###.###.#.#.###.#.#####.#.###.###.#.#.#.#
#.....#.#...#.....#.....#.#.....#...#.....#...#.#.#...#.....#.#.#.#...#...#.....#...........#.#...#.......#.#.#...#.#.#...#.#.#.............#
#######.###.#####.#.#####.#####.#.#############.#.#####.###.###.#.#####.#####.#.#.#####.#####.###.#.#####.###.#.#.#.#.#.###.#.#.###.###.#####
#.....#.........#...#.........#.#.............#.#.#.....#.#.....#.....#.#.....#.#.#.#.......#.#...#.#...#.#...#.#...#.#...#.#.#...#.#...#...#
#.###.#.###.###.#####.#####.#.#.#########.###.#.#.#.#.###.#####.###.#.#.#.#######.#.#.#.#####.#.###.###.#.#.###.#####.#.#.#.#.###.#.#.###.#.#
#...............#...#.#...#.#.#.....#.#...#...#...#.........#.....#.#.....#.......#...#.......#.#...#...#...#.#.......#.#.#...#.....#.#...#.#
#.#.#.#.#.#.#####.###.#.#.###.#####.#.#.#########.###.#####.#.###.#########.#######.###########.###.#.#.#####.#########.#.###.#######.#.###.#
#.#.....#.#...#.......#.#...#.....#.#.#.......#...#.#.....#...#.#...........#.....#.#.........#.....#.#.#.....#...#.....#...........#...#...#
#.#####.#.#.#.#.#######.###.#.###.#.#.###.#.#.#.###.#.###.#####.###############.#.#.#.#.#.#.#########.#.###.#.#.#.###########.#####.#.###.#.#
#.............#.....#...#...#...#.#...#.#.........#.....#.....#.........#.......#.#.#.#.#.#...........#.....#...#...#.......#.#.....#...#...#
#.#.#.#.#.#.#########.###.###.#.#.###.#.#########.###########.#.###.#####.###.#####.#.#.###.###.###################.#.#####.#.#.#####.###.#.#
#.#.#.#.#...#.........#.#.#...#.#...#.....#.#...#.........#.......#.....#.#.#.......#.#.......#...#.....#.........#.#.#...#.#.#.#.......#.#.#
#.#.#.#.###.#.#####.###.#.#.###.###.#####.#.#.#.#########.#.#.###.#####.#.#.###############.#####.###.#.###.#.#.#.#.#.#.#.#.#.#.#####.#.###.#
#.#...#.....#.#.....#...#.#.#.#...#.#...#.#.#.#...#.....#.#.#...#.....#.........#.........#.#.....#...#...#.#.#...#...#.#.#...#.......#.....#
#.#####.###.#.#.###.#.###.#.#.###.###.#.#.#.#.###.###.#.#.#.###.#####.#.#######.#####.###.#.#.#####.#####.###.#.#######.#.#####.#####.###.#.#
#.#.....#.#.#.#.......#...#.....#.#...#.#...#.#.#...#.#.#.#...........#.#.....#.....#.#...#.#...#...#...#.....#.........#.#.........#...#...#
#.###.#.#.#.#.###.#.###.#####.#.#.#.###.###.#.#.###.#.###.###.###.#####.#.#.#######.#.#.#######.###.#.#.#################.###.#.###.#.#.###.#
#.....#.#.........#.#...#...#.#...#...#.....#...#...#...........#.#.....#.#.....#...#.#.........#...#.#.....#.....#.....#...#...#...#.#...#.#
#######.#.#.#.#.###.#.###.#.#.#.###.#.###.#####.#.###.#########.###.###.#.###.###.###.###########.#####.#####.#.###.###.###.###.#.###.#.#.#.#
#.....#.#.#.....#...#...#.#.#.#.....#...#...#.........#.....#.#.........#...#.......#...#...#.........#.......#.....#...#.........#...#.....#
#.#.#.#.#.#############.#.#.#########.#.#####.###.###.#.###.#.#######.#.###.###.###.###.#.#.#.#######.#.###.#########.###.#####.###.###.#.###
#...#.#...#...#.........#.#.........#.#.#.....#.#...#.#.#.#.#...........#...#.#.........#.#.#...#...#.#.........#...#.............#...#.....#
###.###.#.###.#.#######.#.#####.###.#.#.#.#####.###.###.#.#.###########.#.###.#######.#####.###.#.#.#.#########.###.#######.#####.###.#.#.###
#...#.........#.#.#.....#.......#...#.#...........#.....#.#...#.....#...#.........#...#...#.....#.#.#...#.....#...........#.#.....#...#.#...#
#.###.#.#######.#.#.#####.#.#.###.###.#####.#.#########.#.###.#.###.#############.#.#.#.#.#.#####.#.###.###.#########.#####.#.#####.###.#.#.#
#.....#.........#.......#.#.#...#...#...#...#.....#...........#...#.........#.....#.#...#.#.......#...#...#.....#.....#.....#.....#.........#
#.#####.#########.###.###.#.###.###.###.#.#######.#.#.#.###.#.###.#.#####.###.#.#########.#####.#########.#.###.#.#####.#########.#.###.###.#
#.....#...#.........#...#.#.#.#...#...#.#.......#.....#.#...#...#.....#...#...#...........#.#...#.............#.........#.......#.#...#...#.#
#####.###.#.#######.#.#.#.#.#.#.#.#.#.#.#####.#########.#.###########.#.###.#####.#########.#.###.###########.#########.#.#.###.#.###.#.#.#.#
#...#...#.#.#.....#.#.#...#...#.#.#.#.#...#...#.....#...#.......#.....#.....#.....#.......#.#...#.#.......#...#.#.......#.#.................#
#.###.#.#.#.#.###.#.#.#########.###.#####.###.#.###.#.#########.#.###########.#.###.#####.#.###.#.#####.#.#.###.#.###########.###.###.#.###.#
#.......#.#.#...........#.....#...#.....#...#.#.#...#.........#.#.#...#.....#.#...#.#...#.#.#...#.....#.#.#.....#.#.........#.#...#...#.....#
#.#.#####.#.###.#.#####.#.###.#.#.#####.###.###.#.#######.#####.#.#.###.###.#.###.#.#.#.#.#.#.#####.#.#.#.#####.#.#####.###.#.#.#.#.###.#.###
#...#.#.......#.#...#...#.#...#.#.....#...#.....#.....#...#...#...#.....#.#...#.#.#...#.#...#...#...#.#.......#.#.......#...#.#.#.#.....#.#.#
#.#.#.#.#.#####.###.#.###.#.###.###.#.###.###########.#.###.#.#.#.#.#####.###.#.#.#####.#######.#.#.#.#.###.###.#########.###.#.#######.#.#.#
#.......#.#.....#.#...#...#.#.#.#.#.#.#.#...#.....#.............................#.#...#.......#.#.#.#.#.#.#.#.....#.......#...#.........#...#
#####.#.#.#.#####.#######.#.#.#.#.#.#.#.###.#.###.#.#########.#####.#.#########.#.#.#.#.###.###.###.#.#.#.#.#.#####.#######.#.#######.#.###.#
#.....#...........................#.#.#...#.#.#.#.#.........#...#...#...#.....#.#...#.#.#...#...#...#.#...#...#.#...#.......#.....#...#...#.#
#.#####.#.#.#####.#.#.###.#.#.###.#.#.#.###.#.#.#.#########.#.###.#.#.#.#####.#.#####.#.#.#.#.###.#.#.###.#####.#.#####.#.#######.#.###.#.#.#
#.#.....#.#.#...#.#...#.....#.....#.#.#.#...#.#.#...................#.......#.#.#.....#.#.#.#...#.#...#.....#...#.....#.#.....#.#.#...#...#.#
###.#####.#.#.#.#.#####.#.#######.#.#.#.#.###.#.###.###.###########.###.###.#.#.#.#.###.#.#####.#.#.#######.#.#######.#######.#.#.###.#.###.#
#...#.....#...#.#...#...#.......#.#.#.#...........................#.........#...#.#.#...#.....#.#.#...#...#...#.....#...#.....#...#.#.#...#.#
#.#############.###.#.###.###.#.###.#.#.#########.#.#.#####.#####.#.###.#########.#.#.#####.###.#.###.#.#.#####.#.#####.#.#####.###.#.#####.#
#S..................#.........#.....#.............#.........#.....................#.......#.........#...#.......#.........#.........#.......#
#############################################################################################################################################

View File

@@ -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

View File

@@ -1,402 +0,0 @@
ggrru, ugu, gwgg, bwrw, bww, brg, brwu, ruugb, grggr, wrgbuug, bbbrbr, rgrrbrbw, gbwg, wuruug, gbgwbg, rgw, buu, ggbgb, rwg, gr, ggurggr, wruuwgrr, wbgg, gggrb, rgwuu, uuwww, bgrw, uuguubw, bbbrwu, ugurb, uwbggg, rurg, ubb, wrr, rbbbbg, gguuug, gbur, wb, bubbu, gbwru, bgg, ugg, bbrrg, wubr, bgwgbwgg, rguurb, bugu, wuww, urugr, bwb, wug, brr, u, rru, wwgbw, gwu, bw, ugrwggr, rgubuw, bbg, bwru, uwgbwu, gbrugg, rgub, rgbbuwwg, wwr, grw, rwggwwrw, bbbu, wr, wbwu, wwrbuu, rbbgwru, gur, buurr, ggbrg, gwg, wrg, urw, uubub, gwrgb, bbw, rrw, ugrurw, rubrw, bgb, bwgbwbw, guw, ur, wgrbu, bgu, rrrrbrw, uww, uuu, wuugbw, wwbugw, rwbr, ruwbr, uwu, wgrb, b, rrwugru, gwb, burw, rurb, rbrrbgu, uwgw, brubr, bwu, rbw, ugbu, gww, wwrb, wbgbrww, brrwgrg, rugug, grgrrb, wuubbgu, brub, rrwwwb, ugr, wbw, ruwgguu, wgw, rrwrg, bwbbrwbg, rggg, gbgrguw, rwgw, rbbgwbr, gub, rgrrg, wbgggu, bbbgww, ugb, rbbgr, wru, rubbuu, bggrbu, gbg, bgrgbb, wwrwugbg, rrgu, wrrubwu, wrbuu, rgug, bbu, wrww, wbb, wgrwu, bbrurru, wgrugwu, uuw, uggwg, rrbuwu, gruw, ubr, urgug, www, wgrwrrw, rruw, rbg, bbwu, brww, rbwbw, grgr, bgr, wgwwu, wur, gubu, rrubgg, wbrurbb, ugub, wrrr, gbbr, wwubu, uwwbuw, wuu, rgb, bbr, rbrbuwg, urwb, gg, grug, br, wwguuwb, wu, ruu, guuwrw, wgb, gbr, wgggug, rw, brggww, wrgrw, guggub, gbbrug, gbbrb, bugrg, bwr, gwwg, wwbbrggw, urwu, rgwr, rwb, rrub, ggb, wbwrrbw, wrub, wwg, ww, ggg, brugwrr, wbur, ubbbrw, uwugrg, buw, grg, rrr, bgwu, rbggg, rgr, wuwub, rg, guuwu, rrwwwrbr, rrg, gurwg, wburrwug, rwr, wbg, grwbr, bgwbwug, bwg, bru, rbwuug, gggg, gurb, bbb, ubwu, gugbr, buru, gbbg, brb, wgr, guwg, gurgrbug, wgwugwwu, uw, wrbbr, wgwugurr, uwww, urr, bgubug, bbgu, bbuugb, rwug, gurbb, bguw, ubbbub, bbwb, gugbgwb, bb, wrrg, ggr, wrbub, uu, wwbw, ub, uggw, ugbggrw, bur, uuuguru, bgwuu, gwr, uurrrw, rb, buwugrr, brwrrrgb, guu, bgur, wggur, wub, gbb, rr, wubw, uuwgww, bwurwur, gubgg, ubwg, grbr, rwgr, wrubw, grgwb, uuguu, rwgwb, bwrrgg, ubu, bwbwggrw, uwg, bgguu, wwu, grwgw, bwrr, uur, rwuww, bwbb, gwrr, gwgrww, rbgw, grub, wugu, grrwuwg, bburbb, wbgb, ubbr, gggu, wbu, rrbugrbu, gbbubrwg, gwwurw, grbb, gbugu, wguwrw, ubggbb, rbgbu, rwub, gb, wbrgr, wubwwb, brwg, bwwbur, gugwg, gru, rbrwurr, wrb, gwubug, ggbguu, bubg, uruub, wuw, gubbr, gu, uwrubg, wggrbug, uub, ggrb, rwu, ug, ugrggw, wgg, rrb, bbug, wrw, uubbbur, uwgb, bwgr, uru, bu, guuuguw, gwwu, uwb, uwwwb, w, rur, wguuw, guru, gwrrwwb, wwrww, rww, bbur, ruuwr, rbb, bugubgrr, ru, rbubwr, grr, bbrbu, gwww, uwwgw, wwwu, uwr, uguw, rbwrr, bguwg, rguw, guwgbbg, rub, rrur, bwwbgw, rrrg, bgggru, ggu, wrrggu, rug, uuburg, rbu, wggrbgb, brguurw, r, guwrr, bwbgrb, urwgbb, rwgur, urg, gbwrw, grb, gwburg, wbr, bwww, brwr, ugw, uwgu, uggwr, brw, wgu, gug, gbu, gwrur, ggbrb, rbubr, rrggurbw, rwrru, uug, urb, grbu, gbgug, bugg, gbw, rgu, rgurrw, gwbw, ggw, bgub, wwgugug, ugubwg, wuggr, ruw, rbr, bbwuwwgb, wg, ubw, rwwg, wggbr, urubb, wwb, bubr
ggrbbwbbwbuguwbuguwbbuwrbbbrwgurgwggbbwbguurb
gruurruwgbwwrbbggwuwrwugwrguuwwrurugbbgubrurubrgwubg
wguwwgbbggbbrbwurguububrwgbubwbwwuwgrgbuwgubg
gbgrwggwbgwuwbgwgwgubwguwwwuwbwugbwgwrgrubg
uubwgrwrwrruwrwggggwwrbgbbwgwwbwguwbrrwrgugbrbwrurggb
rgruubburgubugugbwuguwururrbbgwuurwwbugburgrbbgbbgugwgbgg
urggwuuwgubugurguwwrrbwuggbwbruuwbwugwwrwrguubbbbw
bgrwuggburgggbubbgrwwrbuuwgwrrwuuurbugwgurubrwwrrugru
rrbbrwgurwgrrgburbwurgbbuwrgrwwgrrgwrbrbrubbrwrg
uururbwwwurbruwwwbubgbrugubrwubgwuuubggburbbu
wrwrrgbrgwgububrgwggbguurgugwbuwgwwbggurbrw
uugbgwuwbgwggrbwrwruwgrrwugbguwguuuuwurugwwbbruwuubg
gwgrrwrguwgwbwgbuwuurgugugguwbrrrbguwrwubgwrgubggbburbu
bbugbburwuggwrugrbgbbubbrrurbwbwburwrgubgwurgubg
wuwubwguwuwwbbwgwugwugurgrbugurwbuubbuurrrrwwbgrgwgwgwgubg
wurgwbwrgguwbbuuurrgrrgrgurgbrubbrgrgwbrrbgrurguurw
brrburwwuwugbwrrrwruuwgrrrgruwrwgrbbgwwrruwwwbrbguuuww
wgurrugrwbbrgubwrgbuwuubrggubbrwwwbwrggwggbrbg
gurgrrwgruwbruwrbbbrugrgrrwrbbubgrbgbbgrwurwuguubgw
rwrrruwrwwruugbgbbururbubgrrugguggbwgwgwguwwurb
wuguguruwrurbwbwggrwuuwwrbwrbguuwwwruuwrguubgwbg
wggbrgubrwrwgwubbgbuwgwggwgubrwurrrrrbggubg
urgbbgggurgrbugbbubwbugrburgrurbgwbwuuuugbbuuuuub
gwbuubrgwrwrguwbwubbruurgrrwwuwrrrrrwbbwuguugguwbrurrbbugw
rrwuubbwruwuwbbbrrgbguwbguwgbruruubggbrbrwbwgbrbrbggu
gbrruuwuwruwgwuubrwwwuugubwubwuwbwwrrgbrgwrr
rwwrrbbgurgwuwgugwrgbgbgurwruwwwruugrbggwubwr
uwbrrugrbgwwgwrguwgrbgwbrbbruugggwgggwwbwrwgr
wguubgwuuwbrbgrgggrgbbguugrwgwgbrgugbrugbbuuurrruruuggrbr
uwggbgrugruguggrrgwbwbguwwgugbgrbuuwugrubbgbuubg
wbuwggugwruuurbwwrrrrbbwruugurwurrbggwgubg
buwrbburrubggwurgburuwrurrgwgbuugrruugbbbgrgurw
ubugwbrbwwrugrbwwrgwugubrrbbrwbbwbubugbububwwwubrrubwur
gwgwwuwurgruubbwgrguuggubrrubgrwwwbwbwbbrrburbbbu
rrbrwrwwrwrwbwbrbrgwwbrwwwrgwubwrrgbuugrugurrbug
wurgrrbuurrbwwgwbguuuwgruwuubuwwgrrrwubgrbgw
bbrwbrbbwgubbbwgubbruwrrbrbrrrgwbbruggbgrr
buurbwrurgwrbugruuwrbbubbbubgbuwurugrbwrubuwbwwgb
uwbwwgugruugbururbgwgrbbwruwrbruggbrrgbburggbwg
grurbwwuwruwwbrrguwbwwrgrruuguubrrubrrrwruwwrrggbuugwu
ubgrrwbwrrbbgrrgwuugrggbwgrrwrrrwbbwubrrrugugwubg
urwbugwwwbrbbggwgwggwuwwggbuurrbuguubbrgubrwgrwubbrgubr
wbbrgrugrgwuuwbubgwrgwrwuubgwwubuguugwgbgwuubg
gwwrwbruwwgwbgwbgrggwwububurbbgggruurwwbgbbrugubbwuwb
grggruggrgggbrubguwggruwbbbgrgruurrrgwguwuubrwbrrurgrubg
wugbrrurrwbgurwgggwwgrurrbwubbuwwwburrwuggubgwwggbwggubgu
bbuwrruwgrwuuwgrwrwgggbwrgrrbugubgururrwuubg
bgwgbwgguwbugrrbwwugwuwgwbuwbwuwrgwbuwubggurbruwruuubr
bwwrrggbuwwgrrgugruuurgrgrubrbwuuwbwgrubg
brbrwrurruwurrwwbuwbggbuwwrwbwwruuwguubbuubgrbbuwwgbrrr
rbwrwwrrurrrgrbuubburbrrruuurruurwwgbbguwrwgggu
wuurbgwrggbuggbgwbubgbubgrrwbrbwgwwrrbgububrbr
rgbugbrgrgwurbguuwburggwubggwrubwwggbbrrbbugbbrggrgwbbuugr
brbubwwubwbwwwrrubwggwgwwgwrbwgwwurwbugrrguurbb
grugwurwrwubbbbgubgbwrugrwwbgwburwwbrgwubu
gurrgwbbbubbggrwrrrwbburwruurgrguwggrbwbuuwguugubrwbwb
rrbgrrubuurwubrrbrrwguugrwrgrrguwggrgbrbgubububbrb
wgrwgwgrgbguwgbrwwgrwbuuubwrgbwguwbbbbuguugrwwwburrbruuuubg
uwgrrgrrbrwbrrbubggggubggbbgbbwbrugwrwrbrrwwgbwr
uburgubgbbbwgwubggwuugwbbgruwubbugbbuurwruggrggwrugrbwubg
rbguwurwwrbggrrgruuwubwgbbrgwwrgbrugguguuwwbbrggwbwurbgubg
wrurwburbugrrubggubgbwwrbwbwggrwrrrwwuguwgguwrbubbubwrb
ugrburuubbrbwgrbugrggwgbwuurgrwuwbuwrrbgubg
wgubrbggbwubgruwgrgrwrrgrugubugrwgrurguwrgrububbbg
bwgbbgwgurwgwugrbbgburgwbburrurubwbbruwgwbububgrgbrwgbuwubg
wuwbuwrbuuggwggbbugbwbbuurgbgrrubbbrgggwrbwugguwubg
wwbgbgugbgggugwrrwwguwbwubggbwgurgwurwrgwubg
bwwubrrwurbgwubbuguuubrgrwrrwuwrugguuwwurubgw
rrbbuwwrwbbruwwububbrbrwburrrrbubugwugbbgrwrw
grrrbwgwugurrwuwwrrbwggubwuugbuwwwgurwgbuurubggbgw
rwgbbgbrgubgugubwwbbruwggbwwwgbuwrrguuwwbubbrwgbgrwg
urgrwrgbrgbggrurubwwrwrwgrbgubbruurbugubww
gbburgbuggrwwgrgguugwbugwwrgurbwbugurubwbrrug
bbruuuruurrgggrwburgbrurwurgrrrbrgwbuwrwrugurwwwbb
wggguggbwguwrrrbwrgugrgwuwrubburbgbruubwuggbubuurgww
ggrubgrggwgburgwurubuubugrgrbrwwwgbbwrbuwwwruwwwwrugwb
rrrbugggrwuubwrbbgbgrwggbggwwwrwbrugruurwgrruuuubg
grurwggwgrubrbbbubgwrbrrwgwugurubgrwwwguwwbrbubwbuuuwgwwbw
uwrrguggwbrgbgrwbgguubgrrbuwurrwbubrggrwbgu
wbwgrbgwgwrwgguwrrugbwburrwugbuwwugwwurrguuuwbbwburubgrbgw
bbbrbrgwbwwgugggwwbggruwwbwurgwggbbbrurrwwbugrrgubg
gbuuguugwrburruuwbbwbbwubrwbrgwwwurrbgwbbugwwbuwuwgruubg
bwbgbwubugwgrwbubbugbwuwbubrrrwwggwbrggubwrbrbubgggw
bbbggrurgggubbbbbburugrwggwwrwggbwuwbbgbggbrbuurugbwugbg
ubgbwbguuwbrbruggwguburwwgbrwuwguwguwurbrbrrurww
bruwrrurrwwwrbrubgrrguwwrrgggbbwrwwgbggrubg
bbwugggwrwgurbrbgrwrwuurwwwruuugbgrrbuwbwbwgbgrwwburuubugg
rgbgugwwwrubgggwwbuwrugwbbwwbwuwwbbgugbwburgrr
rwrgrwbggwugguggrgurbugwbuggrrrrguwbgwubg
urwruuwgrrwggwgrwuwgrggwbuwwbrbwuwwwrubg
urwrbrrbrubbruwbguuwwggubuguwwggwwrugbuwwrbbwwgrrrbggb
uurguwwgbrbbuwrrbrrgrbggrrurbwbrwugrwugruurbgbbu
ggguuubrgwgbwuburubruuggrwwururubgwwbbubbrwbgwbubbwrg
grwbrgwbbgbwwwruubgbwbbbrbgwurrrururrgurubugbrrrugwwbuwbw
rgrubwgbwwgrbwburgwuubwbwwwbgrbbbwbbwbrwgbbrggrwubg
uuggwggrgwugrgruurgbwrugwbrrbbbgwrbbgbrubg
wurrguubwrbwuubgguuwrgrrugbgrrrwrbrwrrrgbuwwrbwrbgrgrgbwbu
gubgbwubgbbbubwgrbubbgwrrguburururbgbbruuuruu
ubwgbrwbwbgguwwruububgrrggrurruuuwwuwubuubgubwwgrubwwurggubg
grwwwubuwurruububbwugubgggwrbgrguwwwugruruubgwbbrwuruubg
ugrgbwwgbrwrwugwubbwuubburrrgrbbgruubgwug
bgrgggwurrbggwubbrgrwbgwwwwwwbgwwbwrwbbrugwrububwgubg
uugwwurrwggwrrbgwbrrgrrurugbgurggurubgbwwubbwrru
bwgggbrubwguurrgwrggggbgrwwwuggbrwbgrgbgbrrugbwwwgbbrbwu
bwgubrubrgbuwgbbuwgbwuurguwuuwwbruwuwbrrbuubg
gbuwugubrbbburrwbrwuubrwwrwburwbrwguggugbrbwburww
brguguururwgwwwbrwuwbgrrrgwwrguwwbuwrwguwgwwgwugwwugubg
brubrwbwwrgwgrgguwwgrrbggbrwgbbwugbrgwggbbgbgrbwgr
wrwgguwbrggwbgururwbrurggurwwrbuurwrrrrwburugggugbwrgubg
grwwwggubgrrrwuwggbwrwgbrrbugrrbuguggwuruwugr
wrwwwwrwubwuugurrbgugrwrbgrurgbgbubgbguuwubbwubg
rgguruwrugrrrbwwuwwrwrrrgguwbgbggwwbuguguguwwgggbr
wwwgwbbgbgbgbuwugwgrrgwbrwguguwgrggbwwbwwggbuuububgwbggugg
ubwruwgbbwwuuwuurburgwgugwuggrbbgrgwguggwrgrggru
rwrwguruubbgubrgubuwgrbwgbgbruwgurgwbbbgbrw
wuggwrbrwwurwuuuruwwrwubwrgwrwwbrugruwbgwbgguuggbubwrrwguu
ubwwuuwbggrwgbuwburuwrubgrgrbubgwrubwbwburubbbgu
bggrbbuuuubrwwrrbgrggrgurugbuwbbbgbwubrrgu
bgrwuggwwbbgubbwrggubrwwwrwwwrwgbuwbbgggwuurbugrg
ggbgubrggbwgrgwbbbbbgugurguwggbrbbgrwuguwwruwbwwruuguww
gbwbrrgwwggguwgguubwubwgrrrwrwbrgbrwbrbwbwuwrr
uwbbwrrugbgrrbwwrwgwbggbwwrwggbruwururbwgrggrrggggwbbu
uubbwuwbgbwgbugbugwrgurrgubwuguwrrbwbbbrgg
bbwrwrwurubrgrbugbgwrgruubuurwurbggbbrguubg
bbgrgbgwbbugwggwbrwubwwugwbwgrbubbubbbgwrururwwgubuuwg
rwbwgwrbgbugrbwgburburbuuggwuguggrgrwwurggwuubgw
uuuurubugrrbgwwrbuwwwbwuuwrgwrgbbwubggbwggwrgrbb
ruuwugbgbrrgrwgwwwgwrbuggbgwubwrrbbrwrrwwgwbgrwrwbg
wbbbwubwgrgwrwgwgwubwrwbwrwuuwbrwggwwrwrrugubgubg
ubwbubugggggrrbggrwwrguubgrwrrbgwuubgbbuwwubuuwubgbuguubg
rrwugrgurguguwggbwurwguuruwgwwrbwugbwrbbggbrrwgww
ruguwurwgwbrwwgburubwuugwbgbgwwrurggbrubbrubwrugugugrwrg
ggburgrubrbbbwgwuuwuugwuubrbuuwgrbwbrurbwuruu
grbbbbrwuurguruurwwgbwrbburrbwugggwrwuruurgbrwwrwgb
ruurgwgggwgbwrgrwbruuurgrbwrbgwuwbbrbggrbrrbgubbw
gurgbwbggrwbrwbbgbwuwwbugrurrbuburbwbgbgrugr
urrbgwugbuwbuwbwgrbrbugrbruwbwbwwwbugrrgrgbubbuurrrugwbwuubg
ruuwgbgbbgrgwrgurgbbggwwuwrrrugwwbgruwugbwrgrruurbrbguu
grbuurbrubrgggbbubrwgbwwgbgrbwubrurbgbuwgubgbwuguwrubgubgw
bwbbrwwruurgugggbuwugwbuuwwrruurguwbuurwgbguurbgbrwbgurgubg
rwggrwbruwgwrbuuwrruguwbbrrwwwrrgruurbwuwggrwbwgurwuubg
gguruuguurugwuwuwuwurwwbgbgbuwrrwwgwugrbuubbbwrrggrubbw
gggrbwgbggurgwrwrwgrurrrgguuwggbwwbrbbbrgwbrubrg
ububggbgrbwbbrwbggwugbwrbrgwbrgrbwugwurgwrubg
ubgugruruururwrwgguggbbgruwwruwuururbgwurwbrubgwgrw
gbgrruwurrbbwbgwbuwggggbwuwwuubrbwurrbrwrrrubg
rgwgrubrwbrwgggruwwbrwrubwwwrwbggwuugrruuwugbrg
ubgwrrgbrgbbrgwbbwubururwbwuwwwugwwwrgbbrbrwgrgrbbur
wbgbwgubbrbuwgrubbbgrwgwrgguburrgbwgbbwrgbgbwwwrwbubr
wurubbubrgwwgwrbwrurrbwgbuugugwbgwbgubbubwuwbwbugbgrwurrg
wrgggrguwgrwbbrgbrbbwwuwggrggburugwwgwuguburbwugrrgbburw
rrrruwugurugwrggbgggwrgwbuwuguwbubbwgrbwgr
rbwbbwbbwgbwggggwrbruwbugrgugubbgwrrrugubg
rbrrbrgurwbgurwbgrwuwgrwwgbbrgurgggrwbuguw
gbbgubwbguururbgrwuwrwbbbgwuurbbuwgwwruwwgubgwwbg
buwrgbgggrruugugbwuruwgwgwwurwugbbbbbrwuwwwbbugubrgrgu
gwbwrubugbrrwurwgrwwwwbwbbrgwubbguurwguuwrrb
rwugguuubbbrrgurrbbwrrwuurrggrruwururrrwwgububwgurubg
bbgbbrbgrwrgwuuwrrwubbuwuwrwuwrburggwwburwbugubgrr
uurwbwubwbgrruwwbbwgwgrrbrubrrbubwrwgubg
rrrgwguwwrwugbggrbururbgrrgugrbgbwugbgrwubg
gbuuwbrubgrrwrgwbwbgbrgbuuubrugwggwurrggbbwuwwgbwwbbuugubg
bbwbgwbwrrwgguwbrwgrgbbubwubwgwgrwguwurrrwburbgugbburuwubg
ggbuubrwrwurwgwbwburwwwgwwwrgguwgurrggbwurrgwgw
grrwrubwgbbrwburgrguurgrurwbwbrbuugrwuwrbwurubgwgu
brwwwrruggbbuwrbbgrugrbwgbwwwrbgbwgburrwrurgubg
grbwugwrugrwrwrgrrbruguwugggbrgbrwbwruwgrgguugbgwbgrur
urwgwwrgurrubugwwuwrbrrrbwwrrbwuuwuuwuwururuguruwbwurgr
urgrwuwuwbbrbwrbuurbbwbbwggbruwruwburgrwgwuwrruuubg
ruuwwrwwwgrrwwgwubwbuwgwubbggrgurruwgwrwugb
urbbgggrrrrrrrrwwbrrbgggurgwwugburwbuuuwwwrurwrrbubwrrwrw
rwbgrbbwubgbuwrrgbbguwbbrbrwbgrbuwwwwugbugwrwurwgwubg
ruwbuggwgbuuburwburgwgurrwrggrrgurrwburgbwbgr
bwwgwggrgrbbggbgrrwbggugwbgrgbbrbwbbrgrbbuubg
gggbbwbwgbbuubwrbggburrbgwwruuguruuguubrwrwwuubgw
bwwwbuwrwrwugubrwbgwrwrguubwrugurrgggubg
grwbuwwburbwbwurguuggrruuuurwwurggbgrbuwwrgr
wubbwuggrgwbrwgbwrgwwwwuubuguuwbgruuwgrwgbuuwrwwurubgwwgw
bbrwbwuwgwwbwwrrruwwbwwuwrguuuuuwrwurbbbbuuugurgugw
wggubgbuubbuurburruwurbgwbwubbgrgwgrwwbbburggbu
buurrrwbgguuurbbbgwrgggggwuwruwwbgguggbwbrrrgrggwg
gwbwrgbrburbguwbgrwuwgburgbrrubrubugbrugubg
rwgrgwwubguggrwubggbrrurwbburbuwrrbuwbgrbgrruwgrrwwubg
wbwwgwrgguguwrrgggbwwbrrgbububwwwugururrrbr
rbgurbrbgwrbgrwuwruguubgwuwbgwguwuwrbruwbbuwubbu
bgrgbwgbrwuruuugrrbugrburburgrbgubbrwbubwgubg
ggruruwrrwwwrbrgbwgwbuubgugguwgbuuwggrwgbgburbgwbr
wrgrrgrwgwbbbrgugguwbwuubbwbruuwwrbgggugwwgbbruugr
ggwwbbwugrgbgwbbbuwwwwuggrgguuwggrrbbwbugwgug
wrugrwwbwgbwruwuwwubugubggbuuwgbwgrurbgbuwguurrggrrbwwwguubg
grwurrbbuuuwrubbrwrubrbbubgugbugbwrgwggurwubg
gbggwurwgguwwurrubrgwbrbbwgbbrugburgbgrwrwguuw
rrwbwuuuugwrbwuwgbbbwbwwwrgrwrurbgrrgwrbwugbrrbrwubgr
uuwwbgguugrbrwgbwrrbbrwrgbubgwrggwwuurrgbwrbgwuugwruuwwbgr
wgrurgbugwwrrwrrrgbbggrwuruuwbrrgrrgubrrubg
uuwrruubrbbgururrrbbrwruubbwwgbwrgwrbuubgw
urwrggbbgbgrwgwugurrrgbuuwbbwrgrwburrrbugwggbuwgbw
urrggbwggggwrgrbgbrbbgrgbgubrggbgbrbwggwuurubg
wwbrbwbrrgwuuugrgwbgrwwgwuwuuwggwbbwggugwrbggwgrugrbubgw
bggggurbgugruwuggwuruububwugrbbubgrwurbbrubgw
bbwwgguwwrggwrwbwbbuwwugugrrggurbwwrgggbwuwbuburubg
rwgbgrubrrbuwwbbbbbggwruwubgbgguwuwwwgwggbubrr
rurwgwbwuugwruguwbwuururgurguggbugwwuguuwrwu
bwrbwruwubbgwguwgrwuubuwgwugwwgrbrrubgwbgbrbwugwbuwwwb
rwgbgrugggbgubugwbbbwggbguugwggrbbbrubwbubgrbb
rgwwrbrbrwrgrbgbwwuwwgwrbuwrgbrrurugwburrggrwuruub
grwbbbubbuububbrrwubgugrgrwruuwrwubrruggbuguubg
bbrrbrbrwbrgwgwuwguuuubbruwwbuuwuuwgwugbgur
uuguwbururbggrgrugbrubgggrrwwuugwgbrubwgbgwwgurr
rgwrgbbwbwwruggguwbrugwbrrwwbwrgwbwrgrrbuuuggbuubgw
wbbbguwbuuugrurggwwbgbuugwwrguggurrrbbbrbgbrb
wrbuuuwrbgwuugubguggrggbgbuguurbrrbrgbrurbrbbuugrw
bgubwwgrbwwwwwbrrrwgbwwugbuwgwruugrgbbuwwgrr
urrggurbwwrurbwbwrbwwwwuurugguwrggwwrrwgbwbrrruru
rwbgwguwurrurbwuwrubbwwbubwwwwbrggugubgw
burgrurbrugburgrbgruwggruuuwgrgwuwrgwurrrrurbwrwwwgbuwubbb
rruwuwgrubrbubugrwbwuuugwuwubbgwrbgwwgubrurwbgwbwwgwgwbwuu
wgrbggrrwbbgurwurwrwrggbwwrwugwrwuugwgwubrubgwbguuwbwwgbu
guuwrrggbrrugbrguggrbubrggbwururwbrgrwrbwb
gwgggggbgrgbbbbuurugwrruuuwrbwrggguwruggwgbbugu
rguwrwrrubbruwruubwggbuwwgbgggguwugwwubwrgwwrubrg
brggwbbbubbrrrwrbwrwbgubbugbbgwgwbrwbggurbbwuubbgrggrbbr
wuuuurbbuwgubwbwrrwbbgbuugrgwgwuburubuuwbw
ubgwrruruwbwgurwrrrrrbrrbrwuubwrwwbrwwrgww
grgbguubrugrgbgggwgrwgrguwbubbwbugrburrugrwbwbgurubgw
rgguwgruburwgbguggbwgrgggrubgwgrguubwubgw
uurubgbbuubbguwrgrwwgguwgbrrwguggggwurbwubg
uguguruuuugbgwgwbuwgbrbrwrwbubbuubugrwwbbgubg
guuwwruugbggwubrrgrbuugbwuwggwrggwgwuurwbgbwbuwbguurbrbggu
bbubwrgbggrwbbwguurrrwrugbugbruwruwwbugrwbugbbgrugwrwr
guwuuwurrububbgrwugruuuguruwbrbubgrrubgggbu
wrburuguguburrbuuwbgurbubwruubbuurgubrugrbgubub
wurbrruurgrrruggbbrbruuugbbgggurbgbgwbwbrbugubg
rwrwwrurrwgwgbrubrbwwrrgwurruwgwguuguubg
uuwwwgbgwuuruwrubrbgrbruggrggbwruurgguguwgbrrbrbwwuubg
uggugggbwrgugwrgwubwrwgrubggburgggwrbgbgbugruwugg
uggbugwwbggrbbuggubrggwrwwurbbuwugwruuubgggbww
rrrugrwrrrgwgbuguwgwugrbuguubwgrwgwbrgbbwguwuuubgwb
uwwrubgrrbbugwgwbgbrgurgrbwbgrwbwrgwruuubgwrrbuu
gwrrrwrrggwrrwgbwruwubuwwbgubgwgbwgggwuwugrgwruurwgwuubg
grrwrbugrbubuwruububbrgbuwrubrgbugrruurgwgrrgubg
gurbbbruuuuwwbbwgrgrwrrwuwubbbgburubwruwuuugwrgbgg
urggrgbwbwbgrgrrbrbwguuwbuwwbggrgbbbgggwuubwbw
ubugrubuugugwwrgwrrrbwwgbrrbruuggguugrugwrurrgrbbguwuwgrg
bubrgbbrwguuwbbgwbbbwbrgrbbbwuwrbubgrwwgbwbrubg
guwwurwgbwgbrurwuuruwbbbguuurbwuwubwbrrgrbwgwugrubrwrwbuu
rrgruubrurwurwguuwbgubruwugbuwwurrbwwuwrwwrrugrubguwubgw
ugurrrwbguggbgwggwurgggrgggrgbwuwgrgwrbugr
uwbguwugrgbgwwbugbbugubgrrgwggrgwguwgugggbu
rgbgwuwuwrrwbggrbuuwrwbrwurrrrrrwrgrgrburbu
gbwurbbbuuwugbwwgubruugwubbbbwrbwrwrrwggwgwgwbuubg
wbuggbrugrrbugbbwrbwgbbgbbgrgwwurburuurbuuuubrwgruwgrrbrubg
wrwggwurggbuwrwbgruugguwbguuurgwuwwwbbruuu
wwrurwrrwbrbwwbrgguugbugbuwwwwwwrurgbrgguguuuubg
wwubbbrubgrbrrggburgwwgugbggggburwbguguwwburbwbbgwubbur
gbubruwrwuwubbrgwuburwrgubbgbuwugruubbwrgrwubg
ugrubrugwbgbbgurrbwuwurgwggrwuwbbbuuuwugbbuugrggbgb
gwggwgwgrwubgubrbrrubrugwrbgrgbgwbuwrburrrurbgrrubgw
wgrrggwwubgurwrrruuwbwrrgwwgwruugburbguuubruwuwbrggbrbb
bbrwguwgwgwbgurbruruubrbbgrbrgburguwuwggwwurrrgu
wrrbgrgguwugwwbgurgwgbuwbwguwbwrruwwrbugwrruuwbbwurbwrru
uwuwurrwrbruwggrbbrrbwubugrbgrrurgrggwrwgrubbb
ubugrbbubgwgggrurbburwbguuugwguwgwguwurrgwuwwbugrrburb
ggrwwgrurwbrrbbbbgrbwggbwrbgurbbuurwwbbwggugww
wbuurbbbrbgruuggburrguubgrrgurbubgwuuurubrr
wgrwbwwwbrurgurrgbruggwwugwubgubububbbuuuuuubrgbwuwuurbw
bbgbggrbbburgubbruuwgggwrubuuwurgrubrwgbrggubg
rbgrbwubwurwbwwurbrruuurbrguwwwrrbugrbubrwugrwb
wrugurgwuwurrbrwugruguggwbwwwuwwwrrrwwubg
gbwuggbbwbbuububruburrrwggwbwbwgrbgwgwguwrubuururbwuubgwub
gbubwwwrruwwubruugrbgbgwrwrrwruwwuggbrburbguggubuugubg
wgbwgwrurwwurwbrububrwbrrgguwwwbwrrbruugrrru
ubrrbrugbwuwubgbbguwrwugggbrgrruuwwuwubbgrwurubg
uruuuuuuwggrbgggugugbwuuurwgruwgwugwrbgubbrrgwubg
brruurbgbburbrugwuuuwbwrurbubbbubgrgrwwurgbugwgwgrugwuuwbb
gurgwuubwrrrwbuguwuwgrbrrubrwgurrrugurbrrrrrbrwwrbugrg
wbwubwwuugrrwrbggurrgbbuwwgrwuguggbubgrrgbrbrbbgwbrubg
rrwubrwrrbgrruwrbbgrwrwuugggwgubgwuwbgwgbrwwgbgbgbgwbgrr
bbwggbbwuwwgbwuwwuuguburgwbrgbrwwruurwbuwrrbuwgbrw
rbgrbuwbuwbbrgrrurrbuwbrwrrrbruggguuuubbrbguru
ugwwubwgwgwbbbbguwbbuggbuwuburuuwwwwbwwrggwgrruwwwwbbubu
brrrrwugbuwwruwbwgbrgwwgwbbbrwrrrgbgwbbbgbubgwrurgrubg
bwrwrrwwbwguwburrrrgwbbrgubrubbbwuwrbrwuwburrugwwrwwrbbruu
gurrwuugurbuubrgbwubbgwubbbbuwruugrrbgurbggrrrguu
gwrwuuruggwbgurwwgwrwuuwwbgggbrwbugbrrgwbgrwrruuuurwrg
grggwgwgbrrbbwbrubgbrggubbbbgbrgbwwbwbrgubggbgbubgw
ugbgubrbrbrggwguwwwrgbgruggurgwgrrugbbbuuubg
gubwugguwrbuggwburrrwguwubbgrubbuwruubrgrgrugrwrrbrbbugwu
rwgwwgubggurrbwrwrguwrrbrggrggwwgwwwruuwgburrrrbuugbg
wwrwurwggggrrrbbbbruurgguwwrrurugurgubrbwgubgwgrbwbguubg
rwguurwrrwwrrwbrbrugwbgrbggbbbuwbrrrgbuggwwwuubg
wubwbgggubbbgguwurwggwbwuwbwwubwguurbwrruwwrubg
bbuugrggbbwubgurwbwrwwuwbwbggurwguggwbwubg
bgrugwuwbgwwrrwwuwubrwurwbuurwwgbrgwwggrwgwuwububwbbuubg
bubrggwuugrgrwgbruugbgrwbgbbbwbwwurrrgwgwwbuggguu
ubrbwbururbrgurgugrgurbwbbwwgrugrbubrugbbbbburbrurgrwgwgu
wuwubuwbbugbgrrwrgbgbrbbugguwbbwwwgwugwwurwwuugbwgg
bubwbgggwugrwgrrrrrrrrugguwwrrbwrrggbruwuurwguuwwgggwwwrgw
wubbbuuwwbbwubgbrgurbggggurwrrbgbrwwuggwubgw
wbubuwuuwwbuwwbwrbrggwwbbuwggbwuuwwrgrbwurguwgbrrwwubgw
gwrwggrubwguubwuggugwrrwgbrwrrrwbubgwuwbbubww
gguwuugugbuubrwbrrrbrrrubwburrgwgwgwbgurbgbrrwbrgr
bbwbbgbbwwuwbrugbwruggbugwbwgurgwgggbrwgug
ubruuuuwrggbrggbugbbwwguwguwuggbbwguuburugrugbrgruuwbbbwubg
wuggrwgwbrgwwbbwbgwrbrwgurwwgbbwrwbgubwrugggbrgrbbrbgrrgubg
rbwrubrgwrgrwugurwbguuugbrbbbwubbwbbguwbrrbbbwrrwg
brubruurbwguwrrwuwrugbuwwwgbrrgubwwgrggwgbru
rrbggwrbbwbbrwrrgrgbgubggbrwwrrbburwwbrwuwbrbbwbrgw
wrggruwrwwwwwwugbrgwgggurubbrbbgguggrwbgugugrrruwu
gggwurggwwgurugububrbbrurgwwrgrwwbwubwubrwgwrubg
uwbbwgrrrbrwbrubuuwwguwguwgubbgruruguwbwubg
bwrrgburgwguuurwggwrwgrubbbuwruwbrgwbuuwubug
ugurrwbgbuwgbuugrbwgugwguwwbrugwbbuwurugugbuuugbu
bgrbwbbuwbrrgggwugwgwrbbuwbugubgrruurubg
ggbrrgubbgurwwrgrgbbuggwrgwruguggbbrrrrbbrbwurwr
ggbgbubuubbgwgrrrbwwgbugrgrwbubburgbuuubgw
ruugggwrbbgbbuuburrgwbwwgbwgurbrbbggbgubgw
guwrbugwuubgubggwgwbruugrwbbwgwrwurrbggrrgwub
bubwgbrguugrwwgbwrwbuuurwrwrgbbuguwwbgbwubg
brubuuwgbgwgrggruruwrrubwbuuwwuubbrrrwbuurwuruuur
grgurgggwggruwuwrgrbgguggrwrbgbugwbuuubg
bwuuwgbrbwgwurrrwbrwwwbuwugbrrggbbgbuwgrubrugubg
wbbbwuwububuuuwbwgwrrbuurbwbrbgwuuwuggwubrguuwggguwuubwggr
uurgwgbgwrwwbguubuurwwrwurbuubwbwgwuurwwwwubgwrugrgru
rgwgbbbgguuwuugugwbrurbwbbbubwurwubggwuurggrugwbgb
gwgbwuwwgwuugruugrruwgbwwgwugbuwbrrbbgwwuwgwbgwugwbbrrguw
grrbbuuggrugbgbbbgbrgubuwrrrwrbwwwguwwgbgwgggwug
wwwrwgbgruubuwbrwuuuwggubwbrgrrguuuwbuwugbrgrbubrbrubg
ruwbrwugbbrggwguurgbrugrgbruuuwugugwurruuwbrbwggubg
uuuwuguwuwrubgbwbgurguubwwrbwrrgbrgrrbbgrrrgwgrur
uwubuubwrggbwwrugrbwrwwruuwbrrbuubbgrruwbg
buuwwwggwbuwwwwgwbwbguwgrwrrgbwuubwgurrguubwwwub
gguurgrurbrgwwrwgugbgurbwguugrgwrrwbruugrrubggw
rbuuwbwgwrrubbrbgrrrugggrrubgbbrbwgbuuurrubg
rbburbbwbwurrrbbggwwgwbgwggbrbubwgrugurbbbrgubwwuwwu
guwrbgbwwuwbbuwrwgurbgwrbwbwburwwggwruruburguw
ugubbggbwbubbgrwuubruwggbbwrgwgbguubbwgwwggrrburuurwrgguuubg
wggburwgrgrwuugrggburubrbwbbbwggrwbwuwguuwbr
burrbuwuwwwbrrwguwggubbrbrgrrguwuwwuuuwwbgguuuwubg
wrbbwubrrugrrbruruuubuuwbruruwburrwguwggbwwuurrgwugbruubgw
gggwbubwwrwbugwuwwuuubgwguwbubgwrbuuwbwubbbrbrugbgbur
wrgbruuguubgwbuwrrbubwwggrrrrbugugggbrrurrrgggbbgrguwrgwb
gugbrwurgruwgrrwgbruuuuwburbgwwwwwubgbrgwwrrrbgubg
wgwurwwbuwbggwgugrbwuruwuwuururbrrgwrbugugrrugubg
wbgwgrwwuubrurwwwuwwuuwrwuwuburwuwwuubgggwuuuwubgubg
rwgwguwuubwuwgwggrwgwrrbbggrwruuggrbubrrgbuugwuruubgrgr
rbububguururbwrurbrubbubuuubguwbrbuugrrbgwwgww
grubwubrgwurubbwbgwgubguguuwbgruwubwwrbuurwgurgbr
uubwgwwuubgggbgbruwuguuwbwurguuguwbgguuwwrb
bwwgbubrwwbugbrrwguwugruwwgbwbururbrbgrubg
ugugggbggbgrwwugrggbwbuwggguugububuwbubbubuwgubgw
ugrubgbbuuuwgbuurbgwbwubguggrurgwrwgbrrgrbruwrgw
rrggurwrrwugguuwrwuruuguggrbwwbrrgwwbrgubgw
rbrbgburgbuuruuugbrggbwgrubrugrbwruuwwwwrgrwwr
rrggbrgrwrbgrbrrwrgwrwwwwuubrgwwggubbwgugrwrurbgrrruwrb
rrbrwrrrruurgbwbggrrwwgubrwgggwwwugrwwubgwruguwugwbbbug
rgbgrwgbbbguggwgwbwugbbbwgbgbrgguurgbbbugrubuwrrgwubw
bggwwrbuurgwwwbrbggggbgbbgwwgwwrbwbbrwbgbbrrbgrgwwbbggbwuw
rwururuuggwbugguwgwgrbubrgbrrbruguuwbbbuurg
gbbbrbgbwrrrgwrrwgrrrbubrggrwrgrgburrrruwwurw
guguugwbrgwugwwwbuwrrbugurbbbruubggwuuwguguwu
uwbggwbururwuwbrggbuwrwubuurbrugrurruwurubuggbbwwgww
rruuububwrruugrurubbbwwugrbruggbrugrrwwgwrguwbburubwwbwbrubg
bbwrggbgrrbuwwggwgwbubwgbwugwgbrurgbwbbbbbuuuubw
gbgbgwrrugggubgrrubwguwuuwwwwguubwggwuwgugwuuubu
rguuubuwbrbrwwgwggbugbubwrrruggwrwuuguwwggugrrbgrbrwwuww
rrgrggruggbgwgggbrgurggurburrurbuburbgrgbbubrwgru
gburrbwbrbuwugwwbbrggwbwwgrbbrwwuwgubbuwbwr
bgurwuggrwuwwwgrrgrwwgurbrbgbruggrbwbgurwbwwwg
bgbbgrubbruggrgrguwrbbgbwguwwubwbrrwwubgw
bgurguwrbbrrrbgrubrwrwgwggbbggbbubgrguggbwggbbugbgbwgrwuw
urugbbrbbbwugruwrwrggbgwbwwrwgrugwugbguwubgb
rgurrwbwwugggbgwubbwbwwwruguggwruuwrwrurbbrwwggbrrbgubbwubg
ugrgwruuruuggwrrurwwwguwwuggrwwgbruburbggbrb
uurgbgbgwgbwgrburrurrrruruurrubwbgurbwubguwgubwbwrbgrr
grbrggbbbgwbbuwwrbuwuruwwrgbuguwgbgrgrgrwwbwgrbw
wwruburuwggbrwbruwurrrgbbwwrwgguruwbrwubbr
bbwburbbrbwubrbwuruugrrwwgbubgugggrwugrbgurgwwgubg
ugbwwbrgubrrrurwgbgubrrbbrbggwburrwuuuuruwgurubgwgubg
wbwubrbgbrbgugrrguggwrrgwbugrwubgwgrrgbgrurbwrbrububwwgwubg
rrububggbrwbrubwubuuwwrbubrbuggwrbubgwwururrgwwurwr
wbrbrgbrbgubguugwruwrrgrwgguurugbguwubbuubwggrrggubwbb
rguuwbrururbwbubggugbwbwuwgggruubwbuubwrrrrug
ruwwggggwruwrurwgrguwwgurbgwrgwuuwrbrrwbgbuubrwubgbg
rugrgrwgbbrgwrggguggbwrugrrrbguwwbguwrbwwwrwugbgwwrwbr
wwubggbwubgrubwrbrgbrbwgbrggbwggggwggggguggrbr
bbuwgwgbbuwbuburgwgbgggugrgrrbrgurrguurugbbuurubggbg
rruwbwwwgurbgugbubwwwuwwuwbururgwwrrwubg
ubgbbuubwbwgrbbrbuwwuuwubrgugurbgruwurwwgu
grbwbubbrrruuuuuwuwrwugwuwgbubwbbwrbwbbubbg
urgrugbgbruwwburwrgrburbubrbbuwrrgwgbgrubg
ggububgubgwgbgguwrbrubwwburugwubuuwrgubg
brgwuugggbbuwbuuuwruwubrgguuugrggbwbwwrbugrwbguurugwgbu
wwwggugwwbbbgwgururugbgrwubgbwrwrggrubgrgwbrbrr
ggburgrrbrbwbrruwwwrwurgbwgrbrgguwrgubbubwwubg
buubugggwrbwrbbbgrbbgwwwwgbrrbbugggggbgguwbruwurwbrwbrgw
rbuurwgrwuuuwrggurbubbgbrgwrbwgrwbbuubgrrbwbwubruubg
wgwwbrrrgwbuubwgwgubwwggurggrrwugbugurrbugwbwrubbrgurbbgw
ugwguuugbrggggurubrbbgbrrwwbbwurrruwrugruwuwubwu
urrbbgwwbburrbrwbwggwrbbwbgwwbruwubrbwbgubbgwrgu

View File

@@ -1,141 +0,0 @@
#############################################################################################################################################
#.......#.........#.....#.....#...#...###...###.....###...#...###.....#.....#.......#.......#.....#...#####.....#...#...#...#...............#
#.#####.#.#######.#.###.#.###.#.#.#.#.###.#.###.###.###.#.#.#.###.###.#.###.#.#####.#.#####.#.###.#.#.#####.###.#.#.#.#.#.#.#.#############.#
#...#...#.......#.#...#.#...#.#.#...#...#.#...#...#.....#.#.#...#...#.#...#.#.....#.#...#...#.#...#.#...#...#...#.#...#.#.#.#...#...........#
###.#.#########.#.###.#.###.#.#.#######.#.###.###.#######.#.###.###.#.###.#.#####.#.###.#.###.#.###.###.#.###.###.#####.#.#.###.#.###########
#...#.....#.....#.#...#.#...#.#.......#.#.#...###.#.......#.#...#...#.....#.......#...#.#...#.#...#.#...#...#.###.....#...#...#.#...........#
#.#######.#.#####.#.###.#.###.#######.#.#.#.#####.#.#######.#.###.###################.#.###.#.###.#.#.#####.#.#######.#######.#.###########.#
#...#.....#.....#.#.#...#...#...#...#.#...#...#...#.......#.#...#...........#.......#...#...#.#...#.#...#...#...#...#.#.......#.#.........#.#
###.#.#########.#.#.#.#####.###.#.#.#.#######.#.#########.#.###.###########.#.#####.#####.###.#.###.###.#.#####.#.#.#.#.#######.#.#######.#.#
###.#.###.....#.#.#.#.#...#.#...#.#.#...#.....#.....#.....#.#...#...###...#...#...#.#.....#...#...#.#...#...#...#.#.#.#.###...#.#.#.....#.#.#
###.#.###.###.#.#.#.#.#.#.#.#.###.#.###.#.#########.#.#####.#.###.#.###.#.#####.#.#.#.#####.#####.#.#.#####.#.###.#.#.#.###.#.#.#.#.###.#.#.#
#...#...#...#.#.#.#.#.#.#...#.#...#.....#...###.....#...#...#...#.#.#...#.###...#...#...###.....#.#.#.#.....#...#.#.#.#.....#...#...#...#...#
#.#####.###.#.#.#.#.#.#.#####.#.###########.###.#######.#.#####.#.#.#.###.###.#########.#######.#.#.#.#.#######.#.#.#.###############.#######
#.....#.....#...#.#.#.#.....#.#...........#...#.#.....#.#.....#.#.#.#.#...#...#.......#.#...###.#.#.#.#.....#...#.#...#.............#.......#
#####.###########.#.#.#####.#.###########.###.#.#.###.#.#####.#.#.#.#.#.###.###.#####.#.#.#.###.#.#.#.#####.#.###.#####.###########.#######.#
#...#.........#...#.#.#...#.#...#...#...#.#...#.#...#...#.....#.#.#...#.###...#.#.....#...#...#.#.#.#.....#.#.###.#...#...........#...#.....#
#.#.#########.#.###.#.#.#.#.###.#.#.#.#.#.#.###.###.#####.#####.#.#####.#####.#.#.###########.#.#.#.#####.#.#.###.#.#.###########.###.#.#####
#.#...........#...#.#.#.#.#...#...#.#.#.#.#.....#...#...#...#...#...#...#...#...#...#.....#...#.#...#.....#.#...#.#.#.......#...#...#.#.....#
#.###############.#.#.#.#.###.#####.#.#.#.#######.###.#.###.#.#####.#.###.#.#######.#.###.#.###.#####.#####.###.#.#.#######.#.#.###.#.#####.#
#...#.....#.....#...#...#...#.....#.#.#.#.#.......#...#.....#...#...#...#.#...#...#.#...#...###.....#.#...#...#.#.#.#...###.#.#.#...#.......#
###.#.###.#.###.###########.#####.#.#.#.#.#.#######.###########.#.#####.#.###.#.#.#.###.###########.#.#.#.###.#.#.#.#.#.###.#.#.#.###########
###...###...#...#...#...#...#...#.#.#.#.#.#...#...#.........#...#.....#.#.#...#.#...#...#...#...#...#...#.....#...#...#...#.#.#...#...#...###
#############.###.#.#.#.#.###.#.#.#.#.#.#.###.#.#.#########.#.#######.#.#.#.###.#####.###.#.#.#.#.#######################.#.#.#####.#.#.#.###
#.............#...#...#.#...#.#.#.#.#.#.#.#...#.#.#...###...#.#...#...#...#...#...#...#...#.#.#.#.....#.........#.........#.#.....#.#.#.#...#
#.#############.#######.###.#.#.#.#.#.#.#.#.###.#.#.#.###.###.#.#.#.#########.###.#.###.###.#.#.#####.#.#######.#.#########.#####.#.#.#.###.#
#.#.............###...#...#.#.#...#...#...#.....#.#.#.#...#...#.#.#...#.......#...#...#.#...#.#.#...#.#.......#.#.......###.......#.#.#.#...#
#.#.###############.#.###.#.#.###################.#.#.#.###.###.#.###.#.#######.#####.#.#.###.#.#.#.#.#######.#.#######.###########.#.#.#.###
#...#...#...........#.....#...#...#...#...#.......#.#.#...#...#.#.#...#.#.....#.....#.#.#...#.#.#.#...#.......#...#...#.......#.....#...#...#
#####.#.#.#####################.#.#.#.#.#.#.#######.#.###.###.#.#.#.###.#.###.#####.#.#.###.#.#.#.#####.#########.#.#.#######.#.###########.#
#...#.#.#.........#.......#.....#...#...#.#.#...###.#.#...#...#.#.#...#...#...#.....#.#...#.#.#.#.#...#...###...#...#.........#...#.....#...#
#.#.#.#.#########.#.#####.#.#############.#.#.#.###.#.#.###.###.#.###.#####.###.#####.###.#.#.#.#.#.#.###.###.#.#################.#.###.#.###
#.#...#.......#...#.#.....#...#...#...#...#...#.#...#.#...#...#.#...#.#...#...#.....#...#.#...#.#...#.#...#...#.......###...#...#.#...#.#...#
#.###########.#.###.#.#######.#.#.#.#.#.#######.#.###.###.###.#.###.#.#.#.###.#####.###.#.#####.#####.#.###.#########.###.#.#.#.#.###.#.###.#
#.........#...#.....#.........#.#...#.#.#.......#...#.###.#...#.#...#...#.#...#...#.#...#.#.....#...#.#.###.#.......#.#...#...#.#.#...#.....#
#########.#.###################.#####.#.#.#########.#.###.#.###.#.#######.#.###.#.#.#.###.#.#####.#.#.#.###.#.#####.#.#.#######.#.#.#########
###...###.#.#...#...#.........#.....#...#...#.....#.#.#...#.#...#...#...#.#.....#.#.#.#...#...#...#...#.....#.....#.#.#...#.....#.#.....#...#
###.#.###.#.#.#.#.#.#.#######.#####.#######.#.###.#.#.#.###.#.#####.#.#.#.#######.#.#.#.#####.#.#################.#.#.###.#.#####.#####.#.#.#
#...#.....#...#.#.#.#.....#...#...#.......#.#.#...#.#.#...#.#.....#.#.#.#.....###.#.#.#.#.....#.....###.........#.#...###.#.......#...#...#.#
#.#############.#.#.#####.#.###.#.#######.#.#.#.###.#.###.#.#####.#.#.#.#####.###.#.#.#.#.#########.###.#######.#.#######.#########.#.#####.#
#.#...........#...#.......#.#...#.#.......#.#.#...#.#.#...#.#.....#.#.#.#...#.#...#.#.#.#...#.....#...#.......#...#.......#.........#.....#.#
#.#.#########.#############.#.###.#.#######.#.###.#.#.#.###.#.#####.#.#.#.#.#.#.###.#.#.###.#.###.###.#######.#####.#######.#############.#.#
#...#.....###.............#.#...#...#.....#...###.#.#.#.#...#...#...#.#.#.#.#.#...#.#...#...#.###.#...#.....#...#...#...#...#...#...#...#...#
#####.###.###############.#.###.#####.###.#######.#.#.#.#.#####.#.###.#.#.#.#.###.#.#####.###.###.#.###.###.###.#.###.#.#.###.#.#.#.#.#.#####
#...#...#.....#...........#.....#...#.#...#.....#...#...#...#...#...#.#.#.#.#S###.#.....#...#...#...###...#...#...#...#.#.....#.#.#...#...###
#.#.###.#####.#.#################.#.#.#.###.###.###########.#.#####.#.#.#.#.#####.#####.###.###.#########.###.#####.###.#######.#.#######.###
#.#.###.....#...#...#.....#.......#...#...#.#...#...#.......#.#...#...#...#...###.#.....#...#...#...#...#...#.#...#...#.........#.......#...#
#.#.#######.#####.#.#.###.#.#############.#.#.###.#.#.#######.#.#.###########.###.#.#####.###.###.#.#.#.###.#.#.#.###.#################.###.#
#.#.#...#...#...#.#.#.###.#.###.........#...#.....#.#.#.....#...#.......#.....###.#...#...#...###.#...#.....#...#.....#.....#...#.......#...#
#.#.#.#.#.###.#.#.#.#.###.#.###.#######.###########.#.#.###.###########.#.#######.###.#.###.#####.#####################.###.#.#.#.#######.###
#.#.#.#.#...#.#...#...#...#.#...#.....#.#...#...#...#.#.#...#.....#...#.#.#...###.#...#...#.....#...#...........###...#...#.#.#.#.#.......###
#.#.#.#.###.#.#########.###.#.###.###.#.#.#.#.#.#.###.#.#.###.###.#.#.#.#.#.#.###.#.#####.#####.###.#.#########.###.#.###.#.#.#.#.#.#########
#.#...#...#...###...###...#.#.....#...#.#.#...#...###...#...#...#.#.#...#...#.###.#.#.....#...#.#...#.#.........#...#...#.#...#...#...#...###
#.#######.#######.#.#####.#.#######.###.#.#################.###.#.#.#########.###.#.#.#####.#.#.#.###.#.#########.#####.#.###########.#.#.###
#.......#.....#...#.#.....#.#.......###...#.........#.......#...#...###...#...###...#...#...#...#.....#...........#...#.#.#...........#.#...#
#######.#####.#.###.#.#####.#.#############.#######.#.#######.#########.#.#.###########.#.#########################.#.#.#.#.###########.###.#
#...###.#.....#...#...#...#.#...#...#.....#.#.......#.....#...###...#...#.#...#######...#.###.................#...#.#...#.#...#...#.....#...#
#.#.###.#.#######.#####.#.#.###.#.#.#.###.#.#.###########.#.#####.#.#.###.###.#######.###.###.###############.#.#.#.#####.###.#.#.#.#####.###
#.#.....#.....###...#...#...###...#...#...#.#.....###...#.#...#...#.#...#.....#######...#.#...#.......#.....#.#.#...#...#.#...#.#...#...#...#
#.###########.#####.#.#################.###.#####.###.#.#.###.#.###.###.###############.#.#.###.#####.#.###.#.#.#####.#.#.#.###.#####.#.###.#
#...#.......#.#...#...###...#...#.......###.#.....#...#.#.....#...#.#...#.....#######...#.#...#.#.....#.#...#...#.....#...#.....#.....#.....#
###.#.#####.#.#.#.#######.#.#.#.#.#########.#.#####.###.#########.#.#.###.###.#######.###.###.#.#.#####.#.#######.###############.###########
#...#.#...#.#.#.#.........#.#.#.#.......#...#.....#...#.#...#...#.#...#...#...#######...#.###...#.......#.........#.......#.....#...........#
#.###.#.#.#.#.#.###########.#.#.#######.#.#######.###.#.#.#.#.#.#.#####.###.###########.#.#########################.#####.#.###.###########.#
#.#...#.#...#...#.........#...#.........#.#.....#...#.#.#.#.#.#.#.#...#...#...#...###E#...#...###...........#.....#.....#.#...#.#.....#.....#
#.#.###.#########.#######.###############.#.###.###.#.#.#.#.#.#.#.#.#.###.###.#.#.###.#####.#.###.#########.#.###.#####.#.###.#.#.###.#.#####
#...###.....#...#.#...###.................#.###.....#.#...#.#.#.#...#.#...#...#.#.#...#.....#.#...#...#...#...###.......#.#...#.#...#.#.....#
###########.#.#.#.#.#.#####################.#########.#####.#.#.#####.#.###.###.#.#.###.#####.#.###.#.#.#.###############.#.###.###.#.#####.#
#...###...#...#...#.#.#...#...#...#...#...#...#.......#...#...#.....#...###...#.#...###.....#.#...#.#...#.......#.......#.#...#...#.#...#...#
#.#.###.#.#########.#.#.#.#.#.#.#.#.#.#.#.###.#.#######.#.#########.#########.#.###########.#.###.#.###########.#.#####.#.###.###.#.###.#.###
#.#.#...#...#...#...#...#...#...#...#...#...#...#.....#.#.........#.#.....###...#.....#...#.#.###...#...........#.#.....#.....#...#...#...###
#.#.#.#####.#.#.#.#########################.#####.###.#.#########.#.#.###.#######.###.#.#.#.#.#######.###########.#.###########.#####.#######
#.#.#.....#.#.#.#.......................###.#.....###.#.........#...#...#.......#...#.#.#...#.#...###.............#.....###...#...#...#...###
#.#.#####.#.#.#.#######################.###.#.#######.#########.#######.#######.###.#.#.#####.#.#.#####################.###.#.###.#.###.#.###
#.#.#...#.#...#.......................#...#...#.....#...........#...#...#.......#...#.#.....#.#.#.#...###.....#.......#.....#...#...#...#...#
#.#.#.#.#.###########################.###.#####.###.#############.#.#.###.#######.###.#####.#.#.#.#.#.###.###.#.#####.#########.#####.#####.#
#.#...#...#...#.......#.....#...#...#.....#...#.#...###...#...###.#.#...#.....###...#.###...#...#...#.....###.#.....#...#...#...#...#...#...#
#.#########.#.#.#####.#.###.#.#.#.#.#######.#.#.#.#####.#.#.#.###.#.###.#####.#####.#.###.###################.#####.###.#.#.#.###.#.###.#.###
#...#.....#.#.#.#.....#.#...#.#...#.....###.#.#.#.......#.#.#.#...#...#.#.....#...#.#.....#.....#...#.......#.#...#.###...#...#...#.....#...#
###.#.###.#.#.#.#.#####.#.###.#########.###.#.#.#########.#.#.#.#####.#.#.#####.#.#.#######.###.#.#.#.#####.#.#.#.#.###########.###########.#
#...#...#.#.#.#.#...#...#...#.#.........#...#...#...#.....#.#.#.....#.#.#.#...#.#.#.......#...#...#.#.#.....#...#.#.#...#...#...#...#.......#
#.#####.#.#.#.#.###.#.#####.#.#.#########.#######.#.#.#####.#.#####.#.#.#.#.#.#.#.#######.###.#####.#.#.#########.#.#.#.#.#.#.###.#.#.#######
#.......#...#...###...#####...#...........#...#...#...###...#...###.#.#.#.#.#...#...#.....#...#...#...#...#...###.#...#...#...#...#.#.......#
###########################################.#.#.#########.#####.###.#.#.#.#.#######.#.#####.###.#.#######.#.#.###.#############.###.#######.#
#.........#.....###.....#.......#.......#...#.#.#...#...#.....#.....#.#.#.#.#.......#.......###.#...#...#...#...#...............###.#.......#
#.#######.#.###.###.###.#.#####.#.#####.#.###.#.#.#.#.#.#####.#######.#.#.#.#.#################.###.#.#.#######.###################.#.#######
#.......#.#...#.....#...#.....#.#.....#.#...#...#.#.#.#.#...#.......#.#.#.#.#.....#.....#.....#...#.#.#.......#...................#...###...#
#######.#.###.#######.#######.#.#####.#.###.#####.#.#.#.#.#.#######.#.#.#.#.#####.#.###.#.###.###.#.#.#######.###################.#######.#.#
#.......#.###.......#.#...#...#.......#.....#...#.#.#.#.#.#...#.....#...#.#.#.....#...#.#...#.###.#.#.......#.#...............#...###...#.#.#
#.#######.#########.#.#.#.#.#################.#.#.#.#.#.#.###.#.#########.#.#.#######.#.###.#.###.#.#######.#.#.#############.#.#####.#.#.#.#
#.......#.#...#.....#...#...#.............###.#...#...#.#...#.#.........#.#.#.....#...#.#...#.....#.....#...#...#.......#...#...#...#.#...#.#
#######.#.#.#.#.#############.###########.###.#########.###.#.#########.#.#.#####.#.###.#.#############.#.#######.#####.#.#.#####.#.#.#####.#
#...#...#...#...#.............#...........#...#.......#.#...#.#...#...#.#.#.#.....#...#...#.....#.....#...###.....#.....#.#...#...#.#.#.....#
#.#.#.###########.#############.###########.###.#####.#.#.###.#.#.#.#.#.#.#.#.#######.#####.###.#.###.#######.#####.#####.###.#.###.#.#.#####
#.#...#.......#...###...........#...#...###...#.....#.#.#...#.#.#.#.#...#...#...#...#...#...###...#...#.......#.....#.....#...#.#...#.#.#...#
#.#####.#####.#.#####.###########.#.#.#.#####.#####.#.#.###.#.#.#.#.###########.#.#.###.#.#########.###.#######.#####.#####.###.#.###.#.#.#.#
#...#...#.....#.#...#...........#.#.#.#.....#.#.....#...###.#.#.#.#...#...#...#.#.#...#...#.......#.....#...#...#...#.#.....#...#.....#...#.#
###.#.###.#####.#.#.###########.#.#.#.#####.#.#.###########.#.#.#.###.#.#.#.#.#.#.###.#####.#####.#######.#.#.###.#.#.#.#####.#############.#
#...#.#...#...#.#.#.#.........#...#...#.....#.#...#...###...#.#.#...#...#.#.#...#.#...#...#.....#.........#...###.#...#.......#...#...#...#.#
#.###.#.###.#.#.#.#.#.#######.#########.#####.###.#.#.###.###.#.###.#####.#.#####.#.###.#.#####.#################.#############.#.#.#.#.#.#.#
#...#.#...#.#.#.#.#...#.....#...#.......#...#.#...#.#.#...#...#.#...#.....#...#...#...#.#.#...#...#.............#...#...........#.#.#.#.#.#.#
###.#.###.#.#.#.#.#####.###.###.#.#######.#.#.#.###.#.#.###.###.#.###.#######.#.#####.#.#.#.#.###.#.###########.###.#.###########.#.#.#.#.#.#
###...#...#.#.#.#.#...#...#...#.#.........#.#.#...#.#.#...#...#.#...#.......#.#.....#.#.#.#.#.###...###.........#...#...........#...#.#.#...#
#######.###.#.#.#.#.#.###.###.#.###########.#.###.#.#.###.###.#.###.#######.#.#####.#.#.#.#.#.#########.#########.#############.#####.#.#####
###...#.....#...#...#.....#...#.............#.#...#.#.###.#...#...#.###...#.#.#...#.#.#.#.#.#.#...#...#...........#.......#...#...###.#.....#
###.#.#####################.#################.#.###.#.###.#.#####.#.###.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#############.#####.#.#.###.###.#####.#
#...#.......###.......#...#.........#.......#.#.#...#...#.#...#...#...#.#.#.#.#.#.#.#.#.#.#.#.#.#...#.#.....#.......#...#...#...#...#.......#
#.#########.###.#####.#.#.#########.#.#####.#.#.#.#####.#.###.#.#####.#.#.#.#.#.#.#.#.#.#.#.#.#.#####.#.###.#.#######.#.#######.###.#########
#.........#.....#...#...#.........#.#...###.#.#...#...#.#...#.#.#.....#.#...#.#.#...#.#.#...#.#.###...#.#...#.........#.......#...#.#.......#
#########.#######.#.#############.#.###.###.#.#####.#.#.###.#.#.#.#####.#####.#.#####.#.#####.#.###.###.#.###################.###.#.#.#####.#
###.....#.......#.#.............#...#...#...#.......#.#...#.#...#...#...#.....#.#.....#.#.....#...#...#.#...#...#...........#.#...#...#.....#
###.###.#######.#.#############.#####.###.###########.###.#.#######.#.###.#####.#.#####.#.#######.###.#.###.#.#.#.#########.#.#.#######.#####
#...#...#.....#...###...........#.....#...#.....#.....###.#.....###.#.###...#...#.#...#.#...#.....#...#...#.#.#.#.....#...#...#.......#.....#
#.###.###.###.#######.###########.#####.###.###.#.#######.#####.###.#.#####.#.###.#.#.#.###.#.#####.#####.#.#.#.#####.#.#.###########.#####.#
#...#...#...#.#.......#.....#...#.#.....#...###.#.......#...#...#...#.....#.#...#.#.#...###.#...###...#...#...#.#...#...#...........#...#...#
###.###.###.#.#.#######.###.#.#.#.#.#####.#####.#######.###.#.###.#######.#.###.#.#.#######.###.#####.#.#######.#.#.###############.###.#.###
#...#...#...#...#...#...#...#.#.#.#.....#.....#...#.....###...###.#.....#.#...#.#.#.......#...#...#...#.#...###...#...#.....#.......#...#...#
#.###.###.#######.#.#.###.###.#.#.#####.#####.###.#.#############.#.###.#.###.#.#.#######.###.###.#.###.#.#.#########.#.###.#.#######.#####.#
#...#.....#...#...#.#.###...#.#...#...#.#...#.#...#.......#.......#...#.#.#...#.#.#.....#...#.#...#...#...#.....#.....#...#.#.......#...#...#
###.#######.#.#.###.#.#####.#.#####.#.#.#.#.#.#.#########.#.#########.#.#.#.###.#.#.###.###.#.#.#####.#########.#.#######.#.#######.###.#.###
###...#...#.#.#.###...#.....#...#...#...#.#...#...#...#...#...#...#...#.#.#...#.#...###...#.#...#...#...#.......#.#.......#.#.......#...#...#
#####.#.#.#.#.#.#######.#######.#.#######.#######.#.#.#.#####.#.#.#.###.#.###.#.#########.#.#####.#.###.#.#######.#.#######.#.#######.#####.#
#.....#.#.#.#.#.#.....#.....#...#...#...#.....###...#.#.....#.#.#.#.###...#...#.....#.....#...#...#.....#.......#.#.....#...#.....###.......#
#.#####.#.#.#.#.#.###.#####.#.#####.#.#.#####.#######.#####.#.#.#.#.#######.#######.#.#######.#.###############.#.#####.#.#######.###########
#...#...#.#.#...#...#.#.....#.#####...#.#...#.....###.#.....#...#.#...#.....#.......#.......#.#.#...#...#.......#...#...#.........#.........#
###.#.###.#.#######.#.#.#####.#########.#.#.#####.###.#.#########.###.#.#####.#############.#.#.#.#.#.#.#.#########.#.#############.#######.#
###.#...#.#.#.......#...#...#...#.......#.#.#.....#...#...#.......#...#.....#.....#.........#.#.#.#.#.#.#.......#...#.........###...#...#...#
###.###.#.#.#.###########.#.###.#.#######.#.#.#####.#####.#.#######.#######.#####.#.#########.#.#.#.#.#.#######.#.###########.###.###.#.#.###
#...#...#...#.....#...#...#...#.#...#...#.#.#.....#.#...#.#.........#...###.#...#.#.#.......#.#...#.#.#.#.......#.....#.....#.....#...#.#...#
#.###.###########.#.#.#.#####.#.###.#.#.#.#.#####.#.#.#.#.###########.#.###.#.#.#.#.#.#####.#.#####.#.#.#.###########.#.###.#######.###.###.#
#...#.....#####...#.#.#.....#.#.#...#.#.#.#...#...#...#.#.....#.......#.....#.#.#.#...#.....#...#...#.#.#...........#.#...#.#...#...#...#...#
###.#####.#####.###.#.#####.#.#.#.###.#.#.###.#.#######.#####.#.#############.#.#.#####.#######.#.###.#.###########.#.###.#.#.#.#.###.###.###
#...#...#...#...#...#.....#.#...#...#.#.#.###.#.......#...#...#.....#...#...#.#.#.....#.#...#...#...#.#.#.....#...#.#.#...#...#...###.#...###
#.###.#.###.#.###.#######.#.#######.#.#.#.###.#######.###.#.#######.#.#.#.#.#.#.#####.#.#.#.#.#####.#.#.#.###.#.#.#.#.#.#############.#.#####
#.....#.....#...#.......#.#.#.......#.#...#...#...#...###.#...#.....#.#...#.#.#.#.....#...#.#.#...#...#.#...#.#.#.#.#.#.............#...#...#
###############.#######.#.#.#.#######.#####.###.#.#.#####.###.#.#####.#####.#.#.#.#########.#.#.#.#####.###.#.#.#.#.#.#############.#####.#.#
###...#.........#...#...#...#.....#...###...#...#...###...#...#.#...#...#...#.#.#...#.......#...#.###...#...#.#.#.#.#.#...#...#...#.....#.#.#
###.#.#.#########.#.#.###########.#.#####.###.#########.###.###.#.#.###.#.###.#.###.#.###########.###.###.###.#.#.#.#.#.#.#.#.#.#.#####.#.#.#
#...#...#.....#...#.#...#.........#.....#...#.........#...#...#.#.#...#.#...#.#...#.#.#.....#...#.#...#...#...#.#.#.#.#.#.#.#.#.#.#...#...#.#
#.#######.###.#.###.###.#.#############.###.#########.###.###.#.#.###.#.###.#.###.#.#.#.###.#.#.#.#.###.###.###.#.#.#.#.#.#.#.#.#.#.#.#####.#
#.........###...###.....#...............###...........###.....#...###...###...###...#...###...#...#.....###.....#...#...#...#...#...#.......#
#############################################################################################################################################

Some files were not shown because too many files have changed in this diff Show More