├── .editorconfig
├── .env.example
├── .gitignore
├── LICENSE
├── README.md
├── requirements.txt
├── scripts
├── common.py
├── download.py
├── new.py
├── readme.py
└── runner.py
└── src
├── day01
├── example.txt
├── input.txt
├── part1.py
└── part2.py
├── day02
├── example.txt
├── input.txt
├── part1.py
└── part2.py
├── day03
├── example.txt
├── input.txt
├── part1.py
└── part2.py
├── day04
├── example.txt
├── input.txt
├── part1.py
└── part2.py
├── day05
├── example.txt
├── input.txt
├── part1.py
└── part2.py
├── day06
├── example.txt
├── input.txt
├── part1.py
└── part2.py
├── day07
├── example.txt
├── input.txt
├── part1.py
└── part2.py
├── day08
├── example.txt
├── input.txt
├── part1.py
└── part2.py
├── day09
├── example.txt
├── input.txt
├── part1.py
└── part2.py
├── day10
├── example.txt
├── input.txt
├── part1.py
└── part2.py
├── day11
├── example.txt
├── input.txt
├── part1.py
└── part2.py
├── day12
├── example.txt
├── input.txt
├── part1.py
└── part2.py
├── day13
├── example.txt
├── input.txt
├── part1.py
└── part2.py
├── day14
├── example.txt
├── input.txt
├── part1.py
└── part2.py
├── day15
├── example.txt
├── input.txt
├── part1.py
└── part2.py
├── day16
├── example.txt
├── input.txt
├── part1.py
└── part2.py
├── day17
├── example.txt
├── input.txt
├── part1.py
└── part2.py
├── day18
├── example.txt
├── input.txt
├── part1.py
└── part2.py
├── day19
├── example.txt
├── input.txt
├── part1.py
└── part2.py
├── day20
├── example.txt
├── input.txt
├── part1.py
├── part2.py
└── solve.py
├── day21
├── example.txt
├── input.txt
├── part1.py
└── part2.py
├── day22
├── example.txt
├── input.txt
├── part1.py
└── part2.py
├── day23
├── example.txt
├── input.txt
├── part1.py
└── part2.py
├── day24
├── example.txt
├── input.txt
├── part1.py
└── part2.py
└── day25
├── example.txt
├── input.txt
└── part1.py
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 4
6 | insert_final_newline = true
7 | trim_trailing_whitespace = true
8 |
9 | [*.{md,txt}]
10 | trim_trailing_whitespace = false
11 |
--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------
1 | # The value of the adventofcode.com cookie named "session"
2 | SESSION_COOKIE=
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by https://www.toptal.com/developers/gitignore/api/python
2 | # Edit at https://www.toptal.com/developers/gitignore?templates=python
3 |
4 | ### Python ###
5 | # Byte-compiled / optimized / DLL files
6 | __pycache__/
7 | *.py[cod]
8 | *$py.class
9 |
10 | # C extensions
11 | *.so
12 |
13 | # Distribution / packaging
14 | .Python
15 | build/
16 | develop-eggs/
17 | dist/
18 | downloads/
19 | eggs/
20 | .eggs/
21 | lib/
22 | lib64/
23 | parts/
24 | sdist/
25 | var/
26 | wheels/
27 | share/python-wheels/
28 | *.egg-info/
29 | .installed.cfg
30 | *.egg
31 | MANIFEST
32 |
33 | # PyInstaller
34 | # Usually these files are written by a python script from a template
35 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
36 | *.manifest
37 | *.spec
38 |
39 | # Installer logs
40 | pip-log.txt
41 | pip-delete-this-directory.txt
42 |
43 | # Unit test / coverage reports
44 | htmlcov/
45 | .tox/
46 | .nox/
47 | .coverage
48 | .coverage.*
49 | .cache
50 | nosetests.xml
51 | coverage.xml
52 | *.cover
53 | *.py,cover
54 | .hypothesis/
55 | .pytest_cache/
56 | cover/
57 |
58 | # Translations
59 | *.mo
60 | *.pot
61 |
62 | # Django stuff:
63 | *.log
64 | local_settings.py
65 | db.sqlite3
66 | db.sqlite3-journal
67 |
68 | # Flask stuff:
69 | instance/
70 | .webassets-cache
71 |
72 | # Scrapy stuff:
73 | .scrapy
74 |
75 | # Sphinx documentation
76 | docs/_build/
77 |
78 | # PyBuilder
79 | .pybuilder/
80 | target/
81 |
82 | # Jupyter Notebook
83 | .ipynb_checkpoints
84 |
85 | # IPython
86 | profile_default/
87 | ipython_config.py
88 |
89 | # pyenv
90 | # For a library or package, you might want to ignore these files since the code is
91 | # intended to run in multiple environments; otherwise, check them in:
92 | # .python-version
93 |
94 | # pipenv
95 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
96 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
97 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
98 | # install all needed dependencies.
99 | #Pipfile.lock
100 |
101 | # poetry
102 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
103 | # This is especially recommended for binary packages to ensure reproducibility, and is more
104 | # commonly ignored for libraries.
105 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
106 | #poetry.lock
107 |
108 | # pdm
109 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
110 | #pdm.lock
111 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
112 | # in version control.
113 | # https://pdm.fming.dev/#use-with-ide
114 | .pdm.toml
115 |
116 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
117 | __pypackages__/
118 |
119 | # Celery stuff
120 | celerybeat-schedule
121 | celerybeat.pid
122 |
123 | # SageMath parsed files
124 | *.sage.py
125 |
126 | # Environments
127 | .env
128 | .venv
129 | env/
130 | venv/
131 | ENV/
132 | env.bak/
133 | venv.bak/
134 |
135 | # Spyder project settings
136 | .spyderproject
137 | .spyproject
138 |
139 | # Rope project settings
140 | .ropeproject
141 |
142 | # mkdocs documentation
143 | /site
144 |
145 | # mypy
146 | .mypy_cache/
147 | .dmypy.json
148 | dmypy.json
149 |
150 | # Pyre type checker
151 | .pyre/
152 |
153 | # pytype static type analyzer
154 | .pytype/
155 |
156 | # Cython debug symbols
157 | cython_debug/
158 |
159 | # PyCharm
160 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
161 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
162 | # and can be added to the global gitignore or merged into this file. For a more nuclear
163 | # option (not recommended) you can uncomment the following to ignore the entire idea folder.
164 | #.idea/
165 |
166 | ### Python Patch ###
167 | # Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration
168 | poetry.toml
169 |
170 | # ruff
171 | .ruff_cache/
172 |
173 | # LSP config files
174 | pyrightconfig.json
175 |
176 | # End of https://www.toptal.com/developers/gitignore/api/python
177 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Jasper van Merle
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Advent of Code 2023
2 |
3 | This repository contains my [Advent of Code 2023](https://adventofcode.com/2023) solutions in Python. I focus on solving speed over code quality, so the code in here may be a bit sloppy.
4 |
5 | ## Results
6 |
7 |
8 |
9 |
10 |
11 |
12 | |
13 | Part 1 |
14 | Part 2 |
15 | Overall leaderboard |
16 |
17 |
18 | |
19 | Time |
20 | Rank |
21 | Score |
22 | Time |
23 | Rank |
24 | Score |
25 | Rank |
26 | Score |
27 |
28 |
29 |
30 |
31 |
32 | Day 1
33 | (code)
34 | |
35 | 00:01:12 |
36 | 31 |
37 | 70 |
38 | 00:08:16 |
39 | 190 |
40 | 0 |
41 | 58 |
42 | 70 |
43 |
44 |
45 |
46 | Day 2
47 | (code)
48 | |
49 | 00:03:22 |
50 | 42 |
51 | 59 |
52 | 00:04:50 |
53 | 29 |
54 | 72 |
55 | 16 |
56 | 201 |
57 |
58 |
59 |
60 | Day 3
61 | (code)
62 | |
63 | 00:05:21 |
64 | 26 |
65 | 75 |
66 | 00:07:45 |
67 | 11 |
68 | 90 |
69 | 6 |
70 | 366 |
71 |
72 |
73 |
74 | Day 4
75 | (code)
76 | |
77 | 00:02:43 |
78 | 79 |
79 | 22 |
80 | 00:07:23 |
81 | 112 |
82 | 0 |
83 | 16 |
84 | 388 |
85 |
86 |
87 |
88 | Day 5
89 | (code)
90 | |
91 | 00:08:04 |
92 | 93 |
93 | 8 |
94 | 00:48:36 |
95 | 864 |
96 | 0 |
97 | 23 |
98 | 396 |
99 |
100 |
101 |
102 | Day 6
103 | (code)
104 | |
105 | 00:04:11 |
106 | 283 |
107 | 0 |
108 | 00:05:04 |
109 | 106 |
110 | 0 |
111 | 29 |
112 | 396 |
113 |
114 |
115 |
116 | Day 7
117 | (code)
118 | |
119 | 00:28:03 |
120 | 2124 |
121 | 0 |
122 | 00:29:51 |
123 | 828 |
124 | 0 |
125 | 35 |
126 | 396 |
127 |
128 |
129 |
130 | Day 8
131 | (code)
132 | |
133 | 00:15:40 |
134 | 4470 |
135 | 0 |
136 | 00:22:31 |
137 | 942 |
138 | 0 |
139 | 49 |
140 | 396 |
141 |
142 |
143 |
144 | Day 9
145 | (code)
146 | |
147 | 00:11:15 |
148 | 1552 |
149 | 0 |
150 | 00:13:37 |
151 | 1233 |
152 | 0 |
153 | 57 |
154 | 396 |
155 |
156 |
157 |
158 | Day 10
159 | (code)
160 | |
161 | 00:12:29 |
162 | 140 |
163 | 0 |
164 | 01:11:56 |
165 | 995 |
166 | 0 |
167 | 65 |
168 | 396 |
169 |
170 |
171 |
172 | Day 11
173 | (code)
174 | |
175 | 00:19:47 |
176 | 2044 |
177 | 0 |
178 | 00:30:30 |
179 | 2218 |
180 | 0 |
181 | 69 |
182 | 396 |
183 |
184 |
185 |
186 | Day 12
187 | (code)
188 | |
189 | 00:18:30 |
190 | 697 |
191 | 0 |
192 | 00:47:09 |
193 | 788 |
194 | 0 |
195 | 78 |
196 | 396 |
197 |
198 |
199 |
200 | Day 13
201 | (code)
202 | |
203 | 00:27:29 |
204 | 1889 |
205 | 0 |
206 | 00:31:32 |
207 | 1068 |
208 | 0 |
209 | 89 |
210 | 396 |
211 |
212 |
213 |
214 | Day 14
215 | (code)
216 | |
217 | 00:03:12 |
218 | 28 |
219 | 73 |
220 | 00:28:51 |
221 | 514 |
222 | 0 |
223 | 78 |
224 | 469 |
225 |
226 |
227 |
228 | Day 15
229 | (code)
230 | |
231 | 00:02:10 |
232 | 100 |
233 | 1 |
234 | 00:09:59 |
235 | 59 |
236 | 42 |
237 | 73 |
238 | 512 |
239 |
240 |
241 |
242 | Day 16
243 | (code)
244 | |
245 | 00:20:21 |
246 | 681 |
247 | 0 |
248 | 00:23:22 |
249 | 459 |
250 | 0 |
251 | 84 |
252 | 512 |
253 |
254 |
255 |
256 | Day 17
257 | (code)
258 | |
259 | 00:22:57 |
260 | 364 |
261 | 0 |
262 | 00:39:31 |
263 | 654 |
264 | 0 |
265 | 91 |
266 | 512 |
267 |
268 |
269 |
270 | Day 18
271 | (code)
272 | |
273 | 00:24:36 |
274 | 1132 |
275 | 0 |
276 | 00:40:02 |
277 | 595 |
278 | 0 |
279 | 98 |
280 | 512 |
281 |
282 |
283 |
284 | Day 19
285 | (code)
286 | |
287 | 00:24:06 |
288 | 1073 |
289 | 0 |
290 | 00:47:13 |
291 | 600 |
292 | 0 |
293 | 100 |
294 | 512 |
295 |
296 |
297 |
298 | Day 20
299 | (code)
300 | |
301 | 00:37:25 |
302 | 493 |
303 | 0 |
304 | 01:03:18 |
305 | 396 |
306 | 0 |
307 | >100 |
308 | 512 |
309 |
310 |
311 |
312 | Day 21
313 | (code)
314 | |
315 | 00:06:34 |
316 | 310 |
317 | 0 |
318 | 00:49:54 |
319 | 30 |
320 | 71 |
321 | 98 |
322 | 583 |
323 |
324 |
325 |
326 | Day 22
327 | (code)
328 | |
329 | 00:28:17 |
330 | 229 |
331 | 0 |
332 | 00:37:43 |
333 | 241 |
334 | 0 |
335 | >100 |
336 | 583 |
337 |
338 |
339 |
340 | Day 23
341 | (code)
342 | |
343 | 00:07:03 |
344 | 38 |
345 | 63 |
346 | 00:27:31 |
347 | 45 |
348 | 56 |
349 | 84 |
350 | 702 |
351 |
352 |
353 |
354 | Day 24
355 | (code)
356 | |
357 | 00:24:47 |
358 | 303 |
359 | 0 |
360 | 00:32:33 |
361 | 14 |
362 | 87 |
363 | 75 |
364 | 789 |
365 |
366 |
367 |
368 | Day 25
369 | (code)
370 | |
371 | 00:06:27 |
372 | 16 |
373 | 85 |
374 | 00:06:33 |
375 | 16 |
376 | 85 |
377 | 63 |
378 | 959 |
379 |
380 |
381 |
382 |
383 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | networkx
2 | python-dotenv
3 | requests
4 | watchfiles
5 | shapely
6 | z3-solver
7 |
--------------------------------------------------------------------------------
/scripts/common.py:
--------------------------------------------------------------------------------
1 | import os
2 | from dotenv import load_dotenv
3 | from requests import Session
4 |
5 | def get_requests_session() -> Session:
6 | session = Session()
7 | session.headers.update({"User-Agent": "https://github.com/jmerle/advent-of-code-2023 by jaspervmerle@gmail.com"})
8 |
9 | load_dotenv()
10 | session.cookies.set("session", os.environ["SESSION_COOKIE"])
11 |
12 | return session
13 |
--------------------------------------------------------------------------------
/scripts/download.py:
--------------------------------------------------------------------------------
1 | from argparse import ArgumentParser
2 | from common import get_requests_session
3 | from pathlib import Path
4 |
5 | def main() -> None:
6 | parser = ArgumentParser(description="Download input data for a day.")
7 | parser.add_argument("day", type=int, help="the day to download input data for")
8 |
9 | args = parser.parse_args()
10 |
11 | project_root = Path(__file__).parent.parent
12 |
13 | input_file = project_root / "src" / f"day{args.day:02}" / "input.txt"
14 | if not input_file.is_file():
15 | raise RuntimeError(f"{input_file} does not exist")
16 |
17 | input_response = get_requests_session().get(f"https://adventofcode.com/2023/day/{args.day}/input")
18 | input_response.raise_for_status()
19 |
20 | input_file.write_text(input_response.text, encoding="utf-8")
21 | print(f"Successfully wrote input data to {input_file.relative_to(project_root)}")
22 |
23 | if __name__ == "__main__":
24 | main()
25 |
--------------------------------------------------------------------------------
/scripts/new.py:
--------------------------------------------------------------------------------
1 | from argparse import ArgumentParser
2 | from pathlib import Path
3 |
4 | PYTHON_TEMPLATE = """
5 | import re
6 | import sys
7 | from collections import *
8 | from dataclasses import *
9 | from math import *
10 |
11 | def main() -> None:
12 | data = sys.stdin.read().strip()
13 |
14 | if __name__ == "__main__":
15 | main()
16 | """.strip() + "\n"
17 |
18 | def main() -> None:
19 | parser = ArgumentParser(description="Create skeleton files for a day.")
20 | parser.add_argument("day", type=int, help="the day to create files for")
21 |
22 | args = parser.parse_args()
23 |
24 | project_root = Path(__file__).parent.parent
25 |
26 | day_directory = project_root / "src" / f"day{args.day:02}"
27 | if day_directory.is_dir():
28 | raise RuntimeError(f"{day_directory} already exists")
29 |
30 | for file, content in [
31 | (day_directory / "example.txt", ""),
32 | (day_directory / "input.txt", ""),
33 | (day_directory / "part1.py", PYTHON_TEMPLATE),
34 | (day_directory / "part2.py", PYTHON_TEMPLATE)
35 | ]:
36 | file.parent.mkdir(parents=True, exist_ok=True)
37 | with file.open("w+", encoding="utf-8") as f:
38 | f.write(content)
39 |
40 | print(f"Successfully created {file.relative_to(project_root)}")
41 |
42 | if __name__ == "__main__":
43 | main()
44 |
--------------------------------------------------------------------------------
/scripts/readme.py:
--------------------------------------------------------------------------------
1 | import re
2 | from common import get_requests_session
3 | from pathlib import Path
4 |
5 | OVERALL_LEADERBOARD_RANKS = [
6 | 58, # Day 1
7 | 16, # Day 2
8 | 6, # Day 3
9 | 16, # Day 4
10 | 23, # Day 5
11 | 29, # Day 6
12 | 35, # Day 7
13 | 49, # Day 8
14 | 57, # Day 9
15 | 65, # Day 10
16 | 69, # Day 11
17 | 78, # Day 12
18 | 89, # Day 13
19 | 78, # Day 14
20 | 73, # Day 15
21 | 84, # Day 16
22 | 91, # Day 17
23 | 98, # Day 18
24 | 100, # Day 19
25 | None, # Day 20
26 | 98, # Day 21
27 | None, # Day 22
28 | 84, # Day 23
29 | 75, # Day 24
30 | 63, # Day 25
31 | ]
32 |
33 | def main() -> None:
34 | self_leaderboard_response = get_requests_session().get("https://adventofcode.com/2023/leaderboard/self")
35 | self_leaderboard_response.raise_for_status()
36 |
37 | rows = ""
38 | overall_score = 0
39 |
40 | matches = re.search(r" Time Rank Score(.*)", self_leaderboard_response.text, flags=re.DOTALL)
41 | for line in reversed(matches.group(1).splitlines()):
42 | line = line.strip()
43 | if len(line) == 0:
44 | continue
45 |
46 | parts = [part for part in line.split(" ") if len(part) > 0]
47 | day, part1_time, part1_rank, part1_score, part2_time, part2_rank, part2_score = parts
48 |
49 | day = int(parts[0])
50 | part1_time = parts[1]
51 | part1_rank = int(parts[2])
52 | part1_score = int(parts[3])
53 | part2_time = parts[4]
54 | part2_rank = int(parts[5])
55 | part2_score = int(parts[6])
56 |
57 | overall_rank = OVERALL_LEADERBOARD_RANKS[day - 1] or ">100"
58 | overall_score += part1_score + part2_score
59 |
60 | rows += f"""
61 |
62 |
63 | Day {day}
64 | (code)
65 | |
66 | {part1_time} |
67 | {part1_rank} |
68 | {part1_score} |
69 | {part2_time} |
70 | {part2_rank} |
71 | {part2_score} |
72 | {overall_rank} |
73 | {overall_score} |
74 |
"""
75 |
76 | table = f"""
77 |
78 |
79 |
80 |
81 | |
82 | Part 1 |
83 | Part 2 |
84 | Overall leaderboard |
85 |
86 |
87 | |
88 | Time |
89 | Rank |
90 | Score |
91 | Time |
92 | Rank |
93 | Score |
94 | Rank |
95 | Score |
96 |
97 |
98 |
99 | {rows.lstrip()}
100 |
101 |
102 |
103 | """.strip()
104 |
105 | readme_file = Path(__file__).parent.parent / "README.md"
106 | readme_content = readme_file.read_text(encoding="utf-8")
107 |
108 | readme_content = re.sub(r"(.*)", table, readme_content, flags=re.DOTALL)
109 |
110 | readme_file.write_text(readme_content, encoding="utf-8")
111 |
112 | print(f"Successfully updated the results table in the readme")
113 |
114 | if __name__ == "__main__":
115 | main()
116 |
--------------------------------------------------------------------------------
/scripts/runner.py:
--------------------------------------------------------------------------------
1 | import subprocess
2 | import sys
3 | from argparse import ArgumentParser
4 | from pathlib import Path
5 | from watchfiles import Change, watch
6 |
7 | def main() -> None:
8 | parser = ArgumentParser(description="Automatically run part1.py and part2.py on save.")
9 | parser.add_argument("data_file_name", type=str, help="the name of the data file to run on")
10 |
11 | args = parser.parse_args()
12 |
13 | print(f"Started runner for {args.data_file_name}")
14 |
15 | project_root = Path(__file__).parent.parent
16 |
17 | process = None
18 | process_code_file = None
19 | process_data_file_fd = None
20 |
21 | try:
22 | for changes in watch(project_root):
23 | for change, changed_file in changes:
24 | if change != Change.modified:
25 | continue
26 |
27 | changed_file = Path(changed_file)
28 | if not changed_file.is_file():
29 | continue
30 |
31 | if changed_file.name in ["part1.py", "part2.py"]:
32 | code_file = changed_file
33 | elif changed_file.name == args.data_file_name and process_code_file is not None:
34 | code_file = process_code_file
35 | else:
36 | continue
37 |
38 | print(f"Running {code_file.relative_to(project_root)} on {args.data_file_name}")
39 |
40 | if process is not None and process.poll() is None:
41 | print("Killing previous process")
42 | process.kill()
43 | process_data_file_fd.close()
44 |
45 | module_name = str(code_file.relative_to(project_root)).replace("/", ".").replace(".py", "")
46 | data_file = code_file.parent / args.data_file_name
47 | data_file_fd = data_file.open("r")
48 |
49 | print()
50 |
51 | if len(data_file.read_text(encoding="utf-8")) == 0:
52 | print(f"{args.data_file_name} is empty!")
53 |
54 | process = subprocess.Popen([sys.executable, "-m", module_name], cwd=project_root, stdin=data_file_fd)
55 | process_code_file = code_file
56 | process_data_file_fd = data_file_fd
57 | except KeyboardInterrupt:
58 | if process is not None and process.poll() is None:
59 | print("Killing current process")
60 | process.kill()
61 | process_data_file_fd.close()
62 |
63 | sys.exit(1)
64 |
65 | if __name__ == "__main__":
66 | main()
67 |
--------------------------------------------------------------------------------
/src/day01/example.txt:
--------------------------------------------------------------------------------
1 | two1nine
2 | eightwothree
3 | abcone2threexyz
4 | xtwone3four
5 | 4nineeightseven2
6 | zoneight234
7 | 7pqrstsixteen
8 |
--------------------------------------------------------------------------------
/src/day01/part1.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | def main() -> None:
4 | data = sys.stdin.read().strip()
5 |
6 | t = 0
7 | for line in data.split("\n"):
8 | nums = ""
9 |
10 | for ch in line:
11 | if ch.isdigit():
12 | nums += ch
13 | break
14 |
15 | for ch in reversed(line):
16 | if ch.isdigit():
17 | nums += ch
18 | break
19 |
20 | t += int(nums)
21 |
22 | print(t)
23 |
24 | if __name__ == "__main__":
25 | main()
26 |
--------------------------------------------------------------------------------
/src/day01/part2.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | def main() -> None:
4 | data = sys.stdin.read().strip()
5 |
6 | a = {
7 | "one": 1,
8 | "two": 2,
9 | "three": 3,
10 | "four": 4,
11 | "five": 5,
12 | "six": 6,
13 | "seven": 7,
14 | "eight": 8,
15 | "nine": 9
16 | }
17 |
18 | for i in range(1, 10):
19 | a[str(i)] = i
20 |
21 | t = 0
22 | for line in data.split("\n"):
23 | first = None
24 | first_index = len(line) + 1
25 |
26 | last = None
27 | last_index = -1
28 |
29 | for k, v in a.items():
30 | if k not in line:
31 | continue
32 |
33 | x = line.index(k)
34 | y = line.rindex(k)
35 |
36 | if x < first_index:
37 | first = v
38 | first_index = x
39 |
40 | if y > last_index:
41 | last = v
42 | last_index = y
43 |
44 | if first is not None and last is not None:
45 | t += int(str(first) + str(last))
46 |
47 | print(t)
48 |
49 | if __name__ == "__main__":
50 | main()
51 |
--------------------------------------------------------------------------------
/src/day02/example.txt:
--------------------------------------------------------------------------------
1 | Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
2 | Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
3 | Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
4 | Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
5 | Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green
6 |
--------------------------------------------------------------------------------
/src/day02/input.txt:
--------------------------------------------------------------------------------
1 | Game 1: 1 green, 6 red, 4 blue; 2 blue, 6 green, 7 red; 3 red, 4 blue, 6 green; 3 green; 3 blue, 2 green, 1 red
2 | Game 2: 2 blue, 4 red, 7 green; 17 red, 3 blue, 2 green; 3 green, 14 red, 1 blue
3 | Game 3: 12 blue, 3 red, 1 green; 8 blue, 9 red; 1 blue, 1 green, 9 red; 4 blue, 1 green, 9 red
4 | Game 4: 2 red, 10 green, 5 blue; 11 blue, 4 green; 6 green, 7 blue, 2 red; 4 blue, 9 green; 6 green, 1 red, 5 blue
5 | Game 5: 10 green, 5 blue, 5 red; 10 blue, 13 green; 2 red, 12 blue; 9 green, 9 red
6 | Game 6: 2 red, 3 green; 1 blue, 15 red, 2 green; 1 green, 7 red
7 | Game 7: 16 blue, 4 green, 9 red; 6 red, 2 blue, 12 green; 2 red, 5 green, 14 blue; 11 blue, 13 red; 10 blue, 3 red, 17 green; 1 green, 12 blue
8 | Game 8: 14 red, 12 green, 1 blue; 5 blue, 7 green, 12 red; 8 green, 1 red, 8 blue; 8 blue, 2 green, 15 red; 9 blue, 12 red, 10 green; 4 blue, 15 red, 1 green
9 | Game 9: 2 red, 7 green, 5 blue; 1 red, 5 blue, 13 green; 5 blue
10 | Game 10: 4 red, 1 green, 4 blue; 7 green, 8 blue, 4 red; 9 green, 3 red, 8 blue; 5 red, 2 green, 7 blue
11 | Game 11: 4 green, 1 blue, 1 red; 3 green, 3 red, 1 blue; 3 green, 1 red, 1 blue
12 | Game 12: 7 red, 6 green, 12 blue; 6 blue, 8 green, 3 red; 12 green, 5 blue, 4 red; 3 red, 16 blue, 8 green; 12 red, 11 green, 6 blue
13 | Game 13: 2 green, 5 red, 12 blue; 8 green, 12 red, 4 blue; 6 blue, 7 green, 13 red
14 | Game 14: 1 blue, 7 green, 5 red; 1 blue, 8 green, 6 red; 3 green, 1 blue, 4 red
15 | Game 15: 11 red, 8 blue, 1 green; 11 red, 1 green; 3 green, 8 red, 2 blue; 4 blue, 11 red, 1 green; 5 blue, 5 red, 2 green
16 | Game 16: 18 green, 4 blue, 2 red; 5 blue, 11 green, 10 red; 8 red, 2 blue, 14 green; 8 red, 7 blue, 1 green; 3 red, 5 blue, 17 green; 6 blue, 5 green, 11 red
17 | Game 17: 3 blue, 3 red, 7 green; 4 blue, 1 red, 2 green; 5 blue, 3 green, 3 red
18 | Game 18: 2 blue, 2 red, 1 green; 4 blue, 2 red, 7 green; 10 blue, 4 red, 3 green; 5 blue, 3 red, 2 green; 4 green, 3 red, 4 blue; 3 green, 5 red, 5 blue
19 | Game 19: 2 red, 1 green, 1 blue; 8 red, 8 blue, 10 green; 16 green, 5 blue, 2 red; 4 red, 9 green
20 | Game 20: 12 red, 1 blue, 1 green; 4 blue, 2 green, 2 red; 3 blue; 5 red, 8 green; 14 red, 4 blue, 6 green
21 | Game 21: 9 red, 7 green, 1 blue; 5 green, 17 red, 11 blue; 14 red, 7 blue, 10 green; 7 green, 7 red, 10 blue; 6 blue, 6 green, 17 red; 16 red, 13 green, 7 blue
22 | Game 22: 4 blue, 1 red; 1 green, 8 blue; 1 green; 6 blue, 1 red
23 | Game 23: 13 red, 7 blue, 1 green; 4 green, 2 blue, 7 red; 4 green, 10 blue, 12 red
24 | Game 24: 9 green, 10 blue; 2 blue, 4 green, 4 red; 9 green, 1 red, 9 blue; 4 green, 5 red, 12 blue
25 | Game 25: 4 red, 1 green; 10 green, 6 red, 4 blue; 4 red, 1 blue, 7 green; 10 green, 3 red, 7 blue
26 | Game 26: 8 red, 1 green, 2 blue; 5 green, 5 red; 6 green, 19 red; 11 red, 2 blue, 8 green; 13 red, 2 blue, 5 green; 15 red, 2 blue, 10 green
27 | Game 27: 17 blue, 1 green; 2 red, 12 blue, 11 green; 16 green, 16 blue; 18 green, 4 blue; 10 blue, 1 red, 8 green
28 | Game 28: 5 red, 1 green, 1 blue; 3 blue, 8 green, 4 red; 6 green, 2 red, 2 blue
29 | Game 29: 3 green, 12 red, 11 blue; 2 green, 15 red, 8 blue; 13 red, 4 green; 17 red, 9 blue, 5 green
30 | Game 30: 10 green; 4 blue, 1 green; 2 blue, 2 red, 7 green; 5 green, 4 blue, 1 red; 4 red, 10 green, 1 blue
31 | Game 31: 15 blue, 2 red; 17 blue, 2 green; 19 blue, 6 red
32 | Game 32: 1 green, 7 red; 8 red, 1 blue; 5 red, 1 blue, 11 green; 3 blue, 17 red
33 | Game 33: 11 red, 9 green, 1 blue; 3 green, 8 blue; 10 red, 4 green, 8 blue; 6 red, 9 blue, 17 green; 15 green, 10 red, 4 blue; 1 red, 2 blue, 7 green
34 | Game 34: 13 red, 6 green; 6 red, 14 green, 2 blue; 3 red, 19 green; 9 green, 9 red
35 | Game 35: 7 green, 3 red; 12 green, 7 blue; 13 green, 7 red, 6 blue; 3 blue, 12 red
36 | Game 36: 6 blue, 11 green, 14 red; 3 blue, 12 green, 4 red; 18 red, 1 blue; 7 red, 9 green, 6 blue
37 | Game 37: 3 red, 16 blue, 6 green; 2 green, 7 blue; 8 blue, 3 red
38 | Game 38: 16 blue, 3 green, 14 red; 8 red, 15 blue; 17 red, 15 blue, 4 green; 1 green, 11 blue, 17 red; 3 green, 10 blue, 17 red
39 | Game 39: 1 green, 2 red, 5 blue; 12 blue, 12 green; 3 blue, 1 red
40 | Game 40: 1 red, 2 blue, 1 green; 7 green, 1 red, 6 blue; 8 blue, 1 red, 6 green; 12 blue, 1 red, 3 green; 4 green, 8 blue
41 | Game 41: 2 red, 2 blue, 5 green; 5 red, 8 blue; 4 green, 4 blue; 1 red, 11 blue
42 | Game 42: 1 red, 3 green, 13 blue; 13 blue, 7 green; 13 green; 1 red, 3 blue, 4 green; 13 blue, 7 green
43 | Game 43: 3 red, 4 green; 7 red, 11 blue, 3 green; 3 green, 12 red, 7 blue; 9 blue, 5 green
44 | Game 44: 4 blue, 9 red, 2 green; 10 blue, 5 red, 2 green; 9 red, 9 blue, 1 green; 8 blue, 2 green, 14 red; 3 blue, 3 green, 6 red; 4 blue, 3 green, 14 red
45 | Game 45: 1 red, 2 green, 2 blue; 2 green, 1 red; 1 green, 2 blue; 1 green, 1 red, 2 blue; 2 red, 2 blue, 1 green
46 | Game 46: 1 green, 3 red, 3 blue; 6 green, 2 blue, 4 red; 1 green, 3 blue, 1 red; 3 green, 1 blue, 5 red; 6 green; 1 red, 1 green, 2 blue
47 | Game 47: 18 green, 1 red, 7 blue; 6 blue, 19 green, 1 red; 5 blue, 7 green, 1 red; 1 red, 5 blue, 16 green; 15 green, 3 blue
48 | Game 48: 4 green, 8 blue, 8 red; 13 green, 5 red, 12 blue; 9 red, 6 blue, 10 green; 18 green, 3 blue, 4 red; 2 blue, 9 red, 8 green
49 | Game 49: 9 blue, 5 red, 9 green; 5 blue, 11 green, 5 red; 12 green, 6 blue
50 | Game 50: 13 red, 8 green, 3 blue; 2 red, 11 green, 3 blue; 16 red, 7 green; 3 blue, 11 green, 15 red; 10 red, 2 blue, 5 green; 7 green, 2 blue, 4 red
51 | Game 51: 2 red, 1 green, 3 blue; 2 green, 11 red, 17 blue; 2 red, 3 green, 6 blue; 4 red, 3 green, 6 blue; 13 red, 12 blue
52 | Game 52: 1 blue, 5 green; 20 green, 6 blue; 9 blue, 6 green; 11 green, 1 red; 1 green, 1 red, 1 blue
53 | Game 53: 8 red, 6 blue; 6 blue, 6 red, 2 green; 5 blue, 2 green, 3 red; 3 green, 3 blue; 4 green, 5 red, 1 blue
54 | Game 54: 4 blue, 1 red, 3 green; 4 green, 10 blue, 9 red; 7 red, 3 blue, 3 green; 9 green, 9 red, 1 blue; 9 blue, 6 red, 7 green; 6 blue, 7 green, 9 red
55 | Game 55: 15 red, 1 blue, 6 green; 11 blue, 3 red; 9 blue, 3 red, 1 green
56 | Game 56: 8 green, 8 red, 9 blue; 8 red, 8 green, 1 blue; 7 red, 10 green, 4 blue; 10 blue, 2 green, 9 red
57 | Game 57: 10 red, 3 green, 2 blue; 1 red, 4 green; 7 red, 1 green, 3 blue; 12 red, 4 blue; 14 red, 5 green, 4 blue
58 | Game 58: 8 green, 3 blue, 7 red; 7 red, 14 blue, 5 green; 3 green, 7 red; 16 blue, 15 green; 1 red, 10 blue
59 | Game 59: 3 red, 13 green, 2 blue; 10 blue, 3 green, 6 red; 3 green, 2 blue; 7 green, 2 blue, 7 red; 17 green, 6 blue, 15 red
60 | Game 60: 2 blue, 2 red, 6 green; 11 green, 1 blue, 2 red; 1 blue, 9 green; 1 red, 4 green, 2 blue; 1 red, 2 blue, 10 green
61 | Game 61: 3 red, 12 blue, 1 green; 3 red, 1 green, 18 blue; 5 blue, 2 red
62 | Game 62: 4 red, 3 blue, 8 green; 2 blue, 8 red, 9 green; 8 blue, 15 green, 1 red
63 | Game 63: 14 green, 2 red, 1 blue; 7 green, 11 blue, 1 red; 7 blue, 3 red; 4 green, 10 blue, 3 red
64 | Game 64: 8 blue, 18 green, 2 red; 3 red, 17 green; 7 green, 1 red, 12 blue; 15 green, 2 red, 4 blue; 7 green, 8 red, 13 blue
65 | Game 65: 6 blue, 5 green, 2 red; 1 red, 4 green; 5 green, 1 blue; 6 blue, 3 red, 2 green; 4 blue, 5 green
66 | Game 66: 11 red, 9 blue, 4 green; 8 red, 8 blue; 9 red, 7 blue; 1 blue, 12 green, 4 red; 2 red, 11 blue, 10 green
67 | Game 67: 1 red, 4 blue, 1 green; 7 red, 1 blue; 3 green, 4 blue, 6 red; 6 green, 3 blue, 14 red; 11 red, 1 blue, 1 green; 4 green, 8 red
68 | Game 68: 3 red, 1 green, 2 blue; 1 red, 9 blue; 2 red, 1 green
69 | Game 69: 3 green, 2 blue, 2 red; 1 red, 6 green; 13 red, 2 blue, 4 green; 4 blue, 13 red, 6 green; 12 red, 2 blue
70 | Game 70: 15 blue, 2 green, 7 red; 3 red, 14 blue; 6 blue, 1 green; 1 red, 2 green, 4 blue; 2 green, 13 red; 12 blue, 3 red
71 | Game 71: 7 red, 3 blue; 1 red, 4 blue; 2 red, 5 green, 1 blue; 6 blue, 8 red, 1 green; 3 green, 7 blue, 8 red
72 | Game 72: 7 green; 4 green, 2 red, 8 blue; 1 blue, 5 green
73 | Game 73: 5 red, 5 green, 2 blue; 8 red, 1 blue, 8 green; 1 red, 3 blue, 7 green
74 | Game 74: 17 green, 9 blue, 4 red; 20 green, 2 red, 7 blue; 7 blue, 2 green, 4 red; 2 blue, 5 red, 20 green; 1 blue, 1 red, 12 green; 19 green, 9 blue, 3 red
75 | Game 75: 1 red, 8 green, 9 blue; 7 blue, 3 green, 1 red; 2 green, 1 red, 9 blue; 5 blue, 1 red, 8 green; 2 green, 1 red, 11 blue; 5 green, 1 red
76 | Game 76: 3 blue, 16 green, 2 red; 10 green, 3 blue, 1 red; 6 blue, 14 red, 13 green; 7 red, 2 green, 13 blue
77 | Game 77: 7 red, 14 green; 1 blue, 1 red; 4 red, 1 green; 7 green, 11 red
78 | Game 78: 1 red, 19 green; 10 green, 14 red, 1 blue; 3 green, 3 blue, 11 red; 7 blue, 1 green; 15 red, 3 green, 4 blue
79 | Game 79: 7 red, 7 green, 6 blue; 3 red, 7 green, 5 blue; 7 red, 8 green, 12 blue
80 | Game 80: 15 red, 6 blue; 1 red, 5 green, 2 blue; 1 green, 3 blue
81 | Game 81: 3 red, 7 blue, 7 green; 7 green, 2 blue, 4 red; 3 green, 5 blue; 9 blue, 3 red, 6 green; 6 green, 1 red, 3 blue; 8 blue, 2 green, 1 red
82 | Game 82: 5 red, 13 green; 3 blue, 13 green; 6 blue, 4 red, 10 green; 5 red, 1 green, 4 blue; 1 blue, 8 red; 4 red, 5 green
83 | Game 83: 17 red, 1 blue, 2 green; 3 green, 3 red, 2 blue; 1 red, 5 blue, 10 green; 4 blue, 9 red, 11 green
84 | Game 84: 13 green, 14 red, 12 blue; 14 blue, 2 red, 1 green; 4 blue, 8 red
85 | Game 85: 3 red, 1 blue; 6 red, 3 blue, 2 green; 5 green, 3 blue, 3 red; 3 green, 5 blue, 1 red; 1 blue, 12 red, 2 green
86 | Game 86: 16 blue, 17 green, 7 red; 14 blue, 13 green; 18 blue, 8 green
87 | Game 87: 1 blue, 1 red; 4 blue, 1 green, 4 red; 1 green, 16 red; 1 green, 12 red, 1 blue
88 | Game 88: 1 red, 6 green; 3 red, 2 blue, 19 green; 11 green, 2 red; 5 blue, 5 green; 5 blue, 9 green, 1 red; 2 blue, 2 red, 4 green
89 | Game 89: 4 green, 11 red; 8 blue, 14 red; 14 blue, 8 green, 9 red; 14 green, 15 red, 10 blue
90 | Game 90: 8 green, 2 red, 1 blue; 11 green, 4 blue, 2 red; 7 green, 2 blue; 13 green, 1 red
91 | Game 91: 1 blue, 3 green; 1 blue; 4 green, 1 blue, 1 red; 1 blue, 2 red; 1 green, 2 red; 2 red, 5 green, 2 blue
92 | Game 92: 16 red, 4 green, 5 blue; 9 blue, 13 green, 5 red; 13 red, 11 green, 7 blue; 11 red, 8 green, 2 blue
93 | Game 93: 4 blue, 3 red, 3 green; 4 blue, 2 red, 1 green; 1 green, 2 red, 2 blue; 1 green, 2 red, 2 blue; 4 green, 1 blue
94 | Game 94: 8 blue, 11 red, 7 green; 8 red, 6 green; 15 blue, 11 green, 2 red; 9 green, 6 red; 16 blue, 5 red, 7 green
95 | Game 95: 13 blue, 1 red, 10 green; 11 green, 9 blue; 6 blue
96 | Game 96: 1 green, 6 red; 1 red; 12 red, 1 green; 6 red, 1 blue
97 | Game 97: 1 red, 9 blue, 8 green; 2 green, 6 blue, 1 red; 6 green, 1 blue
98 | Game 98: 9 blue, 7 green, 8 red; 6 red, 11 blue, 4 green; 11 green, 9 blue, 15 red; 11 red, 6 blue, 16 green
99 | Game 99: 2 blue, 1 red, 9 green; 8 red, 1 blue, 1 green; 2 red, 7 green, 8 blue; 1 red, 5 green, 7 blue; 7 blue, 10 green, 9 red; 1 green, 1 blue, 1 red
100 | Game 100: 3 blue, 6 red, 9 green; 4 red, 3 green; 4 green, 16 red, 1 blue; 14 blue, 1 green
101 |
--------------------------------------------------------------------------------
/src/day02/part1.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from collections import *
3 |
4 | def main() -> None:
5 | data = sys.stdin.read().strip()
6 |
7 | t = 0
8 | for line in data.split("\n"):
9 | parts = line.split(": ")[1].split("; ")
10 |
11 | possible = True
12 | for part in parts:
13 | d = Counter()
14 | for p in part.split(", "):
15 | amount, color = p.split(" ")
16 | d[color] += int(amount)
17 |
18 | for k, v in d.items():
19 | if k not in ["red", "green", "blue"]:
20 | possible = False
21 | break
22 |
23 | if (k == "red" and v > 12) or (k == "green" and v > 13) or (k == "blue" and v > 14):
24 | possible = False
25 | break
26 |
27 | if possible:
28 | t += int(line.split(": ")[0].split(" ")[1])
29 |
30 | print(t)
31 |
32 | if __name__ == "__main__":
33 | main()
34 |
--------------------------------------------------------------------------------
/src/day02/part2.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from collections import *
3 |
4 | def main() -> None:
5 | data = sys.stdin.read().strip()
6 |
7 | t = 0
8 | for line in data.split("\n"):
9 | parts = line.split(": ")[1].split("; ")
10 |
11 | required = Counter()
12 |
13 | for part in parts:
14 | d = Counter()
15 | for p in part.split(", "):
16 | amount, color = p.split(" ")
17 | d[color] += int(amount)
18 |
19 | for k, v in d.items():
20 | required[k] = max(required[k], v)
21 |
22 | t += required["red"] * required["green"] * required["blue"]
23 |
24 | print(t)
25 |
26 | if __name__ == "__main__":
27 | main()
28 |
--------------------------------------------------------------------------------
/src/day03/example.txt:
--------------------------------------------------------------------------------
1 | 467..114..
2 | ...*......
3 | ..35..633.
4 | ......#...
5 | 617*......
6 | .....+.58.
7 | ..592.....
8 | ......755.
9 | ...$.*....
10 | .664.598..
11 |
--------------------------------------------------------------------------------
/src/day03/part1.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | def get_adjacents(x, y, width, height):
4 | out = []
5 |
6 | for dx in range(-1, 2):
7 | for dy in range(-1, 2):
8 | if dx == 0 and dy == 0:
9 | continue
10 |
11 | nx = x + dx
12 | ny = y + dy
13 |
14 | if nx >= 0 and nx < width and ny >= 0 and ny < height:
15 | out.append((nx, ny))
16 |
17 | return out
18 |
19 | def main() -> None:
20 | data = sys.stdin.read().strip()
21 |
22 | grid = data.split("\n")
23 |
24 | width = len(grid[0])
25 | height = len(grid)
26 |
27 | t = 0
28 | for y in range(height):
29 | x = 0
30 | while x < width:
31 | if not grid[y][x].isdigit():
32 | x += 1
33 | continue
34 |
35 | checks = get_adjacents(x, y, width, height)
36 | num = grid[y][x]
37 |
38 | for i in range(x + 1, width):
39 | if not grid[y][i].isdigit():
40 | break
41 |
42 | num += grid[y][i]
43 | checks.extend(get_adjacents(i, y, width, height))
44 | x += 1
45 |
46 | if any(grid[ny][nx] != "." and not grid[ny][nx].isdigit() for nx, ny in checks):
47 | t += int(num)
48 |
49 | x += 1
50 |
51 | print(t)
52 |
53 | if __name__ == "__main__":
54 | main()
55 |
--------------------------------------------------------------------------------
/src/day03/part2.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from collections import *
3 |
4 | def get_adjacents(x, y, width, height):
5 | out = []
6 |
7 | for dx in range(-1, 2):
8 | for dy in range(-1, 2):
9 | if dx == 0 and dy == 0:
10 | continue
11 |
12 | nx = x + dx
13 | ny = y + dy
14 |
15 | if nx >= 0 and nx < width and ny >= 0 and ny < height:
16 | out.append((nx, ny))
17 |
18 | return out
19 |
20 | def main() -> None:
21 | data = sys.stdin.read().strip()
22 |
23 | grid = data.split("\n")
24 |
25 | width = len(grid[0])
26 | height = len(grid)
27 |
28 | d = defaultdict(list)
29 |
30 | t = 0
31 | for y in range(height):
32 | x = 0
33 | while x < width:
34 | if not grid[y][x].isdigit():
35 | x += 1
36 | continue
37 |
38 | checks = get_adjacents(x, y, width, height)
39 | num = grid[y][x]
40 |
41 | for i in range(x + 1, width):
42 | if not grid[y][i].isdigit():
43 | break
44 |
45 | num += grid[y][i]
46 | checks.extend(get_adjacents(i, y, width, height))
47 | x += 1
48 |
49 | for nx, ny in checks:
50 | if grid[ny][nx] == "*":
51 | d[(nx, ny)].append(int(num))
52 | break
53 |
54 | x += 1
55 |
56 | for nums in d.values():
57 | if len(nums) > 1:
58 | result = 1
59 | for num in nums:
60 | result *= num
61 | t += result
62 |
63 | print(t)
64 |
65 | if __name__ == "__main__":
66 | main()
67 |
--------------------------------------------------------------------------------
/src/day04/example.txt:
--------------------------------------------------------------------------------
1 | Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
2 | Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
3 | Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1
4 | Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
5 | Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
6 | Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11
7 |
--------------------------------------------------------------------------------
/src/day04/part1.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | def main() -> None:
4 | data = sys.stdin.read().strip()
5 |
6 | t = 0
7 | for card in data.split("\n"):
8 | parts = [v for v in card.split(" ") if v != ""]
9 | sep = parts.index("|")
10 |
11 | wins = list(map(int, parts[2:sep]))
12 | have = list(map(int, parts[sep + 1:]))
13 |
14 | score = 0
15 | for v in have:
16 | if v in wins:
17 | if score == 0:
18 | score = 1
19 | else:
20 | score *= 2
21 |
22 | t += score
23 |
24 | print(t)
25 |
26 | if __name__ == "__main__":
27 | main()
28 |
--------------------------------------------------------------------------------
/src/day04/part2.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | def main() -> None:
4 | data = sys.stdin.read().strip()
5 |
6 | t = 0
7 | copies = {i: 1 for i in range(data.count("\n") + 1)}
8 |
9 | for i, card in enumerate(data.split("\n")):
10 | parts = [v for v in card.split(" ") if v != ""]
11 | sep = parts.index("|")
12 |
13 | wins = list(map(int, parts[2:sep]))
14 | have = list(map(int, parts[sep + 1:]))
15 |
16 | score = 0
17 | for v in have:
18 | if v in wins:
19 | score += 1
20 |
21 | for j in range(i + 1, i + score + 1):
22 | copies[j] += copies[i]
23 |
24 | t += copies[i]
25 |
26 | print(t)
27 |
28 | if __name__ == "__main__":
29 | main()
30 |
--------------------------------------------------------------------------------
/src/day05/example.txt:
--------------------------------------------------------------------------------
1 | seeds: 79 14 55 13
2 |
3 | seed-to-soil map:
4 | 50 98 2
5 | 52 50 48
6 |
7 | soil-to-fertilizer map:
8 | 0 15 37
9 | 37 52 2
10 | 39 0 15
11 |
12 | fertilizer-to-water map:
13 | 49 53 8
14 | 0 11 42
15 | 42 0 7
16 | 57 7 4
17 |
18 | water-to-light map:
19 | 88 18 7
20 | 18 25 70
21 |
22 | light-to-temperature map:
23 | 45 77 23
24 | 81 45 19
25 | 68 64 13
26 |
27 | temperature-to-humidity map:
28 | 0 69 1
29 | 1 0 69
30 |
31 | humidity-to-location map:
32 | 60 56 37
33 | 56 93 4
34 |
--------------------------------------------------------------------------------
/src/day05/input.txt:
--------------------------------------------------------------------------------
1 | seeds: 5844012 110899473 1132285750 58870036 986162929 109080640 3089574276 100113624 2693179996 275745330 2090752257 201704169 502075018 396653347 1540050181 277513792 1921754120 26668991 3836386950 66795009
2 |
3 | seed-to-soil map:
4 | 3547471595 1239929038 174680800
5 | 3052451552 758183681 481745357
6 | 0 1427884524 1775655006
7 | 2844087171 549819300 208364381
8 | 3767989253 4004864866 5194940
9 | 3534196909 1414609838 13274686
10 | 1775655006 114264781 435554519
11 | 4148908402 4010059806 146058894
12 | 2729822390 0 114264781
13 | 3773184193 4156118700 138848596
14 | 2211209525 3203539530 518612865
15 | 3912032789 3767989253 236875613
16 |
17 | soil-to-fertilizer map:
18 | 912405184 1056091028 152837752
19 | 194471272 1208928780 200072008
20 | 136115250 240819204 58356022
21 | 3502815281 3536983174 299994001
22 | 2321814552 2458149869 18748048
23 | 3173949445 2623931701 9591555
24 | 394543280 888648379 167442649
25 | 1990258415 3891640206 212931291
26 | 1068754270 54862533 153774684
27 | 1222528954 660792432 186471834
28 | 3340878967 3405750148 131233026
29 | 3472111993 3836977175 30703288
30 | 561985929 299175226 225501956
31 | 2942828492 4104571497 88527954
32 | 874532405 850775600 37872779
33 | 3031356446 3867680463 23959743
34 | 842350418 208637217 32181987
35 | 0 524677182 136115250
36 | 1065242936 847264266 3511334
37 | 2203189706 2339525023 118624846
38 | 1929736108 2563409394 60522307
39 | 3802809282 1847367009 492158014
40 | 1847367009 2790861223 82369099
41 | 2442430445 2873230322 500398047
42 | 3183541000 2633523256 157337967
43 | 3141827666 3373628369 32121779
44 | 787487885 0 54862533
45 | 3055316189 2476897917 86511477
46 | 2340562600 4193099451 101867845
47 |
48 | fertilizer-to-water map:
49 | 798315344 439687669 1930292
50 | 1174979421 2966258900 475289790
51 | 439687669 778614573 55925503
52 | 3743699694 3453541232 155280637
53 | 2989334775 1659556189 96021468
54 | 1650269211 3441548690 11992542
55 | 3898980331 3608821869 395986965
56 | 1705125292 2123762646 842496254
57 | 3375514705 1755577657 368184989
58 | 646363825 441617961 94777173
59 | 1662261753 1616692650 42863539
60 | 495613172 627863920 150750653
61 | 2777061135 1174979421 212273640
62 | 741140998 834540076 57174346
63 | 800245636 536395134 91468786
64 | 2547621546 1387253061 229439589
65 | 3085356243 4004808834 290158462
66 |
67 | water-to-light map:
68 | 541719462 212840988 165903288
69 | 3437755571 1615831015 672632835
70 | 1051033542 2678450187 510773217
71 | 243353905 378744276 104057369
72 | 1561806759 3801474127 134575711
73 | 707622750 677109833 258560892
74 | 2580483557 1051033542 195631857
75 | 0 935670725 30512917
76 | 347411274 482801645 194308188
77 | 30512917 0 127836567
78 | 2190497220 2288463850 389986337
79 | 3068589955 1246665399 369165616
80 | 1754579039 3936049838 66442917
81 | 4110388406 3616895237 184578890
82 | 158349484 127836567 85004421
83 | 2776115414 4002492755 292474541
84 | 1821021956 3247419973 369475264
85 | 1696382470 3189223404 58196569
86 |
87 | light-to-temperature map:
88 | 338228166 2812162941 77503977
89 | 3123877206 693964345 40932068
90 | 3939438903 614787731 633466
91 | 3301169239 2299402886 215156012
92 | 3516325251 499164007 115623724
93 | 3852145506 3365439095 87293397
94 | 875755064 3565078024 729889272
95 | 2849390436 734896413 11914872
96 | 2861305308 215265512 77518872
97 | 4220385528 2056242491 68417151
98 | 2221674563 3167682469 34693717
99 | 2765973467 292784384 83416969
100 | 3198884011 1699097031 22283517
101 | 3164809274 2889666918 34074737
102 | 809366712 746811285 52314986
103 | 4096970661 1633036395 58945085
104 | 3221167528 2699611924 80001711
105 | 697021180 3452732492 112345532
106 | 2059345064 799126271 162329499
107 | 4155915746 629494563 64469782
108 | 2431111524 1721380548 334861943
109 | 684283267 2779613635 12737913
110 | 440342453 2923741655 243940814
111 | 3634265609 961455770 217879897
112 | 4288802679 3202376186 6164617
113 | 415732143 1691981480 4798917
114 | 1605644336 1179335667 453700728
115 | 420531060 2792351548 19811393
116 | 3631948975 1696780397 2316634
117 | 2938824180 2514558898 185053026
118 | 215265512 376201353 122962654
119 | 2256368280 2124659642 174743244
120 | 3940072369 3208540803 156898292
121 | 861681698 615421197 14073366
122 |
123 | temperature-to-humidity map:
124 | 841576398 2731200418 60836938
125 | 1860695540 395011682 292982985
126 | 1518037021 3432774193 53954373
127 | 1786573987 2461900019 55353430
128 | 2940303448 1995108352 6974538
129 | 3014069287 1664464874 53916789
130 | 753139746 2190061656 88436652
131 | 2351822957 2925825589 209990361
132 | 3079884326 3498626816 37609115
133 | 4067060121 4186346579 108620717
134 | 4175680838 4102322798 3778367
135 | 1571991394 2415899186 46000833
136 | 2841627583 1157034722 22534242
137 | 1841927417 2517253449 18768123
138 | 2153678525 47765849 108568164
139 | 3251281674 1179568964 226737882
140 | 3067986076 3486728566 11898250
141 | 1308101633 1785172964 209935388
142 | 2262246689 1406306846 89576268
143 | 902413336 2278498308 137400878
144 | 1039814214 3765380846 268287419
145 | 45422022 156334013 238677669
146 | 3617672799 2612163195 119037223
147 | 2947277986 1718381663 66791301
148 | 1617992227 1495883114 168581760
149 | 284099691 687994667 469040055
150 | 4214721882 4106101165 80245414
151 | 2839283756 45422022 2343827
152 | 3117493441 2792037356 133788233
153 | 2864161825 2536021572 76141623
154 | 4179459205 4067060121 35262677
155 | 3736710022 3135815950 296958243
156 | 3478019556 2002082890 139653243
157 | 2610138841 3536235931 229144915
158 | 2561813318 2141736133 48325523
159 |
160 | humidity-to-location map:
161 | 608325534 0 231346900
162 | 222429954 453776854 385895580
163 | 3710263359 3540956206 563631409
164 | 1193511298 1116937854 38719102
165 | 1702450793 1176729484 153572024
166 | 1694669826 1109156887 7780967
167 | 0 231346900 222429954
168 | 1856022817 1686715664 1854240542
169 | 1588644556 4104587615 106025270
170 | 1109156887 4210612885 84354411
171 | 4273894768 1155656956 21072528
172 | 1232230400 1330301508 356414156
173 |
--------------------------------------------------------------------------------
/src/day05/part1.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from collections import *
3 |
4 | def main() -> None:
5 | data = sys.stdin.read().strip()
6 |
7 | seeds = list(map(int, data.split("\n")[0].split(": ")[1].split(" ")))
8 |
9 | d = defaultdict(dict)
10 | trgs = []
11 |
12 | for sec in data.split("\n\n")[1:]:
13 | lines = sec.split("\n")
14 |
15 | parts = lines[0].split("-")
16 | src = parts[0]
17 | trg = parts[2].split(" ")[0]
18 |
19 | d[src][trg] = []
20 | trgs.append(trg)
21 |
22 | for line in lines[1:]:
23 | trg_start, src_start, length = map(int, line.split(" "))
24 | d[src][trg].append((trg_start, src_start, length))
25 |
26 | min_loc = 1e9
27 | for seed in seeds:
28 | current = "seed"
29 | value = seed
30 |
31 | for trg in trgs:
32 | for trg_start, src_start, length in d[current][trg]:
33 | if src_start <= value < src_start + length:
34 | value = trg_start + (value - src_start)
35 | break
36 |
37 | current = trg
38 |
39 | min_loc = min(min_loc, value)
40 |
41 | print(min_loc)
42 |
43 | if __name__ == "__main__":
44 | main()
45 |
--------------------------------------------------------------------------------
/src/day05/part2.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from dataclasses import *
3 | from multiprocessing import *
4 |
5 | @dataclass
6 | class Range:
7 | start: int
8 | length: int
9 |
10 | def contains(self, value: int) -> bool:
11 | return self.start <= value < self.start + self.length
12 |
13 | def check(loc: int) -> int | None:
14 | global seed_ranges
15 | global maps
16 |
17 | value = loc
18 |
19 | for m in maps:
20 | for trg_range, src_start in m:
21 | if trg_range.contains(value):
22 | value = src_start + (value - trg_range.start)
23 | break
24 |
25 | return loc if any(r.contains(value) for r in seed_ranges) else None
26 |
27 | def main() -> None:
28 | global seed_ranges
29 | global maps
30 |
31 | data = sys.stdin.read().strip()
32 |
33 | raw_seeds = list(map(int, data.split("\n")[0].split(": ")[1].split(" ")))
34 | seed_ranges = []
35 | for i in range(0, len(raw_seeds), 2):
36 | seed_ranges.append(Range(raw_seeds[i], raw_seeds[i + 1]))
37 |
38 | maps = []
39 |
40 | for sec in data.split("\n\n")[1:]:
41 | lines = sec.split("\n")
42 |
43 | m = []
44 | for line in lines[1:]:
45 | trg_start, src_start, length = map(int, line.split(" "))
46 | m.append((Range(trg_start, length), src_start))
47 |
48 | maps.append(m)
49 |
50 | maps = maps[::-1]
51 |
52 | with Pool(15) as pool:
53 | for loc in pool.imap(check, range(int(1e9)), int(1e6)):
54 | if loc is not None:
55 | print(loc)
56 | return
57 |
58 | if __name__ == "__main__":
59 | main()
60 |
--------------------------------------------------------------------------------
/src/day06/example.txt:
--------------------------------------------------------------------------------
1 | Time: 7 15 30
2 | Distance: 9 40 200
3 |
--------------------------------------------------------------------------------
/src/day06/input.txt:
--------------------------------------------------------------------------------
1 | Time: 46 82 84 79
2 | Distance: 347 1522 1406 1471
3 |
--------------------------------------------------------------------------------
/src/day06/part1.py:
--------------------------------------------------------------------------------
1 | import re
2 | import sys
3 |
4 | def main() -> None:
5 | data = sys.stdin.read().strip()
6 |
7 | lines = data.split("\n")
8 | times = list(map(int, re.findall(r"(\d+)", lines[0])))
9 | distances = list(map(int, re.findall(r"(\d+)", lines[1])))
10 |
11 | out = 1
12 |
13 | for t, d in zip(times, distances):
14 | count = 0
15 | for speed in range(1, t):
16 | total = (t - speed) * speed
17 |
18 | if total > d:
19 | count += 1
20 |
21 | out *= count
22 |
23 | print(out)
24 |
25 | if __name__ == "__main__":
26 | main()
27 |
--------------------------------------------------------------------------------
/src/day06/part2.py:
--------------------------------------------------------------------------------
1 | import re
2 | import sys
3 |
4 | def main() -> None:
5 | data = sys.stdin.read().strip()
6 |
7 | lines = data.split("\n")
8 | times = [int("".join(re.findall(r"(\d+)", lines[0])))]
9 | distances = [int("".join(re.findall(r"(\d+)", lines[1])))]
10 |
11 | out = 1
12 |
13 | for t, d in zip(times, distances):
14 | count = 0
15 | for speed in range(1, t):
16 | total = (t - speed) * speed
17 |
18 | if total > d:
19 | count += 1
20 |
21 | out *= count
22 |
23 | print(out)
24 |
25 | if __name__ == "__main__":
26 | main()
27 |
--------------------------------------------------------------------------------
/src/day07/example.txt:
--------------------------------------------------------------------------------
1 | 32T3K 765
2 | T55J5 684
3 | KK677 28
4 | KTJJT 220
5 | QQQJA 483
6 |
--------------------------------------------------------------------------------
/src/day07/input.txt:
--------------------------------------------------------------------------------
1 | 467K3 95
2 | JK5QK 838
3 | 44664 725
4 | 8QAK3 134
5 | 53A3A 945
6 | 7QQJ7 164
7 | J8J89 236
8 | 38QAT 166
9 | Q7944 755
10 | 35333 526
11 | 5J787 482
12 | 4K769 829
13 | 37773 960
14 | QJ78K 282
15 | 3J39Q 326
16 | TJ2QQ 255
17 | J4338 337
18 | QK3KK 187
19 | 5K8KQ 380
20 | 93785 500
21 | 795JT 382
22 | Q399Q 391
23 | 99J99 206
24 | T5555 716
25 | Q7Q8Q 990
26 | QQJJQ 346
27 | 34344 332
28 | K4J44 763
29 | 2A36T 974
30 | 77757 461
31 | 55446 907
32 | 99JJ9 962
33 | K29KQ 177
34 | 99666 961
35 | 688KK 249
36 | 5A558 767
37 | TT6K2 630
38 | 5Q4A4 872
39 | JTKQ4 969
40 | A5AAA 421
41 | JAA4Q 680
42 | 55K69 29
43 | 96ATJ 144
44 | 3Q462 523
45 | 73646 203
46 | 5A96A 550
47 | K84TQ 4
48 | 7278T 406
49 | KQQT5 395
50 | 54567 197
51 | T53TA 355
52 | AQA99 601
53 | 88KQQ 968
54 | 55J5J 727
55 | 73TJ9 466
56 | 99799 843
57 | 324QQ 36
58 | 84AAA 190
59 | 7J366 511
60 | JK938 667
61 | KKQJQ 762
62 | 722J4 110
63 | 9TKT9 84
64 | 33JJ3 458
65 | 6K444 498
66 | 4279T 23
67 | K5T28 467
68 | 3KKKK 871
69 | KQAQK 492
70 | 44AKK 865
71 | 5638T 932
72 | A89AK 24
73 | 29K92 403
74 | A69K6 596
75 | KKK84 400
76 | QA748 616
77 | 55AAA 504
78 | 9255Q 684
79 | 56646 330
80 | 6J6J7 222
81 | A59J5 370
82 | 3AA4J 940
83 | K9K38 302
84 | 2AK58 735
85 | 68K4K 422
86 | 95599 324
87 | 8K88J 987
88 | 845Q5 478
89 | 72KQ7 263
90 | 8TJ83 751
91 | 96TTQ 935
92 | AQ6AQ 445
93 | QKQQA 321
94 | A5644 769
95 | QQ5QJ 801
96 | AA574 436
97 | 333QQ 605
98 | J5982 71
99 | QT8A5 956
100 | 2Q46A 982
101 | J3773 317
102 | 3KK93 485
103 | 3A76A 926
104 | 338JJ 502
105 | 8KAQ6 737
106 | KKK28 520
107 | 644Q5 850
108 | 2T6TT 397
109 | 34JA7 549
110 | 743J7 747
111 | 34843 103
112 | 6KKKK 204
113 | Q2J22 548
114 | JKKKK 995
115 | 42446 704
116 | 8732A 238
117 | TT9J2 109
118 | 4758T 33
119 | TTTT7 914
120 | 787J7 647
121 | 59T59 62
122 | 9Q989 985
123 | T886J 554
124 | 543QJ 75
125 | 77637 857
126 | 8888T 83
127 | 92T52 939
128 | 9832A 620
129 | 3TT39 81
130 | 84353 18
131 | A8Q8A 824
132 | T4597 425
133 | K3635 949
134 | KAAA2 320
135 | 42224 243
136 | AA8A3 565
137 | KK63K 114
138 | TT3TT 133
139 | 33T77 141
140 | J868J 774
141 | 422QT 369
142 | 24T2K 344
143 | KK3Q3 8
144 | 424J2 967
145 | 8J6J6 666
146 | K6927 887
147 | 36666 366
148 | 78KT8 867
149 | AT66T 761
150 | 72AT6 155
151 | 2Q6QQ 440
152 | 64J64 594
153 | A2JT8 578
154 | QQAJQ 383
155 | 8Q333 963
156 | 9A22A 503
157 | K86K6 55
158 | 66899 899
159 | 4744J 210
160 | 72K54 860
161 | KQKK4 723
162 | 6TK62 607
163 | 9J955 652
164 | A45A5 766
165 | 4J333 744
166 | 5K555 277
167 | 7777J 657
168 | 7853A 147
169 | 75QQQ 356
170 | T6T93 818
171 | 8T342 643
172 | 498A7 232
173 | 96A2A 471
174 | J55KK 583
175 | KJ7Q6 849
176 | 36A36 707
177 | 23655 290
178 | K444K 371
179 | 5858K 688
180 | KJK8J 258
181 | Q3699 910
182 | 79T64 864
183 | KAQ44 536
184 | T4TJ5 239
185 | 8KK88 589
186 | 42AA4 127
187 | QQ4Q4 746
188 | J9868 472
189 | 95493 170
190 | JK6T5 428
191 | KAATA 775
192 | TK3KT 886
193 | 36633 858
194 | 67767 590
195 | 86A2Q 175
196 | J7J7J 659
197 | 7J457 796
198 | 55335 65
199 | 9288A 664
200 | 88899 499
201 | 7TKTA 327
202 | 6QJ36 701
203 | K7KQK 943
204 | QQAQ2 681
205 | Q9948 444
206 | 85923 335
207 | 82832 283
208 | TQ5QT 92
209 | TK8A3 191
210 | A957K 614
211 | 8877T 623
212 | 5JTT9 253
213 | 2K626 248
214 | 757Q7 817
215 | JJ6T5 827
216 | KJ796 367
217 | 895AQ 608
218 | AA666 950
219 | TT4T2 135
220 | QQQKK 600
221 | A9KK9 925
222 | 49AA7 972
223 | 73TAT 60
224 | 5K49Q 74
225 | AAJ6A 753
226 | 42222 470
227 | J99KK 722
228 | A9AA9 514
229 | 36636 581
230 | 7T5Q9 690
231 | TTK7K 496
232 | 277J4 665
233 | 782TQ 662
234 | 3AK57 734
235 | 29KJ7 343
236 | 72726 378
237 | 67656 541
238 | 22A29 229
239 | JJ5AA 336
240 | QTTJQ 979
241 | J73K6 473
242 | 55AK9 19
243 | 46466 610
244 | 8AAK4 408
245 | 27227 181
246 | 55525 214
247 | 444Q4 505
248 | 65K55 506
249 | KJ84T 529
250 | 82225 250
251 | 59TKA 32
252 | 83J53 178
253 | 599K4 988
254 | 55TTT 759
255 | 59999 431
256 | T44A4 828
257 | A888T 874
258 | J3533 619
259 | 9979K 981
260 | KK998 101
261 | 64965 799
262 | 9A999 934
263 | 9A299 942
264 | 5KKKA 862
265 | 4A865 802
266 | 64QQ4 837
267 | ATATA 98
268 | 6TJQ7 807
269 | K6997 585
270 | 57T5T 457
271 | JT66T 938
272 | JJQK9 105
273 | JJ278 804
274 | JJ5AQ 661
275 | Q2597 930
276 | AAQAQ 31
277 | 5A974 427
278 | TTQQK 868
279 | 7KT7T 730
280 | K4999 112
281 | A8KAQ 672
282 | 6AQQ6 447
283 | 32J32 297
284 | 4QA2J 915
285 | T2Q3Q 712
286 | 34KQT 121
287 | 98379 617
288 | 487QK 44
289 | 55TAJ 909
290 | 6686T 28
291 | 22922 805
292 | T846A 556
293 | J5A6A 399
294 | 55Q55 347
295 | 8488J 593
296 | JKKTT 708
297 | 8288J 768
298 | JKK66 1
299 | 22999 586
300 | 85398 334
301 | 77KK6 782
302 | K34JJ 674
303 | 39K4K 653
304 | QA6K3 720
305 | 78878 715
306 | QA9Q4 745
307 | 3333J 226
308 | 3TT32 686
309 | 44999 401
310 | A2J32 531
311 | Q65A9 905
312 | J6AA7 194
313 | 8J888 163
314 | 7JT74 624
315 | JKKAK 568
316 | 239J2 919
317 | AA4AA 52
318 | 222JJ 184
319 | 546AQ 894
320 | K2KK9 631
321 | 45TQ2 375
322 | TTTT2 146
323 | 26Q77 989
324 | 9866K 851
325 | T3332 292
326 | 66469 758
327 | 48J48 889
328 | 4A4QA 185
329 | J6626 68
330 | 46T4A 660
331 | 83T52 151
332 | 7T7T7 407
333 | 73758 479
334 | 63A44 291
335 | 66QT6 875
336 | 6645J 738
337 | 94Q97 638
338 | T5KT5 411
339 | TJ3J3 866
340 | QT6TQ 842
341 | A448A 433
342 | 556JJ 533
343 | T3TKT 161
344 | 6JT43 265
345 | T5TTT 393
346 | K7KK4 386
347 | 53J6A 845
348 | K7777 756
349 | 63399 685
350 | J85AQ 87
351 | 88585 906
352 | QJTQQ 270
353 | TKKTK 131
354 | 3J3JQ 797
355 | K7Q34 836
356 | K4499 362
357 | 53555 651
358 | 9888T 435
359 | 2J299 557
360 | 8J999 964
361 | 96TQ2 293
362 | 8KTJ8 137
363 | KA6Q7 442
364 | 2J6KQ 900
365 | 446A4 294
366 | AJAA3 671
367 | Q427T 116
368 | 9JQ99 398
369 | 59929 392
370 | 822J8 192
371 | Q92Q7 420
372 | KKJK6 171
373 | TAJ37 487
374 | 8A2J5 10
375 | 22TTT 220
376 | 33623 111
377 | 7Q7AJ 491
378 | A3JJ2 650
379 | J4J23 299
380 | 396KA 896
381 | K3K3J 486
382 | QKKKK 20
383 | 9A2AJ 713
384 | 746K4 56
385 | 96996 885
386 | JTK77 312
387 | Q8888 826
388 | 3T4AJ 771
389 | 97977 219
390 | 9354K 788
391 | 5Q5KK 455
392 | T3734 325
393 | TK26A 156
394 | 7AAAA 924
395 | KJ622 183
396 | 5QTAQ 642
397 | AAAAQ 488
398 | TTTJT 953
399 | Q2222 145
400 | 4A9TJ 245
401 | TT3JK 588
402 | J5555 284
403 | 94AQT 193
404 | 97325 196
405 | 74A8J 37
406 | 24AAA 847
407 | 22A32 381
408 | 4KJ59 542
409 | T6QK4 673
410 | 77877 922
411 | Q2Q66 49
412 | 66688 792
413 | 9T9T9 918
414 | J8878 552
415 | 6A63A 221
416 | AA559 780
417 | 9T47Q 300
418 | AKKA4 501
419 | 33QQ4 64
420 | 6K375 965
421 | T7Q43 82
422 | 3689Q 569
423 | A6A3A 462
424 | T5Q3J 689
425 | 49Q99 895
426 | KA262 490
427 | 87497 13
428 | 4449A 973
429 | 92453 430
430 | 5QA5A 149
431 | 69666 247
432 | K6AJA 992
433 | A4444 729
434 | 44494 298
435 | J5993 927
436 | 26662 555
437 | 4J6A5 613
438 | KK77K 855
439 | 73222 315
440 | 2A2J2 719
441 | K7KT7 43
442 | 98T64 998
443 | 23282 528
444 | 449T7 130
445 | 6QK24 424
446 | AAAA3 179
447 | JA42K 53
448 | 6A6KK 211
449 | J55JJ 742
450 | J5T93 304
451 | TQA23 358
452 | 8J257 240
453 | 39393 522
454 | 68A38 450
455 | QQAK8 970
456 | J77QT 341
457 | T68AA 242
458 | 99933 310
459 | 425KA 69
460 | 99A9J 535
461 | J35JK 113
462 | 4A37T 360
463 | 63333 791
464 | 78J5T 34
465 | 46T46 883
466 | T8JQ3 50
467 | KKKK5 519
468 | T29J8 640
469 | KKK88 646
470 | 3A32A 228
471 | 7A77T 57
472 | 2QQ2J 971
473 | 7Q777 438
474 | 5J545 21
475 | T4AAJ 432
476 | QQJAA 570
477 | KJ79J 853
478 | T3JKA 359
479 | 676K6 724
480 | 4TATT 931
481 | JKKT2 629
482 | J338T 469
483 | 9939J 743
484 | 85A93 241
485 | 945TA 363
486 | 5JK5A 493
487 | Q5JT5 815
488 | 76378 12
489 | T3T53 157
490 | JAA24 732
491 | 55757 200
492 | K727J 115
493 | 259KK 510
494 | 2J739 786
495 | 288AA 598
496 | QJ233 100
497 | QQ56Q 25
498 | 6333J 702
499 | 86797 839
500 | 47T77 361
501 | K4823 3
502 | 6K446 54
503 | 94J75 543
504 | QQQQA 980
505 | 55J66 923
506 | AQT55 645
507 | 55593 314
508 | J6776 379
509 | J23T6 102
510 | 7K7K7 911
511 | JQ5A3 227
512 | KK66K 279
513 | AJJAQ 396
514 | JA252 39
515 | 555KK 714
516 | KJ56K 637
517 | KJ64K 928
518 | 6Q66Q 85
519 | TJTT2 273
520 | K634J 854
521 | 66662 576
522 | 6Q6J6 212
523 | KAAT2 696
524 | 76663 793
525 | T3AQ3 632
526 | 2J994 966
527 | TTTJA 63
528 | 4QJQ4 165
529 | AAAJ8 331
530 | TT666 158
531 | 2KKA2 453
532 | 54444 563
533 | 7KK88 675
534 | 47777 832
535 | 6JJQ9 475
536 | 55275 876
537 | 63489 794
538 | 7K7Q3 208
539 | 6J585 820
540 | 3Q89T 524
541 | 92AK2 6
542 | 66JK9 655
543 | 7J4KQ 139
544 | 666A5 711
545 | 4JTK9 117
546 | 88AJA 368
547 | 34T5T 602
548 | 9933J 278
549 | 97Q63 448
550 | A5555 892
551 | QJ7A2 726
552 | 5KKJ2 917
553 | A5238 108
554 | 33343 663
555 | K33T3 285
556 | 6Q655 937
557 | 38383 880
558 | 47834 252
559 | QJA49 692
560 | A6926 547
561 | 48Q8Q 288
562 | 72J86 107
563 | 5T5T9 449
564 | 2JK25 305
565 | 667T6 136
566 | 7JJ88 429
567 | Q5KQK 394
568 | ATAAA 952
569 | 66949 296
570 | TT222 933
571 | AQ4AK 948
572 | KQJJ7 209
573 | 3465K 709
574 | 74775 126
575 | 8TJ6T 402
576 | 82Q3J 816
577 | Q7855 354
578 | JJ3KK 9
579 | 22223 351
580 | 2K7TA 831
581 | 555AA 984
582 | 83539 168
583 | 444T4 140
584 | 4A8Q4 693
585 | JA8AK 890
586 | 29QTQ 308
587 | KJKKJ 389
588 | A86AK 649
589 | J898T 14
590 | A6AAA 352
591 | 2J222 176
592 | A4669 958
593 | 333K8 635
594 | T4269 844
595 | J4Q54 603
596 | 44AAA 349
597 | QT575 413
598 | AA2J2 859
599 | 7T395 648
600 | K3Q68 251
601 | 7T2T2 790
602 | QQQ33 446
603 | 428A4 879
604 | 36J2Q 434
605 | 69955 991
606 | 7J5A4 812
607 | QQ445 789
608 | 7A69A 93
609 | 4K979 537
610 | K6K73 518
611 | 45555 79
612 | 45A6A 833
613 | KAAA5 307
614 | 48887 80
615 | KK2KK 38
616 | ATJJ5 11
617 | 5K325 388
618 | 42TJA 353
619 | 66J3T 611
620 | A758A 728
621 | TJT77 644
622 | 5JQQ2 898
623 | 9KQT2 404
624 | K42A2 303
625 | Q6QTA 124
626 | 58Q5J 670
627 | K6JTJ 409
628 | T3333 731
629 | J73JK 463
630 | 4A288 452
631 | 79AAJ 41
632 | 2K7T7 15
633 | 7AAA7 888
634 | 44J94 286
635 | 8938K 328
636 | TKKKA 633
637 | 22JT7 577
638 | QQQQ7 683
639 | 66665 89
640 | T72J4 955
641 | J66J6 877
642 | 99433 509
643 | 9K92J 776
644 | JQ7Q2 78
645 | A6T2Q 122
646 | 69Q6A 153
647 | J5JQ5 218
648 | 25KAJ 416
649 | 7A47A 513
650 | 62T26 1000
651 | 96449 281
652 | KKTKK 977
653 | 35642 921
654 | 9K4K9 778
655 | J4244 993
656 | JJAAA 573
657 | 7AA27 626
658 | A685T 376
659 | 4JA9A 957
660 | T886T 267
661 | 737J7 538
662 | 999KK 579
663 | 75KK7 76
664 | Q737Q 809
665 | Q3393 901
666 | 2734Q 754
667 | J2T9K 216
668 | 89859 695
669 | 63343 35
670 | 7JK7K 700
671 | 8828A 765
672 | 29AT5 615
673 | Q838Q 410
674 | A3235 622
675 | TKJKQ 810
676 | 45454 224
677 | 77737 869
678 | JA9T9 333
679 | 2772K 276
680 | 5535A 350
681 | TT5QT 821
682 | 46JKJ 986
683 | 9T8KK 125
684 | 6JAJ7 595
685 | 74647 464
686 | 499A4 612
687 | 4KT7A 22
688 | J3233 891
689 | 44555 959
690 | 8KQ8A 271
691 | 33443 182
692 | 37373 27
693 | 88828 997
694 | Q2Q22 189
695 | 3635A 373
696 | T66TT 717
697 | A4469 207
698 | 2T2KT 749
699 | 4244Q 90
700 | 9234T 348
701 | 33TJ3 289
702 | QAA63 562
703 | 2A2A2 199
704 | J6JK7 929
705 | TT99J 234
706 | T3JQ2 798
707 | 65Q66 154
708 | JTTJT 975
709 | 22699 705
710 | Q6Q6Q 618
711 | 99929 811
712 | 389J6 920
713 | 585Q5 852
714 | A2255 477
715 | TJTJJ 30
716 | K5AK5 772
717 | 2QQ3Q 323
718 | 6888J 454
719 | 7J8K3 609
720 | J463J 572
721 | 32323 223
722 | 686J6 534
723 | Q25J4 47
724 | 29996 882
725 | TTQ8Q 944
726 | 42265 480
727 | 2JQ96 287
728 | QQ868 517
729 | AK447 994
730 | 8J3Q3 897
731 | 42QK5 489
732 | A8A88 384
733 | 3AT3A 941
734 | 44T8T 88
735 | QQ8QQ 787
736 | 488TJ 996
737 | 6KK66 313
738 | 2J262 764
739 | K6KK5 275
740 | K572T 893
741 | 7T7QQ 215
742 | 76965 773
743 | 59575 800
744 | 586QJ 309
745 | QQQQ4 721
746 | 9A9A4 40
747 | 8JJJJ 128
748 | QATA6 162
749 | K6TAQ 415
750 | 95JJ8 72
751 | 9TQ97 319
752 | 2AK22 61
753 | T2TJ2 465
754 | T5274 195
755 | Q4587 266
756 | J97QT 441
757 | 52384 17
758 | Q7J77 414
759 | QQQ6Q 903
760 | 4444J 532
761 | QQKQQ 904
762 | QJ467 16
763 | 25525 785
764 | ATA8A 205
765 | 65542 261
766 | 9QKKK 512
767 | 48844 231
768 | JTJAK 99
769 | QJ8AT 571
770 | 68A88 878
771 | 5353J 94
772 | 2Q33Q 311
773 | KJJ69 946
774 | J83A8 634
775 | QQT6Q 884
776 | KK74J 374
777 | 77474 781
778 | 38888 527
779 | 29457 329
780 | 52452 73
781 | 2K776 256
782 | QJQQQ 268
783 | J24K6 913
784 | 42K88 861
785 | 29QQQ 733
786 | 4J546 806
787 | K2K98 841
788 | Q4644 697
789 | 44K94 834
790 | QAAQT 830
791 | J666T 750
792 | 3T335 437
793 | 9594T 694
794 | 8QQQ3 682
795 | 88887 269
796 | J3KKQ 641
797 | 99993 551
798 | 2K437 699
799 | 75775 710
800 | 5963J 870
801 | TTKT5 582
802 | 2Q82A 439
803 | KJ4Q9 301
804 | Q3558 152
805 | 32333 999
806 | T77TT 599
807 | 3T6JT 627
808 | 2J3T5 560
809 | 25442 86
810 | 8888K 257
811 | 5QJ45 96
812 | QQ7AA 658
813 | 88JJ8 863
814 | 98948 202
815 | 2QJ3J 803
816 | J6488 66
817 | 59559 160
818 | JJKK7 484
819 | 7J223 254
820 | 68889 364
821 | 555J9 822
822 | KKAAA 525
823 | K7557 5
824 | 3Q33A 814
825 | 2384J 587
826 | KK8Q2 777
827 | 494K2 426
828 | 2TJ22 507
829 | QQQ2Q 698
830 | 7229T 954
831 | JJ757 142
832 | 2882A 530
833 | KKTQT 539
834 | 72222 621
835 | 99A5A 736
836 | 22887 936
837 | 3377Q 779
838 | 6A6J6 740
839 | A7AAJ 840
840 | 44JJ4 2
841 | QQTQT 51
842 | 6666A 669
843 | T9279 908
844 | K9J7Q 856
845 | 2AAAJ 748
846 | J3K25 947
847 | TT65T 377
848 | KK2K6 752
849 | K7KKK 150
850 | 9J6J8 120
851 | 72AK6 656
852 | TT6TT 757
853 | QQ9TT 412
854 | 3AA3J 365
855 | 84477 783
856 | KK4K2 591
857 | AK79J 654
858 | J77J7 951
859 | Q7664 606
860 | 7QQ59 59
861 | J2725 795
862 | 96989 417
863 | 7TT64 387
864 | 47JJK 91
865 | 228AA 201
866 | AJJ63 902
867 | A5AKJ 123
868 | 37Q33 741
869 | 8J358 483
870 | Q88QQ 508
871 | 43A33 340
872 | Q9QQQ 516
873 | 232JT 148
874 | 666J6 159
875 | 38363 97
876 | 42285 322
877 | 4Q944 233
878 | TT4TT 342
879 | K8TQA 566
880 | KJKK2 213
881 | QJQJJ 339
882 | 5K932 559
883 | 86888 494
884 | 2QQJQ 70
885 | 7A772 167
886 | 5659T 881
887 | T43A6 186
888 | A2Q22 739
889 | 55K95 679
890 | 2T5QQ 262
891 | 47797 419
892 | 52522 357
893 | 2J734 597
894 | AA3Q3 678
895 | 3Q9A3 567
896 | KJAAJ 813
897 | K8794 495
898 | 7JT77 198
899 | 4KT2A 564
900 | 55QQ5 497
901 | 5K558 272
902 | T2A25 318
903 | K58Q2 825
904 | 7KKJK 628
905 | 6A6A7 676
906 | J7T96 706
907 | A4A96 625
908 | 6KTQ7 372
909 | JAAJ3 916
910 | 99699 106
911 | Q7Q77 468
912 | 8Q88J 545
913 | 2A2J8 983
914 | 777A7 246
915 | 329TA 546
916 | 38388 48
917 | KKKQQ 316
918 | KKKK8 460
919 | 33K8Q 77
920 | A9A29 691
921 | 8J859 237
922 | A9599 540
923 | 23J67 390
924 | JT43J 668
925 | 8J8JQ 338
926 | JQQQ8 456
927 | K9KKK 129
928 | 8KJ8K 67
929 | 7555Q 169
930 | 9QJQ9 459
931 | 7A8Q9 718
932 | 7J765 760
933 | 94744 173
934 | AA35A 264
935 | QKQQ5 423
936 | A6JJ9 819
937 | 4AA44 848
938 | 88385 180
939 | A4T7Q 259
940 | 7J757 584
941 | A96T3 474
942 | JJJJJ 42
943 | 9K372 604
944 | J333Q 118
945 | J7A37 451
946 | Q4447 515
947 | QQ77Q 274
948 | 73333 553
949 | 6747J 521
950 | J56K2 405
951 | KKJJQ 575
952 | QT86A 592
953 | 75A73 476
954 | 29925 295
955 | A778A 823
956 | AAAAJ 580
957 | TT99T 636
958 | QQ3JQ 235
959 | A8778 244
960 | K6638 784
961 | 87Q5A 574
962 | 99499 46
963 | AK7Q7 172
964 | KKK33 443
965 | 38J88 345
966 | 7976K 58
967 | 59669 558
968 | 6659J 217
969 | 7557J 143
970 | 5549K 306
971 | J3982 639
972 | J249A 677
973 | 55955 418
974 | QQQQT 7
975 | 77A47 770
976 | 66K4K 104
977 | Q9T5A 976
978 | 2673Q 230
979 | Q75TK 26
980 | JKJ9K 225
981 | 9TAAT 188
982 | 55JQA 119
983 | 9Q9Q9 385
984 | 24K42 260
985 | T9222 873
986 | 99989 45
987 | 88448 544
988 | T9784 808
989 | 43454 846
990 | TA674 174
991 | 3T3AT 687
992 | 38929 561
993 | 22QQK 912
994 | KQJQQ 978
995 | 23223 481
996 | J7772 835
997 | 3999Q 703
998 | 74K44 280
999 | 4K444 138
1000 | KJ53K 132
1001 |
--------------------------------------------------------------------------------
/src/day07/part1.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from collections import *
3 |
4 | def get_score(item: tuple[str, int]) -> tuple[int, list[int]]:
5 | hand, bid = item
6 |
7 | counts = list(Counter(hand).values())
8 | if 5 in counts:
9 | type = 10
10 | elif 4 in counts:
11 | type = 9
12 | elif 3 in counts:
13 | type = 8 if 2 in counts else 7
14 | elif 2 in counts:
15 | type = 6 if counts.count(2) == 2 else 5
16 | else:
17 | type = 4
18 |
19 | values = list(map("23456789TJQKA".index, hand))
20 |
21 | return (type, values)
22 |
23 | def main() -> None:
24 | data = sys.stdin.read().strip()
25 |
26 | hands = []
27 | for line in data.split("\n"):
28 | hand, bid = line.split(" ")
29 | hands.append((hand, int(bid)))
30 |
31 | hands = sorted(hands, key=get_score)
32 |
33 | t = 0
34 | for i, (hand, bid) in enumerate(hands):
35 | t += bid * (i + 1)
36 |
37 | print(t)
38 |
39 | if __name__ == "__main__":
40 | main()
41 |
--------------------------------------------------------------------------------
/src/day07/part2.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from collections import *
3 |
4 | def get_score(item: tuple[str, int]) -> tuple[int, list[int]]:
5 | hand, bid = item
6 |
7 | counts = sorted(list(Counter(hand.replace("J", "")).values()))
8 |
9 | if len(counts) > 0:
10 | counts[-1] += hand.count("J")
11 | else:
12 | counts.append(5)
13 |
14 | if 5 in counts:
15 | type = 10
16 | elif 4 in counts:
17 | type = 9
18 | elif 3 in counts:
19 | type = 8 if 2 in counts else 7
20 | elif 2 in counts:
21 | type = 6 if counts.count(2) == 2 else 5
22 | else:
23 | type = 4
24 |
25 | values = list(map("J23456789TQKA".index, hand))
26 |
27 | return (type, values)
28 |
29 | def main() -> None:
30 | data = sys.stdin.read().strip()
31 |
32 | hands = []
33 | for line in data.split("\n"):
34 | hand, bid = line.split(" ")
35 | hands.append((hand, int(bid)))
36 |
37 | hands = sorted(hands, key=get_score)
38 |
39 | t = 0
40 | for i, (hand, bid) in enumerate(hands):
41 | t += bid * (i + 1)
42 |
43 | print(t)
44 |
45 | if __name__ == "__main__":
46 | main()
47 |
--------------------------------------------------------------------------------
/src/day08/example.txt:
--------------------------------------------------------------------------------
1 | LR
2 |
3 | 11A = (11B, XXX)
4 | 11B = (XXX, 11Z)
5 | 11Z = (11B, XXX)
6 | 22A = (22B, XXX)
7 | 22B = (22C, 22C)
8 | 22C = (22Z, 22Z)
9 | 22Z = (22B, 22B)
10 | XXX = (XXX, XXX)
11 |
--------------------------------------------------------------------------------
/src/day08/input.txt:
--------------------------------------------------------------------------------
1 | LRLRRLRLRRRLRRRLRRLRLLRLRLRRRLRLRRLLRRLLRRRLLRRRLRRRLRRLLRLRRRLRRLRLRLLRRLLRRRLLRLRRRLRRRLLRLRRRLLRLLRRLRLRRRLLRLRLLRRRLLRLRRRLLLRRRLLLRRLLLRRRLLRLRLRLRRLLRRRLRRLRRRLRRLRRRLRLRRLRLRRRLRLRRRLRRLRRRLRLLLRLRRRLRLLRLRRLRRRLRRLRLRLRLRRLRRLLRLLLRLRLRRRLRRRLLRLLRLRRLRRRLRRLRRRLRLRRRR
2 |
3 | JKT = (KFV, CFQ)
4 | SQQ = (RLK, TRV)
5 | CVT = (KRT, NCV)
6 | JVS = (GXT, QMF)
7 | KPF = (GCH, FCH)
8 | XTQ = (GFM, FSP)
9 | QBJ = (PXR, FMK)
10 | KXQ = (FMK, PXR)
11 | LTM = (CML, TMP)
12 | CMD = (DFJ, GXS)
13 | VJK = (KGN, HBX)
14 | QTP = (KBP, CNM)
15 | MBT = (GTN, QXG)
16 | HGQ = (PFJ, FXL)
17 | MDV = (CVJ, PMR)
18 | KJQ = (TQF, HTS)
19 | CBB = (XRL, XSP)
20 | AAA = (QXT, CDL)
21 | RPS = (FXF, MQL)
22 | BPH = (VBF, FBJ)
23 | RQM = (GVB, RKD)
24 | KNQ = (MPV, DLX)
25 | XSS = (LBB, SVD)
26 | VXB = (MGQ, GCD)
27 | XBR = (JCG, LTM)
28 | HGR = (MFL, GGF)
29 | SJA = (KJB, VFS)
30 | CBL = (JFX, BBF)
31 | KXN = (XCL, VVG)
32 | FKV = (HGQ, TVS)
33 | HBS = (SSP, HPN)
34 | PTG = (GJC, TCN)
35 | DJG = (CSP, XCC)
36 | CNM = (JFS, FXR)
37 | KGD = (MXP, GFC)
38 | PMR = (SXV, RSK)
39 | RPR = (QLD, SBT)
40 | NFK = (DTC, NTR)
41 | JKH = (HSF, RXX)
42 | TXG = (VNS, PVQ)
43 | TRS = (MSQ, BRT)
44 | MLF = (PLL, LMX)
45 | CDD = (SHR, FKT)
46 | CQM = (KSF, FPN)
47 | KSL = (XPD, NMG)
48 | LBB = (TBB, RVJ)
49 | DQJ = (TNP, JLT)
50 | KLC = (KGC, BNK)
51 | CSL = (CVC, MVR)
52 | NCG = (JVS, JTD)
53 | JQL = (CBL, KCH)
54 | FBF = (FKV, DLC)
55 | JHM = (HMD, HCH)
56 | DGP = (BGB, JGR)
57 | SSH = (PHG, MVV)
58 | CSG = (QTP, TPG)
59 | KSF = (FPV, DKV)
60 | DJS = (PCC, RDN)
61 | XLB = (LKT, NCQ)
62 | XDS = (LNG, SLS)
63 | MFT = (KJT, LSH)
64 | STD = (PSS, JQH)
65 | LGM = (JMD, FLJ)
66 | GPR = (KGQ, FFB)
67 | KJT = (XRK, JPP)
68 | FQN = (KNQ, PNH)
69 | CRR = (KSR, DPR)
70 | RRD = (NCG, KKD)
71 | FLJ = (LNL, QPR)
72 | MQL = (SKC, BFB)
73 | FST = (XHS, QDN)
74 | DRT = (MQL, FXF)
75 | RDN = (HQB, HSD)
76 | SQH = (HTS, TQF)
77 | VBN = (BRD, TXB)
78 | CXV = (VMM, TXG)
79 | MSQ = (XSJ, BRG)
80 | PLL = (QSM, PCS)
81 | NTD = (PLN, GKV)
82 | GHP = (NCQ, LKT)
83 | CXG = (XGV, VVT)
84 | CPZ = (MVB, MKR)
85 | GSQ = (FXV, PPG)
86 | BCG = (LMQ, JMM)
87 | FMK = (RQD, QJG)
88 | CJQ = (BFV, XDS)
89 | DLC = (HGQ, TVS)
90 | LML = (JFC, DNN)
91 | XTC = (TDD, VPV)
92 | QHP = (SKP, CTC)
93 | TBB = (QBJ, KXQ)
94 | GPG = (VNX, DPZ)
95 | SSS = (CFM, HQK)
96 | DFJ = (MBV, RPX)
97 | DLX = (RGT, VSJ)
98 | KLL = (JKG, TPV)
99 | NKT = (GDK, LDD)
100 | GCH = (MLF, BFM)
101 | PPG = (BFJ, DCR)
102 | KHF = (HGD, MNX)
103 | SLK = (BXX, KBV)
104 | TDL = (FLP, DLB)
105 | GCS = (VPL, JVR)
106 | FPN = (DKV, FPV)
107 | NKL = (RCL, KQH)
108 | NHS = (FDJ, DXC)
109 | DHN = (RCK, KVD)
110 | QJG = (GPV, XQK)
111 | DKD = (MFB, PTB)
112 | FDJ = (HHQ, BJS)
113 | TPX = (GGF, MFL)
114 | JKG = (HBB, HLJ)
115 | BFV = (LNG, SLS)
116 | XTL = (LCS, XNT)
117 | NRM = (GNX, GKS)
118 | XSJ = (JCT, CDD)
119 | JXR = (CBL, KCH)
120 | TRV = (QDC, HNH)
121 | GXS = (MBV, RPX)
122 | HPN = (HVF, XRJ)
123 | SSD = (FST, NBJ)
124 | KGQ = (DMM, GKG)
125 | DDC = (XTQ, KVK)
126 | XHL = (MKR, MVB)
127 | HXD = (CGG, CGG)
128 | DSH = (BVJ, BJM)
129 | ZZZ = (CDL, QXT)
130 | LQL = (FVD, KLR)
131 | BNK = (VVN, BNP)
132 | PLD = (GJV, HDP)
133 | JCG = (TMP, CML)
134 | VTK = (KQN, JHS)
135 | MNX = (TTP, SVH)
136 | VTC = (DKN, HXM)
137 | JPP = (GPB, QHQ)
138 | HQK = (GGP, FMV)
139 | QDC = (MBB, FGH)
140 | QRD = (JML, VGV)
141 | SXV = (HGL, NGL)
142 | BRJ = (FKV, DLC)
143 | DCF = (PGX, VJK)
144 | BGF = (BQX, PMT)
145 | JML = (FXD, KTT)
146 | GFC = (JBN, KVS)
147 | FBB = (JQN, NQV)
148 | SKC = (CSG, RQJ)
149 | SLX = (NHS, JCS)
150 | QDN = (KHF, VXD)
151 | MBV = (DSC, RPD)
152 | DMM = (MVD, NHX)
153 | QMF = (CVM, HDJ)
154 | JCT = (SHR, FKT)
155 | RKL = (HNF, DKC)
156 | SMV = (RDK, RDK)
157 | TNP = (BHL, XNQ)
158 | XNQ = (JQL, JXR)
159 | GGF = (GDD, XTM)
160 | RQD = (XQK, GPV)
161 | LSJ = (BBC, PJS)
162 | KCR = (VCL, JVJ)
163 | KCH = (JFX, BBF)
164 | QRT = (BTX, KFQ)
165 | JCS = (FDJ, DXC)
166 | GVB = (PXL, NDD)
167 | BMC = (VNV, FSM)
168 | PCS = (QQT, NXG)
169 | BKQ = (QXV, DHP)
170 | GTN = (DTS, DXQ)
171 | KBV = (NBK, GSQ)
172 | GKS = (QLJ, DSH)
173 | MPG = (RMJ, DSM)
174 | GBB = (KQH, RCL)
175 | SGT = (CGG, MLZ)
176 | TCP = (JCG, LTM)
177 | RPD = (GNF, VFG)
178 | PCB = (GMV, MCN)
179 | GVX = (MRF, GXC)
180 | XGF = (KCR, CDF)
181 | PXS = (DLQ, DBS)
182 | GDK = (JKB, MJF)
183 | BPR = (TKH, DKD)
184 | PXL = (XTL, JPJ)
185 | CSP = (NRR, XDK)
186 | RSK = (NGL, HGL)
187 | BTX = (QBF, VPJ)
188 | XPD = (QRD, FQG)
189 | MJQ = (KQN, JHS)
190 | BLC = (TDD, VPV)
191 | TTP = (PTG, CQX)
192 | XSG = (GNV, DMT)
193 | NBJ = (QDN, XHS)
194 | KFQ = (VPJ, QBF)
195 | KNN = (XHL, CPZ)
196 | JVK = (XPJ, NRC)
197 | NRV = (MRD, VVM)
198 | DGC = (MRN, RKL)
199 | VMM = (VNS, PVQ)
200 | HFK = (QHX, MNT)
201 | SCQ = (VKL, XGR)
202 | BXA = (MKR, MVB)
203 | RDK = (LJP, GVX)
204 | KXM = (RCF, CQR)
205 | CMQ = (DJS, DHQ)
206 | VNS = (DDF, SSS)
207 | HJC = (CPM, CJM)
208 | VNX = (VPC, LVQ)
209 | DSM = (BSJ, GCS)
210 | TTT = (FBJ, VBF)
211 | LDN = (CVJ, PMR)
212 | JTD = (QMF, GXT)
213 | XSP = (BPR, SHS)
214 | QXT = (LVG, PLD)
215 | VFS = (XSS, CTN)
216 | TFK = (FLP, DLB)
217 | KLR = (FSQ, BNJ)
218 | GDG = (QQJ, HBN)
219 | QJK = (SHX, MCT)
220 | LKT = (TCJ, XLP)
221 | CMH = (VBB, GPG)
222 | JDV = (BQX, BQX)
223 | VPV = (SFH, BJD)
224 | GFM = (KXM, CPG)
225 | BDX = (LQX, QXJ)
226 | HGL = (VTS, QCT)
227 | GRN = (KJB, VFS)
228 | HNF = (HBC, NFK)
229 | VMN = (CJM, CPM)
230 | GPV = (JQQ, JVH)
231 | BCV = (RQM, FVV)
232 | SSG = (JKH, XMT)
233 | KBP = (FXR, JFS)
234 | VVT = (XVP, LSF)
235 | BPS = (BMK, JFK)
236 | BXJ = (DJG, JRH)
237 | VSS = (NBM, NLM)
238 | PMH = (FLJ, JMD)
239 | BSJ = (JVR, VPL)
240 | GPS = (BKR, TGN)
241 | BKM = (SLX, JCD)
242 | LMM = (GTB, CMD)
243 | KKP = (MJQ, VTK)
244 | NTG = (HXD, HXD)
245 | DHP = (DCD, BKM)
246 | XGP = (DBJ, PKP)
247 | GGP = (SCQ, QFS)
248 | NXR = (DSK, XGP)
249 | XNH = (BHP, SVB)
250 | HLN = (XSP, XRL)
251 | KJH = (SSH, QQC)
252 | QSM = (NXG, QQT)
253 | JHS = (PQH, CVR)
254 | RLK = (HNH, QDC)
255 | KGC = (VVN, BNP)
256 | BPK = (JFC, DNN)
257 | KJB = (CTN, XSS)
258 | VCL = (MPG, XCX)
259 | PKR = (NCG, KKD)
260 | NMG = (QRD, FQG)
261 | JVH = (HDK, NPX)
262 | NBM = (STN, PXS)
263 | MLX = (PNK, BCV)
264 | LVG = (HDP, GJV)
265 | DVN = (PTP, XGF)
266 | XDK = (SQS, VMQ)
267 | CVR = (GBB, NKL)
268 | SKV = (HMD, HCH)
269 | QTA = (HTQ, CLV)
270 | TPG = (KBP, CNM)
271 | VPL = (XVC, JCX)
272 | BKR = (BPS, PJD)
273 | NSP = (NBJ, FST)
274 | HBC = (NTR, DTC)
275 | TRB = (PLN, GKV)
276 | HDK = (KDG, FBC)
277 | CFM = (FMV, GGP)
278 | RPX = (RPD, DSC)
279 | HMD = (HVM, KKP)
280 | SXX = (SHX, MCT)
281 | QJV = (GRN, FPZ)
282 | DKC = (NFK, HBC)
283 | XCL = (MLD, CHG)
284 | XRJ = (LMV, QTK)
285 | HVM = (VTK, MJQ)
286 | VFG = (VTC, PVX)
287 | LQX = (NTG, NTG)
288 | KQD = (GCD, MGQ)
289 | PJD = (BMK, JFK)
290 | FKT = (JDN, CMH)
291 | BHL = (JXR, JQL)
292 | NLM = (PXS, STN)
293 | KDG = (XLB, GHP)
294 | NQV = (GDV, NKS)
295 | QDQ = (SJL, KGD)
296 | DTC = (QNG, PPK)
297 | QHQ = (KDJ, JPF)
298 | BBF = (THF, JVF)
299 | QQJ = (KJH, QDK)
300 | JFC = (GLL, TXF)
301 | KNX = (CVC, MVR)
302 | VBF = (TJM, GQJ)
303 | QQC = (MVV, PHG)
304 | FXF = (BFB, SKC)
305 | FPZ = (VFS, KJB)
306 | PNH = (DLX, MPV)
307 | TXB = (KCQ, QHP)
308 | TRL = (KSH, XJT)
309 | DKV = (MHK, JLV)
310 | MKR = (DRT, RPS)
311 | FPV = (MHK, JLV)
312 | SLV = (MNV, NTC)
313 | SRB = (GDN, CJQ)
314 | BMK = (BBT, TVP)
315 | NQK = (LQL, GCM)
316 | CDF = (VCL, JVJ)
317 | BBH = (SDD, GJR)
318 | DLB = (QDQ, FHL)
319 | XVC = (DXV, NXR)
320 | KFC = (RQK, TJJ)
321 | HDP = (MNM, HHJ)
322 | QDK = (QQC, SSH)
323 | JFS = (QHH, DVN)
324 | FXR = (QHH, DVN)
325 | TGN = (PJD, BPS)
326 | FFB = (DMM, GKG)
327 | DBK = (CJQ, GDN)
328 | RQK = (CXV, FHP)
329 | QTK = (PSM, RPR)
330 | JFX = (THF, JVF)
331 | HCA = (LJP, GVX)
332 | VVN = (CQM, JDK)
333 | CSH = (MBT, RHJ)
334 | HGC = (HXD, SGT)
335 | HNH = (MBB, FGH)
336 | QXJ = (NTG, HGC)
337 | PQH = (GBB, NKL)
338 | SVB = (KJQ, SQH)
339 | PPS = (BVL, KNN)
340 | MVD = (FSK, LSJ)
341 | CGG = (HTQ, CLV)
342 | KSH = (SMV, SMV)
343 | GNF = (VTC, PVX)
344 | QXV = (DCD, BKM)
345 | SPG = (NGG, MFT)
346 | XGR = (XTC, BLC)
347 | DPZ = (LVQ, VPC)
348 | JQN = (NKS, GDV)
349 | QQT = (NGP, CVV)
350 | TQF = (KXN, MKK)
351 | NHX = (FSK, LSJ)
352 | XLT = (GDK, LDD)
353 | KXC = (HJC, VMN)
354 | SVD = (TBB, RVJ)
355 | DXV = (DSK, XGP)
356 | TDD = (BJD, SFH)
357 | LMV = (PSM, RPR)
358 | BBT = (LGT, LGT)
359 | XLP = (FLX, RDG)
360 | DDF = (HQK, CFM)
361 | FSM = (BXJ, LXL)
362 | KHH = (SVL, RSF)
363 | SHR = (JDN, JDN)
364 | GLV = (MDV, LDN)
365 | MFB = (BSD, PGS)
366 | HGD = (TTP, SVH)
367 | KDJ = (NRV, FDM)
368 | DNN = (TXF, GLL)
369 | MFL = (XTM, GDD)
370 | VRB = (JPD, DPH)
371 | DLQ = (TNG, VBN)
372 | PPK = (BPK, LML)
373 | TPV = (HBB, HLJ)
374 | GMV = (QVH, KLC)
375 | VBB = (VNX, VNX)
376 | VVH = (QQJ, HBN)
377 | KTT = (BKS, XNH)
378 | JQH = (QRT, LGC)
379 | GNX = (QLJ, DSH)
380 | DTS = (FBF, BRJ)
381 | FTN = (DDC, NKN)
382 | JRH = (XCC, CSP)
383 | FFC = (NMG, XPD)
384 | HLK = (PRR, TRL)
385 | KRT = (LXC, NRM)
386 | JLT = (XNQ, BHL)
387 | HDJ = (KFN, CSH)
388 | DCN = (LQX, QXJ)
389 | MKK = (VVG, XCL)
390 | FXL = (SPG, XPN)
391 | TXF = (NSP, SSD)
392 | JKN = (FFB, KGQ)
393 | BJD = (GLV, XKH)
394 | XGL = (GPR, JKN)
395 | BJM = (DGP, BPN)
396 | JCB = (DPH, JPD)
397 | MLS = (DPF, XRH)
398 | JCX = (DXV, NXR)
399 | QLJ = (BVJ, BJM)
400 | LJD = (CRR, QCX)
401 | LCS = (JVK, GMN)
402 | HLD = (XGL, LLR)
403 | DSN = (GRN, GRN)
404 | JLV = (HLN, CBB)
405 | PMT = (DSN, QJV)
406 | HVF = (QTK, LMV)
407 | MNV = (KRD, BMC)
408 | LNS = (SLK, KTF)
409 | KKD = (JTD, JVS)
410 | QXG = (DTS, DXQ)
411 | QVH = (KGC, BNK)
412 | PLJ = (TSK, ZZZ)
413 | MRN = (HNF, DKC)
414 | JMM = (JDX, GVG)
415 | MHK = (CBB, HLN)
416 | THF = (LMT, DGC)
417 | TKH = (MFB, PTB)
418 | FCH = (BFM, MLF)
419 | HSF = (PHT, DSP)
420 | MNT = (DFS, KHH)
421 | GNR = (BKR, TGN)
422 | MNM = (FTC, FTN)
423 | BGB = (SXX, QJK)
424 | NGG = (KJT, LSH)
425 | HBN = (QDK, KJH)
426 | TVX = (PMH, LGM)
427 | GDV = (XNJ, BDQ)
428 | TJJ = (FHP, CXV)
429 | QCK = (JXV, NMT)
430 | XTK = (PKR, RRD)
431 | HHQ = (DBK, SRB)
432 | CPG = (CQR, RCF)
433 | XNJ = (LTK, KLL)
434 | LMQ = (JDX, GVG)
435 | DPR = (BQR, QFG)
436 | GXC = (BRR, CXG)
437 | CQR = (KNX, CSL)
438 | GJV = (MNM, HHJ)
439 | HTS = (KXN, MKK)
440 | RSF = (SSG, NNG)
441 | HCH = (HVM, KKP)
442 | RCL = (SQQ, VBL)
443 | NGL = (QCT, VTS)
444 | MCT = (GBN, DCF)
445 | QFS = (VKL, XGR)
446 | BNP = (CQM, JDK)
447 | BPN = (JGR, BGB)
448 | BRG = (JCT, CDD)
449 | PHN = (GNR, GPS)
450 | XBX = (TVX, FMG)
451 | PJS = (XCQ, PPS)
452 | SNF = (NTC, MNV)
453 | CLV = (TCP, XBR)
454 | CVJ = (RSK, SXV)
455 | NRC = (VRB, JCB)
456 | BFM = (PLL, LMX)
457 | GKG = (MVD, NHX)
458 | JPF = (FDM, NRV)
459 | GTB = (DFJ, GXS)
460 | DMT = (BKQ, GGM)
461 | DPH = (BCG, GFJ)
462 | MVB = (DRT, RPS)
463 | HTQ = (TCP, XBR)
464 | MJF = (XTK, GCB)
465 | GRG = (NLM, NBM)
466 | VKL = (BLC, XTC)
467 | NCV = (LXC, NRM)
468 | KTF = (KBV, BXX)
469 | KRD = (FSM, VNV)
470 | DBJ = (NQK, VSB)
471 | XCC = (NRR, XDK)
472 | XRK = (QHQ, GPB)
473 | PVR = (GDG, VVH)
474 | BSD = (GRG, VSS)
475 | PTP = (CDF, KCR)
476 | FDM = (VVM, MRD)
477 | BFB = (RQJ, CSG)
478 | PVX = (HXM, DKN)
479 | PHG = (DQJ, QVP)
480 | GMN = (XPJ, NRC)
481 | QPR = (JKT, QBG)
482 | CQX = (GJC, TCN)
483 | VTS = (HBS, LKG)
484 | BRT = (XSJ, BRG)
485 | LKG = (SSP, HPN)
486 | KVS = (BVN, TRS)
487 | NBK = (FXV, PPG)
488 | XGV = (XVP, LSF)
489 | SKP = (JHM, SKV)
490 | MPV = (VSJ, RGT)
491 | PNR = (XGL, LLR)
492 | BDQ = (KLL, LTK)
493 | JFK = (BBT, TVP)
494 | PCC = (HQB, HSD)
495 | TNL = (CMD, GTB)
496 | JMD = (QPR, LNL)
497 | FMV = (SCQ, QFS)
498 | LMX = (PCS, QSM)
499 | DXC = (BJS, HHQ)
500 | PXR = (QJG, RQD)
501 | FVV = (GVB, RKD)
502 | TSK = (QXT, CDL)
503 | QLD = (TPX, HGR)
504 | VPB = (JDV, BGF)
505 | GDN = (BFV, XDS)
506 | MLZ = (CLV, HTQ)
507 | XNM = (BCV, PNK)
508 | GXT = (CVM, HDJ)
509 | DPF = (XSG, RBT)
510 | DQQ = (GPC, KPF)
511 | BBC = (XCQ, XCQ)
512 | NXG = (NGP, CVV)
513 | RDG = (NKT, XLT)
514 | HHJ = (FTN, FTC)
515 | FTC = (DDC, NKN)
516 | RCK = (LBN, QCK)
517 | MGQ = (VMB, VPB)
518 | LGC = (BTX, KFQ)
519 | VHQ = (DMX, LJD)
520 | JKB = (XTK, GCB)
521 | DCR = (PVR, MGL)
522 | MRF = (CXG, BRR)
523 | XRL = (BPR, SHS)
524 | LBN = (JXV, NMT)
525 | MVV = (DQJ, QVP)
526 | HPH = (DHQ, DJS)
527 | FSP = (KXM, CPG)
528 | GPB = (KDJ, JPF)
529 | VGV = (KTT, FXD)
530 | MCN = (KLC, QVH)
531 | BNJ = (HMV, CVT)
532 | PKG = (RQK, TJJ)
533 | CCR = (PRR, TRL)
534 | NCQ = (TCJ, XLP)
535 | CHG = (PHN, XCG)
536 | HLJ = (CCR, HLK)
537 | VSJ = (LNS, LKP)
538 | SQS = (DCN, BDX)
539 | KFN = (MBT, RHJ)
540 | LGT = (JJQ, JJQ)
541 | MJM = (RDK, MTZ)
542 | LXL = (DJG, JRH)
543 | TMP = (PNX, PCB)
544 | KVD = (LBN, QCK)
545 | RQJ = (TPG, QTP)
546 | XTM = (RPK, FBB)
547 | LNG = (HPH, CMQ)
548 | PKP = (NQK, VSB)
549 | KGN = (LMM, TNL)
550 | QBG = (CFQ, KFV)
551 | NPX = (FBC, KDG)
552 | LXC = (GKS, GNX)
553 | LDD = (JKB, MJF)
554 | QCT = (HBS, LKG)
555 | KQN = (CVR, PQH)
556 | JVJ = (MPG, XCX)
557 | PLN = (PXP, DQQ)
558 | QNG = (LML, BPK)
559 | JGR = (QJK, SXX)
560 | HBX = (TNL, LMM)
561 | JJQ = (TSK, TSK)
562 | XJT = (SMV, MJM)
563 | BQX = (DSN, DSN)
564 | RVJ = (KXQ, QBJ)
565 | PHT = (XXV, DHN)
566 | BFJ = (PVR, MGL)
567 | BHP = (SQH, KJQ)
568 | TJM = (TXM, HFK)
569 | NMT = (HLD, PNR)
570 | DHQ = (PCC, RDN)
571 | PGS = (GRG, VSS)
572 | DSP = (XXV, DHN)
573 | MRD = (VXB, KQD)
574 | LKP = (KTF, SLK)
575 | FSQ = (CVT, HMV)
576 | VVG = (MLD, CHG)
577 | NGP = (NCD, PTT)
578 | NTC = (KRD, BMC)
579 | FHL = (SJL, KGD)
580 | BHV = (JJQ, PLJ)
581 | LJP = (MRF, GXC)
582 | SBT = (HGR, TPX)
583 | SVH = (CQX, PTG)
584 | MVX = (NVV, BBH)
585 | XCG = (GPS, GNR)
586 | RTC = (NVV, BBH)
587 | RGT = (LKP, LNS)
588 | HMV = (KRT, NCV)
589 | KCQ = (SKP, CTC)
590 | FVD = (FSQ, BNJ)
591 | QFG = (DMR, MLS)
592 | SHX = (DCF, GBN)
593 | DMR = (DPF, XRH)
594 | VMB = (JDV, BGF)
595 | TNG = (BRD, TXB)
596 | JDK = (FPN, KSF)
597 | GCB = (RRD, PKR)
598 | XCQ = (BVL, BVL)
599 | DBS = (TNG, VBN)
600 | FXD = (BKS, XNH)
601 | GQJ = (TXM, HFK)
602 | NVV = (GJR, SDD)
603 | MBB = (SNF, SLV)
604 | RMJ = (BSJ, GCS)
605 | JCD = (NHS, JCS)
606 | GBN = (VJK, PGX)
607 | VMQ = (DCN, BDX)
608 | HXM = (BPH, TTT)
609 | CDL = (LVG, PLD)
610 | DCD = (SLX, JCD)
611 | GNV = (GGM, BKQ)
612 | TCN = (KSL, FFC)
613 | SSP = (XRJ, HVF)
614 | PNX = (GMV, MCN)
615 | XCX = (DSM, RMJ)
616 | DMX = (CRR, QCX)
617 | GJC = (KSL, FFC)
618 | RKD = (PXL, NDD)
619 | FLP = (FHL, QDQ)
620 | PTT = (XMF, STD)
621 | TXM = (QHX, MNT)
622 | JVF = (DGC, LMT)
623 | NNG = (XMT, JKH)
624 | NKN = (KVK, XTQ)
625 | SLS = (CMQ, HPH)
626 | MGL = (GDG, VVH)
627 | VPC = (TKR, QNF)
628 | XMT = (RXX, HSF)
629 | QCX = (KSR, DPR)
630 | FBC = (XLB, GHP)
631 | CPM = (RTC, MVX)
632 | FGH = (SNF, SLV)
633 | SJL = (GFC, MXP)
634 | KVK = (FSP, GFM)
635 | VXD = (MNX, HGD)
636 | NDD = (XTL, JPJ)
637 | GJR = (NTD, TRB)
638 | LSH = (XRK, JPP)
639 | JQQ = (HDK, NPX)
640 | THS = (DMX, LJD)
641 | FSK = (BBC, PJS)
642 | PVQ = (DDF, SSS)
643 | RCF = (KNX, CSL)
644 | LMT = (MRN, RKL)
645 | HQB = (XNM, MLX)
646 | QHX = (KHH, DFS)
647 | GDD = (RPK, FBB)
648 | LLR = (JKN, GPR)
649 | XNT = (JVK, GMN)
650 | JBN = (BVN, TRS)
651 | MXP = (KVS, JBN)
652 | FXV = (DCR, BFJ)
653 | XQK = (JQQ, JVH)
654 | TVP = (LGT, BHV)
655 | GGM = (DHP, QXV)
656 | BKS = (BHP, SVB)
657 | DXQ = (FBF, BRJ)
658 | RXX = (DSP, PHT)
659 | GLL = (NSP, SSD)
660 | CTN = (SVD, LBB)
661 | NFX = (PNH, KNQ)
662 | DKN = (BPH, TTT)
663 | GFJ = (LMQ, JMM)
664 | XVP = (KXC, VPD)
665 | NCD = (XMF, STD)
666 | LVQ = (TKR, QNF)
667 | SDD = (TRB, NTD)
668 | VSB = (LQL, GCM)
669 | XMF = (JQH, PSS)
670 | HSD = (XNM, MLX)
671 | LDA = (VPC, LVQ)
672 | RBT = (DMT, GNV)
673 | NRR = (VMQ, SQS)
674 | LTK = (TPV, JKG)
675 | VBL = (RLK, TRV)
676 | GKV = (PXP, DQQ)
677 | JDN = (VBB, VBB)
678 | CML = (PCB, PNX)
679 | LNL = (QBG, JKT)
680 | SFH = (GLV, XKH)
681 | DFS = (RSF, SVL)
682 | FBJ = (GQJ, TJM)
683 | VPD = (HJC, VMN)
684 | STN = (DLQ, DBS)
685 | CVM = (CSH, KFN)
686 | MVR = (NFX, FQN)
687 | KFV = (TDL, TFK)
688 | JQV = (FMG, TVX)
689 | XPN = (MFT, NGG)
690 | TKR = (THS, VHQ)
691 | VPJ = (KFC, PKG)
692 | PTB = (BSD, PGS)
693 | PGX = (KGN, HBX)
694 | XRH = (RBT, XSG)
695 | QHH = (PTP, XGF)
696 | BJS = (DBK, SRB)
697 | KQH = (SQQ, VBL)
698 | LSF = (VPD, KXC)
699 | GVG = (JQV, XBX)
700 | BXX = (NBK, GSQ)
701 | JDX = (JQV, XBX)
702 | VNV = (BXJ, LXL)
703 | SVL = (NNG, SSG)
704 | MLD = (XCG, PHN)
705 | QNF = (THS, VHQ)
706 | PRR = (KSH, KSH)
707 | CFQ = (TDL, TFK)
708 | JVR = (JCX, XVC)
709 | CVV = (PTT, NCD)
710 | CJM = (RTC, MVX)
711 | XKH = (LDN, MDV)
712 | XHS = (KHF, VXD)
713 | MTZ = (GVX, LJP)
714 | BVJ = (DGP, BPN)
715 | VVM = (KQD, VXB)
716 | NTR = (PPK, QNG)
717 | FMG = (LGM, PMH)
718 | GPC = (GCH, FCH)
719 | RHJ = (GTN, QXG)
720 | JPD = (GFJ, BCG)
721 | PNK = (FVV, RQM)
722 | PFJ = (XPN, SPG)
723 | DSC = (VFG, GNF)
724 | PSM = (QLD, SBT)
725 | GCM = (FVD, KLR)
726 | CTC = (SKV, JHM)
727 | GCD = (VMB, VPB)
728 | TVS = (FXL, PFJ)
729 | BVN = (BRT, MSQ)
730 | FLX = (NKT, XLT)
731 | PXP = (KPF, GPC)
732 | QVP = (TNP, JLT)
733 | JXV = (HLD, PNR)
734 | SHS = (DKD, TKH)
735 | FHP = (TXG, VMM)
736 | BRR = (XGV, VVT)
737 | RPK = (JQN, NQV)
738 | NKS = (XNJ, BDQ)
739 | CVC = (NFX, FQN)
740 | PSS = (LGC, QRT)
741 | KSR = (BQR, QFG)
742 | FQG = (VGV, JML)
743 | QBF = (KFC, PKG)
744 | BVL = (XHL, XHL)
745 | JPJ = (LCS, XNT)
746 | TCJ = (FLX, RDG)
747 | BRD = (QHP, KCQ)
748 | XXV = (KVD, RCK)
749 | XPJ = (JCB, VRB)
750 | DSK = (DBJ, PKP)
751 | BQR = (MLS, DMR)
752 | HBB = (CCR, HLK)
753 |
--------------------------------------------------------------------------------
/src/day08/part1.py:
--------------------------------------------------------------------------------
1 | import re
2 | import sys
3 | from math import *
4 |
5 | def main() -> None:
6 | data = sys.stdin.read().strip()
7 |
8 | instrs = data.split("\n")[0]
9 | nodes = {}
10 |
11 | for node in data.split("\n\n")[1].split("\n"):
12 | src, left, right = re.findall(r"([A-Z]{3})", node)
13 | nodes[src] = (left, right)
14 |
15 | current = "AAA"
16 | idx = 0
17 |
18 | t = 0
19 | while current != "ZZZ":
20 | move = instrs[idx]
21 | idx = (idx + 1) % len(instrs)
22 | current = nodes[current][0 if move == "L" else 1]
23 | t += 1
24 |
25 | print(t)
26 |
27 | if __name__ == "__main__":
28 | main()
29 |
--------------------------------------------------------------------------------
/src/day08/part2.py:
--------------------------------------------------------------------------------
1 | import re
2 | import sys
3 | from math import *
4 |
5 | def main() -> None:
6 | data = sys.stdin.read().strip()
7 |
8 | instrs = data.split("\n")[0]
9 | nodes = {}
10 |
11 | current = []
12 |
13 | for node in data.split("\n\n")[1].split("\n"):
14 | src, left, right = re.findall(r"([A-Z0-9]{3})", node)
15 | nodes[src] = (left, right)
16 |
17 | if src[2] == "A":
18 | current.append(src)
19 |
20 | lens = []
21 | for v in current:
22 | node = v
23 | idx = 0
24 |
25 | t = 0
26 | while node[2] != "Z":
27 | move = instrs[idx]
28 | idx = (idx + 1) % len(instrs)
29 | node = nodes[node][0 if move == "L" else 1]
30 | t += 1
31 |
32 | lens.append(t)
33 |
34 | print(lcm(*lens))
35 |
36 | if __name__ == "__main__":
37 | main()
38 |
--------------------------------------------------------------------------------
/src/day09/example.txt:
--------------------------------------------------------------------------------
1 | 0 3 6 9 12 15
2 | 1 3 6 10 15 21
3 | 10 13 16 21 30 45
4 |
--------------------------------------------------------------------------------
/src/day09/part1.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | def main() -> None:
4 | data = sys.stdin.read().strip()
5 |
6 | t = 0
7 | for line in data.split("\n"):
8 | nums = list(map(int, line.split(" ")))
9 |
10 | rows = [nums]
11 | while rows[-1].count(0) != len(rows[-1]):
12 | new_row = []
13 |
14 | for i in range(len(rows[-1]) - 1):
15 | new_row.append(rows[-1][i + 1] - rows[-1][i])
16 |
17 | rows.append(new_row)
18 |
19 | rows[-1].append(0)
20 | for i in range(len(rows) - 2, -1, -1):
21 | rows[i].append(rows[i][-1] + rows[i + 1][-1])
22 |
23 | t += rows[0][-1]
24 |
25 | print(t)
26 |
27 | if __name__ == "__main__":
28 | main()
29 |
--------------------------------------------------------------------------------
/src/day09/part2.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | def main() -> None:
4 | data = sys.stdin.read().strip()
5 |
6 | t = 0
7 | for line in data.split("\n"):
8 | nums = list(map(int, line.split(" ")))
9 |
10 | rows = [nums]
11 | while rows[-1].count(0) != len(rows[-1]):
12 | new_row = []
13 |
14 | for i in range(len(rows[-1]) - 1):
15 | new_row.append(rows[-1][i + 1] - rows[-1][i])
16 |
17 | rows.append(new_row)
18 |
19 | rows[-1].insert(0, 0)
20 | for i in range(len(rows) - 2, -1, -1):
21 | rows[i].insert(0, rows[i][0] - rows[i + 1][0])
22 |
23 | t += rows[0][0]
24 |
25 | print(t)
26 |
27 | if __name__ == "__main__":
28 | main()
29 |
--------------------------------------------------------------------------------
/src/day10/example.txt:
--------------------------------------------------------------------------------
1 | FF7FSF7F7F7F7F7F---7
2 | L|LJ||||||||||||F--J
3 | FL-7LJLJ||||||LJL-77
4 | F--JF--7||LJLJ7F7FJ-
5 | L---JF-JLJ.||-FJLJJ7
6 | |F|F-JF---7F7-L7L|7|
7 | |FFJF7L7F-JF7|JL---7
8 | 7-L-JL7||F7|L7F-7F7|
9 | L.L7LFJ|||||FJL7||LJ
10 | L7JLJL-JLJLJL--JLJ.L
11 |
--------------------------------------------------------------------------------
/src/day10/part1.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from collections import *
3 |
4 | def main() -> None:
5 | data = sys.stdin.read().strip()
6 |
7 | neighbors = defaultdict(list)
8 |
9 | grid = data.split("\n")
10 |
11 | width = len(grid[0])
12 | height = len(grid)
13 |
14 | source = None
15 |
16 | for y in range(height):
17 | for x in range(width):
18 | coord = (x, y)
19 |
20 | if grid[y][x] == "S":
21 | source = coord
22 | elif grid[y][x] == "|":
23 | neighbors[coord].extend([(x, y - 1), (x, y + 1)])
24 | elif grid[y][x] == "-":
25 | neighbors[coord].extend([(x - 1, y), (x + 1, y)])
26 | elif grid[y][x] == "L":
27 | neighbors[coord].extend([(x, y - 1), (x + 1, y)])
28 | elif grid[y][x] == "J":
29 | neighbors[coord].extend([(x, y - 1), (x - 1, y)])
30 | elif grid[y][x] == "7":
31 | neighbors[coord].extend([(x, y + 1), (x - 1, y)])
32 | elif grid[y][x] == "F":
33 | neighbors[coord].extend([(x, y + 1), (x + 1, y)])
34 |
35 | for coord in list(neighbors.keys()):
36 | if source in neighbors[coord]:
37 | neighbors[source].append(coord)
38 |
39 | visited = set()
40 | q = deque()
41 | q.append((source, 0))
42 | max_distance = 0
43 |
44 | while len(q) > 0:
45 | node, distance = q.popleft()
46 |
47 | if node in visited:
48 | continue
49 |
50 | visited.add(node)
51 |
52 | x, y = node
53 | if x < 0 or x >= width or y < 0 or y >= height:
54 | continue
55 |
56 | max_distance = max(max_distance, distance)
57 |
58 | for neighbor in neighbors[node]:
59 | q.append((neighbor, distance + 1))
60 |
61 | print(max_distance)
62 |
63 | if __name__ == "__main__":
64 | main()
65 |
--------------------------------------------------------------------------------
/src/day10/part2.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from collections import *
3 | from multiprocessing import *
4 | from shapely.geometry import *
5 | from shapely.geometry.polygon import *
6 |
7 | def main() -> None:
8 | data = sys.stdin.read().strip()
9 |
10 | neighbors = defaultdict(list)
11 |
12 | grid = data.split("\n")
13 |
14 | width = len(grid[0])
15 | height = len(grid)
16 |
17 | source = None
18 |
19 | for y in range(height):
20 | for x in range(width):
21 | coord = (x, y)
22 |
23 | if grid[y][x] == "S":
24 | source = coord
25 | elif grid[y][x] == "|":
26 | neighbors[coord].extend([(x, y - 1), (x, y + 1)])
27 | elif grid[y][x] == "-":
28 | neighbors[coord].extend([(x - 1, y), (x + 1, y)])
29 | elif grid[y][x] == "L":
30 | neighbors[coord].extend([(x, y - 1), (x + 1, y)])
31 | elif grid[y][x] == "J":
32 | neighbors[coord].extend([(x, y - 1), (x - 1, y)])
33 | elif grid[y][x] == "7":
34 | neighbors[coord].extend([(x, y + 1), (x - 1, y)])
35 | elif grid[y][x] == "F":
36 | neighbors[coord].extend([(x, y + 1), (x + 1, y)])
37 |
38 | for coord in list(neighbors.keys()):
39 | if source in neighbors[coord]:
40 | neighbors[source].append(coord)
41 |
42 | visited = set()
43 | q = deque()
44 | q.append((source, 0))
45 | max_distance = 0
46 |
47 | while len(q) > 0:
48 | node, distance = q.popleft()
49 |
50 | if node in visited:
51 | continue
52 |
53 | x, y = node
54 | if x < 0 or x >= width or y < 0 or y >= height:
55 | continue
56 |
57 | visited.add(node)
58 |
59 | max_distance = max(max_distance, distance)
60 |
61 | for neighbor in neighbors[node]:
62 | q.append((neighbor, distance + 1))
63 |
64 | loop = [source, neighbors[source][0]]
65 | while len(loop) < len(visited):
66 | node = loop[-1]
67 |
68 | for neighbor in neighbors[loop[-1]]:
69 | if neighbor not in loop:
70 | loop.append(neighbor)
71 | break
72 |
73 | loop.append(source)
74 |
75 | poly = Polygon(loop)
76 | with Pool(15) as pool:
77 | points = []
78 |
79 | for y in range(height):
80 | for x in range(width):
81 | if (x, y) not in loop:
82 | points.append(Point(x, y))
83 |
84 | print(sum(pool.map(poly.contains, points)))
85 |
86 | if __name__ == "__main__":
87 | main()
88 |
--------------------------------------------------------------------------------
/src/day11/example.txt:
--------------------------------------------------------------------------------
1 | ...#......
2 | .......#..
3 | #.........
4 | ..........
5 | ......#...
6 | .#........
7 | .........#
8 | ..........
9 | .......#..
10 | #...#.....
11 |
--------------------------------------------------------------------------------
/src/day11/part1.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | def main() -> None:
4 | data = sys.stdin.read().strip()
5 |
6 | lines = []
7 | for line in data.split("\n"):
8 | if "#" in line:
9 | lines.append(line)
10 | else:
11 | lines.extend([line, line])
12 |
13 | doubled_cols = []
14 | for x in range(len(lines[0])):
15 | col = [line[x] for line in lines]
16 | if "#" not in col:
17 | doubled_cols.append(x)
18 |
19 | grid = []
20 | for line in lines:
21 | row = []
22 | for x in range(len(line)):
23 | if x in doubled_cols:
24 | row.extend([line[x], line[x]])
25 | else:
26 | row.append(line[x])
27 |
28 | grid.append(row)
29 |
30 | width = len(grid[0])
31 | height = len(grid)
32 |
33 | galaxies = []
34 | for y in range(height):
35 | for x in range(width):
36 | if grid[y][x] == "#":
37 | galaxies.append((x, y))
38 |
39 | t = 0
40 | for i in range(len(galaxies)):
41 | for j in range(i + 1, len(galaxies)):
42 | ax, ay = galaxies[i]
43 | bx, by = galaxies[j]
44 |
45 | t += abs(ax - bx) + abs(ay - by)
46 |
47 | print(t)
48 |
49 | if __name__ == "__main__":
50 | main()
51 |
--------------------------------------------------------------------------------
/src/day11/part2.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | def main() -> None:
4 | data = sys.stdin.read().strip()
5 |
6 | grid = []
7 | for row in data.split("\n"):
8 | if "#" in row:
9 | grid.append((row, False))
10 | else:
11 | grid.append((row, True))
12 |
13 | expanded_cols = set()
14 | for x in range(len(grid[0][0])):
15 | col = [row[x] for row, _ in grid]
16 | if "#" not in col:
17 | expanded_cols.add(x)
18 |
19 | galaxies = []
20 |
21 | ry = 0
22 | for y, (row, row_expanded) in enumerate(grid):
23 | rx = 0
24 | for x in range(len(row)):
25 | if grid[y][0][x] == "#":
26 | galaxies.append((rx, ry))
27 |
28 | rx += int(1e6) if x in expanded_cols else 1
29 |
30 | ry += int(1e6) if row_expanded else 1
31 |
32 | t = 0
33 | for i in range(len(galaxies)):
34 | for j in range(i + 1, len(galaxies)):
35 | ax, ay = galaxies[i]
36 | bx, by = galaxies[j]
37 |
38 | t += abs(ax - bx) + abs(ay - by)
39 |
40 | print(t)
41 |
42 | if __name__ == "__main__":
43 | main()
44 |
--------------------------------------------------------------------------------
/src/day12/example.txt:
--------------------------------------------------------------------------------
1 | ???.### 1,1,3
2 | .??..??...?##. 1,1,3
3 | ?#?#?#?#?#?#?#? 1,3,1,6
4 | ????.#...#... 4,1,1
5 | ????.######..#####. 1,6,5
6 | ?###???????? 3,2,1
7 |
--------------------------------------------------------------------------------
/src/day12/part1.py:
--------------------------------------------------------------------------------
1 | import itertools
2 | import sys
3 | from multiprocessing import *
4 |
5 | def matches_pattern(arrangement: str, pattern: str) -> bool:
6 | for i, ch in enumerate(pattern):
7 | if ch != "?" and arrangement[i] != ch:
8 | return False
9 |
10 | return True
11 |
12 | def is_valid(arrangement: str, groups: list[int]) -> bool:
13 | idx = 0
14 |
15 | current_length = 0
16 |
17 | for ch in arrangement:
18 | if ch == "#":
19 | current_length += 1
20 | elif current_length > 0:
21 | if idx >= len(groups) or current_length != groups[idx]:
22 | return False
23 |
24 | idx += 1
25 | current_length = 0
26 |
27 | if current_length > 0:
28 | if idx >= len(groups) or current_length != groups[idx]:
29 | return False
30 |
31 | idx += 1
32 | current_length = 0
33 |
34 | return current_length == 0 and idx == len(groups)
35 |
36 | def process(line: str) -> int:
37 | pattern, groups = line.split(" ")
38 | groups = list(map(int, groups.split(",")))
39 |
40 | t = 0
41 | for arrangement in itertools.product("#.", repeat=len(pattern)):
42 | if matches_pattern(arrangement, pattern) and is_valid(arrangement, groups):
43 | t += 1
44 |
45 | return t
46 |
47 | def main() -> None:
48 | data = sys.stdin.read().strip()
49 |
50 | with Pool(15) as pool:
51 | print(sum(pool.map(process, data.split("\n"))))
52 |
53 | if __name__ == "__main__":
54 | main()
55 |
--------------------------------------------------------------------------------
/src/day12/part2.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from functools import *
3 | from multiprocessing import *
4 |
5 | @cache
6 | def count_options(pattern: str, groups: tuple[int]) -> int:
7 | if len(pattern) == 0:
8 | return int(len(groups) == 0)
9 |
10 | if len(groups) == 0:
11 | return int("#" not in pattern)
12 |
13 | if pattern[0] == "?":
14 | return count_options_hashtag(pattern, groups) + count_options(pattern[1:], groups)
15 | elif pattern[0] == "#":
16 | return count_options_hashtag(pattern, groups)
17 | else:
18 | return count_options(pattern[1:], groups)
19 |
20 | @cache
21 | def count_options_hashtag(pattern: str, groups: tuple[int]) -> int:
22 | g = groups[0]
23 | if len(pattern) < g or "." in pattern[:g] or (len(pattern) > g and pattern[g] == "#"):
24 | return 0
25 |
26 | return count_options(pattern[g + 1:], groups[1:])
27 |
28 | def process(line: str) -> int:
29 | pattern, groups = line.split(" ")
30 | groups = tuple(map(int, groups.split(",")))
31 |
32 | pattern = "?".join([pattern] * 5)
33 | groups = groups * 5
34 |
35 | return count_options(pattern, groups)
36 |
37 | def main() -> None:
38 | data = sys.stdin.read().strip()
39 |
40 | with Pool(15) as pool:
41 | print(sum(pool.map(process, data.split("\n"))))
42 |
43 | if __name__ == "__main__":
44 | main()
45 |
--------------------------------------------------------------------------------
/src/day13/example.txt:
--------------------------------------------------------------------------------
1 | #.##..##.
2 | ..#.##.#.
3 | ##......#
4 | ##......#
5 | ..#.##.#.
6 | ..##..##.
7 | #.#.##.#.
8 |
9 | #...##..#
10 | #....#..#
11 | ..##..###
12 | #####.##.
13 | #####.##.
14 | ..##..###
15 | #....#..#
16 |
--------------------------------------------------------------------------------
/src/day13/part1.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | def horizontal_mirror(pattern: list[str]) -> int:
4 | width = len(pattern[0])
5 | height = len(pattern)
6 |
7 | for y in range(height - 1, 0, -1):
8 | possible = True
9 | for x in range(width):
10 | col = "".join([row[x] for row in pattern])
11 | a = col[:y]
12 | b = col[y:]
13 | if len(a) < len(b):
14 | if not b.startswith(a[::-1]):
15 | possible = False
16 | break
17 | else:
18 | if not a.endswith(b[::-1]):
19 | possible = False
20 | break
21 |
22 | if possible:
23 | return y
24 |
25 | return 0
26 |
27 | def vertical_mirror(pattern: list[str]) -> int:
28 | width = len(pattern[0])
29 | height = len(pattern)
30 |
31 | for x in range(width - 1, 0, -1):
32 | possible = True
33 | for row in pattern:
34 | a = row[:x]
35 | b = row[x:]
36 | if len(a) < len(b):
37 | if not b.startswith(a[::-1]):
38 | possible = False
39 | break
40 | else:
41 | if not a.endswith(b[::-1]):
42 | possible = False
43 | break
44 |
45 | if possible:
46 | return x
47 |
48 | return 0
49 |
50 | def main() -> None:
51 | data = sys.stdin.read().strip()
52 |
53 | t = 0
54 | for pattern in data.split("\n\n"):
55 | pattern = pattern.split("\n")
56 | t += vertical_mirror(pattern) + horizontal_mirror(pattern) * 100
57 |
58 | print(t)
59 |
60 | if __name__ == "__main__":
61 | main()
62 |
--------------------------------------------------------------------------------
/src/day13/part2.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | def horizontal_mirror(pattern: list[str]) -> int:
4 | width = len(pattern[0])
5 | height = len(pattern)
6 |
7 | for y in range(height - 1, 0, -1):
8 | error = 0
9 | for x in range(width):
10 | col = "".join([row[x] for row in pattern])
11 |
12 | for i in range(y):
13 | if y + i >= len(col):
14 | break
15 |
16 | if col[y + i] != col[y - i - 1]:
17 | error += 1
18 |
19 | if error == 1:
20 | return y
21 |
22 | return 0
23 |
24 | def vertical_mirror(pattern: list[str]) -> int:
25 | width = len(pattern[0])
26 | height = len(pattern)
27 |
28 | for x in range(width - 1, 0, -1):
29 | error = 0
30 | for row in pattern:
31 | for i in range(x):
32 | if x + i >= len(row):
33 | break
34 |
35 | if row[x + i] != row[x - i - 1]:
36 | error += 1
37 |
38 | if error == 1:
39 | return x
40 |
41 | return 0
42 |
43 | def main() -> None:
44 | data = sys.stdin.read().strip()
45 |
46 | t = 0
47 | for pattern in data.split("\n\n"):
48 | pattern = pattern.split("\n")
49 | t += vertical_mirror(pattern) + horizontal_mirror(pattern) * 100
50 |
51 | print(t)
52 |
53 | if __name__ == "__main__":
54 | main()
55 |
--------------------------------------------------------------------------------
/src/day14/example.txt:
--------------------------------------------------------------------------------
1 | O....#....
2 | O.OO#....#
3 | .....##...
4 | OO.#O....O
5 | .O.....O#.
6 | O.#..O.#.#
7 | ..O..#O..O
8 | .......O..
9 | #....###..
10 | #OO..#....
11 |
--------------------------------------------------------------------------------
/src/day14/input.txt:
--------------------------------------------------------------------------------
1 | ....#.#....O...OO..#..#....OO...#.#..OO#.#O.#.O.#.....O....O......O..........O.....O....#..#O..#O...
2 | O#....O..#O........O.#...OO....#O...O#.#.....O.....O.O....##...O.O..O.#.O......#....O.O.....###....#
3 | ....#.#O..........O...............O.O..#....#..O#.#.........#..#......#..O..O.OO..O.O#O.OO..O..OO..#
4 | ...#OO....O.......O#.OO#.O#..O#.O..O#OO..#OO.O.#..OO......O...##.....#..O##O.#O.......OO.#......#...
5 | .#..#.O..#....#O....#O..OO...#O.#..O..#.....O#....OO......OOO#.#.....#..O.##.OO....#...O.#.O#....#O.
6 | ..#.#OO#..#.O..O.#..#O.......O...###......#.#.O..#.O.#...O.....O.O#...OO...#..O..#...O....#....#.O#.
7 | ......OO....OO...#O.......O##..#........#O....O.........#.###..O...O.O........OO#.....O#.#.##......O
8 | ..#....#.#...O...#..##...#O....##..#..#....O..O...O.#.....O.#.......O.OO....#OOOO.#.....O#.#..OOO...
9 | .O..##.#O...#...O......OOO.......#O.O..#.#....#.....OO.O...OO#.O.O....#.#.............O##....##O##..
10 | O#..O........#..#...#.....#..#O.#O....###...#....#..#OOO.....O.O###.O..#O...O...##..O....O..O....O.#
11 | ...O....#..O.....O..O...O....#.O...#.#....OO..O.##....#.OO..O...##....#..#OOO.#O#...O#O#.....#..OO..
12 | .....#.##.#..OO..#..#O#O#OO.O......O....#.O..##O....#..#..#...O#O.#.O..O....O.......##.O#...O..#...#
13 | .....OO.....#.....OO........#.OOO.O.#OO......#.#....#....#.##..O..###.....#....O.O.......OO.OO.#.#..
14 | #.............OO......OO.OO#.#...#.##.......#.#..O#..#.O.#.....#.O..O...O.O........#O..O..O..O....#.
15 | O..O.O..OO#O...OO...O...#.O....#...O...O#...#.........O...#.#OO..OO..O.O........#OO.##.O#..O......OO
16 | ..##.##.O.##O.O...O.OO#...........#O...O..O..#O...........#.#.###.#.#.O.O....##..#.O.OO...#.....O#..
17 | ....O......OO.O..#.......O..O.#.#O....O..O.#....O..##.O#...#..O#.#.##..O...#O...#.O.....#.O...O#....
18 | .#.O.O.#....##...#..##..#.#.O.#..O.....#..##..#..O.......#....O......O.O.........OO.#...#.#O...O.O.O
19 | ....O#..#....OO#..OO.OO.O..#OO#.O.......#OO.#O..O.#..#..#OO...O.....#...O........#..#..O...O..O.O#..
20 | #.O..........OO#O...........OO....##.#.O.....OOO.#.......#.......O...#..OO....#....#.......O.O....#.
21 | ..O#......O.OO......O##......O#O....#OO...#.OO....OO#.O#.O.#O..O.....O......O.....#.#O...#OO#..O.#O.
22 | .#...#OOO...O....O...OO..#OO.#.O.OO.O.O.O.O...#..O.....O.#O#.O.O.....O##...#....O##.#.O....#..O...OO
23 | ...........#..........O#...#.....O#..O.....#O.O.....O.O..O.#.OO.O...O#......O....O#......OO..O.O..#.
24 | #..#.OO..#.O.##O.O..#....#O#O#..#...#OO..O....O...O..##....OOO.....O#..O..##O..O.O##.OO..#.........O
25 | O.O.##......#...#O.##.#.OO..O....O.O.O#..O..####........O......O....O.......O#.....O.O.#.O#.O.#OO#..
26 | .....OO.#..OO..O..O.#.#....#..OO..OO.....O#......O.#.#........#...........#....#......O....O..OO.#.O
27 | O##..O.#...OO#..#..##O...O##.#O##.O.........O...OO#..O.#.....#O.#.O.....#...##..#O.#...OO.#O.#.#.#..
28 | ...#..O..O....OOOOO..#..#OO..O.#...#....#...O........#.#........O.....O..O....OOO.....#.O..##..O.##O
29 | .O.#O.....#O.O#...#..#.OOO.O#.O....#.O...........#.....#...#...O....O.#...O..#...O#.......O..O......
30 | ..........O##...O....##.....O..#.......##.....#..##.#O....#..O..##O...OO...O.....#.O..#..###O.##..O#
31 | ..###O.O.#.#O....O#.##..O.#..##.##O.O.#..O#.#.O#.O.##...O.......#...O.#.......#..##.O...#..O....O.O.
32 | ...O..O#.##O.....O.O.#O..O#.O##.O.#....O#.#O.O..#......#..###.O#O.##.........O...O...O#....O........
33 | .O....O.#....#.OO#..#O...#.......#......OOO.#OO.O#.#.O......#O#OO..#O.O..#..#.O.............O#.OO#.#
34 | #O.O.....#.O.O#...OO.......O...O..O.#..........O......O.O..#O.#.......O..#O#...O...OO.#..#.#...#...O
35 | .....#....#.....#O..O...O...#.....#OO....#..#O.O.#OO..#.O.O#...#.O.O..#..#..#OO#..#..#..O...#..O#..O
36 | ....O..OOO.##...#.O#......#O.O.O....#O..#.O..#........O#.O...O........#O#O..#..#.O...O.##.O.O.....O#
37 | .O..O#.O..#.....###..#......#OO..........O.#.O#..OOO.###.....#..OO.#O...O...OOOO...O.........O......
38 | O...O.........O......OO...#..O.##..#..#..O.....O..O.........O.O..OO....#..O.#..##OO#.#....#.###.....
39 | .OO.O.#......#.O.......##..O.O.O#..O.OO...O#..#.......#.........OO#.....#..O..O...O.O....#.O..O#....
40 | O...#..O.OO..O.#.O...#.......#.O.O.O.....#.....O..OOO#...O.#O.O#..O...O#...........O#..O........O...
41 | O#O.#O..#.......#..O.#..#....#..O..#..O.#......O.OO.O.....#.O.#....O.#.......O......O#.O...#.#.#.O..
42 | ..O#O.OO..#......#.#.#....#..#...#..O.#..#O.O.......O.##...O.O.O.#O...O.O.O##O..#..O...O..OO.#..#.#.
43 | ...O.#.....#O...O....O....O....OO..........O.O#O.O.O###...##O.#O...#O.#.OO...#..#..O##...O......#...
44 | .##.##..O..O#...#O...OO.#...O..##....O....#.OO...#O.O..#..O.#.....O.O.#.##O..O..O.O.......O...O...#.
45 | O.OO.O.##.O..##OO.............#.....O....#O..O#...#.##.#.#.........OO..OO..O....OO.#O.O..O..........
46 | #..O.O....OO..O..#...O.....O.#.O#.O.#.#OO#......O.O..O.O...#.OO.#.O#..#O.#..OO.#..#.##.....#OO...OO.
47 | ..OO##.#........OOO..O.##....O.O#...OOO......O...O..O.#......#.O...O.#..O.O..O.O..O.O...#O.....OO.#O
48 | O..#..O.#.O...#OO##......O.O.....#O.#O#O.#..#..#.OO..#.O##......O.#O....#.....#...#...O#...O.O....#.
49 | O.........O#O#.#.#......#.O##.O.O#......O.#...OO....#...#..#O#.OO#.###.O.#.#..O..#..#OOO#O#.O...#O.#
50 | .O#.O....O..OO..OO#...#O........O.OO.O#O##.O#O#....#...#O#........#.#O.O#..#..O##..##.........#.O##.
51 | ...##...O.#O.##....#.....O....#..OO..O...#.O.O......OO#..O#..#####.#O..#.#....O.#...O...........#O..
52 | .O.#.O..OO.O...#.#....#...O#....#O..#O.#.O.O.O..#..O#.O...O..O.O#O.....O......#O......#O..#.#O.O..OO
53 | ......#........O.#O.OO.#...O...##.....#......OO...#O#OO..OOO....#......#..##..#.O...OOOO.#....O...#.
54 | O...#O..OO.....OO.OOOOO#.O....#...#...O..#..#O....##.OO.#OO.OO..#O..#O.O#.OOO.............#OOO....##
55 | .#.O.O..O.....#..#....#...OO...#...OO.#........O.O....##..........#.#O...OO###OOO..#...#..OOO..O..O#
56 | O#...OO..O.#........##......#O....#.........#....O#.#....#..O...O#..O.#......OOO.#....O..OO...O##.OO
57 | ....#O#.O..O.O..#O.O#....O.#.O...OO...O..OOO..O.O.O#.#...#.......O.O..#....O...#O.##.....#.#O#.OOO#.
58 | .O###...#...OO.O.....O.....#..OOO.##O....OO.O.............O......O..#.O..#....#..#...#..#O..O...#OO.
59 | ...O...#..........#.O..O.........O.O.....#..#....O#O...#.O.#OO.##O...OO..........#O..#....#O....O...
60 | ..O..O.#.....O#O..#O##O.#O.O##.#.....O.O.O.#.O.....OO..OOO.O#.OO.#...O..O...#.O.OO#..OO.#..OO####OO.
61 | O.......O#..O.O.#.#...O.OOO...#O....#O.O.O.O...#......O.##...#........#..#..#.#.O##..O.OO.#O..O.....
62 | ..O..OO..#....O..OO.#.##....#.......#..#.#..O#..#.#OO#..........#O#O...O.OO...O..#....O...#.......O.
63 | ....#.#.#O..O........#.O#.O#..#.......#.#...##OOOOO.OO.O#..#....OO..OOO.O......O.........#..OO.O.#.O
64 | O...O.....#O###..O.OO.O...O...#...#O.....OO...#.....O.O.O..#...O.O..#O..O.O.#...#O.O..#..O....#OO..#
65 | ...#..#......#.O#....#O#.O....O..O..O..O....O...#..#O..#.....#...O.....OOO..OO.#O#.......#.O...OOOOO
66 | OOO#.O.O.#O....O..#...O..O#O..O#...#...#..O#..O..O.O#......O...#O..O#.O...#.O.#...O...OO.#....O.....
67 | O..#O...O#..#...O.#.O......#.#..#.O...##.O..#O...O#.#.O.....O...OO.OOO.O.#..#.O....##.#.#O..OO...#OO
68 | ...O.O..O.OO.O..O.OOO.O#.#..O.....OO#..OOO.#.#....O.#O.#.O.OO....O..#..O#O###OO#.......##........#..
69 | #...#..O.###.O.#O......OO#......O.O..#O......OO.O.#....#....O...OO##OO#O...O.........O#OOO..........
70 | ..O.O..............O.....OOOO#.OO..O#..O.###.O..O.#.O.O.....O.#O.OOO..OO#..OO.#.....#.......O#...O..
71 | O...#.OOO....OO......O..O......O.....O....O..#O..#.O.............O.#..............#....#O....#O#O...
72 | .OO.OOO.........OOO#.OO....#...#....OO...O..O.....#...#O..#O.O.#.O.#O......O.O.O#..O.O.#...#O....O#.
73 | O.....#OO......#.#..OO.O.##O#......#......O..#...#O#..#O..O..#.........O..##.O..##O.#.#.O.#..OOO#..O
74 | ...O....#..#....OO.O.##...OO#.O##..........##.#..OO.#..O#.#.O..#...O..#..O..#....O..#....O..#.###O..
75 | .O....O...O#....O#O..O..OO...#O.O.....#...#.......#...##.O..#...#.....O......O..##...##......O.#...O
76 | O#.O#OO.O.#O.#.#O..#.O..O..#O#O.#O...........O#.O...O...O....O......O.OO......O..O##..O....OO#...##O
77 | ..O..O.OOO....#O#..O#...#.O....#....#O..O#..##.O.....O.O#O..O.....##...#..#............#....O.O.#.O#
78 | .....O.#..O..#.OO.....O...O..#.......O....#.##.O#O....O.O...#.OO....##O....O....#OO#O.......O#..#O.O
79 | #O.O.#......#.O....O....#..O##......O.#.#....#OO.....O.OOO...#.O.....O#.O.O#..O#..#.....#.OO...OO.O.
80 | ..#O........O.O.O.O.....O..#...O.O.#O.OO....O...#.......##...O.......OO.#O.O.O..O.##...O.O#..##..#O.
81 | O#O....O.O.O#.###O...#.....O..#....#.#.O.....O..####.O.O..#..OO.#..O....##..#O.##.....O...O.....OO..
82 | #...OO.#.#.#...O.#O....#O#.............###.O..O.O.O.#...##O..O#...OO#OO.....###.O..#.#...O.....O..O.
83 | .O.OO#..O..OO#.O#.O..##....O#...O...O....OO.....#.#O.....O......O##......#....#..#......O##.#....#O#
84 | .#O#O..#....##.OO.............O..##....O......#.........#.......#O..O##....#.....#..#......#O.OOO...
85 | .O.O#OO..#..........O.#O.OO......##....#..O###O..OO..O..O.##O..#.......#..O..#..#.#......O...#....#.
86 | .#.O....OO.O....#O..OOO.#....O.....OO..O..O...O...#..O....O......O...........#.O.....#...##..O.O#.OO
87 | .O.O..O#O.OO..OO#.OO.#O.....O...#.OOO....O#......O.OO..#.#..O.....#..O.O#O.O#..O##O..O....O....O....
88 | ..OO......#..#O...OO..O.#..#O##....O..#.#.O...O..#O....#.O.....OO.O.OO...OO...O#.O.....OOO...#....#.
89 | #OO..#.....#OO...O.......O....#...O...O.#O....O....O....#.......O....#..O.....#....OO.##.OO#O.O#....
90 | #..#O....O#...#.#OO..............#OO#OO#.O....O..OO.O.O#...O...#..#O.#.......O....#O..#..#O.....##O.
91 | ...#.....#.#..#OOOO..O.O#O..O..#..O..O.............OO...#.....#O.OO..#..#.....OO.....#O....#..O#....
92 | ...O.#.O.#O.O.O##..O..O.O......O#O##...........O..#..#...........O.O.O...O..#.....OO.O.......#O.....
93 | #.O#O.....#O......O#.......OO.O.O..#..#..#O....#......#.O..O..#O#.###.#..#..#...O.OO....#.#O#..O...#
94 | #..O..#.O.O......#...#......#..#......O...O..#....O#.O.O..O...O..#..#O.OOO..O...#.......O..OO.O....#
95 | ...O..OO#O..#....#....###O...O#.#OO..O...O....O#.#....#.O......#..#...#..#.O......O..O...#.O....#.O.
96 | OO..#..O##.O..O...O..#O....#....#.O.O....O#....OO.#.OO..O..OO..O#...O....OO..#.OOOO.#..O.O.....#..##
97 | .OO.O....O...O#O.....##....O..#O##....O.....##....O.#..#O#O.OOOO..O..O.O.......OO..O.#....O.....O..O
98 | .O.O..O#..#OO..O.O.....OO..OO..##.#..O...........#.O..#.O.#...O...O..OOO..O.#O.#....O.#.OO..O#......
99 | ..O#..O#.O...##..#.#.###....O#..O.O##.O.#.O....OO.#..O.OO.#....O..O#O.#...##...OO#.OO..O.....#.....O
100 | ...#OO#.......O.O.##...#O..O#.O#O#..OO..O..O#O..O.#.OO#.....#.....O...O.O.....#O#.OO.O...O.O#..#O..#
101 |
--------------------------------------------------------------------------------
/src/day14/part1.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | def main() -> None:
4 | data = sys.stdin.read().strip()
5 |
6 | grid = [list(line) for line in data.split("\n")]
7 |
8 | width = len(grid[0])
9 | height = len(grid)
10 |
11 | for _ in range(100):
12 | for y in range(height - 1, 0, -1):
13 | for x in range(width):
14 | if grid[y][x] == "O" and grid[y - 1][x] == ".":
15 | grid[y][x], grid[y - 1][x] = grid[y - 1][x], grid[y][x]
16 |
17 | t = 0
18 | for y in range(height):
19 | for x in range(width):
20 | if grid[y][x] == "O":
21 | t += height - y
22 |
23 | print(t)
24 |
25 | if __name__ == "__main__":
26 | main()
27 |
--------------------------------------------------------------------------------
/src/day14/part2.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | def update(grid: list[list[str]]) -> None:
4 | width = len(grid[0])
5 | height = len(grid)
6 |
7 | for _ in range(100):
8 | for y in range(height - 1, 0, -1):
9 | for x in range(width):
10 | if grid[y][x] == "O" and grid[y - 1][x] == ".":
11 | grid[y][x], grid[y - 1][x] = grid[y - 1][x], grid[y][x]
12 |
13 | for _ in range(100):
14 | for x in range(width - 1, 0, -1):
15 | for y in range(height):
16 | if grid[y][x] == "O" and grid[y][x - 1] == ".":
17 | grid[y][x], grid[y][x - 1] = grid[y][x - 1], grid[y][x]
18 |
19 | for _ in range(100):
20 | for y in range(height - 1):
21 | for x in range(width):
22 | if grid[y][x] == "O" and grid[y + 1][x] == ".":
23 | grid[y][x], grid[y + 1][x] = grid[y + 1][x], grid[y][x]
24 |
25 | for _ in range(100):
26 | for x in range(width - 1):
27 | for y in range(height):
28 | if grid[y][x] == "O" and grid[y][x + 1] == ".":
29 | grid[y][x], grid[y][x + 1] = grid[y][x + 1], grid[y][x]
30 |
31 | def get_load(grid: list[list[str]]) -> int:
32 | width = len(grid[0])
33 | height = len(grid)
34 |
35 | load = 0
36 | for y in range(height):
37 | for x in range(width):
38 | if grid[y][x] == "O":
39 | load += height - y
40 |
41 | return load
42 |
43 | def main() -> None:
44 | data = sys.stdin.read().strip()
45 |
46 | grid = [list(line) for line in data.split("\n")]
47 | last_seen = {}
48 |
49 | iterations = int(1e9)
50 | for i in range(iterations):
51 | update(grid)
52 |
53 | key = "".join("".join(row) for row in grid)
54 | if key in last_seen:
55 | remaining = iterations - i - 1
56 | cycle_length = i - last_seen[key]
57 |
58 | for _ in range(remaining - (remaining // cycle_length * cycle_length)):
59 | update(grid)
60 |
61 | print(get_load(grid))
62 | break
63 |
64 | last_seen[key] = i
65 |
66 | if __name__ == "__main__":
67 | main()
68 |
--------------------------------------------------------------------------------
/src/day15/example.txt:
--------------------------------------------------------------------------------
1 | rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7
2 |
--------------------------------------------------------------------------------
/src/day15/part1.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | def main() -> None:
4 | data = sys.stdin.read().strip()
5 |
6 | t = 0
7 | for step in data.split(","):
8 | v = 0
9 | for ch in step:
10 | v += ord(ch)
11 | v *= 17
12 | v %= 256
13 |
14 | t += v
15 |
16 | print(t)
17 |
18 | if __name__ == "__main__":
19 | main()
20 |
--------------------------------------------------------------------------------
/src/day15/part2.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | def main() -> None:
4 | data = sys.stdin.read().strip()
5 |
6 | boxes = [[] for _ in range(256)]
7 | for step in data.split(","):
8 | if "=" in step:
9 | label, length = step.split("=")
10 | length = int(length)
11 |
12 | v = 0
13 | for ch in label:
14 | v += ord(ch)
15 | v *= 17
16 | v %= 256
17 |
18 | for arr in boxes[v]:
19 | if arr[0] == label:
20 | arr[1] = length
21 | break
22 | else:
23 | boxes[v].append([label, length])
24 | elif step.endswith("-"):
25 | label = step[:-1]
26 |
27 | v = 0
28 | for ch in label:
29 | v += ord(ch)
30 | v *= 17
31 | v %= 256
32 |
33 | boxes[v] = [arr for arr in boxes[v] if arr[0] != label]
34 |
35 | t = 0
36 | for i, box in enumerate(boxes):
37 | for j, arr in enumerate(box):
38 | t += (i + 1) * (j + 1) * arr[1]
39 |
40 | print(t)
41 |
42 | if __name__ == "__main__":
43 | main()
44 |
--------------------------------------------------------------------------------
/src/day16/example.txt:
--------------------------------------------------------------------------------
1 | .|...\....
2 | |.-.\.....
3 | .....|-...
4 | ........|.
5 | ..........
6 | .........\
7 | ..../.\\..
8 | .-.-/..|..
9 | .|....-|.\
10 | ..//.|....
11 |
--------------------------------------------------------------------------------
/src/day16/input.txt:
--------------------------------------------------------------------------------
1 | \..\.|.........|..|................................................................./.-............./-....../.
2 | ............../..--.../...................-....|.......................\../...|..-....\...-|...-...........\..
3 | .......\......................................|..-\.................-..-......................................
4 | ........\..............|......................\........./..............................|..............||......
5 | .........|........|......-...........|....../....-.../.....|/.........-..../.../..........................|...
6 | ..\............................./\............................................................................
7 | ........|....................\............................./.....|\|..-....../............/..-..........\.....
8 | ...\.........................\.............|.........../..............-..../.............../-.................
9 | .||....../..............\.|...............-......................|-..-......../.|.............................
10 | ...|.|.....-...../.............-............./............\.\/........|.............................\|.-..\.-.
11 | ............./....................|.......|.....\..\..............................-.../....|..................
12 | ./......./.|...............\................................................||................................
13 | ......\......|.................|........../......|\|.......-|..................|.....-.-.||../.\..............
14 | ................../...............|.....\........-...-.\...||..\...........\............|.........|...........
15 | ...-........|\|........././/............|...........\.../\...|.......-........\....................-..........
16 | ..../...........\.........................../......-.|...................................../..\........|......
17 | \...............\/......./........-..............|..............--........../....|..-.\...........-........./.
18 | ..........\........\|.........|\.........../........................../.........|............\..........|.....
19 | ...........\....|/.|..........-..............-....-|...\..........-.../............./.........................
20 | ..\..\......../...\\....................../...../.........................|.....\..............|..\...-.......
21 | ...........................-./...................................-/.\.....\...................\.../...........
22 | ..-..................|..................-...\.......|../............./|-............/........|.......|..-.....
23 | ...........-......................-.................|............../.......-./..........|....../..............
24 | .........|.............././...............|..../..............|.........|.....|..\......................|.....
25 | ......./-/...................\\..\......|........................\...\....../.....................|...-.......
26 | .....|.......................|............|...|........|...........-....../..................-...-............
27 | .../................../......|...........................-............|.............-........./............|..
28 | .-.........|.............|-...../..............................\................|........................../..
29 | .........../.........-.......|..-.........................-...............-...-.../...................../.....
30 | ../.......-../....................-...\...\........................-.............-...\...../.|.........../....
31 | ............-...............|........................................../...\.|....|........-.....\|...........
32 | .....................|\............................-..-....../..-|..../..................\................\...
33 | .\.................-......\...|............................./......./.........-............../................
34 | .\.........././............../|......\/..............\........................|........................|...-..
35 | .............../.........|.................................-.......\\.\-..........-......................./-..
36 | -.|......................|.............|............................/....................|...........-........
37 | ../.....-.......|.....-.....\.../\........|.............|.........\./..//\................|.........-.....||..
38 | .\..\.......|......./............\..\.........../........-.../.|..............-..../....\.........../.\.\.....
39 | .............|..........|.........|.|...\-......................-..............|.../............./.........|..
40 | ....|................................................../...........-......-/......................-.....-.....
41 | ............................./.........-............................./..................\..........\..../.....
42 | .....|.....................-.........../.......|..................-.......\...|\...|......\.....\...|.........
43 | ........|............../..../|.|......-................|...../..........|................|...................-
44 | ....../.....//..........\.-|......|.....|..................../..............|.................................
45 | \.-...-....\..................\....................|............||............................../.............
46 | ............................-|...-...........-.../......-.........\..-...|.|\..........-...............\.|//./
47 | ....../......././.|...................|\........../.\.../-...\..........\.-..|\../...........\....\..|.....\..
48 | ...............\.../..../.................\.......-...........\..|..................\\................./.\....
49 | ............-..........-......................|.......|..|....................-......|......\...........|.....
50 | ...............\......|.-............./............\.../.............-|........./...............\|\.....|.....
51 | .\...............|.................|...........\......\................\............\.|...\......./...........
52 | \...|..............-..........|...................|....-.....\......../..........................\........|..|
53 | .........|........./.........|....-........-...................../|./.--.......\........................-..../
54 | ..........................-.....-...............-/............................--...../........................
55 | .....................-.\../\..........|.....................\.......\.../..........|.............\............
56 | ......................../..\.......\...............................................\./........................
57 | ....|......\..|\.-........../......................\|........\...............\.................|..............
58 | ............................./.....|..|............-...\.........-...\....|......\.............-..|...........
59 | ..................-......-.....................-...........-......\...-|-.-................\............|/....
60 | ...|....../............../..\.......................-....\...|.....\..|..\......./.................-.....-....
61 | .........-........|........../..-................................./....-.................-....................
62 | .............................-.......\...............\.....|......-....-.../.................\................
63 | ...../......|...................|..............-........./.............\...\....|.............\.......|.......
64 | .......|............./........./......\..../........|...........\................................-............
65 | /...|././.......|-.|..........|................................/\.\.......-......-........-........\..........
66 | ../................./|.-...\........................|........|........|...\|.\........................./.....-
67 | ................-.........../|..............|.|/...|\...........-.......................-..|../...............
68 | ./..||........|....../........................|.................................../..............\..|./-......
69 | /..-...../......................................\-...........-..................\|................../.........
70 | .............|.-......................|................-../.................-............../..............-...
71 | -.....-|-...............\..........-...........\.......\........................\.........../..../...../......
72 | .-..................../..........|.--.............................-..-....|.\................|....|...\......\
73 | ......./.-........................................\....|........|...../...........|...\|..-...................
74 | \...............|........|.......\|..-..|...-..|-........|........./.\........................................
75 | /.|./....|....-...../\..|...............................-.../........./.............-|.........-..../.-..\....
76 | ../......./...../..|........|../.....\....\.............-.-.................-...\.......|.\...........\.......
77 | ...-........./.............../..................\.|................/..//..................|.......-..\......-.
78 | ./.............../.-..\..........|.............-....................-....-..|...........-.....................
79 | ...........|-..|........................................./\............./-.../.................\........\.....
80 | ................................/...........................\.....................|.|.........................
81 | .........|............\........................................-...../..........|........../.../......\...\...
82 | ../.........|......./..................|........\.../.\.-...-......../../\......../................../........
83 | .-........./.........|....|.|.............................................|.\............/../.................
84 | ./.........................................\....../................../.--.....-..../.....|./.-......|.......\.
85 | .\..................../.-........|.........\............\...........\...............|-../................\....
86 | ........................|......./.-....-....\.|...................-......-..........|........\.........../...|
87 | .............-......./.../......................\.......\............/......................................|.
88 | ............-..........................-..................-.......\--......-.....-.......|..\..-....|........\
89 | ...............|.......\......|....................\.....................-.../.|......|................../....
90 | ---..\-.../.........//....\../....|........\....|-.........-.....|..........-|..............|...../..........|
91 | ......-.............................-.........................-.........../...../.|.../................-.....|
92 | .........-.........\..............|....\..............-......\......../......\.......-\........-.............\
93 | .................../......................|......|.....\..........................-..-......./....-.....-.....
94 | ...\.....................-..-....\.......././....\......./...........................\..............\\........
95 | .................|................./.....................\...../.\.................\.........|...|....|.......
96 | ./............-........................\..|...-............................./............./..\................
97 | -............-..............|.................-..............................-..............................\.
98 | ................................/.....\........|....-.....||............/.|.............-..|....|....-........
99 | /.........|............-./...|././..............\./-............/......../\.\..././../..\..\..............-...
100 | ..../.....................\.........|......-...........|...\/..........//\.......//....-...|/.....\..\........
101 | ../............................/...././...-....-............./.|..\..............|...../.........-.....\....|.
102 | .................................\..../...-.....-.....-....|..\.\...../....../.............../.\..............
103 | ..................|..|.......-......\.../....../....................................................|.......-.
104 | -./.....|...\.....\../.......\..........................\.....|.............|...................|.\.../.../\..
105 | ..................-.....\.............|...|.........-..-............................../............/..|.......
106 | .....................\..../.....|......................................\.\............|/....................\.
107 | .....-..\.........-....\..............-..........................\.....\....................\.........\.....-.
108 | \...\|\...../.\............................\........-.........................../.......-............\........
109 | .............................................-......\.............|..../.......|......../.....................
110 | /.........-............./......|................-........-.............|...-..../.....\.\....\................
111 |
--------------------------------------------------------------------------------
/src/day16/part1.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | def main() -> None:
4 | data = sys.stdin.read().strip()
5 |
6 | grid = [list(line) for line in data.split("\n")]
7 |
8 | width = len(grid[0])
9 | height = len(grid)
10 |
11 | beams = [(0, 0, 1, 0)]
12 | seen = set()
13 | energized = set()
14 |
15 | while len(beams) > 0:
16 | new_beams = []
17 |
18 | for beam in beams:
19 | x, y, dx, dy = beam
20 |
21 | if (x, y, dx, dy) in seen:
22 | continue
23 |
24 | if x < 0 or x >= width or y < 0 or y >= height:
25 | continue
26 |
27 | seen.add((x, y, dx, dy))
28 | energized.add((x, y))
29 |
30 | if grid[y][x] == "/":
31 | if dx == 1 and dy == 0:
32 | dx, dy = 0, -1
33 | elif dx == -1 and dy == 0:
34 | dx, dy = 0, 1
35 | elif dx == 0 and dy == 1:
36 | dx, dy = -1, 0
37 | else:
38 | dx, dy = 1, 0
39 |
40 | new_beams.append((x + dx, y + dy, dx, dy))
41 | elif grid[y][x] == "\\":
42 | if dx == 1 and dy == 0:
43 | dx, dy = 0, 1
44 | elif dx == -1 and dy == 0:
45 | dx, dy = 0, -1
46 | elif dx == 0 and dy == 1:
47 | dx, dy = 1, 0
48 | else:
49 | dx, dy = -1, 0
50 |
51 | new_beams.append((x + dx, y + dy, dx, dy))
52 | elif dy == 0 and grid[y][x] == "|":
53 | new_beams.append((x, y, 0, -1))
54 | new_beams.append((x, y, 0, 1))
55 | elif dx == 0 and grid[y][x] == "-":
56 | new_beams.append((x, y, -1, 0))
57 | new_beams.append((x, y, 1, 0))
58 | else:
59 | new_beams.append((x + dx, y + dy, dx, dy))
60 |
61 | beams = new_beams
62 |
63 | print(len(energized))
64 |
65 | if __name__ == "__main__":
66 | main()
67 |
--------------------------------------------------------------------------------
/src/day16/part2.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | def count_energized(grid: list[list[str]], initial_beam: tuple[int]) -> int:
4 | width = len(grid[0])
5 | height = len(grid)
6 |
7 | beams = [initial_beam]
8 | seen = set()
9 | energized = set()
10 |
11 | while len(beams) > 0:
12 | new_beams = []
13 |
14 | for beam in beams:
15 | x, y, dx, dy = beam
16 |
17 | if (x, y, dx, dy) in seen:
18 | continue
19 |
20 | if x < 0 or x >= width or y < 0 or y >= height:
21 | continue
22 |
23 | seen.add((x, y, dx, dy))
24 | energized.add((x, y))
25 |
26 | if grid[y][x] == "/":
27 | if dx == 1 and dy == 0:
28 | dx, dy = 0, -1
29 | elif dx == -1 and dy == 0:
30 | dx, dy = 0, 1
31 | elif dx == 0 and dy == 1:
32 | dx, dy = -1, 0
33 | else:
34 | dx, dy = 1, 0
35 |
36 | new_beams.append((x + dx, y + dy, dx, dy))
37 | elif grid[y][x] == "\\":
38 | if dx == 1 and dy == 0:
39 | dx, dy = 0, 1
40 | elif dx == -1 and dy == 0:
41 | dx, dy = 0, -1
42 | elif dx == 0 and dy == 1:
43 | dx, dy = 1, 0
44 | else:
45 | dx, dy = -1, 0
46 |
47 | new_beams.append((x + dx, y + dy, dx, dy))
48 | elif dy == 0 and grid[y][x] == "|":
49 | new_beams.append((x, y, 0, -1))
50 | new_beams.append((x, y, 0, 1))
51 | elif dx == 0 and grid[y][x] == "-":
52 | new_beams.append((x, y, -1, 0))
53 | new_beams.append((x, y, 1, 0))
54 | else:
55 | new_beams.append((x + dx, y + dy, dx, dy))
56 |
57 | beams = new_beams
58 |
59 | return len(energized)
60 |
61 | def main() -> None:
62 | data = sys.stdin.read().strip()
63 |
64 | grid = [list(line) for line in data.split("\n")]
65 |
66 | width = len(grid[0])
67 | height = len(grid)
68 |
69 | max_energized = 0
70 |
71 | for x in range(width):
72 | max_energized = max(max_energized, count_energized(grid, (x, 0, 0, 1)))
73 | max_energized = max(max_energized, count_energized(grid, (x, height - 1, 0, -1)))
74 |
75 | for y in range(height):
76 | max_energized = max(max_energized, count_energized(grid, (0, y, 1, 0)))
77 | max_energized = max(max_energized, count_energized(grid, (width - 1, y, -1, 0)))
78 |
79 | print(max_energized)
80 |
81 | if __name__ == "__main__":
82 | main()
83 |
--------------------------------------------------------------------------------
/src/day17/example.txt:
--------------------------------------------------------------------------------
1 | 111111111111
2 | 999999999991
3 | 999999999991
4 | 999999999991
5 | 999999999991
6 |
--------------------------------------------------------------------------------
/src/day17/part1.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from heapq import *
3 |
4 | def main() -> None:
5 | data = sys.stdin.read().strip()
6 |
7 | grid = tuple(data.split("\n"))
8 |
9 | width = len(grid[0])
10 | height = len(grid)
11 |
12 | directions = [(1, 0), (0, 1), (-1, 0), (0, -1)]
13 | heap = [(0, 0, 0, 0, 0), (0, 0, 0, 1, 0)]
14 | seen = set()
15 |
16 | while len(heap) > 0:
17 | heat, x, y, direction, streak = heappop(heap)
18 |
19 | if (x, y, direction, streak) in seen:
20 | continue
21 |
22 | seen.add((x, y, direction, streak))
23 |
24 | if x == width - 1 and y == height - 1:
25 | print(heat)
26 | return
27 |
28 | dx, dy = directions[direction]
29 | x += dx
30 | y += dy
31 |
32 | if x < 0 or x >= width or y < 0 or y >= height:
33 | continue
34 |
35 | heat += int(grid[y][x])
36 |
37 | if streak < 2:
38 | heappush(heap, (heat, x, y, direction, streak + 1))
39 |
40 | heappush(heap, (heat, x, y, (direction + 1) % 4, 0))
41 | heappush(heap, (heat, x, y, (direction - 1) % 4, 0))
42 |
43 | if __name__ == "__main__":
44 | main()
45 |
--------------------------------------------------------------------------------
/src/day17/part2.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from heapq import *
3 |
4 | def main() -> None:
5 | data = sys.stdin.read().strip()
6 |
7 | grid = tuple(data.split("\n"))
8 |
9 | width = len(grid[0])
10 | height = len(grid)
11 |
12 | directions = [(1, 0), (0, 1), (-1, 0), (0, -1)]
13 | heap = [(0, 0, 0, 0, 0), (0, 0, 0, 1, 0)]
14 | seen = set()
15 |
16 | while len(heap) > 0:
17 | heat, x, y, direction, streak = heappop(heap)
18 |
19 | if (x, y, direction, streak) in seen:
20 | continue
21 |
22 | seen.add((x, y, direction, streak))
23 |
24 | if x == width - 1 and y == height - 1:
25 | if streak > 3:
26 | print(heat)
27 | return
28 |
29 | dx, dy = directions[direction]
30 | x += dx
31 | y += dy
32 |
33 | if x < 0 or x >= width or y < 0 or y >= height:
34 | continue
35 |
36 | heat += int(grid[y][x])
37 | streak += 1
38 |
39 | if streak < 10:
40 | heappush(heap, (heat, x, y, direction, streak))
41 |
42 | if streak > 3:
43 | heappush(heap, (heat, x, y, (direction + 1) % 4, 0))
44 | heappush(heap, (heat, x, y, (direction - 1) % 4, 0))
45 |
46 | if __name__ == "__main__":
47 | main()
48 |
--------------------------------------------------------------------------------
/src/day18/example.txt:
--------------------------------------------------------------------------------
1 | R 6 (#70c710)
2 | D 5 (#0dc571)
3 | L 2 (#5713f0)
4 | D 2 (#d2c081)
5 | R 2 (#59c680)
6 | D 2 (#411b91)
7 | L 5 (#8ceee2)
8 | U 2 (#caa173)
9 | L 1 (#1b58a2)
10 | U 2 (#caa171)
11 | R 2 (#7807d2)
12 | U 3 (#a77fa3)
13 | L 2 (#015232)
14 | U 2 (#7a21e3)
15 |
--------------------------------------------------------------------------------
/src/day18/input.txt:
--------------------------------------------------------------------------------
1 | L 5 (#088ba0)
2 | U 3 (#250f31)
3 | L 9 (#61e7e0)
4 | U 3 (#250f33)
5 | L 3 (#1e8420)
6 | U 5 (#36bd43)
7 | R 6 (#32a5b2)
8 | U 7 (#383191)
9 | R 2 (#144d42)
10 | U 2 (#383193)
11 | R 6 (#4204b2)
12 | U 7 (#1a4b53)
13 | R 3 (#21b4f0)
14 | U 7 (#1afab3)
15 | R 3 (#42ab20)
16 | D 8 (#11f323)
17 | R 5 (#3c1e00)
18 | D 8 (#6e7903)
19 | R 7 (#390a00)
20 | U 6 (#0457b3)
21 | R 5 (#123502)
22 | U 8 (#148e03)
23 | R 2 (#452742)
24 | U 3 (#148e01)
25 | R 7 (#1dcbc2)
26 | U 4 (#15b8f3)
27 | R 7 (#4e9e80)
28 | D 8 (#3ed153)
29 | R 5 (#2bc4a0)
30 | D 8 (#29b6c3)
31 | R 2 (#5cdb42)
32 | D 5 (#33cac3)
33 | R 4 (#1a4f52)
34 | U 5 (#135e03)
35 | R 3 (#1d0ca0)
36 | D 5 (#396ca3)
37 | R 5 (#465630)
38 | U 3 (#1dd753)
39 | R 2 (#6362d2)
40 | U 5 (#2fd793)
41 | R 3 (#2a5610)
42 | U 7 (#0f29f3)
43 | R 8 (#66eb00)
44 | D 7 (#20d683)
45 | R 3 (#15fcf0)
46 | U 6 (#43a7d3)
47 | R 2 (#441e02)
48 | U 4 (#2f31a3)
49 | R 10 (#300850)
50 | U 2 (#39d293)
51 | R 2 (#41d100)
52 | U 6 (#320743)
53 | L 7 (#71d952)
54 | U 4 (#193043)
55 | L 3 (#441e00)
56 | U 7 (#2a7503)
57 | L 2 (#07b292)
58 | U 3 (#299211)
59 | R 7 (#64aa22)
60 | U 5 (#299213)
61 | L 10 (#108b42)
62 | U 3 (#0772c3)
63 | L 2 (#2a5612)
64 | U 3 (#0fab63)
65 | L 6 (#663a30)
66 | U 4 (#40d973)
67 | L 3 (#0d5e60)
68 | U 3 (#285103)
69 | L 9 (#451af0)
70 | U 4 (#1d4e43)
71 | L 4 (#451af2)
72 | U 8 (#39a913)
73 | R 5 (#0d5e62)
74 | U 4 (#290d13)
75 | R 4 (#113652)
76 | U 9 (#45ace3)
77 | R 3 (#5503e2)
78 | U 5 (#0c8c43)
79 | R 7 (#68f4e0)
80 | D 5 (#119833)
81 | R 9 (#0e35b0)
82 | U 4 (#56a843)
83 | R 6 (#44ca32)
84 | U 4 (#0d16f3)
85 | L 9 (#42fdb2)
86 | U 4 (#575f23)
87 | L 5 (#2ff902)
88 | U 5 (#0470b3)
89 | L 2 (#270252)
90 | D 5 (#091833)
91 | L 6 (#2ff720)
92 | U 5 (#2836c3)
93 | R 3 (#659ea2)
94 | U 6 (#2c7113)
95 | L 5 (#659ea0)
96 | U 6 (#2827b3)
97 | R 5 (#2ff722)
98 | U 7 (#1c1a43)
99 | R 3 (#2497b0)
100 | D 7 (#299d33)
101 | R 2 (#0ec8f0)
102 | D 5 (#49a851)
103 | R 3 (#37d650)
104 | D 7 (#49a853)
105 | R 8 (#404e10)
106 | U 5 (#06e5c3)
107 | R 3 (#409362)
108 | U 4 (#391103)
109 | L 7 (#2ddba0)
110 | U 3 (#0bc9e1)
111 | R 8 (#5a03e0)
112 | U 8 (#0bc9e3)
113 | L 8 (#41cce0)
114 | U 5 (#0dc663)
115 | R 7 (#1e9d10)
116 | U 3 (#438d13)
117 | R 3 (#30fd72)
118 | U 8 (#4baeb3)
119 | R 6 (#0a2600)
120 | U 10 (#01d6e3)
121 | L 5 (#430fd0)
122 | U 4 (#0a6f73)
123 | L 4 (#1b14d2)
124 | U 7 (#634bb3)
125 | R 9 (#322102)
126 | D 5 (#2a2623)
127 | R 4 (#4f02b2)
128 | D 5 (#244c11)
129 | R 3 (#30e472)
130 | D 6 (#134061)
131 | R 6 (#4d5ef0)
132 | D 5 (#22ea21)
133 | L 7 (#05c6b0)
134 | D 6 (#33b3a1)
135 | L 2 (#164612)
136 | D 4 (#2d0f61)
137 | R 6 (#3cdf92)
138 | D 8 (#2a2d41)
139 | R 6 (#3764e2)
140 | U 3 (#32fca3)
141 | R 5 (#6b2fd0)
142 | U 6 (#3c6513)
143 | R 4 (#6b2fd2)
144 | U 9 (#151243)
145 | R 3 (#218012)
146 | U 9 (#3fe151)
147 | R 2 (#12b722)
148 | U 3 (#0afd41)
149 | R 5 (#5b3f12)
150 | U 9 (#31f0c1)
151 | R 4 (#05e1c2)
152 | U 5 (#096b91)
153 | R 3 (#381280)
154 | U 6 (#1f8291)
155 | R 4 (#381282)
156 | U 3 (#279b01)
157 | R 5 (#030c92)
158 | U 7 (#417ff1)
159 | R 6 (#5b1152)
160 | U 3 (#1add53)
161 | R 3 (#0b3ee2)
162 | U 6 (#4ce103)
163 | R 6 (#0b3ee0)
164 | D 5 (#4d66d3)
165 | R 3 (#27a722)
166 | D 3 (#05ab03)
167 | R 4 (#373e50)
168 | D 5 (#6c3d33)
169 | R 4 (#373e52)
170 | D 9 (#080ec3)
171 | R 6 (#2c82e2)
172 | D 6 (#1731c3)
173 | R 7 (#0b4b60)
174 | D 8 (#22b143)
175 | R 6 (#61da00)
176 | D 7 (#407ed1)
177 | L 5 (#075b90)
178 | D 4 (#407ed3)
179 | L 3 (#5f6480)
180 | D 9 (#22b141)
181 | L 6 (#3012b0)
182 | U 5 (#0a8cb3)
183 | L 4 (#318600)
184 | U 3 (#479bf3)
185 | R 4 (#324280)
186 | U 7 (#2c86a3)
187 | L 7 (#2072a0)
188 | D 4 (#624cb3)
189 | L 9 (#0f7db0)
190 | D 6 (#21abc3)
191 | R 9 (#1325d0)
192 | D 5 (#1f8a41)
193 | L 4 (#2f6ec0)
194 | D 5 (#57a2d1)
195 | L 4 (#3b9370)
196 | U 7 (#25de21)
197 | L 4 (#0cbdd0)
198 | U 3 (#2cfa43)
199 | L 4 (#130402)
200 | D 10 (#361463)
201 | L 5 (#130400)
202 | U 5 (#39fc93)
203 | L 3 (#246bb0)
204 | D 2 (#4abf91)
205 | L 7 (#5b17e0)
206 | D 3 (#3c6ab1)
207 | L 6 (#068d42)
208 | D 5 (#148a91)
209 | L 3 (#41dfe0)
210 | U 10 (#512d51)
211 | L 2 (#262db0)
212 | U 2 (#27b471)
213 | L 4 (#036982)
214 | D 12 (#31a3d1)
215 | L 4 (#036980)
216 | D 3 (#1aee01)
217 | R 10 (#262db2)
218 | D 2 (#1409e1)
219 | R 3 (#41dfe2)
220 | D 3 (#209c71)
221 | L 4 (#068d40)
222 | D 6 (#446921)
223 | R 4 (#10b5a2)
224 | D 2 (#0d6221)
225 | R 5 (#4a6242)
226 | D 3 (#10eb81)
227 | L 4 (#1e26e0)
228 | D 3 (#23fd11)
229 | L 5 (#307170)
230 | D 5 (#716191)
231 | R 3 (#387cb0)
232 | D 8 (#04bda1)
233 | R 8 (#10e9d0)
234 | U 2 (#515da1)
235 | R 2 (#3b4450)
236 | U 9 (#4e6751)
237 | R 5 (#31af90)
238 | D 3 (#2e2951)
239 | R 4 (#6073a0)
240 | D 8 (#06e601)
241 | R 4 (#0302c0)
242 | D 4 (#335f81)
243 | R 11 (#22a740)
244 | D 5 (#3e4ca3)
245 | R 11 (#23ed32)
246 | D 3 (#5b3c03)
247 | R 6 (#23ed30)
248 | D 7 (#1d4d83)
249 | R 5 (#5ae0c0)
250 | D 5 (#3ab641)
251 | R 3 (#3c91e2)
252 | D 8 (#059f81)
253 | R 5 (#0f93c0)
254 | D 6 (#34d761)
255 | R 2 (#022170)
256 | D 6 (#371071)
257 | R 6 (#022172)
258 | D 3 (#09d461)
259 | R 3 (#0f93c2)
260 | U 10 (#0cf061)
261 | R 2 (#3c91e0)
262 | U 4 (#23bc51)
263 | R 4 (#32d760)
264 | U 8 (#3eea73)
265 | R 3 (#099c62)
266 | D 6 (#45c4f3)
267 | R 4 (#099c60)
268 | D 5 (#296c33)
269 | R 8 (#00bad0)
270 | D 8 (#3f4d53)
271 | L 8 (#357a80)
272 | D 3 (#0cc741)
273 | R 6 (#551fb0)
274 | D 9 (#0cc743)
275 | R 3 (#59a840)
276 | D 5 (#039fc1)
277 | R 7 (#1bbd50)
278 | D 6 (#24ae01)
279 | L 5 (#233910)
280 | D 7 (#300613)
281 | L 9 (#39f1b0)
282 | D 3 (#300611)
283 | L 6 (#1cd0e0)
284 | D 3 (#3666a1)
285 | L 4 (#225770)
286 | D 4 (#5eb463)
287 | L 3 (#3d91d0)
288 | U 8 (#4ab363)
289 | L 2 (#59a060)
290 | U 2 (#2950b3)
291 | L 7 (#0d05d2)
292 | U 5 (#178e73)
293 | L 6 (#380f22)
294 | D 5 (#5120f3)
295 | L 3 (#277032)
296 | D 4 (#060761)
297 | R 8 (#0e3912)
298 | D 4 (#4b1991)
299 | R 7 (#4d9402)
300 | D 5 (#178e71)
301 | R 12 (#4e61a2)
302 | D 5 (#5bb183)
303 | R 6 (#00f842)
304 | D 5 (#5fdd03)
305 | R 4 (#10c532)
306 | D 2 (#05b483)
307 | R 4 (#3795e2)
308 | D 11 (#2ed143)
309 | L 4 (#3b2da0)
310 | U 6 (#45ab83)
311 | L 7 (#588760)
312 | U 9 (#129a53)
313 | L 4 (#4066c2)
314 | D 7 (#0d9733)
315 | L 4 (#2489a2)
316 | D 8 (#0d9731)
317 | L 7 (#2ec4a2)
318 | D 6 (#1f12d3)
319 | R 4 (#1fe602)
320 | D 7 (#057393)
321 | R 2 (#3771c0)
322 | D 6 (#056461)
323 | R 4 (#05e3a0)
324 | D 2 (#5cfe23)
325 | R 3 (#4068c0)
326 | D 7 (#2b4153)
327 | R 4 (#35c120)
328 | D 6 (#2d0891)
329 | R 7 (#6e6c62)
330 | D 8 (#365941)
331 | L 9 (#6e6c60)
332 | D 6 (#24dda1)
333 | L 2 (#2d0b50)
334 | D 4 (#056463)
335 | R 4 (#277d60)
336 | D 3 (#40bc61)
337 | R 4 (#2e7130)
338 | U 6 (#40bc63)
339 | R 11 (#497400)
340 | D 6 (#0ed393)
341 | R 5 (#66d050)
342 | D 7 (#437e73)
343 | R 3 (#21fc40)
344 | U 8 (#0d7663)
345 | R 4 (#4ea030)
346 | U 5 (#3ee1b1)
347 | L 4 (#239040)
348 | U 3 (#3160d1)
349 | L 10 (#3f5060)
350 | U 7 (#248831)
351 | R 7 (#1ba900)
352 | U 4 (#109051)
353 | R 7 (#2b1820)
354 | U 4 (#345291)
355 | R 11 (#2fa5c2)
356 | D 3 (#184f81)
357 | L 6 (#2fa5c0)
358 | D 8 (#3ce4d1)
359 | L 2 (#2b1822)
360 | D 7 (#5472d1)
361 | R 8 (#22eaa0)
362 | D 5 (#0d2f21)
363 | R 8 (#351920)
364 | U 9 (#5125d1)
365 | R 5 (#08c970)
366 | D 7 (#133c21)
367 | R 3 (#484fe0)
368 | D 7 (#0113c1)
369 | R 8 (#6f62b0)
370 | D 3 (#16f621)
371 | R 3 (#2a66c0)
372 | U 5 (#105451)
373 | R 6 (#36cc80)
374 | D 5 (#6d8671)
375 | R 4 (#229ce0)
376 | D 2 (#31df41)
377 | R 6 (#5f50c0)
378 | U 9 (#386501)
379 | L 2 (#1f0b12)
380 | U 4 (#36ae41)
381 | L 10 (#1731f2)
382 | U 5 (#517921)
383 | L 9 (#40dd62)
384 | U 6 (#517923)
385 | L 7 (#25dd22)
386 | U 7 (#0914d1)
387 | R 6 (#462962)
388 | U 9 (#378011)
389 | R 2 (#1e6780)
390 | U 3 (#179711)
391 | R 5 (#63ed30)
392 | U 2 (#481f81)
393 | R 4 (#2cf690)
394 | D 7 (#4dfc31)
395 | R 4 (#37ee50)
396 | D 3 (#3e8381)
397 | R 2 (#0bacb2)
398 | D 4 (#0f4b31)
399 | R 3 (#1304c2)
400 | U 4 (#1b2bf1)
401 | R 2 (#201462)
402 | U 4 (#3e6cc3)
403 | R 6 (#48c9b2)
404 | U 10 (#3e6cc1)
405 | L 6 (#0945f2)
406 | U 9 (#2f82d1)
407 | R 5 (#25f520)
408 | D 2 (#13e573)
409 | R 4 (#532820)
410 | D 4 (#13e571)
411 | R 7 (#0c0b80)
412 | D 7 (#385b71)
413 | L 7 (#0bacb0)
414 | D 6 (#433611)
415 | R 2 (#17ac02)
416 | D 3 (#066be3)
417 | R 6 (#563452)
418 | D 4 (#492883)
419 | R 7 (#103102)
420 | U 4 (#4f9461)
421 | R 3 (#3f9812)
422 | D 3 (#4889a1)
423 | R 9 (#272882)
424 | D 4 (#315081)
425 | R 2 (#52c142)
426 | D 9 (#2d10a1)
427 | R 4 (#0346e2)
428 | D 2 (#107821)
429 | R 9 (#4efeb2)
430 | D 2 (#53bca1)
431 | R 2 (#3c0e72)
432 | D 6 (#49f991)
433 | R 5 (#112cf2)
434 | D 2 (#243621)
435 | R 8 (#6b51e2)
436 | D 9 (#341b41)
437 | L 3 (#1c3d42)
438 | D 6 (#27e271)
439 | L 6 (#267432)
440 | D 3 (#52b6c1)
441 | L 4 (#359980)
442 | D 11 (#1ebe91)
443 | L 3 (#3e14a2)
444 | U 3 (#211261)
445 | L 3 (#3452d2)
446 | U 11 (#225291)
447 | L 5 (#27c720)
448 | D 6 (#707e51)
449 | L 5 (#3c60d0)
450 | D 7 (#707e53)
451 | L 5 (#0e3f80)
452 | D 7 (#2e3e91)
453 | L 5 (#3b6e30)
454 | D 4 (#32e213)
455 | L 4 (#375b72)
456 | D 7 (#1fe7a3)
457 | L 3 (#375b70)
458 | U 5 (#3d9863)
459 | L 5 (#3cfba0)
460 | U 8 (#17f261)
461 | L 3 (#112cf0)
462 | U 5 (#0f5b11)
463 | L 3 (#4020d0)
464 | D 6 (#2e4231)
465 | L 8 (#053e90)
466 | D 2 (#4fc851)
467 | L 10 (#2ce8f2)
468 | D 5 (#1d5fa1)
469 | L 6 (#187672)
470 | D 6 (#579551)
471 | L 7 (#221cd2)
472 | U 6 (#2dd571)
473 | L 3 (#6886f2)
474 | D 6 (#321921)
475 | L 2 (#42b222)
476 | D 5 (#075a03)
477 | L 11 (#422fd2)
478 | D 5 (#595193)
479 | L 8 (#17a072)
480 | U 5 (#3c2423)
481 | L 6 (#542ef2)
482 | U 5 (#02c373)
483 | L 4 (#2a4f02)
484 | U 7 (#402271)
485 | L 2 (#0cf6b0)
486 | U 4 (#13a071)
487 | L 3 (#277b10)
488 | D 7 (#3c9e81)
489 | L 6 (#4f7880)
490 | D 8 (#0b1901)
491 | L 3 (#340292)
492 | D 3 (#076ff1)
493 | L 4 (#2118f2)
494 | D 3 (#076ff3)
495 | L 8 (#2ecec2)
496 | U 6 (#0418c1)
497 | L 5 (#368892)
498 | U 5 (#382671)
499 | L 7 (#454ec2)
500 | U 10 (#42c991)
501 | L 4 (#0e86d0)
502 | D 7 (#1d62c1)
503 | L 8 (#0e86d2)
504 | U 8 (#3751a1)
505 | L 8 (#321af2)
506 | D 8 (#64b3f3)
507 | L 5 (#3f1cf2)
508 | D 3 (#3ae963)
509 | L 4 (#3dbbc2)
510 | D 7 (#008451)
511 | R 7 (#0f9032)
512 | D 5 (#67c611)
513 | R 11 (#0f9030)
514 | U 5 (#3752f1)
515 | R 7 (#0ac792)
516 | D 8 (#3cb351)
517 | R 2 (#347a52)
518 | D 3 (#382911)
519 | R 3 (#5b34d2)
520 | D 2 (#49b0b1)
521 | R 10 (#0de010)
522 | D 3 (#1d3fc3)
523 | R 5 (#357230)
524 | D 7 (#280c73)
525 | R 5 (#6def10)
526 | U 5 (#280c71)
527 | R 5 (#235bc0)
528 | U 7 (#1d3fc1)
529 | R 9 (#5d5ca0)
530 | D 4 (#15abb1)
531 | R 3 (#5cbf60)
532 | D 10 (#41dfa1)
533 | L 2 (#232ec2)
534 | D 2 (#3511d1)
535 | L 6 (#232ec0)
536 | D 6 (#575671)
537 | L 6 (#44f6a2)
538 | D 6 (#5aa8f1)
539 | R 6 (#310932)
540 | D 6 (#10c091)
541 | L 5 (#1f8ac2)
542 | D 3 (#21fc31)
543 | L 5 (#2e3ca2)
544 | U 5 (#277bf3)
545 | L 9 (#0bfd22)
546 | U 5 (#277bf1)
547 | R 9 (#390102)
548 | U 7 (#33a471)
549 | L 5 (#041602)
550 | U 4 (#235f11)
551 | L 9 (#20fd92)
552 | D 3 (#69cb71)
553 | L 4 (#333e82)
554 | D 10 (#039d51)
555 | L 6 (#00df02)
556 | D 7 (#602a01)
557 | L 6 (#44dae2)
558 | D 4 (#342721)
559 | R 6 (#088ea2)
560 | D 4 (#2c5b91)
561 | L 6 (#2e3352)
562 | D 6 (#47d9c1)
563 | L 4 (#45d272)
564 | U 11 (#2895e3)
565 | L 2 (#1bcf12)
566 | U 3 (#2dc413)
567 | L 6 (#1bcf10)
568 | D 4 (#3c31b3)
569 | L 8 (#032bb2)
570 | U 7 (#486c23)
571 | L 2 (#032bb0)
572 | U 4 (#3d4b73)
573 | L 3 (#5b1c32)
574 | U 4 (#4ae353)
575 | L 2 (#167e12)
576 | U 8 (#13b6d3)
577 | L 4 (#719a40)
578 | D 7 (#358da3)
579 | L 2 (#5e4700)
580 | D 5 (#448473)
581 | L 4 (#2b0390)
582 | U 3 (#437863)
583 | L 9 (#3fe5a0)
584 | U 2 (#104f93)
585 | L 7 (#1ba080)
586 | U 3 (#104353)
587 | L 7 (#281e40)
588 | U 10 (#4f3f93)
589 | R 7 (#39ede2)
590 | U 6 (#6fa903)
591 | L 4 (#39ede0)
592 | U 7 (#0fb493)
593 | L 6 (#0bb5d2)
594 | U 7 (#03a6a1)
595 | L 5 (#6268d2)
596 | U 2 (#03a6a3)
597 | L 10 (#1585c2)
598 | U 6 (#1f2823)
599 | L 4 (#42ca62)
600 | U 5 (#3e7c83)
601 | L 6 (#1e1160)
602 | D 5 (#068313)
603 | L 5 (#414f22)
604 | U 4 (#4bb1f3)
605 | L 5 (#414f20)
606 | U 7 (#2ea7c3)
607 | L 2 (#1e1162)
608 | U 4 (#06a053)
609 | L 4 (#468032)
610 | U 5 (#0ab563)
611 | L 9 (#1898e0)
612 | U 3 (#124ae3)
613 | L 4 (#324bc0)
614 | D 3 (#53bac3)
615 | L 4 (#3f02b2)
616 | D 8 (#097a11)
617 | R 4 (#68a852)
618 | D 4 (#097a13)
619 | L 2 (#06d032)
620 | D 4 (#2ce463)
621 | L 3 (#5e5b10)
622 | U 3 (#479663)
623 | L 3 (#4f2c20)
624 | U 10 (#059913)
625 | L 2 (#00f400)
626 | U 6 (#095173)
627 | L 4 (#324bc2)
628 | U 4 (#294473)
629 | L 10 (#1898e2)
630 | U 2 (#064dd3)
631 | L 2 (#0a4e42)
632 | U 4 (#41d683)
633 | R 4 (#0a9762)
634 | U 2 (#075d03)
635 | R 8 (#312c42)
636 | U 5 (#29ec71)
637 | L 5 (#32d172)
638 | U 5 (#1f4711)
639 | L 8 (#313232)
640 | U 4 (#3932b1)
641 | R 5 (#1c2b02)
642 | U 9 (#473081)
643 | L 5 (#049552)
644 | U 6 (#09f6b1)
645 | L 5 (#025212)
646 | U 6 (#15d451)
647 | L 4 (#40ae22)
648 | U 7 (#6a1941)
649 | R 4 (#1b4c22)
650 | U 4 (#1411a3)
651 | L 7 (#63bc52)
652 | U 9 (#1411a1)
653 | L 8 (#0cb412)
654 | D 9 (#5ba4b1)
655 | L 4 (#35df62)
656 | U 9 (#311e33)
657 | L 4 (#206802)
658 | U 4 (#3496b3)
659 | L 4 (#678fd2)
660 | U 5 (#110833)
661 | L 5 (#4772e2)
662 | U 5 (#3aa053)
663 | L 3 (#5db2e0)
664 | U 3 (#2ce593)
665 | R 6 (#5db2e2)
666 | U 7 (#3c90c3)
667 | L 6 (#15c962)
668 | U 3 (#148ff3)
669 | L 4 (#64ab02)
670 | D 10 (#1990b3)
671 | L 2 (#1439a2)
672 | D 3 (#1cf7d3)
673 | L 4 (#1a0832)
674 | U 5 (#3e3f43)
675 |
--------------------------------------------------------------------------------
/src/day18/part1.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | def fill(lava, visited, width, height, x, y):
4 | seen = set()
5 | is_lava = True
6 |
7 | queue = [(x, y)]
8 |
9 | while len(queue) > 0:
10 | x, y = queue.pop()
11 |
12 | if (x, y) in seen:
13 | continue
14 |
15 | if lava[y][x]:
16 | continue
17 |
18 | if x == 0 or x == width - 1 or y == 0 or y == height - 1:
19 | is_lava = False
20 | continue
21 |
22 | seen.add((x, y))
23 |
24 | if x > 0:
25 | queue.append((x - 1, y))
26 |
27 | if x < width - 1:
28 | queue.append((x + 1, y))
29 |
30 | if y > 0:
31 | queue.append((x, y - 1))
32 |
33 | if y < height - 1:
34 | queue.append((x, y + 1))
35 |
36 | for x, y in seen:
37 | lava[y][x] = is_lava
38 | visited[y][x] = True
39 |
40 | def main() -> None:
41 | data = sys.stdin.read().strip()
42 |
43 | x, y = 0, 0
44 | loop = set()
45 |
46 | min_x = 1e9
47 | max_x = -1e9
48 | min_y = 1e9
49 | max_y = -1e9
50 |
51 | for line in data.split("\n"):
52 | direction, distance, _ = line.split(" ")
53 | distance = int(distance)
54 |
55 | dx = {"R": 1, "L": -1}.get(direction, 0)
56 | dy = {"D": 1, "U": -1}.get(direction, 0)
57 |
58 | for i in range(distance):
59 | x += dx
60 | y += dy
61 |
62 | loop.add((x, y))
63 |
64 | min_x = min(min_x, x)
65 | max_x = max(max_x, x)
66 | min_y = min(min_y, y)
67 | max_y = max(max_y, y)
68 |
69 | width = max_x - min_x + 1
70 | height = max_y - min_y + 1
71 |
72 | loop = [(x + abs(min_x), y + abs(min_y)) for x, y in loop]
73 |
74 | lava = [[False] * width for _ in range(height)]
75 | visited = [[False] * width for _ in range(height)]
76 |
77 | for x, y in loop:
78 | lava[y][x] = True
79 | visited[y][x] = True
80 |
81 | for y in range(height):
82 | for x in range(width):
83 | if not visited[y][x]:
84 | fill(lava, visited, width, height, x, y)
85 |
86 | print(sum(sum(row) for row in lava))
87 |
88 | if __name__ == "__main__":
89 | main()
90 |
--------------------------------------------------------------------------------
/src/day18/part2.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from shapely.geometry.polygon import *
3 |
4 | def main() -> None:
5 | data = sys.stdin.read().strip()
6 |
7 | x, y = 0, 0
8 | loop = []
9 |
10 | for line in data.split("\n"):
11 | color = line.split(" ")[-1]
12 | distance = int(color[2:-2], 16)
13 | direction = int(color[-2])
14 |
15 | dx = [1, 0, -1, 0][direction]
16 | dy = [0, 1, 0, -1][direction]
17 |
18 | x += dx * distance
19 | y += dy * distance
20 |
21 | loop.append((x, y))
22 |
23 | poly = Polygon(loop)
24 | print(int(poly.area + poly.length // 2 + 1))
25 |
26 | if __name__ == "__main__":
27 | main()
28 |
--------------------------------------------------------------------------------
/src/day19/example.txt:
--------------------------------------------------------------------------------
1 | px{a<2006:qkq,m>2090:A,rfg}
2 | pv{a>1716:R,A}
3 | lnx{m>1548:A,A}
4 | rfg{s<537:gd,x>2440:R,A}
5 | qs{s>3448:A,lnx}
6 | qkq{x<1416:A,crn}
7 | crn{x>2662:A,R}
8 | in{s<1351:px,qqz}
9 | qqz{s>2770:qs,m<1801:hdj,R}
10 | gd{a>3333:R,R}
11 | hdj{m>838:A,pv}
12 |
13 | {x=787,m=2655,a=1222,s=2876}
14 | {x=1679,m=44,a=2067,s=496}
15 | {x=2036,m=264,a=79,s=2244}
16 | {x=2461,m=1339,a=466,s=291}
17 | {x=2127,m=1623,a=2188,s=1013}
18 |
--------------------------------------------------------------------------------
/src/day19/part1.py:
--------------------------------------------------------------------------------
1 | import re
2 | import sys
3 |
4 | def main() -> None:
5 | data = sys.stdin.read().strip()
6 |
7 | sections = data.split("\n\n")
8 |
9 | workflows = {}
10 | for line in sections[0].split("\n"):
11 | id, steps = line.split("{")
12 | workflows[id] = []
13 |
14 | for step in steps[:-1].split(","):
15 | done = False
16 |
17 | for ch in "xmas":
18 | for op in "<>":
19 | if step.startswith(ch + op):
20 | value = int(step[2:].split(":")[0])
21 | nxt = step.split(":")[1]
22 | workflows[id].append((ch, op, value, nxt))
23 | done = True
24 |
25 | if not done:
26 | workflows[id].append((step,))
27 |
28 | t = 0
29 | for part in sections[1].split("\n"):
30 | nums = list(map(int, re.findall(r"(\d+)", part)))
31 | d = {"x": nums[0], "m": nums[1], "a": nums[2], "s": nums[3]}
32 |
33 | workflow = "in"
34 | while workflow != "A" and workflow != "R":
35 | for step in workflows[workflow]:
36 | if len(step) == 4 and step[1] == "<" and d[step[0]] < step[2]:
37 | workflow = step[3]
38 | break
39 | elif len(step) == 4 and step[1] == ">" and d[step[0]] > step[2]:
40 | workflow = step[3]
41 | break
42 | elif len(step) == 1:
43 | workflow = step[0]
44 | break
45 |
46 | if workflow == "A":
47 | t += sum(nums)
48 |
49 | print(t)
50 |
51 | if __name__ == "__main__":
52 | main()
53 |
--------------------------------------------------------------------------------
/src/day19/part2.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from math import *
3 |
4 | def main() -> None:
5 | data = sys.stdin.read().strip()
6 |
7 | sections = data.split("\n\n")
8 |
9 | workflows = {}
10 | for line in sections[0].split("\n"):
11 | id, steps = line.split("{")
12 | workflows[id] = []
13 |
14 | for step in steps[:-1].split(","):
15 | done = False
16 |
17 | for ch in "xmas":
18 | for op in "<>":
19 | if step.startswith(ch + op):
20 | value = int(step[2:].split(":")[0])
21 | nxt = step.split(":")[1]
22 | workflows[id].append((ch, op, value, nxt))
23 | done = True
24 |
25 | if not done:
26 | workflows[id].append((step,))
27 |
28 | queue = [("in", 0, {ch: (1, 4000) for ch in "xmas"})]
29 | t = 0
30 |
31 | while len(queue) > 0:
32 | workflow, idx, bounds = queue.pop()
33 |
34 | if workflow == "A":
35 | t += prod(bounds[ch][1] - bounds[ch][0] + 1 for ch in "xmas")
36 |
37 | if workflow in "AR" or idx >= len(workflows[workflow]):
38 | continue
39 |
40 | step = workflows[workflow][idx]
41 |
42 | if len(step) == 4 and step[1] == "<":
43 | iff = bounds.copy()
44 | els = bounds
45 |
46 | iff[step[0]] = (iff[step[0]][0], step[2] - 1)
47 | els[step[0]] = (step[2], els[step[0]][1])
48 |
49 | queue.append((step[3], 0, iff))
50 | queue.append((workflow, idx + 1, els))
51 | elif len(step) == 4 and step[1] == ">":
52 | iff = bounds.copy()
53 | els = bounds
54 |
55 | iff[step[0]] = (step[2] + 1, iff[step[0]][1])
56 | els[step[0]] = (els[step[0]][0], step[2])
57 |
58 | queue.append((step[3], 0, iff))
59 | queue.append((workflow, idx + 1, els))
60 | elif len(step) == 1:
61 | queue.append((step[0], 0, bounds))
62 |
63 | print(t)
64 |
65 | if __name__ == "__main__":
66 | main()
67 |
--------------------------------------------------------------------------------
/src/day20/example.txt:
--------------------------------------------------------------------------------
1 | broadcaster -> a
2 | %a -> inv, con
3 | &inv -> b
4 | %b -> con
5 | &con -> output
6 |
--------------------------------------------------------------------------------
/src/day20/input.txt:
--------------------------------------------------------------------------------
1 | %tx -> dx
2 | %nx -> fn, rn
3 | %nr -> cj, mh
4 | %nk -> jt, vk
5 | %mv -> fk, rn
6 | &pz -> kt, pg, mb, vr, hp, jp, tx
7 | &jt -> fb, zb, jq, sv, lp
8 | %vp -> lp, jt
9 | &qs -> gf
10 | %lj -> jt, dt
11 | %jh -> mh
12 | %xc -> nx
13 | %hx -> xb
14 | %kd -> pz, pp
15 | %jq -> jt, qt
16 | %lp -> jm
17 | %ph -> mb, pz
18 | &sv -> gf
19 | %ff -> xc
20 | %th -> mh, hx
21 | %kt -> ct
22 | %ct -> kd, pz
23 | &mh -> bc, qs, hx, xb, nv
24 | &pg -> gf
25 | %fn -> kn
26 | %sk -> hr
27 | %nv -> mh, th
28 | %dx -> pz, ph
29 | broadcaster -> bx, jq, nv, jp
30 | %dt -> jt, zb
31 | %fx -> sk, rn
32 | %rv -> rn
33 | %gv -> mh, nr
34 | %fk -> rn, rv
35 | %cj -> mh, vh
36 | %xk -> jt, nk
37 | %vh -> mh, jh
38 | %zb -> fb
39 | %mb -> jc
40 | %kn -> rn, mv
41 | %jc -> pz, kt
42 | &sp -> gf
43 | %hp -> tx
44 | %jf -> bc, mh
45 | %fb -> vp
46 | %xm -> mh, gv
47 | %jm -> jt, xk
48 | %vr -> hp
49 | %hr -> ff
50 | %jp -> pz, vr
51 | &rn -> fn, hr, bx, ff, xc, sp, sk
52 | %pp -> pz
53 | &gf -> rx
54 | %xb -> jf
55 | %bx -> rn, fx
56 | %bc -> xm
57 | %qt -> lj, jt
58 | %vk -> jt
59 |
--------------------------------------------------------------------------------
/src/day20/part1.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from dataclasses import *
3 |
4 | @dataclass
5 | class FlipFlopModule:
6 | id: str
7 | state: bool
8 | targets: list[str]
9 |
10 | def update(self, src: str, high: bool, counts: dict[bool, int], nxt: list[str]) -> None:
11 | counts[high] += 1
12 |
13 | if high:
14 | return
15 |
16 | self.state = not self.state
17 | nxt.append(self.id)
18 |
19 | def pulse(self, modules, counts: dict[bool, int], nxt: list[str]) -> None:
20 | for trg in self.targets:
21 | if trg not in modules:
22 | counts[self.state] += 1
23 | continue
24 |
25 | modules[trg].update(self.id, self.state, counts, nxt)
26 |
27 | @dataclass
28 | class ConjunctionModule:
29 | id: str
30 | high: dict[str, bool]
31 | targets: list[str]
32 |
33 | def update(self, src: str, high: bool, counts: dict[bool, int], nxt: list[str]) -> None:
34 | counts[high] += 1
35 | self.high[src] = high
36 | nxt.append(self.id)
37 |
38 | def pulse(self, modules, counts: dict[bool, int], nxt: list[str]) -> None:
39 | send_high = not all(self.high.values())
40 | for trg in self.targets:
41 | if trg not in modules:
42 | counts[send_high] += 1
43 | continue
44 |
45 | modules[trg].update(self.id, send_high, counts, nxt)
46 |
47 | @dataclass
48 | class BroadcastModule:
49 | id: str
50 | targets: list[str]
51 |
52 | last_high: bool = False
53 |
54 | def update(self, src: str, high: bool, counts: dict[bool, int], nxt: list[str]) -> None:
55 | counts[high] += 1
56 | self.last_high = high
57 | nxt.append(self.id)
58 |
59 | def pulse(self, modules, counts: dict[bool, int], nxt: list[str]) -> None:
60 | for trg in self.targets:
61 | if trg not in modules:
62 | counts[self.last_high] += 1
63 | continue
64 |
65 | modules[trg].update(self.id, self.last_high, counts, nxt)
66 |
67 | def main() -> None:
68 | data = sys.stdin.read().strip()
69 |
70 | modules = {}
71 | for line in data.split("\n"):
72 | src, trg = line.split(" -> ")
73 | trg = trg.split(", ")
74 |
75 | if src[0] == "%":
76 | module = FlipFlopModule(src[1:], False, trg)
77 | elif src[0] == "&":
78 | module = ConjunctionModule(src[1:], {}, trg)
79 | else:
80 | module = BroadcastModule(src, trg)
81 |
82 | modules[module.id] = module
83 |
84 | for src_module in modules.values():
85 | if not isinstance(src_module, ConjunctionModule):
86 | for trg in src_module.targets:
87 | trg_module = modules[trg]
88 | if isinstance(trg_module, ConjunctionModule):
89 | trg_module.high[src_module.id] = False
90 |
91 | counts = {False: 0, True: 0}
92 |
93 | for _ in range(1000):
94 | nxt = []
95 | modules["broadcaster"].update("button", False, counts, nxt)
96 |
97 | while len(nxt) > 0:
98 | new_nxt = []
99 |
100 | for id in nxt:
101 | modules[id].pulse(modules, counts, new_nxt)
102 |
103 | nxt = new_nxt
104 |
105 | print(counts[False] * counts[True])
106 |
107 | if __name__ == "__main__":
108 | main()
109 |
--------------------------------------------------------------------------------
/src/day20/part2.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from dataclasses import *
3 | from math import *
4 |
5 | check = ["qs", "sv", "pg", "sp"]
6 |
7 | @dataclass
8 | class FlipFlopModule:
9 | id: str
10 | state: bool
11 | targets: list[str]
12 |
13 | def update(self, src: str, high: bool, nxt: list[str], cycles: dict[str, list[int]], presses: int) -> None:
14 | if high:
15 | return
16 |
17 | self.state = not self.state
18 | nxt.append(self.id)
19 |
20 | def pulse(self, modules, nxt: list[str], cycles: dict[str, list[int]], presses: int) -> None:
21 | for trg in self.targets:
22 | if trg not in modules:
23 | continue
24 |
25 | modules[trg].update(self.id, self.state, nxt, cycles, presses)
26 |
27 | @dataclass
28 | class ConjunctionModule:
29 | id: str
30 | high: dict[str, bool]
31 | targets: list[str]
32 |
33 | def update(self, src: str, high: bool, nxt: list[str], cycles: dict[str, list[int]], presses: int) -> None:
34 | self.high[src] = high
35 | nxt.append(self.id)
36 |
37 | def pulse(self, modules, nxt: list[str], cycles: dict[str, list[int]], presses: int) -> None:
38 | send_high = not all(self.high.values())
39 |
40 | if send_high and self.id in check and self.id not in cycles:
41 | cycles[self.id] = presses
42 |
43 | for trg in self.targets:
44 | if trg not in modules:
45 | continue
46 |
47 | modules[trg].update(self.id, send_high, nxt, cycles, presses)
48 |
49 | @dataclass
50 | class BroadcastModule:
51 | id: str
52 | targets: list[str]
53 |
54 | last_high: bool = False
55 |
56 | def update(self, src: str, high: bool, nxt: list[str], cycles: dict[str, list[int]], presses: int) -> None:
57 | self.last_high = high
58 | nxt.append(self.id)
59 |
60 | def pulse(self, modules, nxt: list[str], cycles: dict[str, list[int]], presses: int) -> None:
61 | for trg in self.targets:
62 | if trg not in modules:
63 | continue
64 |
65 | modules[trg].update(self.id, self.last_high, nxt, cycles, presses)
66 |
67 | def main() -> None:
68 | data = sys.stdin.read().strip()
69 |
70 | modules = {}
71 | for line in data.split("\n"):
72 | src, trg = line.split(" -> ")
73 | trg = trg.split(", ")
74 |
75 | if src[0] == "%":
76 | module = FlipFlopModule(src[1:], False, trg)
77 | elif src[0] == "&":
78 | module = ConjunctionModule(src[1:], {}, trg)
79 | else:
80 | module = BroadcastModule(src, trg)
81 |
82 | modules[module.id] = module
83 |
84 | for src_module in modules.values():
85 | for trg in src_module.targets:
86 | if trg not in modules:
87 | continue
88 |
89 | trg_module = modules[trg]
90 | if isinstance(trg_module, ConjunctionModule):
91 | trg_module.high[src_module.id] = False
92 |
93 | cycles = {}
94 | presses = 0
95 |
96 | while len(cycles) < len(check):
97 | nxt = []
98 | modules["broadcaster"].update("button", False, nxt, cycles, presses)
99 | presses += 1
100 |
101 | while len(nxt) > 0:
102 | new_nxt = []
103 |
104 | for id in nxt:
105 | modules[id].pulse(modules, new_nxt, cycles, presses)
106 |
107 | nxt = new_nxt
108 |
109 | print(lcm(*cycles.values()))
110 |
111 | if __name__ == "__main__":
112 | main()
113 |
--------------------------------------------------------------------------------
/src/day20/solve.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import re
3 | from copy import deepcopy
4 | from math import gcd
5 | from collections import defaultdict, Counter, deque
6 | import heapq
7 | import math
8 | D = open(sys.argv[1]).read().strip()
9 | L = D.split('\n')
10 | G = [[c for c in row] for row in L]
11 | R = len(G)
12 | C = len(G[0])
13 |
14 | def lcm(xs):
15 | ans = 1
16 | for x in xs:
17 | ans = (ans*x)//math.gcd(x,ans)
18 | return ans
19 |
20 | TYP = {}
21 |
22 | R = {}
23 | for line in L:
24 | src, dest = line.split('->')
25 | src = src.strip()
26 | dest = dest.strip()
27 | dest = dest.split(', ')
28 | R[src] = dest
29 | TYP[src[1:]] = src[0]
30 |
31 | def adjust(y):
32 | if y in TYP:
33 | return TYP[y]+y
34 | else:
35 | return y
36 |
37 | FROM = {}
38 | INV = defaultdict(list)
39 | for x,ys in R.items():
40 | R[x] = [adjust(y) for y in ys]
41 | for y in R[x]:
42 | if y[0]=='&':
43 | if y not in FROM:
44 | FROM[y] = {}
45 | FROM[y][x] = 'lo'
46 | INV[y].append(x)
47 |
48 | assert len(INV['rx'])==1
49 | assert INV['rx'][0][0]=='&'
50 | WATCH = INV[INV['rx'][0]]
51 |
52 | lo = 0
53 | hi = 0
54 | Q = deque()
55 | ON = set()
56 | PREV = {}
57 | COUNT = defaultdict(int)
58 | TO_LCM = []
59 | for t in range(1, 10**8):
60 | Q.append(('broadcaster', 'button', 'lo'))
61 |
62 | while Q:
63 | x, from_, typ = Q.popleft()
64 |
65 | if typ=='lo':
66 | # Assume &df -> rx AND &a -> df, &b -> df, etc.
67 | # We want to know when &a,&b get 'lo' input, because then they will send a 'hi' input to &df
68 | # When will &df get lo inputs from all of them?
69 | # Assume that they get lo inputs on a perfect cycle and that df must get a 'hi' input from all of them on the same
70 | # timestamp. I assume they get a lot of 'hi' inputs on other timestamps that "reset" them?
71 | if x in PREV and COUNT[x]==2 and x in WATCH:
72 | #print(f't={t} cycle={t-PREV[x]} x={x} new_typ={new_typ}')
73 | TO_LCM.append(t-PREV[x])
74 | PREV[x] = t
75 | COUNT[x] += 1
76 | if len(TO_LCM) == len(WATCH):
77 | print(lcm(TO_LCM))
78 | sys.exit(0)
79 |
80 | if x=='rx' and typ=='lo':
81 | # won't happen; takes too long
82 | print(t+1)
83 |
84 | if typ=='lo':
85 | lo += 1
86 | else:
87 | hi += 1
88 |
89 | if x not in R:
90 | continue
91 | if x=='broadcaster':
92 | for y in R[x]:
93 | Q.append((y, x, typ))
94 | elif x[0]=='%':
95 | if typ=='hi':
96 | continue
97 | else:
98 | if x not in ON:
99 | ON.add(x)
100 | new_typ = 'hi'
101 | else:
102 | ON.discard(x)
103 | new_typ = 'lo'
104 | for y in R[x]:
105 | Q.append((y, x, new_typ))
106 | elif x[0]=='&':
107 | FROM[x][from_] = typ
108 | new_typ = ('lo' if all(y=='hi' for y in FROM[x].values()) else 'hi')
109 | for y in R[x]:
110 | Q.append((y, x, new_typ))
111 | else:
112 | assert False, x
113 | if t==1000:
114 | print(lo*hi)
115 |
--------------------------------------------------------------------------------
/src/day21/example.txt:
--------------------------------------------------------------------------------
1 | ...........
2 | .....###.#.
3 | .###.##..#.
4 | ..#.#...#..
5 | ....#.#....
6 | .##..S####.
7 | .##..#...#.
8 | .......##..
9 | .##.#.####.
10 | .##..##.##.
11 | ...........
12 |
--------------------------------------------------------------------------------
/src/day21/input.txt:
--------------------------------------------------------------------------------
1 | ...................................................................................................................................
2 | .#...............#..#...........#....#................................................##......##..........#..............#.........
3 | ......#...................#...#..#..........#.#.......#.....................#.............##.....#....#......#..#........#.......#.
4 | .#....#...#...#..#.................#.....#....#.#..#..........................#.....#...........#.............#....................
5 | .#.............................##...##......#........#......................#.........##...#..#.................##.........#.#.....
6 | ....#.#....#.................#..#..#........#...#.#.#..#......................#........#....#..............#.....##................
7 | ....#.....#......#....#.##....#.##........#.....#......#........................#..........#.............#...................#.....
8 | ...........#...........##.#..........##.....#...#...##........#.................#.......#.............#......#..#..........#.......
9 | ..#...........#.............#...................................#.....................##...........#..............#.#....#.........
10 | ....#.....#.........#....#......##..............#...#........#.##....#........#..#....#..........#...................#..........#..
11 | ............#.........#............#.#...........#.........#.........................#......#..#......#..#..#.......#.....#........
12 | .........#.................#........#..#.....#.............#........................#..#...#...#..#..#.....#...#..#......#....#....
13 | ..........#.#.#...............#.........#....##.#..........##......##...............#...#...###.##...#.......#..............#......
14 | ....#.........#...#........#.##.............#............#........#....##......................#..........#......#...#.......#.....
15 | .....##..#......#...#........#................#............................#..........#............##..#...#.....#..#........##....
16 | ..#........#.#.###.....#....#..#.....#.....#..........................#.....#...........#.##..........#..........#...#...#.........
17 | ...................#.................................#.....#....#...#...#...................#..#......#....#.#.##................#.
18 | .........#...#..#.#....#........#..........#................#.#....#...#.............................#..................#..#.#.....
19 | ...........#...#.#...................#..........................#..........#...................#...............#.###........#..#...
20 | ......#.......#...............#.........#.#...........#.####............#...#............#...##..##..........#............#........
21 | ..............................#..#.###..................#.....#......#..#.#..#...#..............#...#.....#.##..#.............#....
22 | ...............#.......#.#....#......#.#..........#..#.................#.#........#.......#.................#...............#...##.
23 | ............#.................#....................#............#....#.....#...............#........###........#.#..#.##...#.......
24 | ...#.....#.#..#.....#....#...#......#...........................#..#..#.......................#..............#..........#..........
25 | .#....##..............#.##....#...#................#............#..........#......##....................##....#.#..#......#..##....
26 | .....#.........#...##.#.#......................#....#...#...#.............#...................#...#..#...#...###......#...#....#...
27 | ........##......#.....#......................................#....###.#...#..........#.............#.....#.....#..........#.#......
28 | ........##.#...##.........##.....................#.#...........#........#.......................#...#.....#..............#.#.......
29 | ..........#.##.#..#..#..#.......#.....................................#.......##....#................#....#.....#...##.#....#..##..
30 | ..##.......#.........#..................##........#.....#.....................#.....#...................#.....#.#.........#........
31 | ....#........#.....#...................#.#..#..........................#...........#.............................#......#....#.....
32 | ..........................................#............#..#.......................#...#.#..#..................#.#............##....
33 | ...#..#....#......#....................................................................#..............#.#................#.......#.
34 | ..#.....##.............#.#.#...........#........#.................#..................#....................#..............#..###....
35 | ...##..#............#...#..#.........#..#.....#...........................#.....#....#...#...............#....#.............#...#..
36 | ...........#.......#...............................#..#.#...#.#...#...#........#.............##......................#...........#.
37 | ...............#..................#...............#.............#..#......................#......................##..........#.....
38 | ...........#..#....#.##...........#....#.##.#..........#...#.........#..........#.#..............................##.........#..#.#.
39 | ......#...#.#..##..................##................#####.#........#....#..#........#....#.....#................##..........#.....
40 | ....#.#........#.....#.......................##.......................#..#.#...........#.........................#..#..............
41 | ...#...........#..............#.......#.#....#......#...#....#.....#.....#...............#...........................#......#....#.
42 | ....#...........#..#.................#...##....#.............#..................#...........#.#.#............................#.....
43 | ........#..................#..#.#.........................###...#..#.#.#..##......#........##..#.....#..........#.....#.........#..
44 | .....#.#.#....#...#..............#.#..#.......#.........###..#..........#.......#..#....................#....................##....
45 | ........#.......#...............##................#..............................#...#.#.....#....#.....##........#.#......#.......
46 | .....#.##.....................#....#......###..#...........#........#....#..........#...#....#.........................#.......#...
47 | ..#.....#...#................#...##.#.......#....#.....#...............#.#....................#...#.......#..........#.............
48 | ........#.............#.#................#..#.....#....#.#......................#.....#.................##..#......................
49 | ..#..........#..........#..............#.........#..#.........#..............#.#.....#......###...#.....................#..........
50 | ......................#...#.#.#..#........#....###......##.........#.............#........#..#...#........#....................#...
51 | ..#..#...................#...#..#..#....#..##............#...#.............#.....#....##...............#...................##..#...
52 | ...#................###...............#...........#..............................#...#.........#.....#..#..#.................#...#.
53 | ....#.#..................##....#...#...#.........#....#.......#......#..........##..#..#..##.........#.....................#.......
54 | ......#..........#....#.....#.#.....#...#..........#.#......##.#......#............#.....#.....###.......#.#.#..#..................
55 | ...#.#.........##........#...#.....#......#...#.......#..................................#.........................................
56 | ..............#........................#.......###..#.......#.......#.#.......#....#.............#.......#...#.....#...............
57 | .#..#..........#...........##..............#...#.........#.....##.#....................................#.......................#...
58 | ...................#........#....#.#...........#............#.#.#.##...##............#.#.....................#.....................
59 | ...........#....#........#...........#...#..##....#.#........#..#......#..##....................#...#..............................
60 | .............#..........#.....#.......##......#......##.....#......##............................##.........#.........#.#..........
61 | ..............#.#...#.....#.....##..............#.......#.#..#.#......#...................#....#........#..........................
62 | .....................##..#.#.....#..........#......#......#..#....#.#.............#...#......#..#..................................
63 | ...............#.#.##........#.........#..........#.....#............#...#.......##.........#........##....#..#....................
64 | ...........##....#.............#.................#...#..#...#........#...#.#..#..#.................#...#.....#.....................
65 | ..................................#........#..........#...........##.#.##....#.#..#............#.#.............#...................
66 | .................................................................S.................................................................
67 | ......#..................###.##........#..#.....#....................#............#....#.#...#.#....#.###......#....##.......#.....
68 | ......................#.##......#.#......#..#....#.....................#...........#.....#..............#.#..#......#..............
69 | ..............................#..#............#......##.#.........#........#........#........................#.....................
70 | ..........#........#..........##.#.#..#...................#.#.#............#...............#...#.......#....#...##.................
71 | ............#.....#..........#.#.......#.#.........#....#.#.....#....#..........#.......#..............#........#..#....##.........
72 | ............#.............................#.................#......#..................#..#.....#..#...............#...##...........
73 | .................###....#...#.#..............#.#..............#.......#...##....#.....#............#...#..##.##........#.......#.#.
74 | ....................#..#..##.#.#..##.....##...............#........#......##................#......................................
75 | ...................#.......#....#....#.......#..#.............#..........#.#..........#.##.............#...........................
76 | ....................................#..#...#....#......##..#.......#...#................#.....#....#.#.......#...#.#...............
77 | .##...##.......#........#...#...#......#...#..............#..............##..##...#.........#...##...#.....................#..#....
78 | .#....#.............#.#....#....#...............#..#....#..........#.......#......#.....#.................#.....................#..
79 | .#............................#......##......#..#.#........#.....................#.#..#..##..#......#....................#..#......
80 | .......#............#....#....#...#..#........#...............#......#.......#..................#......#...#.............#.........
81 | ..#.................#.####..#...........#...........#..............#..#.##..##....#................#.....#.................#...#...
82 | .....#..............#...#........#................#....##.##..#..............#..##......#..#.........#................##...#...#...
83 | .........##..........#.......#..........#.#....#......#...........###...........#.......................#..#.#................#.#..
84 | .......#......#.......#......................................#..............#.................#..#........#..........#..........#..
85 | .......#...#..............#.......##...........#.#.#......#.........#.......#....#........#..#..#........#.................#.......
86 | .#.....##.#.#.................#.###...................##......#....##..##................#...............#.........................
87 | ..........##..#............#.#............#.......#..#.............#.......##.....##..#...##...#...................#...##.#...#....
88 | .##...#.....##.............#.........#...............#.............................#...........#....................#.....##.......
89 | ..........##.#.............#............#...#..#....#...........#.....#..........#...#.......#..#.#................................
90 | ..#.....................................#.....................#......#...............#...#........#......................#.##......
91 | .........#.#....#....#...............#......#...#........##...........#.......#....#....#...#......#.............#.....#....##.....
92 | .............#....................#...........#...................#.#...................#.#..#....................#..........#.....
93 | .....#.............#..#...................#................#......#...#.......#......#....#..##...................#.#.##.....#..#..
94 | .#..##...#........#......................#...##.#..##.........................#............#.#............#..#.....................
95 | .#...................#................#..............##...........#........#.#.....#.#...#.................#...##...#....#..#......
96 | ....#.......#..#...#.#...#.............#..#.##...#....#....#.......................#......#....#........#..#.......................
97 | ........###.......##..................#.......#....#.##....#..................##..........................#..#........#.........#..
98 | .##.......##.....#.........#..........#......#...............#........#.#..#..........#...............#.#...#..........#...........
99 | .#...##............#.........#..........##.....#..#......#......#....##...#...##.....#..#..............#.#.......##....#.#.#...#.#.
100 | ...........#...........................#..........#.#..........#....#..........#....................#.....##.............#.......#.
101 | .........#..................##............#..................#................#.#.......#.............###..#....#.......#........#.
102 | .......#...............#................#........#.....#.................##......#.......................#...............#.........
103 | ...##............#......#....................#...##.............#......#....#.....##.........................#.............#.......
104 | .#.......#.#.#..#.......#......#..............#...#.........#......##.##.....#.....................#.....#.....#......##......#....
105 | .#...................#.#....#.....#..........#..#...#.......................#...#....#.....................#....#...###.....#......
106 | ......#.....#......#....#.#.................#.........#.##...............##...................#..#......#..#.............#.........
107 | ..#........#....#.#............................................#......#...#.......#.....................#...................#......
108 | .........#...#.#.....................................#....#..........................................##...#........................
109 | ..#...............##.#............#....#........##.#....#..................#...#...........#...#..#..#....#..........#....#....#...
110 | ............#.#.......###.......##.##.....................#...#.#...#..#....#...##............#.#.#..............#..#.#...#........
111 | ................................#..#.#....................#..#.#......#..###...............#..#...#...##.#.......#.......#.........
112 | ....#........#.......#..#..........##.........................#....#......##..#................#......#..#......#.#......#.#.......
113 | .#..............#.#....#..........#.#....................#......#............................#....#......##...#.#.......#..........
114 | ....#.....##...#........#..#...........#...#.........#...............#.................#.#..#.................#..............#.....
115 | ...........................................##.............#.#.....#......#................#...#........#.......#..#.#..............
116 | ......#.....#..#.......##....#..........#......................#............#..........#...#...............#..#..#....#...#...#....
117 | ..........#...##.....................#.................##...............##.............#..##...........#.#............#.....##.....
118 | .#.#........................#...#.....#...........................#........................#........#.....#.#.#...........#........
119 | ..#...#....................#..#...#.........#...#........#.#...#...................#..#.#.....................#...........#........
120 | ...#.#.......#...#.................#......#...#...#....................##.................#..........##.......#..#.....#........#..
121 | ..................#.......#................#...............#.#....#....#......................#.....#.......#.........##...#.......
122 | ..#.......#.#..............#..###........##.#.................................##..........#........#..........#.....#.....#........
123 | .........##.....#.........#..........#...........#.#.................#.........#..............#...............#......#.#...##......
124 | ...............#.......#.#...#...........#.....#...#........................#..............#.......#.#......#....#......#....#.....
125 | .................##.#.#........##..........................................#....#.........##......#.......#..#..................#..
126 | ...#..##......#.....#.............##.#..##....#...............................##......###.#....###.#.........#...........#...#.##..
127 | ..#..#..............#.....#.....#..#..##.......#..##.....#.................#...#................#..#........#...##...#.............
128 | .#..................#............#.#..................................................#......#.#.......###...........#........##.#.
129 | ............#..........#....#.....#...#.....#........#.#.........................#.#....#....#.##..........#......#................
130 | ....#....#..#....................#.....#........##......#...#.........##.....#...##...#...##.##..............#....#......#..#...#..
131 | ...................................................................................................................................
132 |
--------------------------------------------------------------------------------
/src/day21/part1.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from collections import *
3 |
4 | def main() -> None:
5 | data = sys.stdin.read().strip()
6 |
7 | grid = data.split("\n")
8 |
9 | width = len(grid[0])
10 | height = len(grid)
11 |
12 | seen = set()
13 | garden = defaultdict(set)
14 | queue = []
15 |
16 | for y in range(height):
17 | for x in range(width):
18 | if grid[y][x] == "S":
19 | queue.append((x, y, 0))
20 |
21 | while len(queue) > 0:
22 | x, y, step = queue.pop()
23 |
24 | if (x, y, step) in seen:
25 | continue
26 |
27 | seen.add((x, y, step))
28 |
29 | if x < 0 or x >= width or y < 0 or y >= height:
30 | continue
31 |
32 | if grid[y][x] in ".S":
33 | garden[step].add((x, y))
34 | else:
35 | continue
36 |
37 | if step == 64:
38 | continue
39 |
40 | for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
41 | queue.append((x + dx, y + dy, step + 1))
42 |
43 | print(len(garden[64]))
44 |
45 | if __name__ == "__main__":
46 | main()
47 |
--------------------------------------------------------------------------------
/src/day21/part2.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from collections import *
3 |
4 | def main() -> None:
5 | data = sys.stdin.read().strip()
6 |
7 | grid = data.split("\n")
8 |
9 | width = len(grid[0])
10 | height = len(grid)
11 |
12 | seen = set()
13 | garden = defaultdict(set)
14 | queue = []
15 |
16 | for y in range(height):
17 | for x in range(width):
18 | if grid[y][x] == "S":
19 | queue.append((x, y, 0))
20 |
21 | while len(queue) > 0:
22 | x, y, step = queue.pop()
23 |
24 | if (x, y, step) in seen:
25 | continue
26 |
27 | seen.add((x, y, step))
28 |
29 | if grid[y % height][x % width] in ".S":
30 | if (step - 65) % 131 == 0:
31 | garden[step].add((x, y))
32 | else:
33 | continue
34 |
35 | if step == 327:
36 | continue
37 |
38 | for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
39 | queue.append((x + dx, y + dy, step + 1))
40 |
41 | # This one took quite a while to find, the general idea is:
42 | # After a while, every steps the difference between the answer
43 | # at steps and increases by a constant amount
44 |
45 | # for i in range(65, 459 - width, width):
46 | # print(i, i + width, len(garden[i + width]) - len(garden[i]))
47 |
48 | steps = 327
49 | score = len(garden[steps])
50 | increment = len(garden[steps]) - len(garden[steps - width])
51 |
52 | while steps != 26501365:
53 | increment += 30188
54 | score += increment
55 | steps += width
56 |
57 | print(score)
58 |
59 | if __name__ == "__main__":
60 | main()
61 |
--------------------------------------------------------------------------------
/src/day22/example.txt:
--------------------------------------------------------------------------------
1 | 1,0,1~1,2,1
2 | 0,0,2~2,0,2
3 | 0,2,3~2,2,3
4 | 0,0,4~0,2,4
5 | 2,0,5~2,2,5
6 | 0,1,6~2,1,6
7 | 1,1,8~1,1,9
8 |
--------------------------------------------------------------------------------
/src/day22/part1.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | def main() -> None:
4 | data = sys.stdin.read().strip()
5 |
6 | bricks = []
7 | occupied_cubes = set()
8 |
9 | for line in data.split("\n"):
10 | lhs, rhs = line.split("~")
11 | lhs = list(map(int, lhs.split(",")))
12 | rhs = list(map(int, rhs.split(",")))
13 |
14 | cubes = []
15 | for x in range(lhs[0], rhs[0] + 1):
16 | for y in range(lhs[1], rhs[1] + 1):
17 | for z in range(lhs[2], rhs[2] + 1):
18 | cubes.append((x, y, z))
19 |
20 | bricks.append(cubes)
21 | occupied_cubes = occupied_cubes | set(cubes)
22 |
23 | changed = True
24 | while changed:
25 | changed = False
26 | new_occupied_cubes = occupied_cubes
27 |
28 | for brick in bricks:
29 | old_brick = brick[:]
30 |
31 | min_z = {}
32 | for x, y, z in brick:
33 | if (x, y) in min_z:
34 | min_z[(x, y)] = min(min_z[(x, y)], z)
35 | else:
36 | min_z[(x, y)] = z
37 |
38 | z_modifier = 0
39 | while True:
40 | z_modifier += 1
41 |
42 | required_empty = {(x, y, min_z[(x, y)] - z_modifier) for x, y, z in brick}
43 | if any(z <= 0 for x, y, z in required_empty) or any(cube in occupied_cubes for cube in required_empty):
44 | z_modifier -= 1
45 | break
46 |
47 | if z_modifier == 0:
48 | continue
49 |
50 | for i in range(len(brick)):
51 | brick[i] = (brick[i][0], brick[i][1], brick[i][2] - z_modifier)
52 |
53 | changed = True
54 | new_occupied_cubes = (new_occupied_cubes - set(old_brick)) | set(brick)
55 |
56 | occupied_cubes = new_occupied_cubes
57 |
58 | t = 0
59 | for a in bricks:
60 | new_occupied_cubes = occupied_cubes - set(a)
61 |
62 | can_disintegrate = True
63 | for b in bricks:
64 | if a == b:
65 | continue
66 |
67 | min_z = {}
68 | for x, y, z in b:
69 | if (x, y) in min_z:
70 | min_z[(x, y)] = min(min_z[(x, y)], z)
71 | else:
72 | min_z[(x, y)] = z
73 |
74 | required_empty = {(x, y, min_z[(x, y)] - 1) for x, y, z in b}
75 |
76 | if all(z > 0 for x, y, z in required_empty) and all(cube not in new_occupied_cubes for cube in required_empty):
77 | can_disintegrate = False
78 | break
79 |
80 | if can_disintegrate:
81 | t += 1
82 |
83 | print(t)
84 |
85 | if __name__ == "__main__":
86 | main()
87 |
--------------------------------------------------------------------------------
/src/day22/part2.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | def main() -> None:
4 | data = sys.stdin.read().strip()
5 |
6 | bricks = []
7 | occupied_cubes = set()
8 |
9 | for line in data.split("\n"):
10 | lhs, rhs = line.split("~")
11 | lhs = list(map(int, lhs.split(",")))
12 | rhs = list(map(int, rhs.split(",")))
13 |
14 | cubes = []
15 | for x in range(lhs[0], rhs[0] + 1):
16 | for y in range(lhs[1], rhs[1] + 1):
17 | for z in range(lhs[2], rhs[2] + 1):
18 | cubes.append((x, y, z))
19 |
20 | bricks.append(cubes)
21 | occupied_cubes = occupied_cubes | set(cubes)
22 |
23 | changed = True
24 | while changed:
25 | changed = False
26 | new_occupied_cubes = occupied_cubes
27 |
28 | for brick in bricks:
29 | old_brick = brick[:]
30 |
31 | min_z = {}
32 | for x, y, z in brick:
33 | if (x, y) in min_z:
34 | min_z[(x, y)] = min(min_z[(x, y)], z)
35 | else:
36 | min_z[(x, y)] = z
37 |
38 | z_modifier = 0
39 | while True:
40 | z_modifier += 1
41 |
42 | required_empty = {(x, y, min_z[(x, y)] - z_modifier) for x, y, z in brick}
43 | if any(z <= 0 for x, y, z in required_empty) or any(cube in occupied_cubes for cube in required_empty):
44 | z_modifier -= 1
45 | break
46 |
47 | if z_modifier == 0:
48 | continue
49 |
50 | for i in range(len(brick)):
51 | brick[i] = (brick[i][0], brick[i][1], brick[i][2] - z_modifier)
52 |
53 | changed = True
54 | new_occupied_cubes = (new_occupied_cubes - set(old_brick)) | set(brick)
55 |
56 | occupied_cubes = new_occupied_cubes
57 |
58 | t = 0
59 | for a in bricks:
60 | new_occupied_cubes = occupied_cubes - set(a)
61 |
62 | new_bricks = [brick[:] for brick in bricks if brick != a]
63 | fallen_bricks = set()
64 |
65 | changed = True
66 | while changed:
67 | changed = False
68 | new_new_occupied_cubes = new_occupied_cubes
69 |
70 | for i, brick in enumerate(new_bricks):
71 | old_brick = brick[:]
72 |
73 | min_z = {}
74 | for x, y, z in brick:
75 | if (x, y) in min_z:
76 | min_z[(x, y)] = min(min_z[(x, y)], z)
77 | else:
78 | min_z[(x, y)] = z
79 |
80 | z_modifier = 0
81 | while True:
82 | z_modifier += 1
83 |
84 | required_empty = {(x, y, min_z[(x, y)] - z_modifier) for x, y, z in brick}
85 | if any(z <= 0 for x, y, z in required_empty) or any(cube in new_occupied_cubes for cube in required_empty):
86 | z_modifier -= 1
87 | break
88 |
89 | if z_modifier == 0:
90 | continue
91 |
92 | for j in range(len(brick)):
93 | brick[j] = (brick[j][0], brick[j][1], brick[j][2] - z_modifier)
94 |
95 | changed = True
96 | fallen_bricks.add(i)
97 |
98 | new_new_occupied_cubes = (new_new_occupied_cubes - set(old_brick)) | set(brick)
99 |
100 | new_occupied_cubes = new_new_occupied_cubes
101 |
102 | t += len(fallen_bricks)
103 |
104 | print(t)
105 |
106 | if __name__ == "__main__":
107 | main()
108 |
--------------------------------------------------------------------------------
/src/day23/example.txt:
--------------------------------------------------------------------------------
1 | #.#####################
2 | #.......#########...###
3 | #######.#########.#.###
4 | ###.....#.>.>.###.#.###
5 | ###v#####.#v#.###.#.###
6 | ###.>...#.#.#.....#...#
7 | ###v###.#.#.#########.#
8 | ###...#.#.#.......#...#
9 | #####.#.#.#######.#.###
10 | #.....#.#.#.......#...#
11 | #.#####.#.#.#########v#
12 | #.#...#...#...###...>.#
13 | #.#.#v#######v###.###v#
14 | #...#.>.#...>.>.#.###.#
15 | #####v#.#.###v#.#.###.#
16 | #.....#...#...#.#.#...#
17 | #.#########.###.#.#.###
18 | #...###...#...#...#.###
19 | ###.###.#.###v#####v###
20 | #...#...#.#.>.>.#.>.###
21 | #.###.###.#.###.#.#v###
22 | #.....###...###...#...#
23 | #####################.#
24 |
--------------------------------------------------------------------------------
/src/day23/part1.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | def main() -> None:
4 | data = sys.stdin.read().strip()
5 |
6 | grid = data.split("\n")
7 |
8 | width = len(grid[0])
9 | height = len(grid)
10 |
11 | source = (1, 0)
12 | queue = [(source, set([source]))]
13 |
14 | max_length = 0
15 |
16 | directions = {
17 | ">": [(1, 0)],
18 | "<": [(-1, 0)],
19 | "v": [(0, 1)],
20 | "^": [(0, -1)],
21 | ".": [(-1, 0), (1, 0), (0, -1), (0, 1)]
22 | }
23 |
24 | while len(queue) > 0:
25 | (x, y), visited = queue.pop()
26 |
27 | if x == width - 2 and y == height - 1:
28 | max_length = max(max_length, len(visited) - 1)
29 | continue
30 |
31 | for dx, dy in directions[grid[y][x]]:
32 | nx, ny = x + dx, y + dy
33 |
34 | if nx < 0 or nx >= width or ny < 0 or ny >= height:
35 | continue
36 |
37 | if grid[ny][nx] == "#":
38 | continue
39 |
40 | if (nx, ny) in visited:
41 | continue
42 |
43 | queue.append(((nx, ny), visited | set([(nx, ny)])))
44 |
45 | print(max_length)
46 |
47 | if __name__ == "__main__":
48 | main()
49 |
--------------------------------------------------------------------------------
/src/day23/part2.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from graph_tool import Graph
3 | from graph_tool.topology import all_paths
4 |
5 | def main() -> None:
6 | data = sys.stdin.read().strip()
7 |
8 | grid = data.split("\n")
9 |
10 | width = len(grid[0])
11 | height = len(grid)
12 |
13 | edges = []
14 | for y in range(height):
15 | for x in range(width):
16 | for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
17 | nx, ny = x + dx, y + dy
18 |
19 | if nx < 0 or nx >= width or ny < 0 or ny >= height:
20 | continue
21 |
22 | if grid[ny][nx] == "#":
23 | continue
24 |
25 | edges.append((y * height + x, ny * height + nx))
26 |
27 | graph = Graph(edges)
28 | max_length = 0
29 |
30 | for path in all_paths(graph, 1, (height - 1) * height + (width - 2)):
31 | max_length = max(max_length, len(path) - 1)
32 |
33 | print(max_length)
34 |
35 | if __name__ == "__main__":
36 | main()
37 |
--------------------------------------------------------------------------------
/src/day24/example.txt:
--------------------------------------------------------------------------------
1 | 19, 13, 30 @ -2, 1, -2
2 | 18, 19, 22 @ -1, -1, -2
3 | 20, 25, 34 @ -2, -2, -4
4 | 12, 31, 28 @ -1, -2, -1
5 | 20, 19, 15 @ 1, -5, -3
6 |
--------------------------------------------------------------------------------
/src/day24/part1.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | def is_after(pos: list[int], vel: list[int], x: float, y: float) -> bool:
4 | return abs(pos[0] + vel[0] - x) <= abs(pos[0] - x) and abs(pos[1] + vel[1] - y) <= abs(pos[1] - y)
5 |
6 | def main() -> None:
7 | data = sys.stdin.read().strip()
8 |
9 | stones = []
10 | for line in data.split("\n"):
11 | pos, vel = line.split(" @ ")
12 | pos = list(map(int, pos.split(", ")))
13 | vel = list(map(int, vel.split(", ")))
14 |
15 | x1, y1, z1 = pos
16 | x2, y2, z2 = x1 + vel[0], y1 + vel[1], z1 + vel[2]
17 | slope = (y2 - y1) / (x2 - x1)
18 | intercept = y1 - slope * x1
19 |
20 | stones.append((pos, vel, slope, intercept))
21 |
22 | min_bound = 200000000000000
23 | max_bound = 400000000000000
24 |
25 | t = 0
26 | for i, a in enumerate(stones):
27 | for b in stones[i + 1:]:
28 | if a[2] == b[2]:
29 | continue
30 |
31 | x = (b[3] - a[3]) / (a[2] - b[2])
32 | y = a[2] * x + a[3]
33 |
34 | if x < min_bound or x > max_bound or y < min_bound or y > max_bound:
35 | continue
36 |
37 | if is_after(a[0], a[1], x, y) and is_after(b[0], b[1], x, y):
38 | t += 1
39 |
40 | print(t)
41 |
42 | if __name__ == "__main__":
43 | main()
44 |
--------------------------------------------------------------------------------
/src/day24/part2.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from z3 import *
3 |
4 | def main() -> None:
5 | data = sys.stdin.read().strip()
6 |
7 | stones = []
8 | for line in data.split("\n"):
9 | pos, vel = line.split(" @ ")
10 | pos = list(map(int, pos.split(", ")))
11 | vel = list(map(int, vel.split(", ")))
12 |
13 | stones.append((pos, vel))
14 |
15 | solver = Solver()
16 |
17 | x = Real("x")
18 | y = Real("y")
19 | z = Real("z")
20 |
21 | vx = Real("vx")
22 | vy = Real("vy")
23 | vz = Real("vz")
24 |
25 | for i, stone in enumerate(stones):
26 | t_intercept = Real(f"t_{i}")
27 |
28 | sp = stone[0]
29 | sv = stone[1]
30 |
31 | solver.add(x + vx * t_intercept == sp[0] + sv[0] * t_intercept)
32 | solver.add(y + vy * t_intercept == sp[1] + sv[1] * t_intercept)
33 | solver.add(z + vz * t_intercept == sp[2] + sv[2] * t_intercept)
34 |
35 | solver.check()
36 | print(solver.model().eval(x + y + z))
37 |
38 | if __name__ == "__main__":
39 | main()
40 |
--------------------------------------------------------------------------------
/src/day25/example.txt:
--------------------------------------------------------------------------------
1 | jqt: rhn xhk nvd
2 | rsh: frs pzl lsr
3 | xhk: hfx
4 | cmg: qnr nvd lhk bvb
5 | rhn: xhk bvb hfx
6 | bvb: xhk hfx
7 | pzl: lsr hfx nvd
8 | qnr: nvd
9 | ntq: jqt hfx bvb xhk
10 | nvd: lhk
11 | lsr: lhk
12 | rzs: qnr cmg lsr rsh
13 | frs: qnr lhk lsr
14 |
--------------------------------------------------------------------------------
/src/day25/part1.py:
--------------------------------------------------------------------------------
1 | import networkx as nx
2 | import sys
3 |
4 | def main() -> None:
5 | data = sys.stdin.read().strip()
6 |
7 | graph = nx.Graph()
8 | for line in data.split("\n"):
9 | component, neighbors = line.split(": ")
10 | for neighbor in neighbors.split(" "):
11 | graph.add_edge(component, neighbor)
12 |
13 | _, groups = nx.stoer_wagner(graph)
14 | print(len(groups[0]) * len(groups[1]))
15 |
16 | if __name__ == "__main__":
17 | main()
18 |
--------------------------------------------------------------------------------