├── .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 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 |
Part 1Part 2Overall leaderboard
TimeRankScoreTimeRankScoreRankScore
32 | Day 1 33 | (code) 34 | 00:01:12317000:08:1619005870
46 | Day 2 47 | (code) 48 | 00:03:22425900:04:50297216201
60 | Day 3 61 | (code) 62 | 00:05:21267500:07:4511906366
74 | Day 4 75 | (code) 76 | 00:02:43792200:07:23112016388
88 | Day 5 89 | (code) 90 | 00:08:0493800:48:36864023396
102 | Day 6 103 | (code) 104 | 00:04:11283000:05:04106029396
116 | Day 7 117 | (code) 118 | 00:28:032124000:29:51828035396
130 | Day 8 131 | (code) 132 | 00:15:404470000:22:31942049396
144 | Day 9 145 | (code) 146 | 00:11:151552000:13:371233057396
158 | Day 10 159 | (code) 160 | 00:12:29140001:11:56995065396
172 | Day 11 173 | (code) 174 | 00:19:472044000:30:302218069396
186 | Day 12 187 | (code) 188 | 00:18:30697000:47:09788078396
200 | Day 13 201 | (code) 202 | 00:27:291889000:31:321068089396
214 | Day 14 215 | (code) 216 | 00:03:12287300:28:51514078469
228 | Day 15 229 | (code) 230 | 00:02:10100100:09:59594273512
242 | Day 16 243 | (code) 244 | 00:20:21681000:23:22459084512
256 | Day 17 257 | (code) 258 | 00:22:57364000:39:31654091512
270 | Day 18 271 | (code) 272 | 00:24:361132000:40:02595098512
284 | Day 19 285 | (code) 286 | 00:24:061073000:47:136000100512
298 | Day 20 299 | (code) 300 | 00:37:25493001:03:183960>100512
312 | Day 21 313 | (code) 314 | 00:06:34310000:49:54307198583
326 | Day 22 327 | (code) 328 | 00:28:17229000:37:432410>100583
340 | Day 23 341 | (code) 342 | 00:07:03386300:27:31455684702
354 | Day 24 355 | (code) 356 | 00:24:47303000:32:33148775789
368 | Day 25 369 | (code) 370 | 00:06:27168500:06:33168563959
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 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | {rows.lstrip()} 100 | 101 |
Part 1Part 2Overall leaderboard
TimeRankScoreTimeRankScoreRankScore
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 | --------------------------------------------------------------------------------