From 84c4cf9991660470229f03661116ca50062f4f8a Mon Sep 17 00:00:00 2001 From: Gabe Venberg Date: Thu, 16 Apr 2026 14:45:29 +0200 Subject: [PATCH] porting over AOC from previous years to a monorepo. --- 2020/.gitignore | 140 ++ 2020/.python-version | 1 + 2020/README.md | 3 + 2020/days/01/day1.py | 54 + 2020/days/01/example1 | 6 + 2020/days/01/input | 200 +++ 2020/days/01/test_day1.py | 33 + 2020/days/02/day2.py | 51 + 2020/days/02/example1 | 3 + 2020/days/02/input | 1000 ++++++++++++ 2020/days/02/test_day2.py | 37 + 2020/days/03/day3.py | 38 + 2020/days/03/example1 | 11 + 2020/days/03/input | 323 ++++ 2020/days/03/test_day3.py | 43 + 2020/days/04/day4.py | 132 ++ 2020/days/04/example1 | 13 + 2020/days/04/input | 1146 ++++++++++++++ 2020/days/04/test_day4.py | 65 + 2020/days/05/day5.py | 46 + 2020/days/05/example1 | 4 + 2020/days/05/input | 859 ++++++++++ 2020/days/05/test_day5.py | 33 + 2020/days/06/day6.py | 47 + 2020/days/06/example1 | 15 + 2020/days/06/input | 2199 ++++++++++++++++++++++++++ 2020/days/06/test_day6.py | 55 + 2020/main.py | 6 + 2020/pyproject.toml | 9 + 2020/template/template.py | 31 + 2020/template/test_template.py | 33 + 2020/uv.lock | 75 + 2022/.gitignore | 1 + 2022/Cargo.lock | 197 +++ 2022/Cargo.toml | 21 + 2022/aoc_libs/Cargo.toml | 6 + 2022/aoc_libs/src/lib.rs | 1 + 2022/aoc_libs/src/points.rs | 211 +++ 2022/days/01/Cargo.toml | 6 + 2022/days/01/src/input.txt | 2255 +++++++++++++++++++++++++++ 2022/days/01/src/main.rs | 14 + 2022/days/01/src/parse.rs | 48 + 2022/days/01/src/part1.rs | 27 + 2022/days/01/src/part2.rs | 27 + 2022/days/02/Cargo.toml | 6 + 2022/days/02/src/input.txt | 2500 ++++++++++++++++++++++++++++++ 2022/days/02/src/main.rs | 13 + 2022/days/02/src/part1.rs | 62 + 2022/days/02/src/part2.rs | 87 ++ 2022/days/02/src/utilities.rs | 36 + 2022/days/03/Cargo.toml | 6 + 2022/days/03/src/input.txt | 300 ++++ 2022/days/03/src/main.rs | 14 + 2022/days/03/src/part1.rs | 54 + 2022/days/03/src/part2.rs | 78 + 2022/days/03/src/utilities.rs | 93 ++ 2022/days/04/Cargo.toml | 10 + 2022/days/04/src/input.txt | 1000 ++++++++++++ 2022/days/04/src/main.rs | 14 + 2022/days/04/src/part1.rs | 27 + 2022/days/04/src/part2.rs | 27 + 2022/days/04/src/utilities.rs | 79 + 2022/days/05/Cargo.toml | 10 + 2022/days/05/src/input.txt | 514 ++++++ 2022/days/05/src/main.rs | 14 + 2022/days/05/src/part1.rs | 48 + 2022/days/05/src/part2.rs | 48 + 2022/days/05/src/utilities.rs | 144 ++ 2022/days/06/Cargo.toml | 6 + 2022/days/06/src/input.txt | 1 + 2022/days/06/src/main.rs | 14 + 2022/days/06/src/part1.rs | 23 + 2022/days/06/src/part2.rs | 23 + 2022/days/06/src/utilities.rs | 19 + 2022/days/07/Cargo.toml | 11 + 2022/days/07/src/file_tree.rs | 305 ++++ 2022/days/07/src/input.txt | 1030 ++++++++++++ 2022/days/07/src/main.rs | 19 + 2022/days/07/src/parser.rs | 262 ++++ 2022/days/07/src/part1.rs | 37 + 2022/days/07/src/part2.rs | 44 + 2022/days/08/Cargo.toml | 6 + 2022/days/08/src/input.txt | 99 ++ 2022/days/08/src/main.rs | 16 + 2022/days/08/src/part1.rs | 85 + 2022/days/08/src/part2.rs | 109 ++ 2022/days/08/src/utilities.rs | 26 + 2022/days/09/Cargo.toml | 11 + 2022/days/09/src/input.txt | 2000 ++++++++++++++++++++++++ 2022/days/09/src/main.rs | 15 + 2022/days/09/src/parse.rs | 75 + 2022/days/09/src/part1.rs | 53 + 2022/days/09/src/part2.rs | 31 + 2022/days/09/src/rope.rs | 160 ++ 2022/days/10/Cargo.toml | 10 + 2022/days/10/src/crt.rs | 118 ++ 2022/days/10/src/input.txt | 139 ++ 2022/days/10/src/machine.rs | 455 ++++++ 2022/days/10/src/main.rs | 16 + 2022/days/10/src/parse.rs | 344 ++++ 2022/days/10/src/part1.rs | 191 +++ 2022/days/10/src/part2.rs | 19 + 2022/template/Cargo.toml | 9 + 2022/template/src/input.txt | 0 2022/template/src/main.rs | 14 + 2022/template/src/parse.rs | 16 + 2022/template/src/part1.rs | 15 + 2022/template/src/part2.rs | 15 + 2023/.gitignore | 1 + 2023/Cargo.lock | 184 +++ 2023/Cargo.toml | 23 + 2023/aoc_libs/Cargo.toml | 6 + 2023/aoc_libs/src/distances.rs | 3 + 2023/aoc_libs/src/lib.rs | 4 + 2023/aoc_libs/src/misc.rs | 43 + 2023/aoc_libs/src/points.rs | 229 +++ 2023/aoc_libs/src/range.rs | 118 ++ 2023/days/01/Cargo.toml | 11 + 2023/days/01/src/input.txt | 1000 ++++++++++++ 2023/days/01/src/main.rs | 15 + 2023/days/01/src/parse.rs | 77 + 2023/days/01/src/part1.rs | 27 + 2023/days/01/src/part2.rs | 30 + 2023/days/02/Cargo.toml | 10 + 2023/days/02/src/input.txt | 100 ++ 2023/days/02/src/main.rs | 14 + 2023/days/02/src/parse.rs | 294 ++++ 2023/days/02/src/part1.rs | 121 ++ 2023/days/02/src/part2.rs | 112 ++ 2023/days/03/Cargo.toml | 9 + 2023/days/03/src/input.txt | 140 ++ 2023/days/03/src/main.rs | 14 + 2023/days/03/src/parse.rs | 560 +++++++ 2023/days/03/src/part1.rs | 106 ++ 2023/days/03/src/part2.rs | 105 ++ 2023/days/04/Cargo.toml | 11 + 2023/days/04/src/input.txt | 193 +++ 2023/days/04/src/main.rs | 14 + 2023/days/04/src/parse.rs | 128 ++ 2023/days/04/src/part1.rs | 65 + 2023/days/04/src/part2.rs | 65 + 2023/days/05/Cargo.toml | 10 + 2023/days/05/src/input.txt | 252 +++ 2023/days/05/src/main.rs | 14 + 2023/days/05/src/parse.rs | 543 +++++++ 2023/days/05/src/part1.rs | 156 ++ 2023/days/05/src/part2.rs | 168 ++ 2023/days/06/Cargo.toml | 10 + 2023/days/06/src/input.txt | 2 + 2023/days/06/src/main.rs | 15 + 2023/days/06/src/parse.rs | 148 ++ 2023/days/06/src/part1.rs | 26 + 2023/days/06/src/part2.rs | 16 + 2023/days/07/Cargo.toml | 10 + 2023/days/07/src/input.txt | 1000 ++++++++++++ 2023/days/07/src/main.rs | 14 + 2023/days/07/src/parse.rs | 648 ++++++++ 2023/days/07/src/part1.rs | 104 ++ 2023/days/07/src/part2.rs | 129 ++ 2023/days/08/Cargo.toml | 12 + 2023/days/08/src/input.txt | 752 +++++++++ 2023/days/08/src/main.rs | 14 + 2023/days/08/src/parse.rs | 79 + 2023/days/08/src/part1.rs | 37 + 2023/days/08/src/part2.rs | 113 ++ 2023/days/09/Cargo.toml | 9 + 2023/days/09/src/input.txt | 200 +++ 2023/days/09/src/main.rs | 14 + 2023/days/09/src/parse.rs | 48 + 2023/days/09/src/part1.rs | 20 + 2023/days/09/src/part2.rs | 26 + 2023/days/11/Cargo.toml | 11 + 2023/days/11/src/input.txt | 140 ++ 2023/days/11/src/main.rs | 14 + 2023/days/11/src/parse.rs | 388 +++++ 2023/days/11/src/part1.rs | 27 + 2023/days/11/src/part2.rs | 28 + 2023/template/Cargo.toml | 9 + 2023/template/src/input.txt | 0 2023/template/src/main.rs | 14 + 2023/template/src/parse.rs | 16 + 2023/template/src/part1.rs | 15 + 2023/template/src/part2.rs | 15 + 2024/.gitignore | 6 + 2024/README.md | 2 + 2024/build.zig | 75 + 2024/build.zig.zon | 46 + 2024/src/days/template/input.txt | 0 2024/src/days/template/lib.zig | 1 + 2024/src/days/template/main.zig | 10 + 2024/src/days/template/part1.zig | 14 + 2024/src/days/template/part2.zig | 14 + 2024/src/utils/mod.zig | 1 + LICENSE | 287 ++++ 194 files changed, 30104 insertions(+) create mode 100644 2020/.gitignore create mode 100644 2020/.python-version create mode 100644 2020/README.md create mode 100755 2020/days/01/day1.py create mode 100644 2020/days/01/example1 create mode 100644 2020/days/01/input create mode 100644 2020/days/01/test_day1.py create mode 100755 2020/days/02/day2.py create mode 100644 2020/days/02/example1 create mode 100644 2020/days/02/input create mode 100644 2020/days/02/test_day2.py create mode 100755 2020/days/03/day3.py create mode 100644 2020/days/03/example1 create mode 100644 2020/days/03/input create mode 100644 2020/days/03/test_day3.py create mode 100755 2020/days/04/day4.py create mode 100644 2020/days/04/example1 create mode 100644 2020/days/04/input create mode 100644 2020/days/04/test_day4.py create mode 100755 2020/days/05/day5.py create mode 100644 2020/days/05/example1 create mode 100644 2020/days/05/input create mode 100644 2020/days/05/test_day5.py create mode 100755 2020/days/06/day6.py create mode 100644 2020/days/06/example1 create mode 100644 2020/days/06/input create mode 100644 2020/days/06/test_day6.py create mode 100644 2020/main.py create mode 100644 2020/pyproject.toml create mode 100755 2020/template/template.py create mode 100644 2020/template/test_template.py create mode 100644 2020/uv.lock create mode 100644 2022/.gitignore create mode 100644 2022/Cargo.lock create mode 100644 2022/Cargo.toml create mode 100644 2022/aoc_libs/Cargo.toml create mode 100644 2022/aoc_libs/src/lib.rs create mode 100644 2022/aoc_libs/src/points.rs create mode 100644 2022/days/01/Cargo.toml create mode 100644 2022/days/01/src/input.txt create mode 100644 2022/days/01/src/main.rs create mode 100644 2022/days/01/src/parse.rs create mode 100644 2022/days/01/src/part1.rs create mode 100644 2022/days/01/src/part2.rs create mode 100644 2022/days/02/Cargo.toml create mode 100644 2022/days/02/src/input.txt create mode 100644 2022/days/02/src/main.rs create mode 100644 2022/days/02/src/part1.rs create mode 100644 2022/days/02/src/part2.rs create mode 100644 2022/days/02/src/utilities.rs create mode 100644 2022/days/03/Cargo.toml create mode 100644 2022/days/03/src/input.txt create mode 100644 2022/days/03/src/main.rs create mode 100644 2022/days/03/src/part1.rs create mode 100644 2022/days/03/src/part2.rs create mode 100644 2022/days/03/src/utilities.rs create mode 100644 2022/days/04/Cargo.toml create mode 100644 2022/days/04/src/input.txt create mode 100644 2022/days/04/src/main.rs create mode 100644 2022/days/04/src/part1.rs create mode 100644 2022/days/04/src/part2.rs create mode 100644 2022/days/04/src/utilities.rs create mode 100644 2022/days/05/Cargo.toml create mode 100644 2022/days/05/src/input.txt create mode 100644 2022/days/05/src/main.rs create mode 100644 2022/days/05/src/part1.rs create mode 100644 2022/days/05/src/part2.rs create mode 100644 2022/days/05/src/utilities.rs create mode 100644 2022/days/06/Cargo.toml create mode 100644 2022/days/06/src/input.txt create mode 100644 2022/days/06/src/main.rs create mode 100644 2022/days/06/src/part1.rs create mode 100644 2022/days/06/src/part2.rs create mode 100644 2022/days/06/src/utilities.rs create mode 100644 2022/days/07/Cargo.toml create mode 100644 2022/days/07/src/file_tree.rs create mode 100644 2022/days/07/src/input.txt create mode 100644 2022/days/07/src/main.rs create mode 100644 2022/days/07/src/parser.rs create mode 100644 2022/days/07/src/part1.rs create mode 100644 2022/days/07/src/part2.rs create mode 100644 2022/days/08/Cargo.toml create mode 100644 2022/days/08/src/input.txt create mode 100644 2022/days/08/src/main.rs create mode 100644 2022/days/08/src/part1.rs create mode 100644 2022/days/08/src/part2.rs create mode 100644 2022/days/08/src/utilities.rs create mode 100644 2022/days/09/Cargo.toml create mode 100644 2022/days/09/src/input.txt create mode 100644 2022/days/09/src/main.rs create mode 100644 2022/days/09/src/parse.rs create mode 100644 2022/days/09/src/part1.rs create mode 100644 2022/days/09/src/part2.rs create mode 100644 2022/days/09/src/rope.rs create mode 100644 2022/days/10/Cargo.toml create mode 100644 2022/days/10/src/crt.rs create mode 100644 2022/days/10/src/input.txt create mode 100644 2022/days/10/src/machine.rs create mode 100644 2022/days/10/src/main.rs create mode 100644 2022/days/10/src/parse.rs create mode 100644 2022/days/10/src/part1.rs create mode 100644 2022/days/10/src/part2.rs create mode 100644 2022/template/Cargo.toml create mode 100644 2022/template/src/input.txt create mode 100644 2022/template/src/main.rs create mode 100644 2022/template/src/parse.rs create mode 100644 2022/template/src/part1.rs create mode 100644 2022/template/src/part2.rs create mode 100644 2023/.gitignore create mode 100644 2023/Cargo.lock create mode 100644 2023/Cargo.toml create mode 100644 2023/aoc_libs/Cargo.toml create mode 100644 2023/aoc_libs/src/distances.rs create mode 100644 2023/aoc_libs/src/lib.rs create mode 100644 2023/aoc_libs/src/misc.rs create mode 100644 2023/aoc_libs/src/points.rs create mode 100644 2023/aoc_libs/src/range.rs create mode 100644 2023/days/01/Cargo.toml create mode 100644 2023/days/01/src/input.txt create mode 100644 2023/days/01/src/main.rs create mode 100644 2023/days/01/src/parse.rs create mode 100644 2023/days/01/src/part1.rs create mode 100644 2023/days/01/src/part2.rs create mode 100644 2023/days/02/Cargo.toml create mode 100644 2023/days/02/src/input.txt create mode 100644 2023/days/02/src/main.rs create mode 100644 2023/days/02/src/parse.rs create mode 100644 2023/days/02/src/part1.rs create mode 100644 2023/days/02/src/part2.rs create mode 100644 2023/days/03/Cargo.toml create mode 100644 2023/days/03/src/input.txt create mode 100644 2023/days/03/src/main.rs create mode 100644 2023/days/03/src/parse.rs create mode 100644 2023/days/03/src/part1.rs create mode 100644 2023/days/03/src/part2.rs create mode 100644 2023/days/04/Cargo.toml create mode 100644 2023/days/04/src/input.txt create mode 100644 2023/days/04/src/main.rs create mode 100644 2023/days/04/src/parse.rs create mode 100644 2023/days/04/src/part1.rs create mode 100644 2023/days/04/src/part2.rs create mode 100644 2023/days/05/Cargo.toml create mode 100644 2023/days/05/src/input.txt create mode 100644 2023/days/05/src/main.rs create mode 100644 2023/days/05/src/parse.rs create mode 100644 2023/days/05/src/part1.rs create mode 100644 2023/days/05/src/part2.rs create mode 100644 2023/days/06/Cargo.toml create mode 100644 2023/days/06/src/input.txt create mode 100644 2023/days/06/src/main.rs create mode 100644 2023/days/06/src/parse.rs create mode 100644 2023/days/06/src/part1.rs create mode 100644 2023/days/06/src/part2.rs create mode 100644 2023/days/07/Cargo.toml create mode 100644 2023/days/07/src/input.txt create mode 100644 2023/days/07/src/main.rs create mode 100644 2023/days/07/src/parse.rs create mode 100644 2023/days/07/src/part1.rs create mode 100644 2023/days/07/src/part2.rs create mode 100644 2023/days/08/Cargo.toml create mode 100644 2023/days/08/src/input.txt create mode 100644 2023/days/08/src/main.rs create mode 100644 2023/days/08/src/parse.rs create mode 100644 2023/days/08/src/part1.rs create mode 100644 2023/days/08/src/part2.rs create mode 100644 2023/days/09/Cargo.toml create mode 100644 2023/days/09/src/input.txt create mode 100644 2023/days/09/src/main.rs create mode 100644 2023/days/09/src/parse.rs create mode 100644 2023/days/09/src/part1.rs create mode 100644 2023/days/09/src/part2.rs create mode 100644 2023/days/11/Cargo.toml create mode 100644 2023/days/11/src/input.txt create mode 100644 2023/days/11/src/main.rs create mode 100644 2023/days/11/src/parse.rs create mode 100644 2023/days/11/src/part1.rs create mode 100644 2023/days/11/src/part2.rs create mode 100644 2023/template/Cargo.toml create mode 100644 2023/template/src/input.txt create mode 100644 2023/template/src/main.rs create mode 100644 2023/template/src/parse.rs create mode 100644 2023/template/src/part1.rs create mode 100644 2023/template/src/part2.rs create mode 100644 2024/.gitignore create mode 100644 2024/README.md create mode 100644 2024/build.zig create mode 100644 2024/build.zig.zon create mode 100644 2024/src/days/template/input.txt create mode 100644 2024/src/days/template/lib.zig create mode 100644 2024/src/days/template/main.zig create mode 100644 2024/src/days/template/part1.zig create mode 100644 2024/src/days/template/part2.zig create mode 100644 2024/src/utils/mod.zig create mode 100644 LICENSE diff --git a/2020/.gitignore b/2020/.gitignore new file mode 100644 index 0000000..f8b73e7 --- /dev/null +++ b/2020/.gitignore @@ -0,0 +1,140 @@ +# ---> Python +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + diff --git a/2020/.python-version b/2020/.python-version new file mode 100644 index 0000000..24ee5b1 --- /dev/null +++ b/2020/.python-version @@ -0,0 +1 @@ +3.13 diff --git a/2020/README.md b/2020/README.md new file mode 100644 index 0000000..11702d4 --- /dev/null +++ b/2020/README.md @@ -0,0 +1,3 @@ +# advent_of_code_2020 + +Python [advent of code](https://adventofcode.com/2020) 2020 \ No newline at end of file diff --git a/2020/days/01/day1.py b/2020/days/01/day1.py new file mode 100755 index 0000000..6010417 --- /dev/null +++ b/2020/days/01/day1.py @@ -0,0 +1,54 @@ +#! /usr/bin/env python3 + +import pathlib +import sys +import re +from dataclasses import dataclass + +def parse(puzzle_input): + """Parse input""" + return [int(string) for string in puzzle_input.splitlines()] + +def part1(data:list[int]): + """Solve part 1""" + data.sort() + while True: + if len(data)<2: + raise ValueError('no match found') + s = data[0]+data[-1] + if s>2020: + data.pop(-1) + elif s<2020: + data.pop(0) + else: + return data[0]*data[-1] + +def part2(data): + """Solve part 2""" + data.sort() + while True: + if len(data)<3: + raise ValueError('no match found') + if data[0]+data[1]+data[-1]>2020: + data.pop(-1) + elif data[0]+data[-1]+data[-2]<2020: + data.pop(0) + elif data[0]+data[1]+data[-1]==2020: + return data[0]*data[1]*data[-1] + else: + return data[0]*data[-1]*data[-2] + +def solve(puzzle_input): + """Solve the puzzle for the given input""" + data = parse(puzzle_input) + solution1 = part1(data.copy()) + solution2 = part2(data.copy()) + + return solution1, solution2 + +if __name__ == "__main__": + for path in sys.argv[1:]: + print(f"{path}:") + puzzle_input = pathlib.Path(path).read_text().strip() + solutions = solve(puzzle_input) + print("\n".join(str(solution) for solution in solutions)) diff --git a/2020/days/01/example1 b/2020/days/01/example1 new file mode 100644 index 0000000..e3fb011 --- /dev/null +++ b/2020/days/01/example1 @@ -0,0 +1,6 @@ +1721 +979 +366 +299 +675 +1456 diff --git a/2020/days/01/input b/2020/days/01/input new file mode 100644 index 0000000..13585a4 --- /dev/null +++ b/2020/days/01/input @@ -0,0 +1,200 @@ +1772 +1065 +1827 +1671 +1181 +1915 +1657 +1632 +1053 +1546 +1039 +1388 +1698 +1174 +1275 +1250 +1988 +1078 +1075 +1958 +1617 +1387 +1543 +1965 +1867 +1771 +1755 +1331 +1677 +1935 +1488 +911 +1001 +1516 +1949 +1626 +1083 +1402 +1223 +1179 +2001 +1790 +1551 +1117 +1990 +1968 +1532 +1999 +1175 +1126 +1869 +1666 +1753 +513 +1349 +1139 +1941 +1823 +1647 +1835 +1943 +1459 +1833 +1398 +1877 +1625 +1749 +1631 +1864 +1826 +1499 +1336 +1264 +1091 +1558 +1321 +1754 +1729 +1585 +1740 +1767 +1774 +1164 +1318 +1930 +1236 +1995 +1611 +1319 +1361 +1119 +1563 +1578 +1047 +1797 +1787 +1038 +1921 +1656 +1898 +1828 +1727 +1825 +2010 +536 +1395 +1865 +1882 +1638 +1954 +1565 +1296 +1723 +1187 +60 +1130 +1102 +1963 +1048 +1493 +1795 +472 +1496 +1278 +1444 +1889 +860 +1975 +1961 +1070 +1570 +1495 +1644 +1881 +1293 +1090 +1906 +1385 +1549 +1143 +1195 +2004 +1397 +1032 +1681 +2000 +1574 +1400 +1911 +1868 +1917 +1872 +1696 +1086 +1291 +1761 +1703 +1202 +1486 +1705 +1924 +1186 +1676 +1615 +1951 +1556 +1604 +1534 +2002 +1334 +1109 +1108 +1713 +1422 +1909 +1418 +1592 +1887 +1037 +1568 +1914 +1780 +1929 +1973 +1684 +1581 +1148 +1931 +1619 +1082 +1166 +1913 +1312 +1330 +1540 +1841 +1977 +1769 +1691 +1821 diff --git a/2020/days/01/test_day1.py b/2020/days/01/test_day1.py new file mode 100644 index 0000000..ace4f15 --- /dev/null +++ b/2020/days/01/test_day1.py @@ -0,0 +1,33 @@ +#! /usr/bin/env python3 + +import pathlib +import pytest +import day1 as aoc + +PUZZLE_DIR = pathlib.Path(__file__).parent + +#these test fixtures setup the test, mainly by reading the filename into a string in this simple case. +@pytest.fixture +def example1(): + puzzle_input = (PUZZLE_DIR / "example1").read_text().strip() + return aoc.parse(puzzle_input) + +@pytest.fixture +def example2(): + puzzle_input = (PUZZLE_DIR / "example2").read_text().strip() + return aoc.parse(puzzle_input) + +# @pytest.mark.skip(reason="Not implemented") +def test_parse_example1(example1): + """Test that input is parsed properly""" + assert example1 == [1721, 979, 366, 299, 675, 1456] + +# @pytest.mark.skip(reason="Not implemented") +def test_part1_example1(example1): + """Test part 1 on example input""" + assert aoc.part1(example1) == 514579 + +# @pytest.mark.skip(reason="Not implemented") +def test_part2_example2(example1): + """Test part 2 on example input""" + assert aoc.part2(example1) == 241861950 diff --git a/2020/days/02/day2.py b/2020/days/02/day2.py new file mode 100755 index 0000000..d4b1197 --- /dev/null +++ b/2020/days/02/day2.py @@ -0,0 +1,51 @@ +#! /usr/bin/env python3 + +import pathlib +import sys +import re +from dataclasses import dataclass + +@dataclass +class PasswordSpec: + first:int + second:int + letter:str + password:str + +def parse(puzzle_input: str): + """Parse input""" + regex = re.compile(r'^(\d+)-(\d+) (\w): (\w+)$') + toInt = lambda x: PasswordSpec(int(x[0]), int(x[1]), x[2], x[3]) + return [toInt(regex.match(i).groups()) for i in puzzle_input.splitlines()] + +def part1(data): + """Solve part 1""" + test = lambda x: x.first<=x.password.count(x.letter)<=x.second + # these two lines are equivilant. + # return sum(1 for p in data if test(p)) + return len([1 for p in data if test(p)]) + +def test_password(passwordSpec: PasswordSpec): + if passwordSpec.password[passwordSpec.first-1]==passwordSpec.letter: + return passwordSpec.password[passwordSpec.second-1]!=passwordSpec.letter + else: + return passwordSpec.password[passwordSpec.second-1]==passwordSpec.letter + +def part2(data): + """Solve part 2""" + return sum(1 for p in data if test_password(p)) + +def solve(puzzle_input): + """Solve the puzzle for the given input""" + data = parse(puzzle_input) + solution1 = part1(data) + solution2 = part2(data) + + return solution1, solution2 + +if __name__ == "__main__": + for path in sys.argv[1:]: + print(f"{path}:") + puzzle_input = pathlib.Path(path).read_text().strip() + solutions = solve(puzzle_input) + print("\n".join(str(solution) for solution in solutions)) diff --git a/2020/days/02/example1 b/2020/days/02/example1 new file mode 100644 index 0000000..fe19c03 --- /dev/null +++ b/2020/days/02/example1 @@ -0,0 +1,3 @@ +1-3 a: abcde +1-3 b: cdefg +2-9 c: ccccccccc diff --git a/2020/days/02/input b/2020/days/02/input new file mode 100644 index 0000000..44339b6 --- /dev/null +++ b/2020/days/02/input @@ -0,0 +1,1000 @@ +14-15 v: vdvvvvvsvvvvvfpv +3-11 k: kkqkkfkkvkgfknkx +6-10 j: jjjjjjjjjj +5-10 s: nskdmzwrmpmhsrzts +13-15 v: vvvvvvkvvvvjzvv +11-13 h: hhhhhbhhhhdhhh +14-15 r: rrrrrrrrzrrrrrtl +2-9 c: llhctjgbz +13-15 s: ssssxssssssssjs +6-8 c: lccccqcc +8-9 n: nnnnnmnch +4-5 n: jnnnmmpxngbrknzb +4-7 n: knlnqnnndnn +13-18 g: ggggggggnggggggggggp +5-6 m: mmmmgm +5-10 l: lvlllglllpll +7-12 z: pszgzqzzzzkw +1-2 j: pjjqw +15-16 n: nnnnnnnnnnnnnnpn +8-14 z: mzzzjzzzzhzzzztznzz +5-19 q: rnsdfgkqlqjdvrmtsqqh +1-5 f: ffffff +4-5 h: hhhhh +1-7 g: cglgjgflgggxv +2-3 g: gggpg +2-8 m: gbsmqmmmsmh +1-2 j: jjhkmqr +10-12 s: sssstsstpsssssp +9-15 k: tkbkkknkcnkgwkfkkkpk +6-7 m: mmmmmmmm +6-7 s: lsspssss +9-13 k: kkgjrvkkkkkkmkkkkzd +3-5 m: lbmmmzpwm +2-12 x: xxgwxxtbttcxzmlfwx +10-13 k: kkkkvkkkkkgkwkzkkkk +10-12 t: ttdftttttrtqt +4-8 z: zbzzzzzz +8-11 g: gctgdgwtspgg +2-5 l: lllvl +4-5 f: fwdspfmtts +5-8 z: zzhzmzzdzzz +11-12 x: xxxxwxxxxxxx +17-18 h: hhhhhhhhhhhhhhhhqm +9-14 j: jtkjwxjgjjjjjzjq +5-6 p: ddgdbkpdsd +2-5 c: xczcczc +6-15 t: ttgjktpwqthftfrt +13-16 t: tttttttttttttttq +9-11 t: tgttttttftttc +4-9 z: zzmzzzzzzzzzc +5-8 d: sddtvddb +5-6 l: llllpd +15-16 s: sssssssssssssssb +14-16 p: ppppppppppppppph +2-10 r: mjnczrrnlnv +9-10 s: ssspsssssrd +3-5 d: dddddq +2-3 v: llfv +7-12 n: dnnnlnbnnnncn +5-6 g: gsgggg +5-9 t: tltbtttttt +1-20 r: rtqtcmmgzfqmxtxqhdrn +2-6 l: hlkkll +4-6 c: cwccccc +3-4 c: gcrdcz +1-8 v: vvlvdgpvg +6-17 g: gjccgdglgzgtcggdx +1-17 l: nlczbmbrwcvgtjmcvcq +5-11 z: nzppckcknfwllzzzrpp +6-11 s: smsdjvsssss +3-4 t: cttt +1-4 q: tbcq +2-4 m: jmmmmm +2-8 h: hhhhhhhm +9-11 h: phrhhhvhchqhmhh +6-9 v: vvvvvmvvrvvvvv +1-2 f: nxfgjfffp +5-8 w: wwwwtnckwd +6-12 x: xxnxscxkxxtf +8-11 l: lllllllllstmllllll +9-11 p: ppppppppvtfpp +5-17 f: ffvwffpkfjffbtlfnftl +2-6 b: gbbgbbbbrbxk +8-9 t: trtftttttt +13-17 r: rrgrrvrrrrrbrrzrqr +10-11 k: kkkkkkrkkkk +9-11 c: cccccccccncc +2-5 j: jdfwzrjjtjt +10-13 r: zrrprxhrrxzmmrbr +8-13 s: sssjsssgssssbs +5-6 b: bbbhhkh +8-9 z: fzrzzzzxgfz +7-9 l: bllllmllhl +5-11 g: mqbfgrlgxfgcgggjdstc +4-11 m: mmmgmmmmmmmxms +14-17 p: lpppppppppzpppppp +7-9 d: ddddddddd +14-15 n: nnnnnnnnnnnnntz +8-17 n: nnnbgzqbnndnzfsnmsmj +12-15 l: lllkqllwdxlllvl +3-11 t: lpdztztgmdwtztj +2-5 m: rslsm +5-11 c: ckptcgwqshct +3-4 v: vvvdv +4-8 d: dddrhddhddd +2-5 n: brnnnnn +1-4 p: qtpp +5-7 l: lxblllflwl +16-17 t: ttttttttttttttthm +5-18 h: hhhthhhhhhhhhhhhhh +9-17 j: jjjjjjjjbnjjjjjjjjj +6-7 g: gfggnggrgg +4-6 n: nnnnwq +8-9 z: zzzczxzpwzlzdcsz +7-10 w: wwswwwvwwtwww +6-8 w: whwwwwlww +2-14 c: cpccccccrccccck +1-3 t: bqtbfdrdltn +3-8 w: qwjhwrnjwsb +2-4 g: gghg +2-11 d: htdtljjxrnddxbdnfkwf +12-14 b: bgbglrlpckgsxbjvqm +9-14 q: qqgvqqqqqqmqqq +2-16 m: mbmmmmmmhmmmmmzsbm +11-12 n: nnxnnnnnnnnn +6-12 r: rbrfbrnrrrprrczrqr +1-3 n: nmnqtz +17-18 h: hhhhhhhhhhhhhhhhfs +11-13 k: rkmkwrknzfkkm +2-3 w: bwwwwz +8-12 s: mssssssssssc +8-10 f: vzpcxfdfvqjpdkdh +1-2 b: kbbx +2-11 d: gqddddcdddf +3-9 z: lzzqztpzzlzlz +8-12 k: gkkfkkkmpkkkkktk +1-4 l: lsqm +9-11 m: mmzmmmmmmmv +16-18 f: fffchfffffffffffffw +7-8 v: wfhbqvxrvqpqvv +15-16 v: vvvvvvvvvvvvvvtvv +1-8 c: scwcrqclccccc +12-15 d: bpdvrddgdtfdgdd +2-4 k: gkkk +14-15 x: lxsxljxfxwxxjcwnxxv +6-7 p: hjxqnppmknskpb +7-13 b: bbbbbbcblbbbbbvb +7-9 j: gjjjpjjjhvqj +3-6 n: nnnnnnn +7-12 h: wxlhhhbjhhhhxhm +3-5 t: ttttt +3-4 n: ntnn +8-16 b: bhrjmbbbsbbbfbbbpbb +4-10 p: npsjlpppzgncww +4-6 p: pvpfxqp +1-2 f: fvxjf +3-6 t: trnktdttt +3-5 v: vvvvvmd +3-6 z: bzmdfpbwckf +3-4 h: hhhh +2-4 x: tshbsbxlkpgs +1-4 p: ppppbppppppppppp +2-4 c: cccwc +6-11 w: sbwwwwwqwmkw +1-2 f: bxff +3-8 h: rshhnqkvhh +2-4 l: lpllll +9-13 m: ltlmvcnnmmgtm +4-5 j: szjjjmjb +6-11 h: hkhdhkhhhhh +1-4 v: vvlq +16-17 b: pbdnsbbxbxgbdcqcr +1-18 n: nnnnnmbnnnnnnnnnnn +7-12 p: ppwtxzpvpppf +4-5 r: rrrrr +13-14 s: sgmdvqpxqqtstgspskf +4-7 h: hhhwchwh +7-18 d: ddlddddhjhbdddjdddd +4-6 l: llllll +15-16 n: nnnnnnnnnnnnnnzn +11-16 p: pppdplppppgpppmppppt +4-5 w: fwzbn +1-3 p: sjpfb +3-4 b: bbgbb +2-13 n: pdnnjnnnnnnnnnn +6-11 w: wwwkwdwwvcmwg +1-6 t: dhtmfk +4-7 d: wgrtpqldqldl +2-15 z: zjzzzzzzgzzzzjzpzh +1-6 h: hshhch +1-2 n: kdnnnnnqnnnnn +6-8 m: mdfjcclk +7-19 d: ddwdddddfnddddddddj +12-15 q: snqnppbsfjzvkxgkfc +6-7 n: nnnnnnn +3-4 x: xxghmxsz +5-6 t: tttgtsjts +3-5 f: mftfffcgwc +12-13 w: wpwwwwwwwwwzw +3-7 m: mmmmmmmmm +15-18 x: xxxtxxwdvxxxxxxxxkxs +4-5 w: wnpwwzw +17-19 n: nnnnnnnnnnnnqnnnndn +7-8 d: ddddddrf +9-11 t: ttqtttthttxttt +1-4 c: gccbr +5-11 w: wwwwtwmwwwwlw +6-8 v: vvmwvhvxvgsvftv +2-11 s: lkvssdschmsgqbbws +3-7 k: kmkxkckvg +3-10 l: llxllllllglrllhl +1-3 b: gbbb +18-19 v: vvvsvvvvvvvvvvvvvvv +8-9 d: tzddvdddddd +2-4 t: tgtbpcv +1-3 r: hrzrt +2-4 f: ffqq +5-6 c: cccjzh +3-4 j: jjln +6-8 l: lllllllllll +9-10 n: nnnnnnnnfr +8-9 x: xxxxxxxvcx +5-10 w: wpwwwbwwww +14-15 p: pppppppppppdphrppp +9-19 h: whhcthhxhhhhhhghjtwz +9-13 z: zzzzzpzzzhtzvnzzzzz +11-13 l: llllllllzlqql +6-11 b: bhlwpmbbbjzbcxwzmtc +2-3 q: fqqhfqr +12-14 m: mmmmdmmmmmmmsm +1-3 t: gggctqtfpxtrt +2-3 k: kbkk +11-14 d: dddddcdddfddddd +8-19 n: pnnnjnnnwgnnnnsnnnd +9-10 r: rrtrrrvrqrrrpr +4-12 k: kxskkkckkkzkz +1-10 h: tjvhhphpzhjrlhhht +8-9 c: pkcccccmc +3-5 h: slwlgwnhcxxdhk +1-8 l: cllllllqll +3-4 q: wzqthkjvqct +4-6 d: ddddddddddd +2-6 q: qqqbxm +6-9 b: bbbbbbqbsw +3-6 c: ccwkpdjccfvc +9-10 r: rrrrtrrrrr +1-5 d: phzdmtzshlz +5-7 q: fqqqqqrqq +4-5 v: vvvvr +3-5 k: kkgkk +3-7 h: wxhgkfhhhqnhdfhg +5-7 m: mmmwmmmmm +1-3 z: qsvrzwnxzvl +7-12 x: tpzblhzfdmxqqmmjfwq +9-12 m: mmmqmmmmmdmmmm +15-18 t: ttttttttttttttthtt +2-12 b: tblhkbgnbbfqvd +2-3 m: rmqv +8-17 m: jmcndnqmdjdtqnbvmpn +5-14 l: lxlfvjnbllllmlllllsb +4-5 r: rtlmrxxrrnrt +6-7 k: kkksmkg +16-19 q: bkwfqstbmqqhzqvqvcqd +12-13 l: lllllllllllpll +2-9 m: zgxdbmzrmbbdbw +7-9 d: bdddddzdk +18-19 g: wfwggwhxrnnspmvgjrg +17-18 w: wwwwwwwwwwwwwwwwwwww +2-6 z: kzzzfzbh +3-4 c: pcqk +5-6 t: tthtpx +10-13 x: xxxxxxxtdtkxqxqxxxx +1-2 b: qbwd +13-19 l: llhxsxlllllpllllllfl +14-15 n: nnnnmnnnnnnnnnqn +6-7 m: mjmhsdmmm +3-5 r: qqshck +8-15 c: clbcccrccscccpcwcc +9-12 k: kkcwkklkkkcnkkxkk +4-5 v: vvvppvv +2-8 t: dxtgttjj +1-8 r: tqrlhfzk +8-9 n: zhmtnfsrr +10-15 d: ddddmldddzddgnk +13-17 z: jzpzzzzzzzvwnzzbz +1-5 d: ddkdd +4-6 x: xsxgbf +3-8 k: wkckkkcw +5-7 r: ndprnrxrrrbzrpnrz +4-6 n: nnnnnnn +7-8 q: qbmxfhqqqqmhqqq +9-10 k: swgkcrkdkkjfmkkkjl +6-8 s: kzqbsxrchhvvfvkqhz +3-4 h: hmgh +10-11 b: bsbfbkbwbhh +9-13 z: nnzzbvzzrzkjnbzqfzzp +1-11 x: xsxnqgjsqzxxnxd +12-13 m: mmmmmmmmmmmvm +11-20 n: vjsnfnnsgnnnmnnnnnwn +4-11 q: qqqhqnpqbnrqhpd +10-16 s: hszrsssktsspdtsrssss +1-4 m: ldmhj +3-14 l: llxjlmllflzdbll +11-17 m: mmmmmmmmmmmmmmpmmmm +1-7 c: jcccccl +15-16 x: xjxxxxxxxxxxxxxxx +5-7 v: cvtvcvv +7-12 p: npppqpgptpjkjpdp +12-16 c: cwvmnknsbccvccrckqcf +5-13 v: vrvvvjvvpvvvwvbv +2-14 l: bkllllllllllldlllk +4-6 x: qxxxpxs +9-11 s: sbssssssssm +7-8 q: vgctvvqq +3-8 g: ggtgggggggg +5-6 b: pbbctbbbvnbjbbb +1-2 w: jwww +12-14 z: zszzzzznzzztzz +2-3 j: fnmgcjbjt +4-9 c: cccphccccpthcwwc +5-12 g: ggsgxggggsgqggggg +4-5 v: vvvvvv +8-17 q: hdhtqlwpzqqqqqpqqhq +9-15 s: sschdsssnvssvss +7-8 d: sdhkdtpcdwgddtdd +1-2 d: ddjdd +5-9 b: zbzbbbklzbbb +9-10 g: gggggggggg +2-4 t: kttt +6-13 t: pttsttttttttzt +16-17 h: hhhhhhhhmhhhhhhtdhh +4-10 r: rmpldrbrqcfqrkhbnqc +6-14 z: zjzcpzzxzzzctzjz +6-17 v: hsfctvxwpgsvfnfxwncq +14-16 p: ppppppppppppplpppppp +15-18 l: lllllslllllllgnllf +7-15 v: vvvvvvfpvnvvsvvgvv +3-4 x: xxsx +8-13 z: zzwzzrzzzzzqqz +7-8 r: hrsrrrrzrb +3-4 b: bzfg +5-7 h: dhhthhhhr +1-4 v: vcvv +5-6 k: pkkkqkkk +13-20 j: jjjjjsjjjjjjjjjjjjjj +3-6 p: pgtpptpxptvc +1-3 v: tvvvv +6-15 b: mbbbbbbbbbbbbkbb +11-15 q: qmqqqqqhqqqqqqqqdqcs +2-6 g: dggggr +1-4 j: jjldsjjhfg +2-4 h: vhkwhhnhbhx +3-5 z: zzzzzz +2-4 s: stmw +12-13 k: wkbcmmkhpklkdnnkdvk +19-20 b: bbbbbbbbbbbbbbbbbbbj +6-9 w: vwwwtcpwwgw +3-5 j: jbsjpjj +10-13 c: cdccqpccccccc +7-9 q: qpqqqqqqw +15-16 p: ppppppppppppppbd +6-13 n: nnnnnqnnnnndknnnnnn +11-14 t: ttttqtttttjtttt +4-6 t: tttltz +3-5 n: nnnrj +2-13 h: hhhhhhshhmhlkh +1-6 x: xxxxxcxxxx +4-7 v: ddswdvq +3-5 d: xjksdvdddddwcrqzj +6-7 x: xxxxxfxx +3-6 b: bbqbbll +9-12 p: pppppppplppj +12-13 w: wwwwwwwwwwwwzww +5-11 q: qztqqwvldnm +1-4 m: qmmj +3-7 l: llpllwllt +2-8 h: hmhhhhhrsfhh +8-10 g: gggggggqgv +5-7 g: pggzgggggggb +4-7 v: gvvxvrv +3-4 l: llkf +2-6 q: wqzpqqvdhhjlhkhmwtft +2-3 n: nnnrd +1-5 h: kfqqk +7-12 z: qczzzzdlclzzdpfgzzz +2-4 m: vrjmnqrmrmvm +4-6 h: hhhbkhpghh +5-7 z: zzzzgwbz +5-7 d: ddddkfdbdnd +8-10 q: qqxqqgtxqwqg +5-14 b: bbbbzbbrbbrbbnbbbbbb +8-10 z: vzzpzkzzgzzzzz +8-9 w: wwwwwwwwb +5-11 d: ddqdhddgddddd +2-9 h: fhhhhhhhhhh +7-12 b: bbjbbwxbcwbbnb +1-3 m: tmmdmmmm +2-3 b: bqtnkbjhlrvz +2-9 z: nzrbzzrzlzzzvzt +2-4 v: vvmv +9-10 q: fccjqpwhqqq +2-12 q: qqqqqfqqqqqqvqqq +1-4 c: cxnc +5-6 q: qqzhqqzqqqj +2-3 k: vkkk +8-9 n: nnmnnnxnnnnnqtwp +2-3 b: jrbzvcb +4-5 w: wwlnk +4-15 d: wdpddddmdddddddddd +10-14 d: dddqdxfddjbfddd +5-6 t: pttttmttp +3-4 b: bbgdbbb +5-6 b: rgtqbbb +7-14 b: pwpbbhbvbzxfbbb +6-10 p: zppvhbpmcpwpprp +1-15 p: bpfdpppxxmkppppmg +9-14 w: hmlxdbdcqmxxhw +1-9 t: zrqqtdbwpqdd +4-6 n: knrnlnznn +4-9 l: gclwdmllglblnlzn +5-7 c: ckccbvvgtlc +8-11 p: ppppppppxpp +13-14 w: wwwwwwwwwwwdwh +17-18 k: kkkkkkkkkkkkkkkkkk +7-11 c: qccmcnccccc +2-7 m: vmbnrmmngtqkjlmmt +9-12 m: mtmmmmmmmxnr +8-12 j: rjjdjvdjjfhj +14-16 h: hhlhwhhhhhhhhgbhh +10-12 w: dxwwwwlwwwwkwlwpwdl +1-3 w: wmwcwrfbpwtzwf +1-6 j: bjjjjjjj +8-13 f: ffffffffffffgf +1-6 g: lghdgt +6-8 s: sssslsfb +16-17 c: cccccccccnmcccmkc +3-4 z: zmzz +8-11 c: cccccccdcccc +8-15 p: lcnvhbjldhfsgwfvtbp +3-4 q: qqqq +5-7 b: bcpqbdq +1-4 t: ttttttttttttdtttt +3-14 v: cvlrwvzvjkdbdd +4-8 l: fcdhlwwl +4-5 m: mmmmpm +3-4 h: hhqlhl +5-6 r: mrrrqrr +4-5 c: cvccc +11-15 p: pppppppshpjpppszppp +6-8 j: fjzbjjjjvkjj +3-7 q: qqsqqqqq +1-16 p: jpppqppppppvppdwp +2-5 g: jgwlxzgbhpmqp +5-6 p: pppppplppp +7-18 r: wmbbsjrmmzzdlxbwcfhp +1-4 w: wvwqn +6-7 p: pppppcmp +15-16 h: zhhhhhhhhhhhhhhhhh +2-16 h: hrhhhhlthhwhqjhht +14-17 k: kkkkkdkkkkxkkskkxkk +15-16 d: dddddddddddddddf +2-17 v: vwvvvvvvvvvbvvmvvr +7-8 v: vvvvvvtd +1-4 f: lftr +2-4 h: hhrq +10-15 s: qsnnssxsvtfssdssss +16-17 n: nnnnnnnnnnnnnnnnn +1-4 r: bldfswjgvrsf +10-11 n: lnxknqwlnnxc +9-14 k: tjxclnrddxnpmg +3-10 v: tvvvqmvsvcvsc +3-4 v: vnxrv +1-6 k: kkgkdkmj +3-4 h: jhbrh +8-9 c: ctczkccknntcccrc +13-14 t: ttsttdtcttttttj +1-9 b: bfwjbbxbd +9-10 m: xmdvtsbmgg +5-6 w: wwwwww +2-6 l: djlwlwkl +5-6 h: hhvjtrkhh +3-5 b: bsbbl +5-7 p: vxpwppsppp +2-4 d: zbnddd +3-4 s: msjss +4-7 l: llqllll +6-18 w: wwwwwwwwwwwwwwwwwlw +13-14 h: hqnlxqhfwlvhhh +7-9 p: ppppppcphpp +5-8 x: bjfxkbqxpzxhxwvxx +4-5 h: hhhpphgh +4-5 c: sczcccccc +4-10 n: nnfnnnsdgnnsj +5-6 j: jwjjmjj +1-9 c: hcrlmrcdjwhqn +3-5 x: xxjxvx +7-13 x: xxvxxblxxnxxlx +3-6 w: wwjwwwf +14-18 m: mnmmmmmmmmmmmmjmmmm +3-5 t: tslttjqvnb +1-2 v: sfkvhj +2-4 c: ccctc +5-10 r: rrqptljvxtkrwsfdbr +3-4 q: qbwqngvm +1-4 t: nttnt +8-10 f: fqmfrffftv +6-7 h: hkhhhhhv +9-17 f: hfzhbmrxsfwfxdffh +1-10 t: tthttgtgtgttctt +2-3 b: tlbsbcxzbfplpjlsvncg +8-16 t: tdtttttpttttttttttt +8-16 k: jkkmzlkkgvkkkwtj +13-16 v: vvvvvvvnvvdvhvvw +7-9 v: vvvvxvhlqvzmc +4-6 l: gdjscq +9-17 f: fffffqffsfffffffhff +4-5 g: ggggb +2-4 w: wnmh +7-8 g: ggjgrqfgg +11-13 k: rrkgxzkkqnljs +11-15 v: vsvvvqvvvvwvvjcvvv +13-15 c: ccccccccccccccvccc +1-6 n: jpmcnjdbdn +3-4 v: xvlffppmgzwvv +6-12 j: jjjjjslsjbpj +10-11 l: lrhljlqllldblll +8-11 h: hdhghhczmxhhhhhw +2-3 z: ztnt +6-8 x: jxxxxqxmm +2-6 n: nwnnntnnjt +8-13 z: ztzzzzzbzzzzq +4-13 v: vxvvvxvmvvvvvvhvv +11-13 t: ntttftttxtstttwt +5-6 d: dddznd +10-15 t: trxttttttbbstttt +2-4 t: tblp +8-11 l: xllllllwlldl +12-13 m: mmsmmmmmmmmvcm +3-4 t: tthb +10-12 c: cpsclccmccctccc +11-12 k: pkkkrkkkkqkfkk +11-13 v: vvbvvlvvvvvvt +6-11 p: xkxfdpkkrdpb +13-14 h: hhqskrdhrhphbb +2-6 r: rdrrrr +1-4 p: nppg +5-6 h: hgpbhh +4-5 l: mrgzlxlchgjgwrlmvxl +6-11 b: bbbbbbbbbbbbb +2-5 s: svsvss +10-18 j: jjjdjjjjzjfjjjjjbj +1-14 p: tjphtjfnbhhgrmzdp +2-4 v: vvvv +5-7 q: vqvnbqdqhwqxqv +6-7 m: mmmmmlj +9-10 g: ggggggggggg +7-13 n: sqnjnnrnnfnnn +2-4 f: fbrfkhfkfcgjfp +2-3 b: wfwjlbx +16-17 r: rrrrrrrrrdrrrrrrr +3-7 b: vkksbzbbhpwb +2-4 m: fmcr +9-20 v: vfvvxnvvdwhvxvvvqlvj +6-9 b: jgjrcbnftrlbhp +4-9 x: hrqtpwzjxxx +7-9 h: hhhhhxnhdh +7-8 k: kkkkrtsphkk +6-7 n: jnnnblnnj +10-15 d: dddddddddkddddt +2-8 p: npbdhcgpl +9-10 x: xqxxxxxzxvx +5-9 k: khtkkwkkxqm +1-5 t: stttttttgttttt +5-13 w: wwhfjkshrwfpnlwjjmq +4-9 x: rzfrxzcxvxxx +3-4 g: hgfgg +2-3 n: nnnn +11-14 j: jjjjjjjjjjjjjj +9-10 m: mmmmmmmmmm +7-8 m: mmmmzmkmjhhwzmmwp +2-5 r: rrzrr +3-4 w: vnwpww +5-9 h: hzhhhhhjgmswvbxfr +6-10 h: cvhhhlhhhz +4-5 g: xxgggzg +1-2 d: dddcf +5-8 v: vvvvvvvpxv +7-9 b: bbkbjbpsbbbbtkblmr +6-8 f: fffffmfgfff +2-8 f: zfskzfjjwfjsf +4-5 v: lvdvdvv +4-5 p: ppbkrjp +6-14 z: zzzzzrzzzzzzzhzzw +5-7 g: cbbfngwggzs +2-4 n: nfpnnhnkpgmjdgc +11-14 h: hhhqchbhhhwhhhqjjhhn +5-7 q: qqqqqqq +2-3 s: sssjs +11-17 w: wwwxwwwwwwhwwwwwrwww +12-13 n: nnhtsnxqndxnlnnn +8-10 j: jjjjjjjhjj +15-16 z: zzzzzzzzzzzzzzzg +2-5 j: jfjpk +1-10 z: mzfzzzzzzpzzz +13-15 v: vcvvrvdvvvvvvvvvvv +11-12 j: jljjljqjvjmhjjj +1-7 c: cctccvv +6-17 s: slqssbsswsssszswsss +16-17 s: klksgsgtpsnrpslzs +12-13 m: mmmmmmmmmxmmfm +18-20 v: vvvvvvrvvvvvvvvvvlvs +18-19 d: ddddddddddddddddddv +4-5 p: srsjp +2-5 d: czvdk +5-11 w: pwgbslprbkk +15-16 b: bbbbbbbbbbjbbbbqnb +7-8 h: hhhhhwxt +11-12 g: ggggggggtqggg +10-11 m: mmmmmmmmmfk +4-6 m: qvlmmbmmmdrmpcqmmfq +1-10 r: xrrrrdrrrnrvzrrrrmrr +5-9 p: pljpvppkgc +13-14 j: jjjjjjjqjjjjwv +6-8 g: gggggggqg +2-7 b: bbkkdwb +3-16 q: fqqqqlqqqqqqqqqhqqqh +3-5 x: xfjxv +1-2 h: hhtkkpvhk +1-13 d: dddddddddddddddddd +7-8 x: kxxvngmqxcrqsxxlx +1-4 m: zvmr +1-11 n: wnfnnnsnftrnnfn +6-13 h: gcrjcphhhhpgh +1-4 h: jghv +7-10 m: mvtqpjmvvmvgp +4-7 j: pjjhjjjj +4-5 c: ccmcc +1-3 d: ddddd +2-4 g: gdglgwn +3-8 z: mbzznvds +3-11 k: fkjttkdkkqbkkkkr +5-10 n: nnnnwvnnncnnnnn +1-5 p: wdnxzn +2-4 h: phhhhhth +10-12 p: ppwpwkpgppvppppr +2-6 r: cdrxrrfrrztbq +6-15 g: gpjggfgcglqgfggw +3-4 q: qfqgq +2-6 m: mmmmmf +10-11 f: fffffffffff +5-12 g: bvggjfggkggggrqn +5-16 q: qbqjqqqxzqqqnqmhqq +3-5 g: gggggg +3-6 w: wzpxfbkkwtfdswwq +6-7 x: xccxxrwfp +12-13 q: qqqqqqqqqqqqq +7-12 k: kpkkkktkkkkf +5-7 f: kjlffrf +9-12 b: rnlzpmxcbbbbbzb +7-16 t: tztqtdvrrtgtzjtbtpt +14-15 g: ghkblgpbgbrtdgg +6-10 h: hdtqhhhhmlhh +6-13 g: gggggzgggwggl +7-9 v: kvtqvdsvvvwvpvgkhfl +10-12 b: bbbbbbbbbmbtbbbb +11-18 d: ddbddldhgzpkdcdddwd +12-13 k: kkklkkkkkkkkkk +3-4 v: rdvztvgv +4-9 n: zzjtntjcdlt +11-14 r: rrrrgrrrrbrrrrrrrrr +1-4 q: qkvq +2-9 z: wgpmpmxdz +13-19 p: pmpqjpppppppjpppppkp +3-4 s: smxwrsmt +1-5 m: mmsmhmm +11-14 p: pptmpppnpppspp +11-12 c: crcccpccfpcncccc +17-18 x: xnqxxxxxxxxxxxxxxxxx +1-2 v: cppsvk +4-6 p: gnpppg +2-9 r: krbjwprvrrsmrbrjcfl +2-12 x: cnqxhvppvzkxc +1-4 g: bgggg +3-4 j: jjjj +4-6 l: lwnlljgsdtl +1-8 v: vvfhxlcq +11-17 s: wsssmjsjbfstglsss +6-10 p: pprkpdpsgvm +13-15 r: rrqrrrrrrrrrrrrr +3-4 v: vvvj +1-10 k: kxprmfhcqkcknpqqggt +9-10 k: lrkkkkkkxtk +2-14 r: rrdtrmxjwrxgrv +8-12 q: qqqqqqqwqqqqq +4-7 v: vvddhcs +3-4 h: ghhzsvfkghshhz +9-12 z: zzwctlnpzlzzzbhz +14-16 w: wwwwwwwwwwwwwlwlwwww +11-16 r: frrrrrrrrgrnfrrcdr +2-3 l: jrlkln +11-12 w: dhwpwzdpwzkf +8-12 h: shpthhjhlhhhsd +4-5 n: nnnnnnnnnnnnn +5-9 d: dddtqdddm +2-8 p: kpkhwtptjl +1-9 k: rhvfjdgmjfckqnbjkxk +8-12 s: srsfbqgqcjgstkldlzbj +10-11 x: xkmxbndwvxx +10-19 k: zksnmwtkdkzkkxnvkjk +4-5 f: qjnfpsfqqfgmf +1-9 f: fvfffprxffffsphpfff +2-9 j: njgjjjbqjnmjxbhj +2-5 z: zzzxzbfp +8-15 f: ffffdqflmfffffrfw +5-15 c: cxmltcccmcmgvjg +2-3 p: pzqp +2-8 d: fttcqdzdq +6-10 p: sgphkqkspxbpfsjd +5-6 p: pppppf +5-15 r: rrrgrrrrsrcrrrnr +11-12 t: ttttttttttlt +10-11 w: wwwwwwwhxtwwww +9-10 h: wklhbssjkr +9-14 j: rjjgjjjfhjjpnbjjjj +2-3 d: dddd +6-14 q: qqqqqkqmqqqqqqq +14-15 w: wwwwwwwwwwlwwxw +5-9 s: vzssssssn +13-14 n: nnnnnnnnnnnnxt +1-9 w: cpwtwvngszwwzpwwcw +1-2 n: nnnnnn +7-18 b: bbbbbwbbbbbbbbbbrbb +4-7 f: pfgfwhw +7-13 q: qqqqqqsqqqqqhqqqq +3-10 n: gnpjzgndrntnb +9-13 q: qlqqqqqqqqrrqpqh +16-19 m: mrqcmmpmmmmmmmmcqmfm +5-11 p: fgkdvbqwpsfbpjpprgp +7-11 q: fqqwdqfkqqqrssqqtp +5-6 t: trtfkvg +17-18 h: hhhhhhhhhhhhhhhhhh +6-18 l: lllllklllllllllllbll +4-9 q: hqqxqqqql +1-5 j: jjjjnjjjj +3-4 g: jxggg +14-16 j: zljnjjsjjjjjjjjjfjjj +7-9 m: pmzmmzjmxpcbrqnmmmm +3-7 z: zlczjzlnrtkfss +2-15 s: xzswpvgnwwjkzws +15-16 z: zkzzzzzztzqzzzwzzzz +6-12 f: fcffffffpfffhx +9-14 p: kptdgpcvplhjhnppst +9-11 h: hhhhhhhhhhmhx +2-3 c: cccc +8-18 s: sszslksjsrsssssssws +1-6 h: rgvjlphbbhhhnkzz +2-7 r: rlzrhrrrk +17-19 h: hhhhhhhhhhhhhhhhhhhh +2-4 j: wjzjqj +5-6 b: bbbvdx +7-13 k: ztqlwthlsdkrdww +1-2 m: tmmm +16-19 d: ddcddddddjdjdddpddd +2-3 n: tvxj +13-14 z: zzzzzzzzzzzzpz +6-7 x: xxxxxxl +2-3 q: qnrw +7-10 l: ljlvfhgrmllkhlxlq +2-4 b: bbbq +16-17 h: hshhhhhhhmhhhhhckh +1-6 r: rrkrrr +14-16 n: nnnnnnnnnnnnnnqnnn +5-11 h: fhhlhhhhhhjktdhngj +3-4 g: gzgdvgqgq +2-4 r: hvrg +7-11 b: bbgcbbbqbwsbgbbbk +5-9 m: hfpmxpmvmb +17-20 v: vvvtvtvvvvvvvvvvqvvb +1-20 z: pszbttwrmqvlrgkmmlwz +9-16 h: hhhhhhhhhhhhhbhth +1-2 n: nhnhh +1-10 n: wnnnnnnfnrnn +1-5 k: sjkkk +1-7 k: lklkkkpkk +4-6 n: nnnznwn +14-15 s: sssssssssssssds +9-14 z: zzzzjzbzzzzzzzz +16-19 g: ggggfrgzgggggggnggg +9-13 v: vphvvvvvvjvvvmvv +2-3 l: lvvxpvvqzhdzrk +4-7 c: qdhclzccwcbmvcsz +5-8 s: stsskssws +3-4 c: kbxp +2-10 b: dtlqbbsvzbbklbgbf +8-10 s: smsslsbrsbcvsjsts +2-4 k: kkkkl +15-16 x: xxzxfxxrdxxfxpxrxn +11-18 h: hhnrdhhhhhhhhhhhjxh +1-2 n: plzvhknwjn +4-9 w: wwzkwwwwxww +2-3 l: lllp +3-9 j: fkzjnhqzpjjd +4-6 k: skkltk +3-4 k: klvkkkk +3-4 k: kkkg +10-11 d: bqdkzpxnfdd +12-14 r: rqrrrrrrrrrlfxrr +2-3 r: znrf +1-4 j: hgzjjtnw +1-6 w: mwwtwwww +14-16 d: spddddtddzjsbdcx +3-4 x: xxbf +11-12 r: vrrrkdrsrnhrnrvrr +1-4 c: clmw +3-8 t: ztvndgtx +7-10 z: zzzzzzzzzzzzzv +4-12 t: tbrthtwtchtt +1-7 h: hwhqrvhqhfh +4-7 s: ssfssss +5-13 s: kjtsspjmzrfxp +4-7 z: zzzzzzzz +5-15 h: gvhhrscmwmdhhhghhn +7-8 r: rrrrrrns +6-9 r: zrrrrrddr +7-15 v: vvghgtjwwvzwhrk +14-17 c: cccccsccccccnbtchc +2-3 k: kgrgr +15-17 k: kkkkkkkkkkkkkkvkk +10-11 f: fffffffffvj +6-8 r: prdnmrrzg +3-4 f: kcfx +4-5 k: kkkkkz +4-15 t: ztttttqhcpstwtt +1-6 g: cvgghtg +9-15 j: jtrxvjtjhjjjsjj +9-10 f: fffcffffff +10-11 r: hjflczjkqrq +3-8 k: jssmkkkbpkkjsvnhwkh +6-10 g: ngggkggmbggtcgg +15-16 x: xxxxxxxxxxxcxxjx +8-9 k: kkkkkkkkn +7-8 b: rbbbbbxdbb +2-5 w: wwwdwmkhvd +1-6 v: hfpwkxgvv +12-14 z: zzzzzzzzzzzjzz +14-16 s: ssrsmssssssssssss +3-6 z: zdmzjkc +2-4 m: mmbb +13-18 w: lwwwwwkrwwwwwwwwwksw +5-6 r: bwjrjgrrrrjbg +5-9 r: rrxmrrlrrj +2-4 g: gggk +5-10 s: ssssgmssrscptfrc +6-8 q: qqqqqzqqq +16-17 m: kmmmmmqmxmlpsmmmm +7-10 t: thxvtttztttjttvtkrcc +2-4 p: pppp +4-8 q: njdqbqqqrxd +2-5 w: gwmwklnkfmwjjggw +10-16 m: mmmmmmmmmzkmmmmw +1-2 w: btkxj +1-3 z: pzphlh +7-10 j: jjjjrpcpjgjjkz +3-5 j: jjljjj +1-5 l: lkzflppcgpll +4-6 m: mmmmmrm +2-4 m: vmzmmmdhcmntntlrgqk +8-9 x: xxwxxxlbxxx +1-2 s: rwrbhvt +1-5 d: dfdhdd +6-7 z: zzzzzfz +12-14 v: vvvdlvqvvnvkkm +2-7 s: skftlhmfdgpsp +9-11 q: rlqcqvqqqqqqqqq +5-6 g: ggmgwtg +5-7 m: mmmmmmmmmmmmmm +4-12 f: qffmdmffzfdff +8-10 k: lkwlkvkkkkkkkkkqk +15-17 p: qppppqppppppppzpv +3-4 x: xxxxx +7-8 x: xxqxdxxxxx +6-10 b: bbbbmsnkfbdrbnbtlnvb +3-16 d: ddmdddddrddddddp +8-11 n: nnnnnnnmnjdd +3-4 v: vvgd +11-13 n: nnnnnnnnnnfnn +5-10 n: nnnnpjnngcnqnn +7-11 w: wtwbbtzswqt +1-6 f: fffffwfff +8-10 q: qqvqqqqqqq +2-3 h: hhhh +17-18 m: mmmmmmmmmmmmmmmmqmmm +10-11 f: ffffffffffdff +2-4 z: zzzz +5-6 g: gggghz +6-19 n: nnnnnqnnnnnxnvnknnnn +2-6 h: rhhdbk +2-5 w: fnkwgww +4-5 c: cqcdgtmcccrbcckng +1-12 h: hkwptjwxmmgfhbvgj +4-5 g: pbhtb +1-11 h: hhhhhhhhhhhhh +5-11 v: gfrfvfqmgsnrtqkvq +13-14 s: sstssssscssdssss +3-8 b: tzjqgnkbbzzvrsb +8-9 b: bbbbbbbvb +7-13 r: rrhdcvrrtxmrzrmfxr +3-6 s: lsshsk +2-6 g: rqzpqtxmbggsgg +4-5 b: lbbffb +3-4 m: kmpm +8-18 w: wwwwhwwhwwwwmwwpbdw +6-7 n: nnnnnjn +6-9 r: ggrrsqrrrqrhbmrqzgd +7-9 g: rggggggzc +1-8 n: nnltwnnwn +6-8 r: rrrrrpxvr +4-12 c: ccccccccccchcccc +1-3 g: mrbgf +6-12 p: zfpsppknppvpmlrspbn +1-4 g: jxmmns +1-11 q: zdzhtqsxkcrklwk +2-4 x: svqmxxl +7-8 l: lllrwllll +9-18 v: zkhlxtqvvcvndkzkvvt +2-9 f: fksffshzx +2-5 j: jkjnj +4-15 j: qjjjmvjjpvmjjjbj +1-5 p: kpppx +1-6 v: vjttbvffvdhvk +4-17 l: wlsqvxkrjlltlnxnmds +1-3 p: pdzqnp +1-3 h: hhhh +2-14 z: mmvzzvzzkzhzszvqzzf +3-6 q: qqrjsxqqq +3-5 h: hrhvr +1-8 k: kkskktnkklzdkjgk +17-18 p: ppppvpppqppppmpppxpp +2-8 f: fffjsfbp +9-10 v: vvvfvvvtvxltsvv +6-12 j: jpvptjqpkjwjr +15-16 v: vvvvvvvvvvvvvvvp +6-8 q: qqpqbqqvqq +10-12 n: nnnnnnnnnnnjn +13-14 n: nnnnnnwnnnnnxgnn +2-3 k: kkkxl +2-3 w: ldmm +14-19 m: fphmmmmmmkmmmbmdmmw +4-7 w: wwwgjwww +8-9 d: dddwdddddd +6-7 w: wwwfwfvtw +2-6 j: hlcpkj +1-3 m: xsmmc +1-9 b: bbbbbbbbbbb +1-4 z: zsgz +2-12 v: vpvvvvvvvvvmvv +2-16 c: vccjrtcckcccckcsc +4-15 d: cqxpptqpwmqbvsvvt +2-14 q: qqqfqwpqzqsmqqvqrxjr +9-10 w: wvkfhfkhwjvw +6-10 q: tqqmqktxqfvq +4-11 f: kvqlfqxfrsf +7-14 m: rmxmmmmmmmmmmmmxmm +18-19 v: vvvvvvvsvvvvvvvvvvvv +7-8 x: fxnxxjjx +5-6 d: dzddrd +9-11 b: bbbbbrbssqtbb +14-16 x: sxxxlxxxxxsxxxxxxxx +5-9 t: wtttttbptttttqttmtt +11-13 l: lllllflllwsll +7-8 r: rrrmprjcv +6-9 p: plvpdzzppptpkpkpgp +2-13 g: chmjgvkvsplztzvtlzl +6-8 z: czzzzjzkg +1-5 l: jlltpfwlrl +6-7 d: jddcggqmdddd +3-5 c: cxbbc +13-14 p: ppqpppppppppbs +3-7 w: rwwnqlw +4-5 v: vvvvv +9-10 v: vvvvvvvvvm +3-5 z: zmxzlz +7-8 c: cccccchdc +2-4 d: drddctmgd +3-4 n: nnnn +3-10 q: cbqszqfqqqbvrrtsfq +4-17 p: pppkppppppppppppwp +11-12 n: nnnnnnnnnnnn +14-15 d: dddddddddddddxn +6-11 k: gbmbzkcmzskpkhp +2-10 z: zrzzzzzzzjzzz +1-2 q: wvqq +11-14 d: ddddddddddhddn +2-7 h: hhhhhhhhxh +10-19 m: mmkmmmmdmmmmmqhvpldm +2-10 j: jbmjjjrcjj +7-9 c: ccccplccccc +7-19 c: cckcbwlcccccccccczp +9-13 z: zzzzzzjmzzzzp +16-20 j: vjkjjcjjrjjmtnbjjjnj diff --git a/2020/days/02/test_day2.py b/2020/days/02/test_day2.py new file mode 100644 index 0000000..03f48ec --- /dev/null +++ b/2020/days/02/test_day2.py @@ -0,0 +1,37 @@ +#! /usr/bin/env python3 + +import pathlib +import pytest +import day2 as aoc + +PUZZLE_DIR = pathlib.Path(__file__).parent + +#these test fixtures setup the test, mainly by reading the filename into a string in this simple case. +@pytest.fixture +def example1(): + puzzle_input = (PUZZLE_DIR / "example1").read_text().strip() + return aoc.parse(puzzle_input) + +@pytest.fixture +def example2(): + puzzle_input = (PUZZLE_DIR / "example2").read_text().strip() + return aoc.parse(puzzle_input) + +# @pytest.mark.skip(reason="Not implemented") +def test_parse_example1(example1): + """Test that input is parsed properly""" + assert example1 == [ + aoc.PasswordSpec(first=1, second=3, letter='a', password='abcde'), + aoc.PasswordSpec(first=1, second=3, letter='b', password='cdefg'), + aoc.PasswordSpec(first=2, second=9, letter='c', password='ccccccccc') + ] + +# @pytest.mark.skip(reason="Not implemented") +def test_part1_example1(example1): + """Test part 1 on example input""" + assert aoc.part1(example1) == 2 + +# @pytest.mark.skip(reason="Not implemented") +def test_part2_example2(example1): + """Test part 2 on example input""" + assert aoc.part2(example1) == 1 diff --git a/2020/days/03/day3.py b/2020/days/03/day3.py new file mode 100755 index 0000000..e15d716 --- /dev/null +++ b/2020/days/03/day3.py @@ -0,0 +1,38 @@ +#! /usr/bin/env python3 + +import pathlib +import sys +import re +from dataclasses import dataclass +from pprint import pprint + +def parse(puzzle_input: str): + """Parse input""" + # returns a 2 dimentional array where true means there is a tree there. + return [[i=='#' for i in j] for j in puzzle_input.splitlines()] + +def part1(data): + """Solve part 1""" + return solveForSlope(data, 3, 1) + +def solveForSlope(data, right: int, down: int): + return sum(1 for index, row in enumerate(data[::down]) if row[(right*index)%len(row)]) + +def part2(data): + """Solve part 2""" + return solveForSlope(data,1,1)*solveForSlope(data,3,1)*solveForSlope(data,5,1)*solveForSlope(data,7,1)*solveForSlope(data,1,2) + +def solve(puzzle_input): + """Solve the puzzle for the given input""" + data = parse(puzzle_input) + solution1 = part1(data) + solution2 = part2(data) + + return solution1, solution2 + +if __name__ == "__main__": + for path in sys.argv[1:]: + print(f"{path}:") + puzzle_input = pathlib.Path(path).read_text().strip() + solutions = solve(puzzle_input) + print("\n".join(str(solution) for solution in solutions)) diff --git a/2020/days/03/example1 b/2020/days/03/example1 new file mode 100644 index 0000000..7e88cdc --- /dev/null +++ b/2020/days/03/example1 @@ -0,0 +1,11 @@ +..##....... +#...#...#.. +.#....#..#. +..#.#...#.# +.#...##..#. +..#.##..... +.#.#.#....# +.#........# +#.##...#... +#...##....# +.#..#...#.# diff --git a/2020/days/03/input b/2020/days/03/input new file mode 100644 index 0000000..e4e0663 --- /dev/null +++ b/2020/days/03/input @@ -0,0 +1,323 @@ +........#.............#........ +...#....#...#....#............. +.#..#...#............#.....#..# +..#......#..##............###.. +..........#......#..#..#....... +.#..#.......#.........#.#...... +.........#..#....##..#.##....#. +..#....##...#.................. +##..........#.##...#....##..#.. +...#....#...#..............#... +...........................#..# +..##.##.#..................#... +...#.##..#............#........ +........#.......#...#.....##.#. +.##..........#......#.......#.. +...#..........#...#..#.......#. +......#...#...#.##.......#.#... +........#...#...#...##......... +#..............#.#....#.......# +..#..#..#.#....#............... +.....#........#...#..........#. +##......#...#..#.##.......#.... +..#.#.....#.#.............#.#.# +#..#..##......##...#........... +..#......#........#.....#...... +.....#.......#....#.#...#...... +...#........#...........#...#.. +.......#.#...........###....#.. +...#...........##....##........ +#....#..####....#.....#..#....# +..........#...........#........ +...#.......#....#.#.........#.. +....#...#.......#..###......... +......#......#..#......#..#.... +...#.....#............#..#..... +...#.#.#.#..#.......#.....#.... +#....##...#.........#...##..... +#..#.......#..#..#..#...##..... +#.......#............#.....#... +.#........##....##...#........# +.....#...#..................... +.......#........#.............. +.....#............#.#.#...#.#.. +.....##..#.............#....... +..#.##..#........#..#...#...... +.........#.#....#...........#.. +.#.....#..#....#.....#...#..... +....#.#................#....... +...............##......#...#... +.##...#...#.......##.#....#.... +............#........#.......#. +......##.#.#................... +.#.#..............#.......#.... +#.....#...#.......#..#...#..... +.............#....#..#......#.. +........#...##................# +.......#...#..#..##............ +..#..#...##...#..#.#.....#...#. +.#.#...#.........#.#........... +...###....#.......#...#........ +........#......##.#...#..##..#. +.....................#.#....... +.............#...........#...#. +#..#..#.....#.#...#............ +...#....#.....#...........#.... +..##.....##...#......#..##..... +#.....#.....###.#.....#....##.. +.#...........###............... +..................#..##.#...#.. +................#....##.#...... +.#.#.#...#....#.........#..#.#. +#.......#........##............ +.......##.#....#.#............# +..........#..##.#....#......... +........##..#....#............. +.........#....#...........##... +#.........#.#..#..#..........#. +.....#........#......#......... +....#.#.#...............#...... +.#..#..##...#.##..........#.... +..#....................#.#..... +.........#....#...........#.#.# +........#....##.##............. +..#.....#.......#..#......#.... +#..........#.#.....#.#....#.... +........##.#.....#..#.....#.#.. +...................#...#....#.# +............#..#....#...#...#.. +..............#.#.........#.... +...#..#..#.#..##..##........... +.#...........................#. +.#.......#...........#....#.#.# +......#..#...#........#...##... +.........#......#.#.......#...# +...#..##................#...... +.............#.#..##....#.#.... +...............#..#......#..... +.#......#.#.#....#........#.... +........#..#.##..#..#.........# +...#....#.#...#..#.......#..#.. +..#...##.........#..#...#...... +...#...........#.............#. +....#.....................#.... +.....#..#...............#.#...# +....#..........#........#...... +..#....#........##..##......... +...#....#..#.#.......#...#..... +..#........#....#...##....#.#.. +.#...#........##.....#....###.. +#....#....##......#........#... +.........#..#.#..........#....# +....#...#.....#.......##....... +..............#..........#.##.. +#...#..#..............#......#. +.................#......##....# +..#..##..#.......#..#.#......#. +.............#........#.....#.# +.#.##............#..#.......... +..#...#...........#..##........ +.#....#...#....#.......#....... +...#.#..#..#..#....#.....#..#.. +....#..##..............#...#... +#..........###......###........ +.##.##......#..#............#.. +.#...........#.#.....#...#..... +#.#..#...#............#........ +.........#...#...#..........##. +.......###..#..........#....... +...........###.....#........#.. +.#.............#.....#......#.. +...#.....#....#.#.........##... +....##..##...#.......##........ +......#....##.........#......#. +..........#.....##..#.....#..#. +..........####...#..#.........# +.##....#..#.#...#.......#...... +...#.#.##.#.#...#....#.#.#..... +.........#...##........##.....# +..#........#..........##...##.# +##...##..........#.#........... +..............#......#......... +........#.....#.#.......#...... +.#...#.....#....#.#..#......... +.....#....................##... +....#..................#.#...## +.....#............#..##........ +#..........#....#.#.......##.#. +....#..#.....................#. +#..#....##.....#............... +..#...#..#..##....#.#.......... +.......#......#.#.......#.....# +...#.#.......#...#.##.......... +....#..........#....#.#.#...... +.......#..#..........#..##..... +#......#......#...#......#...#. +###..#....##......##........#.. +.#..........#.....#.......#.#.. +.......#.....#.....#.#......... +..#...#....#................... +..............#.##............. +.#...#.......#.##...#.#.......# +.......#......................# +....#.#...#.#........#......... +.#......#....#...#............. +#.......#...###.....#.#.#..#... +#....##.#...............##..... +..#.......#..................#. +.....####...............#...... +.##......#......#.#.......##.#. +#......##..###....#....#......# +.##.......##.##...#.##......... +......##............#.......#.. +......#..#.....##.#............ +.#..........#.....##........... +#.........#......#......##.#... +.........#.......#..#......#.#. +.........#.......#...........#. +.#..##.#..................##... +.............#.............#... +.....##........#......##...##.. +..#..#.#.....#..#....#......... +.....#....#.....#.....#........ +#......##.....#....#....#...... +#.................#..#.#......# +.......#..#......#....#.#...#.# +....#.........#..#..........#.# +##......#............#...#...#. +....##......#...#.....#....##.. +.#...##.........#.............. +......#.....................#.. +..#..........###....#.......... +#....#...#..#.............#.... +#........#.#......#....#....... +.#...#.......#..#...#.#...#..#. +................##.#.....#..... +###.......#...#................ +...#.......#...#.#.....#....... +..#.........#.....#.#.......#.. +......#.......................# +#.....#.#..#....#.......#...... +...#....#..#....####........... +.............#.....#...##...... +.......#.........#...#..#...... +.##..#.........#....#.#........ +....##...#.#...........#....#.. +.........................##.... +..###.......##....#.#.........# +.#....#.#.#...........##....#.. +......#...#..#..#..#..#.......# +..#....#.#.......#..#..#..#...# +.....##...#.##....#.#...#...... +.........#..#....#..#.......... +.##..##.........#.#.....#...... +..........#...##...#.#...#..... +#.##..#..#.............#....... +...#...........#.......#......# +.......#....#....#...##.......# +..#.##........###..#......#.... +...#...........###......#..#..# +.#.........#.#.........#.#..... +##.......##.##.##......##...... +............#...#..........#... +....................#.......... +...#..#...........#...#...#.... +.................#...#......### +...#................#.#.##..... +...............#........#...... +#.............##......#.#..#... +..#.#.....#..#.##.....##...#... +......#.........#......#....... +#.......#......#....#........#. +.#..##.....#.........#......... +....##.##.#...#.........##.#... +...............#..#..#..##..... +.#..#...............###........ +.##............##.............. +...............#...##...#...#.# +..#.#......#.#..#.............# +#.#..#..##.........#.#.#...#... +....##.#....................##. +.........#..#.....#.....#..#..# +....#......#......#.##....#.... +........###..#.............#..# +##................#.........#.. +#.....#.......#....#........... +..#.......#..#........#....#... +..#.#.##..#.#...##........#.##. +..#..........#............#.... +..........#...............##... +..........###........#.#....... +.....###..#.............#...... +##.............#...#.....#..... +.....#......#....#........#.#.. +............#..#..............# +.................#...........## +#........#.........###.....#... +..#.#..............##......#.#. +.#...........#.........#..##..# +............................... +.#.....#..#....#....#......#... +.#...#......#.#..#....#.......# +......#.##.......#......#...... +......#..###..#................ +#..#.....#........##...#....... +......##.........##....#...##.. +.#..........#.................# +#..#.......#...............#... +.........#..###....#.#.##.#.... +..#...#.##..##...............## +.........#..................... +.#....##...#......#....#....... +............#..........#..#.... +...#......##....#....#........# +.#...................#......... +#.#........###....#..........#. +.........#....#....#........##. +.#....#..#.........#..#........ +...............#..#...#..#...## +.........#....##....#......#... +.#............................. +...#........#...#.#...#.#..#... +.....#..##...#.#............... +#.....#....#.........#......... +#...#...........##.........#... +..##........#.#...#...#......#. +...........#.....#...#.#....... +......###....#.....#........... +......##...#..........#....#.#. +.......##..##..........#....... +....#............#..#....##.... +..##...................#.#..... +...#.#..#.#.................... +.#..##..#............##.###..#. +#.#...#....#.#..........#.#.... +........#....#.....#........... +..##....#...#.......#.......... +...........##.##....#.......... +.....#............#............ +.......#.............#....#.... +.................#......#...... +......##.......#....#..##...#.. +.#..#....#..................... +...#.#.#...#......##........... +##........##.#....#....#....... +.......#.....#..#..#...#.##.... +#..........#....#.#..#..#..#... +...##..............#........... +.........#.....#.#....#.......# +.........#....##..#..##..#..... +.....#......................#.. +...###...#..#......#........... +....#.....................#.... +............................... +..#.....###.......#..#....#.... +#..........#.................#. +......#.......###.......#..##.. +.............#.##.............. +......#..#.#..#...........#.... +...#....##.#...#..#.#...#....#. +..................#...#....#.## +......#.#....#................. +......#.#.....#.....#..##...... +#..##...........#..#.....#.##.. diff --git a/2020/days/03/test_day3.py b/2020/days/03/test_day3.py new file mode 100644 index 0000000..0654e7e --- /dev/null +++ b/2020/days/03/test_day3.py @@ -0,0 +1,43 @@ +#! /usr/bin/env python3 + +import pathlib +import pytest +import day3 as aoc + +PUZZLE_DIR = pathlib.Path(__file__).parent + +#these test fixtures setup the test, mainly by reading the filename into a string in this simple case. +@pytest.fixture +def example1(): + puzzle_input = (PUZZLE_DIR / "example1").read_text().strip() + return aoc.parse(puzzle_input) + +@pytest.fixture +def example2(): + puzzle_input = (PUZZLE_DIR / "example1").read_text().strip() + return aoc.parse(puzzle_input) + +# @pytest.mark.skip(reason="Not implemented") +def test_parse_example1(example1): + """Test that input is parsed properly""" + assert example1 == [[False, False, True, True, False, False, False, False, False, False, False], + [True, False, False, False, True, False, False, False, True, False, False], + [False, True, False, False, False, False, True, False, False, True, False], + [False, False, True, False, True, False, False, False, True, False, True], + [False, True, False, False, False, True, True, False, False, True, False], + [False, False, True, False, True, True, False, False, False, False, False], + [False, True, False, True, False, True, False, False, False, False, True], + [False, True, False, False, False, False, False, False, False, False, True], + [True, False, True, True, False, False, False, True, False, False, False], + [True, False, False, False, True, True, False, False, False, False, True], + [False, True, False, False, True, False, False, False, True, False, True]] + +# @pytest.mark.skip(reason="Not implemented") +def test_part1_example1(example1): + """Test part 1 on example input""" + assert aoc.part1(example1) == 7 + +# @pytest.mark.skip(reason="Not implemented") +def test_part2_example2(example2): + """Test part 2 on example input""" + assert aoc.part2(example2) == 336 diff --git a/2020/days/04/day4.py b/2020/days/04/day4.py new file mode 100755 index 0000000..c9bc902 --- /dev/null +++ b/2020/days/04/day4.py @@ -0,0 +1,132 @@ +#! /usr/bin/env python3 + +import pathlib +import sys +import re +from dataclasses import dataclass +from pprint import pprint + +@dataclass +class Passport: + birthYear: int | None + issueYear: int | None + expirationYear: int | None + height: str | None + hairColor: str | None + eyeColor: str | None + passportId: str | None + countryId: str | None + +def regexUnwrap(match, group:int)->str | None: + return match[group] if match is not None else None + +def parse(puzzle_input: str)->list[Passport]: + """Parse input""" + rawRecords = [i.replace('\n', ' ') for i in puzzle_input.split('\n\n')] + records = [] + for rawRecord in rawRecords: + birthYear=re.search(r'byr:(\S+)', rawRecord) + issueYear=re.search(r'iyr:(\S+)', rawRecord) + expirationYear=re.search(r'eyr:(\S+)', rawRecord) + height=re.search(r'hgt:(\S+)', rawRecord) + hairColor=re.search(r'hcl:(\S+)', rawRecord) + eyeColor=re.search(r'ecl:(\S+)', rawRecord) + passportId=re.search(r'pid:(\S+)', rawRecord) + countryId=re.search(r'cid:(\S+)', rawRecord) + records.append(Passport( + int(birthYear[1]) if birthYear is not None else None, + int(issueYear[1]) if issueYear is not None else None, + int(expirationYear[1]) if expirationYear is not None else None, + regexUnwrap(height,1), + regexUnwrap(hairColor,1), + regexUnwrap(eyeColor,1), + regexUnwrap(passportId,1), + regexUnwrap(countryId,1), + )) + return records + +def lazyCheckPassport(passport: Passport)->bool: + return ( + passport.birthYear is not None + and passport.issueYear is not None + and passport.expirationYear is not None + and passport.height is not None + and passport.hairColor is not None + and passport.eyeColor is not None + and passport.passportId is not None + ) + +def part1(data): + """Solve part 1""" + return sum(1 for record in data if lazyCheckPassport(record)) + +def checkBirthYear(passport: Passport)->bool: + if passport.birthYear is None: return False + return (1920<=passport.birthYear<=2002) + +def checkIssueYear(passport: Passport)->bool: + if passport.issueYear is None: return False + return (2010<=passport.issueYear<=2020) + +def checkExpirationYear(passport: Passport)->bool: + if passport.expirationYear is None: return False + return (2020<=passport.expirationYear<=2030) + +def checkHeight(passport: Passport)->bool: + if passport.height is None: return False + rematch = re.match(r'(\d+)((?:in)|(?:cm))', passport.height) + if rematch is None: return False + number = int(rematch.group(1)) + unit = rematch.group(2) + if unit == 'in': + return (59<=number<=76) + else: + return (150<=number<=193) + +def checkHairColour(passport: Passport)->bool: + if passport.hairColor is None: return False + return (re.match(r'#[0123456789abcdef]{6}$', passport.hairColor) is not None) + +def checkEyeColour(passport: Passport)->bool: + if passport.eyeColor is None: return False + return (passport.eyeColor == 'amb' + or passport.eyeColor == 'blu' + or passport.eyeColor == 'brn' + or passport.eyeColor == 'gry' + or passport.eyeColor == 'grn' + or passport.eyeColor == 'hzl' + or passport.eyeColor == 'oth' + ) + +def checkPassportId(passport: Passport)->bool: + if passport.passportId is None: return False + return (re.match(r'[0-9]{9}$', passport.passportId) is not None) + +def checkPassport(passport: Passport)->bool: + return (checkBirthYear(passport) + and checkIssueYear(passport) + and checkExpirationYear(passport) + and checkHeight(passport) + and checkHairColour(passport) + and checkEyeColour(passport) + and checkPassportId(passport) + ) + +def part2(data): + """Solve part 2""" + return sum(1 for record in data if checkPassport(record)) + +def solve(puzzle_input): + """Solve the puzzle for the given input""" + data = parse(puzzle_input) + solution1 = part1(data) + solution2 = part2(data) + + return solution1, solution2 + +if __name__ == "__main__": + for path in sys.argv[1:]: + print(f"{path}:") + puzzle_input = pathlib.Path(path).read_text().strip() + solutions = solve(puzzle_input) + print("\n".join(str(solution) for solution in solutions)) diff --git a/2020/days/04/example1 b/2020/days/04/example1 new file mode 100644 index 0000000..0ff208e --- /dev/null +++ b/2020/days/04/example1 @@ -0,0 +1,13 @@ +ecl:gry pid:860033327 eyr:2020 hcl:#fffffd +byr:1937 iyr:2017 cid:147 hgt:183cm + +iyr:2013 ecl:amb cid:350 eyr:2023 pid:028048884 +hcl:#cfa07d byr:1929 + +hcl:#ae17e1 iyr:2013 +eyr:2024 +ecl:brn pid:760753108 byr:1931 +hgt:179cm + +hcl:#cfa07d eyr:2025 pid:166559648 +iyr:2011 ecl:brn hgt:59in diff --git a/2020/days/04/input b/2020/days/04/input new file mode 100644 index 0000000..8becd55 --- /dev/null +++ b/2020/days/04/input @@ -0,0 +1,1146 @@ +byr:1983 iyr:2017 +pid:796082981 cid:129 eyr:2030 +ecl:oth hgt:182cm + +iyr:2019 +cid:314 +eyr:2039 hcl:#cfa07d hgt:171cm ecl:#0180ce byr:2006 pid:8204115568 + +byr:1991 eyr:2022 hcl:#341e13 iyr:2016 pid:729933757 hgt:167cm ecl:gry + +hcl:231d64 cid:124 ecl:gmt eyr:2039 +hgt:189in +pid:#9c3ea1 + +ecl:#1f58f9 +pid:#758e59 +iyr:2022 +hcl:z +byr:2016 hgt:68 eyr:1933 + +hcl:#fffffd ecl:gry eyr:2022 +hgt:172cm pid:781914826 byr:1930 iyr:2018 + +hcl:#08df7e ecl:grn byr:1942 +eyr:2028 iyr:2011 cid:141 pid:319110455 +hgt:186cm + +pid:991343040 hgt:179cm +hcl:#a97842 iyr:2020 +eyr:2024 +byr:1984 cid:181 + +pid:188cm byr:2005 +hgt:170cm cid:163 ecl:#a08502 hcl:2964fb eyr:1994 +iyr:2005 + +ecl:grn hcl:#fffffd iyr:2013 +pid:705547886 +byr:1928 hgt:168cm eyr:2030 + +cid:219 +pid:016251942 hcl:#602927 hgt:163cm +byr:1943 eyr:2029 ecl:oth iyr:2019 + +ecl:gry hgt:184cm eyr:2026 +iyr:2010 +pid:117647952 hcl:#efcc98 +byr:1942 + +cid:243 hcl:#888785 ecl:blu eyr:2027 pid:362697676 +iyr:2011 byr:1962 hgt:154cm + +hgt:154cm byr:1965 ecl:blu eyr:2030 +pid:779104554 iyr:2016 hcl:#435634 + +hcl:z eyr:1996 iyr:1993 +pid:#50f768 +ecl:zzz hgt:62cm byr:2017 + +ecl:grn byr:1988 iyr:2016 +hgt:167cm +hcl:#cfa07d +eyr:2030 pid:951967790 + +pid:320348494 iyr:2018 cid:281 +byr:2004 +hcl:#06a58b +eyr:2033 +ecl:zzz +hgt:76cm + +cid:83 ecl:brn eyr:2028 +byr:1941 iyr:2016 +hcl:#341e13 pid:806979833 +hgt:179cm + +ecl:brn +byr:1982 iyr:2010 eyr:2029 pid:535752324 hcl:#efcc98 + +ecl:oth +hgt:70in hcl:#866857 eyr:2025 pid:203320330 iyr:2018 byr:2000 + +hgt:70cm byr:2015 pid:#218eb5 hcl:#0ec4fe iyr:2014 cid:228 ecl:#c8533a +eyr:2035 + +hcl:#6b5442 +eyr:2020 ecl:hzl iyr:2017 hgt:173cm +cid:330 byr:1988 pid:173148327 + +iyr:2011 byr:1964 hgt:83 ecl:grn hcl:#c0946f pid:931162400 eyr:2028 + +cid:239 +byr:1960 ecl:hzl +hgt:164cm +hcl:#51040b iyr:2018 eyr:2025 + +cid:163 hgt:154cm +iyr:2015 eyr:2027 pid:838964596 +byr:1972 ecl:oth hcl:#efcc98 + +hgt:181cm +eyr:2028 ecl:blu +pid:853714682 hcl:#623a2f byr:1976 iyr:2020 + +cid:225 byr:1957 +hcl:#a97842 iyr:2013 eyr:2025 +pid:511588647 hgt:173cm ecl:blu + +hcl:#efcc98 +byr:1993 +ecl:oth +pid:871652492 eyr:2028 hgt:177cm iyr:2016 +cid:220 + +ecl:hzl +hgt:165cm +hcl:#733820 eyr:2028 cid:57 byr:1973 iyr:2018 pid:018982018 + +pid:491710153 iyr:2012 ecl:#c85046 hcl:#b6652a +eyr:2040 hgt:175cm byr:1981 + +pid:917105765 eyr:2021 hgt:181cm iyr:2019 cid:159 byr:1995 +ecl:gry + +hcl:#9d2ec4 iyr:2011 +eyr:2028 pid:149288934 hgt:63in ecl:blu byr:1960 + +byr:1923 pid:705818464 eyr:2024 cid:221 ecl:oth hcl:#7d3b0c hgt:193cm iyr:2014 + +pid:117111015 eyr:2030 +byr:1967 hcl:#ceb3a1 ecl:blu +hgt:157cm +iyr:2011 + +iyr:2019 ecl:oth +hcl:#fffffd hgt:172cm pid:215010680 +eyr:2025 + +pid:157cm cid:277 +iyr:1976 hgt:159in hcl:#341e13 ecl:#6c7644 eyr:2029 byr:1965 + +pid:787186482 ecl:brn +byr:1980 hcl:#f5dfb9 eyr:2020 +iyr:2018 hgt:188cm + +cid:168 +eyr:2023 hcl:#07c809 +iyr:2013 +hgt:169cm pid:250679100 byr:1945 ecl:gry + +hcl:#6b5442 pid:683134187 iyr:2013 eyr:2023 byr:1965 hgt:171cm ecl:hzl + +eyr:2028 hgt:180cm ecl:blu byr:1952 cid:314 iyr:2016 +pid:720794393 hcl:#602927 + +byr:1982 iyr:2016 +ecl:brn eyr:2027 +hgt:156cm pid:185583837 hcl:#ddbf30 + +hcl:#ceb3a1 pid:987624973 +eyr:2026 +iyr:2013 byr:1988 hgt:175cm ecl:grn + +eyr:2028 byr:1974 pid:350988773 hcl:#a97842 iyr:2015 +ecl:oth +hgt:160cm + +hcl:#b6652a +eyr:2028 +pid:717504683 byr:1970 +iyr:2013 +ecl:gry +hgt:156cm + +pid:453874703 iyr:2015 hcl:#a97842 ecl:hzl byr:1986 hgt:175cm cid:132 eyr:2025 + +hcl:#7d3b0c +eyr:2026 +ecl:brn hgt:154cm +byr:1959 pid:580659686 iyr:2015 + +ecl:amb hgt:191cm iyr:2018 +pid:681417707 byr:1994 eyr:2023 hcl:#c0946f + +eyr:2022 pid:302326561 iyr:2018 ecl:blu byr:1987 cid:89 hcl:#a97842 hgt:184cm + +eyr:2020 pid:457081226 +ecl:blu hcl:#866857 iyr:2011 +hgt:159cm byr:1959 + +eyr:2024 cid:322 byr:1991 pid:210415503 +hgt:69in ecl:grn +hcl:#623a2f + +ecl:blu iyr:2012 pid:524745721 hcl:#c0946f eyr:2026 hgt:176cm byr:1964 + +hgt:189cm iyr:2014 pid:679155617 hcl:#efcc98 eyr:2027 +cid:88 byr:1974 +ecl:blu + +byr:1935 eyr:2029 +iyr:2020 +hcl:#733820 ecl:blu hgt:190cm pid:509009432 + +hcl:#fffffd pid:446558583 byr:1931 ecl:brn iyr:2019 +hgt:159cm cid:146 +eyr:2024 + +eyr:2028 hcl:#efcc98 pid:330588516 hgt:65cm +byr:1972 iyr:2014 ecl:oth + +ecl:blu hgt:175cm cid:197 pid:068138358 eyr:2023 iyr:2017 hcl:#0441c6 byr:1999 + +byr:1992 hgt:193cm +ecl:brn iyr:2018 hcl:#866857 pid:905992465 +eyr:2022 + +hgt:95 byr:1965 +pid:810311252 eyr:2034 hcl:z iyr:1985 cid:254 + +hcl:#c0946f byr:1985 eyr:2030 hgt:161cm iyr:2010 ecl:gry pid:616639221 + +iyr:2011 eyr:2023 hgt:172cm cid:260 ecl:hzl +pid:594747312 +hcl:#a97842 byr:1937 + +eyr:2028 pid:134536806 cid:83 +ecl:brn byr:1928 +iyr:2015 +hcl:#fffffd hgt:157cm + +iyr:2016 +pid:035433923 hgt:180cm ecl:amb eyr:2027 byr:1934 +cid:195 hcl:#583d02 + +eyr:1936 cid:130 byr:1969 hgt:74cm hcl:50e1a7 ecl:gmt iyr:2010 pid:82008848 + +hcl:#733820 +eyr:2020 +hgt:174cm iyr:2018 ecl:hzl byr:1983 pid:087167304 + +byr:1972 hcl:#888785 eyr:2020 pid:593301831 iyr:2013 ecl:hzl hgt:188cm + +cid:282 hcl:#888785 hgt:170cm ecl:oth eyr:2029 +byr:1942 pid:014356555 iyr:2020 + +byr:1966 hcl:#623a2f ecl:oth hgt:165cm +eyr:2028 iyr:2012 pid:558908746 + +pid:#4f5b92 +hcl:#6b5442 hgt:188cm +byr:1994 iyr:2014 cid:127 eyr:2020 +ecl:oth + +hgt:153cm +ecl:brn iyr:2020 +eyr:2026 hcl:#18171d +pid:101990935 +byr:1932 + +iyr:2011 byr:1981 hgt:157cm hcl:#c0946f +eyr:2029 pid:545992967 +ecl:utc + +byr:1929 hcl:#602927 iyr:2018 ecl:grn +eyr:2027 +pid:256056759 +hgt:178cm + +iyr:2016 pid:813526512 eyr:2027 hcl:#20799c +ecl:blu +byr:1971 hgt:185cm + +iyr:2021 eyr:2040 +pid:5135078781 byr:2013 hcl:#7d3b0c hgt:62cm ecl:#dedf53 + +iyr:2013 +byr:1979 cid:269 hgt:179cm pid:871628606 eyr:2026 hcl:#53b66c +ecl:grn + +eyr:2020 +hcl:#ceb3a1 byr:1988 ecl:oth iyr:2012 +pid:558371571 + +pid:908462345 byr:1972 hgt:183cm ecl:gry cid:51 hcl:#af82df eyr:2023 iyr:2019 + +pid:106942710 ecl:hzl +hgt:157cm hcl:z eyr:2025 iyr:2016 +byr:1998 cid:271 + +iyr:2011 ecl:oth pid:191542220 +byr:1951 eyr:2027 hcl:#c0946f hgt:190cm + +eyr:2028 hgt:193cm pid:235913726 iyr:2012 hcl:#325350 +ecl:amb + +iyr:2018 hcl:#a97842 ecl:hzl byr:1988 pid:481250123 +cid:328 hgt:165cm eyr:2028 + +ecl:#a51d9c hcl:91236c pid:2538922220 byr:2017 eyr:2004 +iyr:2026 hgt:174 + +pid:959660262 eyr:2022 cid:339 hgt:170cm iyr:2012 +hcl:#cfa07d ecl:brn + +hcl:#866857 +ecl:dne hgt:70cm eyr:2013 iyr:1980 pid:780067045 +byr:1950 + +iyr:2011 +byr:1981 +pid:902964474 ecl:gry eyr:2021 +hgt:154cm +hcl:#602927 cid:156 + +iyr:2016 +hgt:156cm ecl:brn cid:315 eyr:2023 byr:1997 +hcl:#623a2f pid:339892714 + +ecl:brn hgt:73in cid:184 byr:1960 eyr:2024 iyr:2014 hcl:#888785 +pid:561655785 + +pid:579663338 +eyr:1977 +hcl:#ceb3a1 ecl:grt hgt:188cm +byr:2017 +iyr:2018 + +byr:1941 eyr:2029 pid:252436521 +hgt:170cm ecl:hzl + +hcl:#888785 +pid:378073052 +hgt:185cm +cid:343 byr:2001 +ecl:oth iyr:1988 eyr:2029 + +pid:286459107 byr:1973 eyr:2023 ecl:oth cid:273 +hgt:184cm + +pid:406853460 eyr:2028 hcl:#b6652a +hgt:179cm +iyr:2020 cid:346 +ecl:brn byr:1973 + +hcl:#ceb3a1 eyr:2026 pid:001798001 ecl:gry hgt:157cm +cid:235 +byr:1968 +iyr:2013 + +hcl:#b6652a hgt:151cm pid:504383643 iyr:2018 +ecl:brn byr:1990 +eyr:2021 + +hgt:164cm iyr:2015 hcl:#888785 byr:1998 pid:045813631 cid:237 +ecl:grn +eyr:2026 + +hcl:#733820 hgt:172cm +eyr:2030 iyr:2015 ecl:gry pid:507769390 byr:1979 cid:212 + +cid:138 hgt:176cm hcl:#efcc98 +eyr:2024 byr:1984 +ecl:brn iyr:2015 pid:968062470 + +hcl:#733820 iyr:2015 ecl:oth +eyr:2028 pid:431922630 hgt:160cm byr:1941 + +iyr:2017 +eyr:2023 ecl:grn cid:294 byr:1969 +hcl:#602927 pid:720065302 +hgt:67in + +ecl:gry byr:2002 eyr:2024 hcl:#7d3b0c +hgt:174cm +iyr:2012 pid:296913847 + +pid:42057861 hcl:bb7ace eyr:2023 byr:2013 hgt:188 ecl:#312118 iyr:2024 + +eyr:2021 +byr:1958 +hgt:170cm ecl:brn iyr:2012 +pid:064919306 cid:349 hcl:#602927 + +eyr:2022 +pid:248168906 +iyr:2013 byr:1996 hcl:#cfa07d +hgt:151cm ecl:hzl + +cid:301 ecl:brn hcl:#fffffd +hgt:183cm +pid:806659387 +eyr:2021 +byr:1970 iyr:2013 + +cid:192 +iyr:2013 +ecl:#5ad460 hgt:64cm +pid:001255475 byr:1984 eyr:2027 hcl:#cfa07d + +iyr:2012 pid:194936105 eyr:2028 byr:2000 ecl:oth hcl:#733820 hgt:158cm + +cid:323 +hcl:#a97842 eyr:2027 pid:625573908 +iyr:2019 byr:1987 ecl:grn +hgt:191cm + +pid:997956152 hgt:193cm ecl:hzl eyr:2024 byr:1983 +cid:113 hcl:#888785 +iyr:2013 + +iyr:2017 hgt:153cm hcl:#733820 byr:1984 eyr:2025 pid:138608494 ecl:blu + +ecl:brn +byr:1987 hgt:174cm +iyr:2013 pid:459148475 eyr:2023 hcl:#623a2f cid:266 + +byr:2000 iyr:2017 ecl:brn pid:469155516 hcl:#b6652a +eyr:2027 hgt:193cm + +byr:1967 eyr:2028 pid:064940030 +iyr:2016 +ecl:gry hcl:#18171d hgt:74in + +iyr:2020 hcl:#efcc98 +byr:1968 hgt:164cm ecl:hzl pid:834180009 eyr:2022 + +pid:021397352 +iyr:2018 hcl:#341e13 byr:1978 eyr:2022 ecl:oth hgt:67in + +hgt:160cm cid:213 ecl:#a46ef7 pid:157cm eyr:2020 iyr:2020 byr:1923 + +iyr:2016 +cid:235 pid:454188395 eyr:2022 hgt:73in ecl:hzl +hcl:#7d3b0c byr:1964 + +iyr:1930 eyr:2033 hgt:76cm pid:41117341 byr:2028 ecl:utc +hcl:#6b5442 + +pid:41316572 +hcl:#cfa07d byr:1965 eyr:2027 hgt:179cm iyr:2010 +ecl:grn + +hgt:152cm pid:886168412 iyr:2027 +eyr:1989 hcl:9993d6 byr:2005 ecl:zzz + +pid:661569613 hgt:166cm +hcl:#18171d iyr:2010 byr:1922 eyr:2030 ecl:brn + +byr:1958 +ecl:blu pid:978855125 +eyr:2020 iyr:2019 +hgt:190cm hcl:#18171d + +hgt:68in iyr:2012 hcl:#ceb3a1 eyr:2028 ecl:oth pid:067088299 +byr:1975 + +eyr:2020 +pid:507464869 hcl:#fffffd hgt:156cm iyr:2016 +byr:1957 ecl:blu + +cid:259 eyr:2025 byr:1954 +ecl:gry hgt:167cm pid:832017347 iyr:2020 hcl:#623a2f + +hgt:69in hcl:#a97842 +pid:426496916 byr:1947 eyr:2021 iyr:2015 ecl:oth + +eyr:2025 ecl:blu pid:543125976 cid:192 iyr:2017 +byr:1920 hgt:154cm hcl:#a7ecdc + +hgt:69in iyr:2017 +byr:1932 hcl:#6b5442 +ecl:hzl cid:349 pid:494399909 eyr:2029 + +eyr:2030 ecl:gry hcl:#6b5442 +iyr:2010 byr:1938 cid:100 pid:477259022 hgt:67in + +hgt:145 byr:2009 hcl:#b6652a iyr:2015 +pid:180cm ecl:dne cid:315 eyr:1920 + +byr:1930 hgt:65in +eyr:2022 ecl:blu +pid:671271699 +iyr:2010 +hcl:#b6652a + +byr:1989 eyr:2020 +ecl:hzl +hcl:#341e13 +pid:625435489 +hgt:189cm cid:72 +iyr:2013 + +hgt:184 +byr:2025 ecl:#a1368a eyr:2038 cid:111 +iyr:2025 hcl:z pid:7952164402 + +pid:165478949 +hcl:453b30 ecl:amb hgt:75cm eyr:1987 iyr:2015 +byr:1960 + +eyr:2022 ecl:blu +cid:100 +hcl:ead803 iyr:2025 byr:2018 + +eyr:2024 +ecl:gry hgt:167cm +hcl:#623a2f cid:259 +byr:1932 iyr:2014 pid:360279704 + +hgt:191cm +ecl:oth pid:070592110 cid:275 eyr:2027 +iyr:2011 hcl:#4a4252 byr:1937 + +ecl:blu cid:256 iyr:2017 eyr:2027 hcl:#341e13 hgt:150cm +pid:152140902 byr:1923 + +eyr:1972 iyr:2020 ecl:gry hcl:#888098 byr:1974 hgt:188cm +pid:586853292 + +iyr:2014 +ecl:brn hcl:#866857 eyr:2020 +hgt:184cm pid:422142863 byr:1999 + +iyr:2025 ecl:amb eyr:1928 hcl:#18171d byr:2008 hgt:62cm pid:42120034 + +byr:1923 cid:85 iyr:2017 +hcl:#602927 eyr:2026 pid:922322363 +hgt:68in ecl:amb + +cid:97 hcl:#602927 +pid:436567964 +eyr:2028 iyr:2016 +byr:1994 + +hcl:#9c166d +eyr:2025 pid:834335216 iyr:2011 ecl:blu byr:1946 hgt:174cm + +byr:2018 iyr:2027 hgt:187in +cid:118 eyr:2038 +ecl:lzr hcl:z + +ecl:blu +byr:1998 pid:186cm eyr:2026 hcl:z iyr:2027 hgt:70in + +hcl:#623a2f eyr:2020 ecl:amb iyr:2010 pid:743059641 cid:240 hgt:169cm byr:1957 + +ecl:oth pid:089778639 cid:305 eyr:2027 iyr:2012 byr:1935 +hcl:#efcc98 + +hgt:151cm hcl:#602927 cid:97 byr:1968 iyr:2014 pid:447599233 +ecl:oth +eyr:2030 + +pid:621084188 byr:1941 ecl:gry cid:188 iyr:2012 hgt:75in eyr:2028 hcl:#6b5442 + +hcl:#c0946f +ecl:amb +hgt:66cm +pid:185cm byr:2022 eyr:2039 iyr:2024 +cid:321 + +hgt:177cm byr:1954 ecl:amb pid:445374119 cid:137 hcl:#341e13 iyr:2010 +eyr:2020 + +hgt:160cm +byr:1923 +ecl:grn +eyr:2021 iyr:2012 +pid:286304911 +hcl:#18171d + +hgt:153cm byr:1933 +iyr:2015 +ecl:gry +pid:365430749 eyr:2029 + +cid:294 pid:817081355 byr:1969 +eyr:2030 ecl:oth iyr:2014 hgt:181cm hcl:#623a2f + +iyr:2011 +ecl:gry hgt:177cm eyr:2025 pid:446342686 hcl:#b6652a byr:1991 +cid:241 + +byr:1999 +iyr:2018 +cid:306 hcl:#18171d eyr:2021 +hgt:188cm ecl:gry pid:473752814 + +byr:2002 hcl:#733820 +pid:867697169 +ecl:gry hgt:165cm eyr:2020 +cid:316 + +eyr:2026 cid:59 hgt:175cm byr:1993 pid:531385722 +ecl:hzl hcl:#733820 + +eyr:2027 +cid:50 pid:433963708 +byr:1969 +iyr:2011 ecl:hzl hgt:164cm +hcl:#b6652a + +eyr:2020 ecl:gry hgt:186cm pid:917147781 hcl:#341e13 +iyr:2016 cid:68 + +pid:857547233 hgt:64in +cid:274 +eyr:2020 ecl:hzl iyr:2019 hcl:#866857 byr:1948 + +eyr:2022 hgt:183cm pid:557280094 +byr:1936 hcl:#602927 iyr:2019 ecl:oth + +byr:1933 eyr:2023 +iyr:2020 +ecl:blu hgt:72in + +pid:682285472 +ecl:blu hgt:166cm eyr:2021 +byr:1993 +hcl:#ceb3a1 iyr:2011 cid:266 + +iyr:2012 cid:172 ecl:#04ce29 eyr:2021 hgt:160cm byr:1926 pid:2235389773 + +eyr:2029 hcl:#cfa07d pid:387564370 cid:276 hgt:74in +ecl:amb +byr:1926 iyr:2019 + +eyr:2026 +hcl:#733820 +pid:230583200 byr:1997 +ecl:brn +iyr:2010 +hgt:179cm + +byr:1946 hcl:#866857 ecl:#87b6f4 hgt:150cm pid:298537901 +eyr:2024 iyr:2011 + +hcl:#cfa07d +byr:1961 +eyr:2022 +hgt:167cm +pid:230816154 ecl:oth iyr:2018 +cid:164 + +pid:167899852 hcl:#18171d eyr:2023 hgt:173cm ecl:amb byr:1960 iyr:2010 + +hcl:#866857 +hgt:165cm +ecl:hzl pid:325078465 byr:2002 +cid:61 eyr:2025 iyr:2020 + +cid:268 +hcl:#a97842 iyr:2011 byr:1966 pid:450468785 +eyr:2030 hgt:173cm +ecl:gry + +hgt:181cm +eyr:2026 cid:77 pid:229016136 ecl:grn byr:1929 + +ecl:#ad9ae9 hcl:z iyr:2012 +byr:2029 +cid:77 pid:#b1f685 eyr:2015 + +ecl:amb byr:1920 +eyr:2026 hcl:#92e796 iyr:2011 pid:503853254 hgt:186cm +cid:101 + +hcl:#7d3b0c eyr:2022 ecl:amb pid:536474715 hgt:64in +iyr:2026 byr:1924 + +hgt:72in ecl:hzl hcl:#888785 eyr:2030 pid:048654766 byr:1977 iyr:2016 + +hgt:171cm ecl:brn byr:1976 pid:844553043 +eyr:2024 +cid:241 + +cid:243 eyr:2023 pid:998276626 iyr:2011 hcl:#623a2f ecl:oth hgt:183cm byr:1920 + +eyr:2030 +ecl:amb pid:896953299 +hgt:157cm byr:1934 hcl:#9c12d8 iyr:2015 + +hcl:#cfa07d iyr:2011 byr:1974 pid:451819357 hgt:168cm ecl:grn eyr:2024 + +iyr:2018 +pid:908304519 hcl:#fffffd byr:1936 cid:203 +ecl:amb hgt:76in +eyr:2029 + +byr:1967 +hgt:186cm +eyr:2026 +hcl:#ceb3a1 ecl:grn +pid:594830518 iyr:2017 + +pid:20921789 iyr:2024 hcl:z byr:2026 ecl:zzz hgt:153cm eyr:2037 + +hcl:#888785 iyr:2016 cid:323 byr:1958 ecl:gry pid:118638859 eyr:2029 +hgt:163cm + +hgt:167cm ecl:brn eyr:2020 +pid:557999801 +byr:1988 +cid:273 iyr:2011 +hcl:#fffffd + +ecl:gry pid:206008517 eyr:2022 +hcl:#ceb3a1 +byr:1983 hgt:187cm + +eyr:2020 +byr:1931 cid:78 +hcl:#6b5442 ecl:oth hgt:170cm pid:039713280 iyr:2015 + +eyr:2024 ecl:amb +byr:2002 hgt:162cm hcl:#866857 +iyr:2012 pid:696390563 cid:184 + +hgt:189cm byr:1992 pid:712592503 iyr:2012 ecl:oth hcl:#602927 +eyr:2029 + +ecl:hzl +byr:1965 hgt:182cm eyr:2023 +iyr:2014 hcl:#a97842 + +byr:1927 ecl:gry +hcl:#d91aa0 pid:082227536 eyr:2021 +iyr:2011 + +eyr:2003 iyr:1953 byr:1954 +cid:327 hgt:62in ecl:utc +hcl:z pid:#97c11a + +cid:252 pid:98689392 +iyr:2020 hgt:103 +hcl:298df8 byr:1934 +ecl:oth eyr:2012 + +hcl:#fffffd eyr:2020 +byr:1993 ecl:brn +pid:338398225 iyr:2015 hgt:159cm + +iyr:2017 pid:624798709 hgt:151cm eyr:2029 +ecl:gry cid:111 +hcl:#866857 + +byr:2010 +ecl:hzl eyr:1975 hgt:150cm iyr:1930 hcl:159a9a + +iyr:2010 +hcl:#7d3b0c eyr:2024 cid:224 hgt:163cm byr:1971 pid:631469024 ecl:grn + +ecl:hzl iyr:2017 hgt:167cm +hcl:#623a2f pid:417970460 byr:1949 eyr:2020 + +eyr:2030 +hgt:84 byr:2007 ecl:xry cid:153 pid:9655548750 iyr:1957 + +ecl:oth hcl:#733820 cid:336 byr:1996 iyr:2014 pid:736143470 eyr:2025 hgt:182cm + +hgt:69in hcl:#623a2f +cid:126 iyr:2019 pid:638479310 eyr:2022 ecl:grn byr:1935 + +cid:240 +pid:804066884 byr:1987 hcl:#049f0e +eyr:2023 +hgt:174cm +ecl:brn +iyr:2020 + +ecl:amb iyr:2010 +pid:200411701 +cid:70 eyr:2023 +hcl:#341e13 byr:1974 hgt:61in + +eyr:2022 hgt:186cm hcl:#18171d ecl:hzl pid:613033358 +iyr:2014 + +hgt:189cm +iyr:2020 pid:874302209 byr:1928 ecl:blu +hcl:#1c52f4 +eyr:2029 + +byr:2026 +eyr:2007 pid:166cm iyr:2030 ecl:utc +hgt:137 hcl:8e8916 + +pid:781251989 +eyr:2029 hgt:178cm iyr:2010 byr:1942 hcl:#cfa07d + +pid:671017167 eyr:2030 ecl:amb byr:2002 hgt:166cm +iyr:2011 hcl:#7d3b0c + +pid:369327568 byr:1955 ecl:hzl iyr:2013 hcl:#341e13 eyr:2020 cid:90 hgt:154cm + +pid:169149205 iyr:1947 ecl:amb eyr:1977 +byr:2003 +hcl:z +hgt:75cm + +hcl:#cfa07d iyr:2016 +eyr:2022 pid:941218673 byr:1999 cid:186 +ecl:brn hgt:173cm + +hgt:159cm eyr:2021 byr:1962 hcl:#efcc98 +pid:792538993 iyr:2011 ecl:blu +cid:222 + +pid:#994231 byr:2024 iyr:1977 hcl:b98ff6 eyr:2010 hgt:71 +ecl:#875a67 + +byr:2007 +iyr:2023 hgt:141 +eyr:2021 ecl:grt pid:22002588 + +hgt:190cm +pid:524515058 +cid:217 +ecl:grn byr:1999 +eyr:2027 +iyr:2019 + +ecl:dne byr:2019 eyr:1942 hgt:62cm pid:5866040917 +iyr:2018 hcl:z + +pid:754032301 byr:1985 eyr:2029 hgt:185cm iyr:2016 +ecl:oth + +ecl:amb byr:1948 iyr:2010 hgt:157cm pid:153547581 eyr:2027 hcl:#cfa07d + +eyr:2026 byr:1942 pid:368975422 +hcl:#733820 +cid:322 hgt:188cm +iyr:2019 +ecl:blu + +ecl:brn +pid:535822939 byr:1994 +eyr:2027 iyr:2020 hcl:#18171d hgt:193cm + +pid:706755664 +hcl:#7d3b0c +ecl:grn cid:304 +hgt:152cm byr:1972 iyr:2013 eyr:2021 + +hgt:163cm +byr:1922 iyr:2014 eyr:2028 pid:852815945 cid:324 +ecl:brn hcl:53b08b + +hcl:#888785 +eyr:2023 +iyr:2020 byr:1962 ecl:blu +pid:407158186 +cid:269 + +ecl:blu +eyr:2027 pid:567155642 hcl:#a97842 hgt:74in byr:1995 +iyr:2016 + +iyr:2017 eyr:2020 +pid:782403650 +byr:1952 ecl:gry hgt:193cm cid:273 hcl:#efcc98 + +byr:1963 eyr:2021 +pid:639445576 hcl:#c0946f iyr:2013 +cid:306 ecl:blu hgt:154cm + +hgt:68in cid:191 +hcl:#7d3b0c +iyr:2017 byr:1935 ecl:gry + +ecl:brn iyr:2019 +eyr:2021 +hcl:#733820 +byr:2017 +pid:714110829 hgt:155cm cid:178 + +cid:203 pid:455383907 +ecl:grn byr:1965 +hcl:#866857 eyr:2024 hgt:172cm iyr:2012 + +iyr:2018 eyr:2033 +pid:462538213 byr:1974 hcl:#c0946f +ecl:amb hgt:160cm + +hcl:#623a2f +pid:116799148 cid:336 +ecl:grn eyr:2027 +iyr:2020 +byr:1976 + +pid:654088396 +ecl:utc eyr:2021 +byr:2016 +hcl:#866857 +iyr:2030 hgt:191cm + +byr:1939 +eyr:2023 +iyr:2011 hgt:168cm +cid:141 ecl:brn +hcl:#6b5442 + +eyr:2025 hgt:61in +byr:1977 +ecl:brn iyr:2016 cid:198 pid:401742648 + +ecl:brn +iyr:2012 eyr:2027 +byr:1990 hcl:#6b5442 +pid:476691172 +hgt:72in + +cid:176 ecl:oth iyr:2011 hcl:#c0946f +eyr:2028 +byr:1957 pid:959615191 + +byr:2027 +iyr:2021 hcl:#733820 hgt:165cm pid:6155507056 + +iyr:2012 ecl:blu +pid:397461435 eyr:2022 byr:1993 hgt:170cm +hcl:#b59662 cid:185 + +ecl:hzl byr:2015 +hcl:z hgt:185cm eyr:2036 iyr:2017 +pid:172cm + +ecl:oth +hgt:181cm iyr:2019 +cid:113 byr:2000 +hcl:#866857 pid:045077916 eyr:2029 + +iyr:2013 ecl:grn +pid:717028913 byr:1953 eyr:2025 +hgt:191cm hcl:#6b5442 + +pid:825834003 eyr:2027 byr:1941 +hgt:163cm iyr:2010 hcl:#6b5442 ecl:amb + +eyr:2026 hgt:59in +hcl:#e9ebf8 byr:1966 +iyr:2018 pid:677886127 ecl:grn + +hcl:#888785 pid:771218458 ecl:hzl eyr:2029 +cid:153 byr:1991 iyr:2011 +hgt:76in + +hgt:161cm hcl:#888785 +ecl:brn byr:1928 pid:913959218 eyr:2020 iyr:2013 + +hgt:188cm eyr:2026 +byr:1964 ecl:blu hcl:#733820 iyr:2017 pid:874400552 + +ecl:hzl iyr:2017 +cid:59 pid:130750853 byr:1964 eyr:2028 hgt:177cm hcl:#602927 + +pid:200888672 ecl:oth iyr:2016 eyr:2020 hcl:#efcc98 hgt:163cm + +eyr:2026 +ecl:gry +hgt:189cm +hcl:#c0946f iyr:2019 pid:741121671 byr:1971 + +ecl:amb eyr:2028 hcl:#888785 iyr:2017 pid:060053163 byr:1952 hgt:191cm + +hcl:#55c45a +eyr:2022 ecl:blu +iyr:2019 pid:326991534 +hgt:158cm +cid:149 + +hcl:#a97842 iyr:2013 ecl:hzl byr:1941 hgt:179cm + +hgt:68in hcl:#18171d +eyr:2021 byr:1938 ecl:oth iyr:2015 +pid:888616887 + +eyr:2026 iyr:2018 ecl:oth byr:1990 +hcl:#efcc98 +pid:472330538 +hgt:192cm + +byr:1933 ecl:grn hcl:#7d3b0c hgt:74in iyr:2011 +eyr:2028 cid:55 + +iyr:2014 hgt:165cm ecl:blu hcl:#18171d byr:1998 pid:601177268 cid:64 eyr:2027 + +iyr:2011 ecl:grn cid:188 pid:440822084 eyr:2028 +hcl:#c0946f byr:1987 hgt:154cm + +hcl:#f29c57 +cid:114 iyr:2010 +byr:1989 eyr:2023 hgt:61in +pid:166071094 + +hgt:71cm +iyr:2022 byr:1965 +ecl:#bb3dce pid:88829820 eyr:2040 hcl:z + +hgt:62in hcl:#7d3b0c pid:585528668 +eyr:2028 ecl:oth +byr:1941 + +ecl:oth eyr:2030 +byr:1952 +iyr:2018 pid:422437243 hgt:185cm + +pid:054717793 byr:1989 hcl:#18171d +iyr:2014 +ecl:grn +eyr:2025 hgt:151cm + +eyr:2027 +hcl:#cfa07d pid:071196833 +cid:297 byr:1932 hgt:173in +ecl:grn iyr:2016 + +hcl:#6b1c3d eyr:2026 pid:963034490 iyr:2011 +hgt:175cm byr:1961 ecl:oth + +hgt:69in +hcl:#b6652a ecl:oth +pid:771661551 iyr:2016 eyr:2023 byr:1960 + +cid:63 +pid:190cm byr:2021 ecl:#252d02 eyr:1931 +iyr:1966 hgt:101 hcl:dc9531 + +byr:1976 eyr:1925 +ecl:grt cid:203 +iyr:2019 +pid:170cm hgt:181in + +iyr:2014 ecl:amb +hgt:182cm cid:283 byr:1983 +pid:307867769 eyr:2024 hcl:#cfa07d + +hgt:157cm hcl:#ceb3a1 eyr:2026 pid:109243500 +byr:1926 +iyr:2015 ecl:oth cid:330 + +hcl:#602927 byr:1940 pid:389818848 +iyr:2016 ecl:brn +hgt:68in eyr:2023 + +ecl:brn pid:340990019 +eyr:2020 iyr:2011 +hcl:#fffffd hgt:175cm byr:2001 + +cid:264 +hgt:154cm pid:128094068 +hcl:#888785 iyr:2013 eyr:2027 +byr:1929 ecl:amb + +cid:270 hcl:#602927 hgt:156cm iyr:2018 +byr:1983 +eyr:2020 pid:621875145 +ecl:gry + +cid:345 pid:68093057 ecl:grt +iyr:2019 byr:1992 hgt:109 hcl:35d6e4 eyr:1976 + +pid:714839913 ecl:grn hcl:#733820 iyr:2020 hgt:153cm +byr:1996 eyr:2027 + +pid:820650878 eyr:2027 +hcl:#866857 byr:1957 +iyr:2015 ecl:grn hgt:167cm + +pid:600488426 +hcl:#ceb3a1 hgt:151cm +ecl:amb eyr:2021 byr:1936 iyr:2015 cid:326 + +cid:256 hgt:169cm +iyr:2014 +pid:261369952 eyr:2028 byr:1982 +ecl:brn +hcl:#733820 + +eyr:2021 iyr:2011 +pid:745066100 hcl:#3bbbd5 byr:1998 ecl:amb hgt:166cm +cid:257 + +ecl:#a38be3 cid:256 hgt:154 eyr:2033 +byr:2006 pid:5154675209 hcl:z + +hgt:160cm cid:103 ecl:gry byr:2000 hcl:#a97842 eyr:2026 pid:528503931 +iyr:2010 + +eyr:2025 cid:131 iyr:2011 +byr:2001 +pid:346722892 +hcl:#cc0362 +hgt:168cm +ecl:brn + +hcl:#ceb3a1 iyr:2012 +hgt:188cm pid:760916817 byr:1985 +eyr:2020 ecl:oth + +hgt:179cm +cid:317 +ecl:amb pid:411265118 iyr:2018 +byr:1982 hcl:#733820 eyr:2028 + +byr:1927 hcl:#7d3b0c iyr:2020 ecl:gry +hgt:155cm pid:937138356 eyr:2021 + +hcl:#efcc98 pid:793804751 eyr:2022 byr:1961 hgt:193cm iyr:2016 cid:222 + +pid:715207875 hcl:#18171d eyr:2030 byr:1974 hgt:157cm ecl:blu +iyr:2019 + +eyr:2022 pid:134624402 hgt:159cm cid:154 +byr:1938 hcl:#cfa07d +iyr:2018 ecl:gry + +ecl:oth eyr:2021 +cid:259 pid:0484880795 hcl:#cfa07d hgt:189cm iyr:2019 byr:1958 + +byr:1960 +pid:752967111 iyr:2010 hcl:#52a9af +hgt:151cm ecl:amb eyr:2025 + +eyr:2028 byr:1974 ecl:oth cid:348 +hcl:#b6652a hgt:164cm iyr:2018 + +eyr:2029 +byr:1942 cid:232 iyr:2016 hgt:193cm +hcl:#733820 pid:175cm ecl:oth + +byr:1990 hcl:#b6652a eyr:2028 iyr:2011 pid:054326137 hgt:153cm ecl:blu + +byr:1933 +pid:659875882 hgt:181cm +eyr:2023 iyr:2012 +ecl:grn hcl:#18171d + +ecl:grn iyr:2019 hcl:#866857 byr:1946 +eyr:2023 hgt:193cm pid:494553757 + +cid:331 +ecl:blu eyr:2021 hcl:#733820 hgt:174cm +iyr:2010 byr:1950 pid:405416908 diff --git a/2020/days/04/test_day4.py b/2020/days/04/test_day4.py new file mode 100644 index 0000000..31d3bcb --- /dev/null +++ b/2020/days/04/test_day4.py @@ -0,0 +1,65 @@ +#! /usr/bin/env python3 + +import pathlib +import pytest +import day4 as aoc +from day4 import Passport + +PUZZLE_DIR = pathlib.Path(__file__).parent + +#these test fixtures setup the test, mainly by reading the filename into a string in this simple case. +@pytest.fixture +def example1(): + puzzle_input = (PUZZLE_DIR / "example1").read_text().strip() + return aoc.parse(puzzle_input) + +@pytest.fixture +def example2(): + puzzle_input = (PUZZLE_DIR / "example2").read_text().strip() + return aoc.parse(puzzle_input) + +# @pytest.mark.skip(reason="Not implemented") +def test_parse_example1(example1): + """Test that input is parsed properly""" + assert example1 == [Passport(birthYear=1937, + issueYear=2017, + expirationYear=2020, + height='183cm', + hairColor='#fffffd', + eyeColor='gry', + passportId='860033327', + countryId='147'), + Passport(birthYear=1929, + issueYear=2013, + expirationYear=2023, + height=None, + hairColor='#cfa07d', + eyeColor='amb', + passportId='028048884', + countryId='350'), + Passport(birthYear=1931, + issueYear=2013, + expirationYear=2024, + height='179cm', + hairColor='#ae17e1', + eyeColor='brn', + passportId='760753108', + countryId=None), + Passport(birthYear=None, + issueYear=2011, + expirationYear=2025, + height='59in', + hairColor='#cfa07d', + eyeColor='brn', + passportId='166559648', + countryId=None)] + +# @pytest.mark.skip(reason="Not implemented") +def test_part1_example1(example1): + """Test part 1 on example input""" + assert aoc.part1(example1) == 2 + +# @pytest.mark.skip(reason="Not implemented") +def test_part2_example2(example1): + """Test part 2 on example input""" + assert aoc.part2(example1) == 2 diff --git a/2020/days/05/day5.py b/2020/days/05/day5.py new file mode 100755 index 0000000..6a7d0ab --- /dev/null +++ b/2020/days/05/day5.py @@ -0,0 +1,46 @@ +#! /usr/bin/env python3 + +import pathlib +import sys +import re +from dataclasses import dataclass +from pprint import pprint + +def row_to_int(string: str)->int: + return int(string.replace('F','0').replace('B','1'),2) + +def col_to_int(string: str)->int: + return int(string.replace('L','0').replace('R','1'),2) + +def parse(puzzle_input: str): + """Parse input""" + rows_and_cols = [(row_to_int(x[:7]),col_to_int(x[7:])) for x in puzzle_input.splitlines()] + return set([x[0]*8+x[1] for x in rows_and_cols]) + +def part1(data): + """Solve part 1""" + return max(data) + +def part2(data): + """Solve part 2""" + for row in range(128): + for col in range(8): + potentialID=row*8+col + if potentialID not in data: + if (potentialID+1 in data) and (potentialID-1 in data): + return potentialID + +def solve(puzzle_input): + """Solve the puzzle for the given input""" + data = parse(puzzle_input) + solution1 = part1(data) + solution2 = part2(data) + + return solution1, solution2 + +if __name__ == "__main__": + for path in sys.argv[1:]: + print(f"{path}:") + puzzle_input = pathlib.Path(path).read_text().strip() + solutions = solve(puzzle_input) + print("\n".join(str(solution) for solution in solutions)) diff --git a/2020/days/05/example1 b/2020/days/05/example1 new file mode 100644 index 0000000..6b89eb8 --- /dev/null +++ b/2020/days/05/example1 @@ -0,0 +1,4 @@ +FBFBBFFRLR +BFFFBBFRRR +FFFBBBFRRR +BBFFBBFRLL diff --git a/2020/days/05/input b/2020/days/05/input new file mode 100644 index 0000000..17dfa0b --- /dev/null +++ b/2020/days/05/input @@ -0,0 +1,859 @@ +BBFFBFFRRR +FBBFFBBLRR +FFBFBFBRRR +FFFBFBFRRR +BBFFBBFLRR +BFFBFBFLRL +FBBBBBFRRR +FFFFBFFLLR +BFBFFBFLLR +FFBBFFFLRR +BFFFFFFLLL +FBFFBFFRLL +FFBFFBFRLR +FBBBFBFRRR +FBFFBBBRRL +FBFFBFFLRL +BFBBFFFLLL +FBBFBFBRRL +BFFBFFFLRR +FFFFBFFRLR +FFFBBBFRLR +FBFFFBFLLL +BFBFBBBLRR +FBBBFFBRLR +BBFFFFFLLL +BFFFFBFRRL +FBBBFBFRRL +FFBBBFBRLR +FFFFBBFLLL +FBFBFBBRLL +BFFFBFBRLL +FFBFBFBRLR +FBFFFBBRLR +BBFFFBBLRR +BFFBBFFRRL +BFBBBFFRRR +FFBFBFFRRL +FBFBBFBLLR +BFFBFBBRRR +BFFFFBFLLR +FFFBFFFRRR +FBFFFBFRLR +BFBFFBFRLR +FBBBFFFLLR +FBBFFBFLLL +BFBBFBFLLR +FFBFBBFLLL +BFFFBFBLRL +FBBFBBBLLL +FFFBFFBLLR +BFFFFFFRRR +BFBBBBFRRL +FFBFBBFRLL +FBBBFBBLRL +BFFBFBFLRR +BBFFFBFRRL +BFFBBFFLRR +BFBFFFFLLR +FBFBFFFLRR +BFBBFBBLRL +FBFBFFFRLR +FFBBBFFRLR +BBFBBFFRLR +BFFFFBBRLL +FFFBFBBLRR +FFFFBFBRRL +BFFBFBFRRL +FBFFBBBRRR +BFBBFFBLRL +FFBBFFFLLL +FBFBBFBRRR +FBBBFFFLRL +FBBFFBFLRR +FBBBBBFRRL +BFFFBBBLRL +FFFBBFBRLL +FFFFFBBLLR +FFBFBBBRLL +FFBBFBFLLR +FBFBBFFLLL +FFFBFFBRLL +BFBBFBFRLR +BFBFBBFRRL +FFFBFFFLRL +FBBFBBFRLR +BFFBFFBRRL +BBFFFBBRLR +FBBBBBFRLL +FFBBFFFRLL +BBFBFBBRLR +FFBBBFFLLR +BFBBBBBLLL +FFFBFBBLLL +FBFFBFFRRL +FBFBFFBLLL +BFFBBBFRRL +FBBBBBFLLL +FBFBBFBLRR +FFBBBBFLLR +BBFFBFFRRL +FBBBBBFLRR +FBFFFFFRLR +FBFFBBFLLR +FFBBBFBLRR +BFFFBBBRRL +FBFBFBFRRL +FFFBFBBRLL +FFBFBFBLRL +FBBBFBBLLL +FBBBFBFLRL +FBBBBFFLRL +FBFBBBBRLR +FBBFFBFLLR +FBFFBBFLRR +FBFFFBBLLL +BBFFBBFRRR +FBBFBBBRLL +BFFBBBFLLR +FBFFFFFLRR +FBFFBBFRRL +BFFBBFBLLL +FBBBFBBLLR +FBBBBFBLRL +FBBBFFFRRR +FFFFBBFRRR +BFBFFFFRRR +BFBFFBBLRL +BFFFFFBLLR +BFBBFFFRRR +FBFFFBFRRL +BFFBBFFLRL +FFFBFFBRRL +FFBFBFBLLL +FFBFBFFLLL +BBFFFBBRRR +FFFFFBFLRL +BFBFFFBLRL +BFBFBFFLRR +BFFBBBBRLL +BFFFBFFRRR +BBFBFFBRLL +FBFFFBBRRL +FFBBFBBRRL +FFBFFFFLLR +FFFBFFFLLL +FBBFFBBLRL +BFBFBBFLLR +FBFBFFFRRL +BBFFFFFLRR +BBFFFBFLRL +BBFFBBBLLL +BFBBFBFLLL +BFBFFBFRRL +FBFFFFBRRL +FBFFBBBRLR +BFBBFBBRLL +BFFBBFFLLR +FBBBFFBLRL +BFFFBFFRLR +FFFBFFBRLR +BFFBBBFLLL +FBBBBFFRLL +FFFFBBBRLR +FBFFBFFLRR +FBFBFBBRRL +FFFFFFBRRR +FFFBBBFLRL +FBFFBFBLLR +FFFBBBBLRL +BBFBFFBLLL +FBFFFFBLLR +BBFBFBBRRR +BFBFFFBRRR +FBBFBFFRLL +FBBBBFFRLR +FFBBFBBLRL +BBFBFFBLLR +FBBBBBBLRL +BFFFBBFLLL +BBFBBFFLLR +FBFFBFBLRL +BFFFBBBLRR +BBFFFFFRRR +BFBFBBBRLR +BBFFFBFLRR +FBBFBBFLLR +BBFBFFBLRR +BFBBBFFLRR +FBBFBFFRRL +FBFBFBBLRR +BFBBFFBRLL +FFFBBFBRLR +BFFBBBFRRR +FBFFBFFRLR +FFFBBBBRLL +FFFFFBBRLR +FBBFBFBLLR +FBBFBBFLRR +BBFFBBFLLR +FFFBFBBLLR +FFBFBFFLRR +BFBBFBFRLL +BFFFFBFRRR +BBFBFFFLRL +BFFFFBFLLL +FBFBFBFLRL +BFBBFBBLLR +BFFBFFFRLL +BBFBFFFRLR +BBFFBFFRLL +FFFBFBBRLR +FBFBBBFLRL +FFBFFBBRLR +BBFFFBBLRL +BFBBBBFLRR +FFBFFFBLRL +FFBBBFBRLL +BBFFBFFLRR +BBFFBFFRLR +FFFFFBFRRR +BBFBFBBLRL +BFFBBBBLLL +FBBBBFBRRR +FFBBBBBLRL +FBBFBBFRRR +FFBBFFBRLL +BFBFBFBLRR +BBFBFFFRRR +BFFFBBFRRR +FBFBFFFLLL +FBBFBFBRRR +BBFFBFBLLR +BBFBFBFLRR +BFFFFBBLRL +BFBBBFFLRL +BBFBFFBLRL +BFFBBFFRLL +FBFFBFFLLR +FBFBFBBLLL +BBFBFBFLRL +BBFFBBBLRL +FFFFFBBRLL +FFFBBBBRRR +FFBBFFFRLR +FFBFFFBRRR +FBFBFFBLRR +FFBFFBBLLL +FBBFBBFLRL +FBFFBBBLRL +FBBBBFFRRR +BFBBBBBLLR +FFBFBBBLRR +FFFFBFBLRR +BFFFFFFRLL +FBBFFFBLRR +BFBBBBBRLL +FFBBFFBLRL +BFBBBFFRLR +FFBFFBFLLL +FFBBFBFRLR +BFBFFBBLRR +FFFFBFFLRR +FFBFFBFLRL +BBFFBBFRRL +FFBFFFFLLL +BBFBFFBRLR +FBFBFBBRLR +BBFFBBBRRR +FBFFBBBRLL +BFBFFBBRRR +BBFFFBFRLL +FBBFBBBLRL +FBBFFFFLRR +BBFFFBBLLL +FFBFFFFLRL +FBBFFBFLRL +FBBBBFFLLR +BFBBFBFRRR +FBBFFFBLLL +FFBFBFFRLL +FFFBBBFLRR +FFFBFFFLRR +FBFFBFFRRR +BFFFBFFLLR +BFFFFFFRLR +BFFFBFFLLL +FBBBFBBRRL +BFBFFFBLLL +FBFBBBBRRR +BFBBBFBRLR +BBFFFFBRLR +FBFFFFFRLL +FBBFFBBRLR +BBFBBFFLRR +BBFFBFFLLR +BBFFBBFRLL +FBFFFFFRRL +FFBFBBFRRR +FFBFFFFRLL +BFFFFBBLRR +BFBFBFBLRL +FBBFFFFRRR +FFBBFBBRRR +BFBBBBBRLR +FBFFFBBLLR +BBFFFBFRLR +FBFFFBBRRR +FBBFFBFRLR +BFFFBFBRRR +FFBBBBBLLL +FFFFFBFLLR +FBBFBFBRLL +BFBFBFBRRL +BBFFFFBRRL +FFBFBBFLLR +FFBBBFFRRL +FBFFBFBRLR +FBBFFFFRLL +BFFBFFFLLR +FBFFFBBLRR +BFFBFFFLLL +BFBFBBBRRR +BFFFFBFLRL +FFFFBFBLLL +FFFBFFBLLL +BFFFBBFRRL +BFBFBBFRLL +FFFBBBBLLL +BFFBFBBRLR +BFBBBBBLRR +BFBBBFBRRL +FFBFFFBRLR +BFFBFFFLRL +FFBFBBBLLL +BFBFBBFRRR +BFBFFBFRRR +FFBFFFBRLL +FBFFFFFLRL +BBFFBBFLLL +BFBFBBBRLL +FFFBFFFRRL +FBBBBBBLLR +FFFBFBBLRL +FBBFBBFRLL +FFBFFFFRRR +FFFBBBFLLR +BFFBBFFRLR +FFFFFBFLRR +FFFBBBBLLR +FBFFBFBRRL +FBBFFFFLLL +FFFFFBFRRL +BFFBBBFRLL +FFFBBFFRLL +FFFBBFFLRR +FFFFBBFRLL +BFBBBBBRRR +BFFBFBFLLL +BBFBFBFLLR +FFBBBBFRLR +FFFBBBFRLL +BFBBBBFRRR +FBFBFFBRLR +FFBFBBFRRL +BBFFBBBRRL +FFBFBBFRLR +FFFFBFFRLL +FBFFFBBRLL +BBFFBFBRRL +BFBFBFBLLR +FBFBFBBLRL +FBBFFFFRRL +FFFBBFFRRR +FFBBBBBLRR +BBFBFBBLRR +FFFFBBBLRR +FFBBBBBRLL +FFBFFFBRRL +BFBBFFFRLL +FBBBFBFRLL +BBFFBFFLRL +BBFFBFBRLR +BFFBBBBRRR +FBBBBBBRRL +BBFBFFFRLL +BFFBBFFRRR +BFBBFFFRRL +FFBFFBFLRR +FBFBBFFRLL +FBBFBBFRRL +BBFBBFFRRR +FFBBFBFRRL +FFBBFBFLLL +FBBFFFFLLR +BFBFFBBRLR +BFBBFFFLLR +FBBBFFFLLL +FFFBFFBLRR +FFFBFBFRLR +BFFBBBBRLR +FBFFBBBLLR +FFFFBBBRRR +FFBBBBFLLL +FBBBBFBLLR +BFBFBFFRRL +BBFFBBBLRR +FBBFFBFRRL +FFFBBBFLLL +BFFFFBBLLL +BBFBFBFRRR +BFBBBFBLRR +FBBFBBBLLR +FFBBBBFLRL +FFFBFFBLRL +FBBBFFBRRL +BFFBBFBRLL +BFBFBFBRRR +BBFBFBBRLL +FBFFFBFRLL +BFFFBFBLRR +BFBFFFFLRL +BBFFFFBLRR +BFBBFFBRRL +BBFBFBBLLR +FFFBBBFRRL +BFBBBFFRRL +FFBFFBFLLR +FFBBBFBLLL +FBFBBBFLLL +FFBBBBBRLR +BBFFBBBRLL +BFBFBBBRRL +FFBBFBBRLL +FBFBBFBLRL +BBFFBFBLLL +FBFBFFFLRL +FFBFFBBLRL +FFBFBBFLRL +BBFBFBBLLL +FFBBFBFRLL +BBFBBFFLLL +FBFFFFBLRL +FBFBBBFRLR +FFBFFBFRLL +FBBFFFBRRR +FBFBFFBLRL +BFFFFBBLLR +FBFBFBBRRR +BBFFBBFLRL +BFBBFFFRLR +FBFFFFFLLR +FBBFFBBLLL +FFFFFBBRRL +FFFBBFBRRL +BFFBBBBRRL +FBFFFBFLRL +FFBBFFFLLR +FBBBBBBLRR +BFFFBBFRLL +FFBFFFBLLR +FBBBFFFRLL +FFFFBBBLRL +BBFFBFBLRR +FFFFBBFLRR +BFFBFBFRLR +FFBFBBBLRL +FBFBFBFLLR +FFBBFBBRLR +BFBFBFFRRR +BBFFFFBRLL +FFBFBFFRRR +FFBFBBFLRR +BFBBFBFLRR +FFFFBBBLLR +FFBBBBBRRL +FBBFFBBRRR +FFFBBBBRLR +BFFBBBFLRL +BFBBFFBRRR +BBFFBBFRLR +FBBBBBFLRL +FFFBBFFLLL +BFBBBFFRLL +FBFFFFFLLL +FBFBBFBLLL +FFFBFFBRRR +BFBFBFFLLL +BFBFBFBLLL +BFBBBFFLLL +FFFFBBFRLR +BFFBBFBRRL +BFBBFBBLLL +FBBFBFBRLR +BFFFBFFLRL +FBFBBFFLRL +FFFFFBFLLL +FBBFFBFRRR +FBFBBBBLLL +FBBBBBFRLR +FBFFBBFRLL +FFBFFBFRRR +FFBFFFFRRL +BFFBFBBLLR +BFBBFBBRRR +FFBBFBBLRR +FBFFFFBRLR +FFBBBBFRLL +BBFFFBFRRR +FFFBFBBRRR +BFFFBFFRLL +BFFBBBBLRR +FBBBBFBLLL +BFFFFFFLLR +BFBFFFFLRR +BFFBBBBLLR +FFBBBFBRRR +FBBFBFFRRR +FBBFFFBRLR +BFBFBBFRLR +BFFBFFBRLL +FBFBBFBRLR +BFFFFFBLRR +BFFBFFBRRR +BFBFFBFLRL +BBFFFBFLLL +BBFBFBFLLL +BFBFBFFLRL +FBBFBFFLLL +FBFFBFBLLL +BFFFBFBRLR +FFFBFFFRLL +BBFBFFFLLL +BFFFBBBRLR +FBFBFBFLRR +FFBBBBFRRR +FBFBFBFRLR +BBFFBFFLLL +FBBBBFBLRR +FBBBBBFLLR +BFBFFFFRLL +FBFFFBFLRR +FFBFFFBLLL +BFBFFBBLLR +FFBBBFBLLR +FBFFFBBLRL +FFBBBFFRRR +FBBBFBFLLR +FBBBBFFLRR +FBFFBBBLLL +FFBFBFFLLR +FFFFFBBLLL +BFFFFFBLRL +BBFFFFBRRR +BFBFFFBRRL +BBFFFFFRRL +BFBBBBBLRL +FBBBBFBRLL +FFBFFFFLRR +BFBBBFFLLR +BFFFFBBRLR +FFBBFFBRRL +BFBFBFFRLR +FFBBBBFLRR +BFBFFBFLLL +FBBFFBBRRL +FFFBBFFLLR +FFFFBFFRRR +BFFBBBFRLR +BFFFFFBRRR +FFBFBFBLLR +FFFBBBFRRR +BBFBFBFRLR +FFBBFFBLLR +FBFBBBBLRL +FFFBFBFLRL +FFFFBBBRLL +FBFFFFBRRR +FFBBBFFRLL +FBFBFFBRRL +BFFBFFBLLL +FFFFFBFRLL +BBFFFBBRLL +FBBFBFBLRL +BFBFBFFLLR +BFBBFBBRLR +FFBFFFBLRR +BBFBFFFLRR +FBBFBBBLRR +FBBBFFBLLR +BFBBBBBRRL +BFBBFFBLLR +FBBBFBFLRR +BFFBFBBLLL +BFFBFFBLRL +BFBFBFBRLR +FBFFBBBLRR +FBFBBBBRRL +BFBFBBFLLL +FBFBBBBLRR +BFFBBFBRLR +FFFBFBFRRL +BFFFFBBRRR +FBFFBBFRLR +BFBBFBFLRL +BFFFBBBLLL +BFFFFFBRLR +BBFFFFBLRL +BFFBFFFRRR +BFBBBBFRLL +FBFBBFBRLL +FBBFFFBLLR +FFFBBFBRRR +FBFBBBBLLR +FFFFBFFLLL +FFFFFBFRLR +BFFFFBFRLR +FBBFFFBLRL +BFBFFBFLRR +FFFFFFBRLL +FFBBFFFLRL +BBFFFFBLLL +FFFBBFFRRL +FBBFBBFLLL +FBFFBFBLRR +FFBBFBBLLL +BFFFBBBRRR +BFFFBBBLLR +BBFBFBFRLL +BFFFBBFRLR +FFBFBBBRRL +FBFBFFFRRR +FBBBBBBRRR +FFBBBFFLRL +BFFBFBBRRL +BFBFBFFRLL +BFFFBFFRRL +BBFFBBBRLR +BBFFFFFRLL +FFBBFFBRRR +FBBFBFFLLR +FBBBFBBRLR +FFBFFBBRRL +FBBBFFBLLL +FBBFFFBRRL +BFFBFFFRRL +FBBFBFFRLR +BFFBBBBLRL +FFBFFBBRRR +FBFBBBFLRR +BFBBBBFRLR +FFFBFBFLLL +FBBBBBBRLL +FFBFFBBLRR +BBFFFFFLLR +FFFFBBFRRL +BBFFFFFRLR +FBFBFFBRLL +BBFFBFBRRR +FBFFFBFLLR +FFBBFBBLLR +FBFBFFFRLL +BFBBBFBRLL +FFFFFFBRLR +FFBBFFFRRL +BBFBBFFRLL +FBBFFFFRLR +BBFBBFFLRL +FBBFFBBLLR +BFFFBBFLLR +BBFBFBBRRL +BFFBFFBLLR +FFBBFBFRRR +FBBBBFBRLR +FFFBFBFLLR +FFBBBFBRRL +FFBBBFFLLL +FFBFBBBRLR +FBFBBFFLRR +FFFBFBBRRL +FFFFBFBRRR +FFFFBBBLLL +FFFBFBFLRR +BFBBBFBLLR +BFBFFFFRRL +BFBBFFBLRR +FFBFFBFRRL +BFBBFBFRRL +BFFFFFBRRL +FBBBBFFLLL +FFBFBBBLLR +FBBBFBFRLR +FFFBBFFRLR +BBFFBFBRLL +BBFBFBFRRL +FFBBBBFRRL +FBBBFBBLRR +BFFBFFBRLR +FFBBFFBRLR +FFBFBFBLRR +BFBFFFBLLR +BFFFBBFLRL +FBBBFBBRLL +BBFFFBFLLR +BBFFFBBRRL +BFBFFFBRLL +BFBFFFBLRR +FFBFBFFRLR +BFFFFFFRRL +BFFFBFFLRR +BFBBBBFLRL +FFFBFFFLLR +BFFFFFFLRR +BBFBBFFRRL +BFFFFFFLRL +FFFFBFBRLL +BFFBBFBLRR +FFFFBFFLRL +BBFFFFFLRL +FBBFBFBLRR +FBFBBFFRLR +FFFFFBBRRR +BFFFBFBRRL +FBFFBFBRRR +BBFFFBBLLR +BFFBFBBLRR +FFFBFBFRLL +FBFBBFFRRR +FFBFBBBRRR +BFBFFFBRLR +FBBFFFBRLL +FFBFBFBRRL +FFBBBFBLRL +FBBFBBBRRL +FBFFBFBRLL +BFBFBBFLRL +FFFBBBBLRR +BFFBFBBRLL +FFFBFFFRLR +FBFBFFBLLR +FBFFBBFLLL +FBBBFBBRRR +FBBFBBBRRR +FBFBBBFRRL +BFBBFBBRRL +BFBFBBBLRL +FBBFBBBRLR +FFBBFFBLRR +FBBFBFFLRL +FBFBFFBRRR +FFBBBBBLLR +BFBBFFFLRR +FFBBFBFLRR +BFBBBBFLLR +BFBFFBBRRL +FBFBBFFRRL +BFFFFFBLLL +FBBBBFBRRL +FBBBFFBRLL +BBFBFFFLLR +FFFBBFBLLL +BFFFBBBRLL +BFBFFBBLLL +BFBFBBBLLR +FBFFBBFLRL +FFFFBBFLRL +FBBFFFFLRL +FBBBBFFRRL +BFBBFBBLRR +BFBFBFBRLL +FBBBFBFLLL +FBFBBBBRLL +FBBBFFBLRR +FFBBFBFLRL +FFFFBFBLRL +FFBBBFFLRR +FFBBFFFRRR +FFBFFBBRLL +FFFFBFFRRL +FBBFFBFRLL +BFFFBBFLRR +BFBFFBBRLL +BFFBBFFLLL +FBBBBBBLLL +BFFBFBFRRR +BFBFFFFRLR +BFFBFBBLRL +BFBBBFBLRL +FBFBFBFRLL +FBBFBFFLRR +BFBBBFBLLL +BFFBBBFLRR +BFBBBBFLLL +BFBBFFBRLR +FFFBBFBLRR +FFFFBBFLLR +FFBFFBBLLR +FBFBBBFLLR +BFBBBFBRRR +BFFFFFBRLL +BBFBFFBRRL +BFBBFFBLLL +FFFBBBBRRL +FBFBBBFRRR +BFFBBFBLRL +BFFBFFFRLR +FFFFFBBLRR +FBFBFFFLLR +FFBFFFFRLR +FBFFFBFRRR +FBFBFBFRRR +FFBFBFBRLL +FFFFFFBRRL +FFBBBBBRRR +FFFBBFFLRL +BFFFBFBLLL +FBFFFFBLRR +FBBBBBBRLR +FBFBBFBRRL +FFBBFFBLLL +FBFFBBFRRR +FBFFFFBLLL +BBFBFFFRRL +FFFFBFBLLR +BFFBFBFLLR +BBFBFFBRRR +FBFFFFFRRR +FFBFBFFLRL +BFFBBFBLLR +FBBBFFFRRL +BFFBBFBRRR +BFBFBBFLRR +FBBBFFFRLR +FBBFBFBLLL +FBFBFBFLLL +BFBBFFFLRL +BBFFBBBLLR +BFFFFBBRRL +FFFBBFBLLR +BFFFFBFRLL +FFFFFBBLRL +FBFBBBFRLL +BFBFFBFRLL +FBFFBFFLLL +FBFBFBBLLR +FFFFBFBRLR +BFFFBFBLLR +BFFBFFBLRR +BFFFFBFLRR +FBBFFBBRLL +FFFFBBBRRL +FBBBFFBRRR +BFFBFBFRLL +BBFFBFBLRL +FFFBBFBLRL +BBFFFFBLLR +FBFFFFBRLL +BFBFBBBLLL +FBFBBFFLLR +FBBBFFFLRR diff --git a/2020/days/05/test_day5.py b/2020/days/05/test_day5.py new file mode 100644 index 0000000..d634049 --- /dev/null +++ b/2020/days/05/test_day5.py @@ -0,0 +1,33 @@ +#! /usr/bin/env python3 + +import pathlib +import pytest +import day5 as aoc + +PUZZLE_DIR = pathlib.Path(__file__).parent + +#these test fixtures setup the test, mainly by reading the filename into a string in this simple case. +@pytest.fixture +def example1(): + puzzle_input = (PUZZLE_DIR / "example1").read_text().strip() + return aoc.parse(puzzle_input) + +@pytest.fixture +def example2(): + puzzle_input = (PUZZLE_DIR / "input").read_text().strip() + return aoc.parse(puzzle_input) + +# @pytest.mark.skip(reason="Not implemented") +def test_parse_example1(example1): + """Test that input is parsed properly""" + assert example1 == {119, 357, 567, 820} + +# @pytest.mark.skip(reason="Not implemented") +def test_part1_example1(example1): + """Test part 1 on example input""" + assert aoc.part1(example1) == 820 + +# @pytest.mark.skip(reason="Not implemented") +def test_part2_example2(example2): + """Test part 2 on example input""" + assert aoc.part2(example2) == 640 diff --git a/2020/days/06/day6.py b/2020/days/06/day6.py new file mode 100755 index 0000000..3488ba2 --- /dev/null +++ b/2020/days/06/day6.py @@ -0,0 +1,47 @@ +#! /usr/bin/env python3 + +import pathlib +import sys +import re +from dataclasses import dataclass +from pprint import pprint + +def parse(puzzle_input: str): + """Parse input""" + records = [[list(y) for y in x.splitlines()] for x in puzzle_input.split('\n\n')] + return records + +def part1(data): + """Solve part 1""" + results = [] + for group in data: + result = set() + for person in group: + result |= set(person) + results.append(len(result)) + return sum(results) + +def part2(data): + """Solve part 2""" + results = [] + for group in data: + result = set(group[0]) + for person in group: + result &= set(person) + results.append(len(result)) + return sum(results) + +def solve(puzzle_input): + """Solve the puzzle for the given input""" + data = parse(puzzle_input) + solution1 = part1(data) + solution2 = part2(data) + + return solution1, solution2 + +if __name__ == "__main__": + for path in sys.argv[1:]: + print(f"{path}:") + puzzle_input = pathlib.Path(path).read_text().strip() + solutions = solve(puzzle_input) + print("\n".join(str(solution) for solution in solutions)) diff --git a/2020/days/06/example1 b/2020/days/06/example1 new file mode 100644 index 0000000..0f5b3bc --- /dev/null +++ b/2020/days/06/example1 @@ -0,0 +1,15 @@ +abc + +a +b +c + +ab +ac + +a +a +a +a + +b diff --git a/2020/days/06/input b/2020/days/06/input new file mode 100644 index 0000000..ae67ede --- /dev/null +++ b/2020/days/06/input @@ -0,0 +1,2199 @@ +nvlyak +nyvha +yaen +qynia + +kend +endk + +atxcykpvmb +pcvmthyxbak +ayvpcbtkxm +cvpkyabtmx +typbmvckxa + +s +s +s +s + +on +aoqc +owq +coa + +pw +wpi +pwxlhqor +pw + +nx +xn + +dlevrzpucfmsq +pceimlrfsquvd +dpceruqsfmlv +hgxudfpqyvbcslrjname + +kczmswvorg +uryvlqaogmdixs +rmostvg +gsrmovb + +ref +fer + +vmwdhgnlfiyoepsujbk +epudykjwhignmfbovsl +fjvuimnwbkogsldhpey +ibmhuscpgeolfkynvdwj +psjgubfvlhaknodeiywm + +fmnpljusix +vqrefngyjdahclk +lfjons + +y +uiwl + +lsuqkmjinrzhgevfpwto +gkmodihnsjtful +ciguflhkojmtsn +thkjnoufsimgl +oskgmdfljntuhi + +gaktdwxhmqvfrpsuc +hmtwkgipdvaurxqf +akrmpxtughdqwfbv +gumqniswhrdkvftaxp +hagouqxpzrjlmedftywkv + +zkbyecw +kczeybw +wbeyakuzc + +iwdkjlarzfynvechgbxsq +jetfxrzdbcksnavilmwgyh +wvexlryjbizfgkhanqdcs + +vk +kv +kv +vk + +yrguw +rguyw +pwuryg +gnuwry + +dyhkusanvjwc +ukaywncj +uyqjknwac +aknyjcuw +jnukwaytxc + +toczmkldrevywiajgn +jyldmgewcvrozinkat +iynkmatdjerlogzwvc + +pthyrfjgqelxa +qfejxtrynlh +xwdfkuziyhejtqovrmlc + +osjrgc +vohfpa +goc +gjo + +j +jon +j +xdj + +bpqhmgwzakfrtjvuno +eafupgombqnwrkzth +frwqtdngpbhuaklzmo +wgtnuchpkqibfzmravso +mfbtvkghauzopnrwq + +xiocgdwpastbmyj +rdzgcbtfaomsy +dstgbcymozkqal + +xvc +cvx +xvc +xvc + +dhvtlqkeniymjzoa +eoazjnhvtkyqdlm +koltmeyqjhzdva +doumkhrlyzjqeagtcv + +mn +mfhw + +kx +x +jm + +x +xv + +tdhyubvwqfxejslpringc +xqhvtbfwrygsdapjiulnec +vnwbsurdiexghpjtlycqf + +pqtdgsmkolzryca +qjguxdratfeclpmoy + +twnviyzmlk +gknjmyqvziwl + +deoabzihqvycxn +iqcxadpehvry + +dbflcxvnapwgei +pchmodnafl +hadcflpn +dlcfanp + +tk +kt + +peuroxtzyg +iwdcnlqfskmbavjh + +mjfh +ynkbrsdpwoqtagci +lvx +ujxez +xl + +gyuszwb +sioduawzrglb +tsbumxwzg +zwgeuxbs + +tujvkwpy +tyvrpmjfk +vwpkuyjt + +wdkqailvjmfcshugy +qugwvlxdsikhfmyjac +dkiscawvyfqhmjlug + +noblsu +snloub +sulobn +lonubsm + +osecqjbfg +fljbmiose +ojesfbt + +zmctviabre +ajzmicetrvb +ctmivabzre +yrztbmieavc +mivcbtazer + +tyql +osmjgxzrcakn +iwftdbl + +nmqflphkvyjcatgbzd +jxzemtvdknwqr + +ilxrytkdpmsevfjchozqw +tpdrjxwihvlycozemsfkq +hitwfmzvjpylcodbqxsrke + +flhp +pflh + +ao +a +o +o +gljzn + +ajmkvwqu +ogvjzwta +whalvuj + +mhktpynfrjgblaqueox +anmjxplvibukhztqersy +tabljcpemkyrxhunwq + +lnkvfawqo +nofpsqwavylz +vofwalqen +hcnowiaqlfv + +dofxbaqrtnyvkpljmhsu +uklstfynmbxhapojqi +tufmnpaqyojsklxhb +oanlusqmxftkpjbhy + +tpjle +the +vtpez +ytern +ouecxwfkt + +jbna +xepqbmufn +ybjni + +jklhaxoqysbt +tzwpcf +tenfcvdmpzu + +kyqumgfrdiapzwojtvch +fvczqjrgadiwhnpluomk +dpwkmrjzauiqvfgcho +nkpwrmzidfahcvjuogq +azrkxioghpvcudmwqfj + +udjshwgpeaozimcl +fylwnoevcza +evlakborcfwz + +xhued +iubgewo + +lywovcemagd +ahveyomxsl +oqzyfljavbe + +pkyn +befycqpi +pysk +yp + +mgi +mgi +digm +gmi + +cgdqeoyfjranxuv +lwnkzeptsdqihvcujmg + +wzqrhgibdxuyl +ludbwqxgiyr +yruxibwdgql +bgtwqxruylid +buyrwlidgxq + +gqwvxspbl +xvbwpsgql +bspgxwvql +cwlxsvqgpb +sgpxqblwv + +camqk +onaslperix +jauw +yatm + +z +z +z +z +z + +fx +fxe + +goemcr +roegm +sgmxiero +ogmert +germo + +czgdxtiprhnwqeujkfl +dyhmkanzwbv + +n +e + +dkcjqbw +o +gp +h + +zbwcu +ubf +mveurnab + +tqwbxuc +qcwutxb +ucbxwqt +xqwutbc +xqtuwcba + +uwhqrt +wrtq +trwq +crtqw +wrtqc + +rqfntm +nrqm +rqmn + +limsht +alstikh +ilhst +uhitls +lsahti + +oaex +vsgyo +lziu + +cwqdlxbst +cdxtlwbsq + +hgqc +hgdq +qhg + +eh +he +eh + +zfutalwkxms +ukxltsfzmwa + +zpklocsqgwyhb +zobyqhlcksgpw +zhspqwovjylkgbc + +ymkudfqethwgji +emtuyfwghjdqki +zwyeumktfhjdirgq +wymqgifkudjteh + +edhqnrxtpz +tqdxznrhep +qzepndrthx +exzrhnqptds +zetyhrpdqunx + +vmleax +valxum +vpmlax +axlpvumz +clvamxbn + +ebt +xr +rl +u + +vzny +nz +nz + +ywebzj +ywefjzb +bxwnjcyzkep +zjeywfpb +yldrbhsizajewvu + +hfd +dmf +fadh +dvmf +fcousnld + +egar +hwnrgzcp +bgofedjr +jkruvsylg +rdvgue + +jsge +hesqg +esug + +xaoz +ocuqev +fwgrlp +otxv + +fzemjdhwb +xhdmjzbe + +ytsfpumedxqvzhl +fdteschymvxqlpz +phyrfwtqlaxgvznesd +hvlextsbqpzyfd +jydlhetzoqfpsvix + +jxkrobp +rsplxbgk +yxmbpkorhj + +injbuyktrcs +bcsriktuny +skyrhbtnucxe + +duck +cykuv +osfcurnlwax +uvmc + +vpt +tpv +pvt +vpt +vtp + +dacxvsi +icaxsd +xdihcneas + +nf +nkf +fn + +yrewaxckd +wtydesfcr +erdftwqyc + +hmfezapkqjyri +ekqajhyzfpmri +raikjeqmhfypz +qjmyrekfzphai +frtjeqkimhazpys + +ryxmsbqovuidphfwecajnz +hdjmiqbxnpvouyfcewsazr +vubyrcmqeswafxjzhinpdo +cbjmnaoqurlhsifvwzdexyp + +iu +ui +isutlr +iu +iu + +lftaziorb +rvamfeyjgqnx +frtak +aifr +aftzr + +us +schk + +bjafywgieth +tifbhyjgwade +imhwefbgatjy +wgtyifejbah + +a +yj +b +iab + +qkgazumerlhb +syritxopfvd + +gdiakrne +ygdpcwqfbmikzanver +dolarkigen +gtkanierdh + +axv +axdvl + +erpjfh +prgjfeh +hrejpf +pejfhr +ejrhfp + +zijsrtcqdxmy +mtxdfyji +timydgxj +jtmhvakxidyn +iyjmwdvxnt + +rh +har + +tdoyugpljirwenzx +nurlzgjtyopide +jnrlitgpzdoyue +zlptnudjryogie +pzgyeoliturnjd + +ivcyexsotkzqmr +sgfjhqnpy + +omw +joq +mop + +welbhpzftgjinqyk +gwpdjqacitshlbykfzmrx + +sygqwn +fwyqsdg +scgwqy + +gdjzwbhltxs +dlkojzbq +jfavyipcembun + +cydkuqlhan +uavstnychbqxk +azqntcuyhk + +k +bf +z +w + +gyh +e + +rhmpg +pmhgr +rpmhg + +pas +vhtsaqfgnu +kpjsa +sab +jcopska + +tsjabirpehudncx +custniapedhxrb +cepnuastxhdirb +shbpetcdaxuinr +dbtiepaucrshnx + +tuswfrqpgxk +kprjsdtqxunf +pxwfrtuqske +xwskmfprqut +pfrtxqskhu + +szirxjtu +zuxjtsi +jutsxiz +usjitxz +ijstxuz + +zqesxfbmrivokl +mevkzirbfol +fbkomeyvilrz + +rlwoeckxnh +xebkornwcl +xcoknwler +wnlkrcoex +kecronwxl + +fmdbraihnpxytkcgezu +kbeyxmadczhritnpuf +pnhfmubicxteadrzyk +updrybtmhzefcnxkia +kbezfjwmhytnixacudpr + +w +w +w +w + +fgwdoctvpzymhbrkjxn +yaqjctxvsrozmwk +xkwozitrvmeqjcyl +cwkazxtrmlijyov + +vnym +bvmy +yvm +byvm +vym + +mxjblongrfahycqvpu +ncywhdpxefajbrgloqu + +sgukdmfqvbwcei +zigahlxojdnpc + +fudobaklngyjqpstmiz +psflydzmbtkiqaojgnu +itgzqsfdyabnolpjkum +sitlkyuqnjodzmpbagf +ytdijopqublaksmngzf + +vhaobfn +ohbnfav +vahofbn +naovhfb + +tfhsqwcbrv +iqrbzspnwyhtfc + +pfbwotesuyhkvgx +vnrlcxayzdmih + +nbyhpfklvtqo +qbtjopfyk +qpoeybfkt + +uvmgzs +pvsmizrug +ghvmszu +mugszcv +kusmvzg + +mua +amu +uma +mua + +d +m + +s +s +yuk +s + +gtjqp +pfotsh +pshgbt +wpeztyr +bqjtplo + +zwbvestiaoljy +gmnzshupfqre + +anvsdkbltiugc +tqsdcanuibgvkl +stkrvabegidclxun +takcsgnuvmdibl +cvqsklngiubadt + +txvfnuwcljpqkeryoamigd +jgarvmodftpniekquxszcyhb + +htu +hegb +whf + +jn +nj +jn + +vcjlxekmqzoduphynw +hkyeojlvndumcwzx +ozhdnvjeckwlmuxy +ujxdyznvlcmokhew +vdywzekucjnhoxlm + +blxuhyvjrzow +uzlwokmsripy + +rum +mrl +rbwfmz +durmq + +obcpqvkitduelwf +ahcrwiltpuedfobxkv +cvijgzoukptwdfble +kpqjduetilovfcbw + +irfqsp +wifas + +xvgyrpq +yrpqvhgzx +fspxmrivkwgycnequ +axhyqrpvgz +xdygqvrpa + +xrlmcsibvea +bdcveasxzip +esvbclaxi +vaxsbcei +xaeibsvc + +songrtmwhpydqizlf +halvzroefxcsubt + +uqozritygam +kmtryqvz +qfmjstkyrz + +rqtepcofhuylnxaj +xoptqwruhijsmnzcylfe +hxqcpyfjntleuro +brjyuoetfxpndlvcqh + +prltixwohdmfjukgqzsv +orluxtzpvjafdqwkhsgbe + +iyhuarewvbfjmlz +vramijyfzhbew +zyehbmwvifjra +vjmweybazihrf + +duixtbqyhomsla +suinmaxtlqdoyhb +htiquxmaybosld + +pselyhov +zhwpovekt +snheopv +ivxophe +nhpoeuv + +amqcriebkojlwyuxnhfdptgzvs +uovdszkygbjhanefqxplimtwcr + +ozngukih +nvksbd + +grkotivmcxnyubwleqspjzhfad +ekmqxnfabwiduopjsgclzvyhtr + +jzv +wzxfivmjb +zjvp +zjv +jzvs + +js +evqis +qxs +swyct +s + +n +n +zn + +udjtxws +usdwixj + +lf +l + +cdsaxzlv +jcsxlnydtrzvk +lvdqamzsxhc +udlxwczvgs + +gutwbrhjxyeam +jrleawgbsnxthimyu +rbjexdythumwag +hrwjmoexytqaubg +uwymabxrhjqgdect + +vipjrlbsmcogxznty +vetpngyzsbmoxcrijl +hoxvbsnjlfygmrczpti +pmlgzyasvxticjbrknod + +xzakbvtehnlciswmyufjdrgo +kocmslwbgvuxijernzydfhat +vcdxgkslnzoarmjwutyiefbh +tzhugvbcnokyxsfliwardmej + +up +u +pu +fu + +cbzjelmqivw +ickezvjlqm + +srwnt +nwrtj +rswnt + +hfjxoskd +dlpzeyjai + +mt +tm +mt +mt +tm + +rpxenfzmhwdvacbygiujkqot +lhbvkwmpfyazrtojcquxind +qtcjdairznhuwxmpsvyfkob + +apvk +qvapk + +ujscpqtgbyezdfhnwoil +bftognyujilpwhsqzdce +zbhslwipdjeqntcfouyg +tyuqdlfepgzshcoiwnbj +dzqxjblenucpwshtoiyfg + +cdxtsaunbwkezlrp +vbdpsuktlxczerwan +pnxudwaclrtebksz + +tq +t +zt +t +jtqg + +fvmhiloanbgjzptryucdkxw +jzhwtkbdpoxfacirngluyvm +pwnybcjmgxurfzivoklhdta +brtavopdklnhxwgzmifyjcu +ncifvypdtgwxbzakhjrmulo + +kwhiguft +uxyo +ux + +ruyoe +ezqhbi +clndewsfta +e +qrke + +doa +doa +doa + +xt +tx +xt +xt +xt + +roxwktbmgiyc +qtbejyxzlpcaighfod +oscgtuyiwvrbkxn + +agcdevxkmbnzqjl +jrdzmnclbgkvexqwa + +pqjtyenfmxdaorw +qayjpxmfdterwon +frdtlawxmjnoeqpy + +aze +zea +veaz +yzxdequoa + +eq +uetqs + +jsmezrk +zskmer +zmkers +krezsm + +mfzqsukgcw +cmskguzfqw +gksucwfmqz +uwqsgfzmck +wfzucmgsqk + +wftx +fwtd +twf + +bizwg +gzwosd +afzqrwun +cjpzwb + +qjntchmdbgpe +nqtephjgmdbc +qjeltdcphgbmn +nqtbcjhepmdg + +g +g +gr +g +g + +yulnpwc +uplcwn +nplemufywc +calkisogupw + +sigh +igsh +ghski + +naqpd +xydrsjwlibzm +qdevh +cd + +mraejinsdp +mierdjansp +qpsmrianjde +npirjedams +ridpaejmns + +o +o +o +o + +lhfqsxm +xlmsqfh +slfqmxh + +jhivsoabqlfpeuw +fvxrelbhuncowqjtsz + +yajhetclfk +jnqbylmpwgxcf +azchyrsivjeltdf + +n +n +n +n +n + +hkuaq +hkqua +uakqh +khqtalu +ahxkuqy + +tguprf +pfu +ufp +uofp + +lnmtjo +njolmt + +qymzdw +vjckmtl +oipreghfausnxb + +niswjectqkldzyg +wunjdetklisczyqg +gldcysiqznjtekw +iqwdczjsytkleng +lgyiezdncjqktws + +dntm +atm +tma +tm +txm + +ntpcwask +skcna +nksac + +prai +pria +arpi +irpa + +mzldgbrtovj +tbjgldozmvr +ogzvdlrjtbm + +ft +fq + +jgstdlzarcemiopynukfw +ywlhakgzeoxdnjmsirc +moicgebadzlwkysrnxj + +jpeiqxbz +xipjebzt + +rnpf +fqhu +agprm +wedyzci +bxur + +aynswjoklfeqzcitxudbrvh +ihrbxwvdqsyoejpnfkzc + +hrqliwxtfbk +qiwfrxbtkhl +kihqxrftlwb +wrhlxbtqkif +tfbqriwlkhx + +bwdhnqk +wbhkqtd +qwbkhdx + +fpcboialrdgqkejntyzm +lmieayocqpkznbrtdfgj +mbtdrpozfljkeyangiqc +pmdjlerfkybgnaoqzitc +pganmcfbtedkrzloyqij + +zfrvn +zfnr +znrf + +nuq +ltiuacgjs +aug + +xj +lyzixn +eaxwuf + +aeywqjkl +eanklwju +kjelzaw +ealjwtk +azklwej + +ncqxulrmfvedao +eodqxlvmrncu +elrmnuqpcdoxv +qloxudmvnecahr +lcdxqwmurvznjeo + +aijnhvxemsqztfk +xnvkehsiqmzft +tehvxnfskiwqzm +epsmzhixqvtnkfr +htkinzvqefxmrs + +wgfzomlbhujxs +ezvrxmkycafwob + +lhyrq +ylfherq +hlreyq +wqlyerh +hgsqlyru + +acnkurdevm +duernacvm +nteaducorvs + +hxvqtsjzgn +iakeoyr + +id +i +di +hkxi + +fqunm +funxikw +xfiuknz + +wvgpqlzxnui +livzmwyqgpnu + +eanbkcjlxpsm +ofmdwrqe + +w +ws +wr +w +w + +aylsbi +lyaiqsgb +vyeblmasuhi +yblsia +ylbsiaq + +fpbhozqdljytwcnxsvr +zarwdgqhtvyxcnpbsofji +dbzhsfwrvqnyjxtpoc +qwxpbnycrfjsozvhtd +tsoypwnmzfjhbvdxcqr + +bezfskqut +egbpkdflqtmouzs +kxzenfustqb +tsebufkzq + +hoekryzuqt +oreuqhyktz +teorhukzqy +kyqehortuz + +d +uqwgitdaj +dz +vod +fvd + +smjqnlt +jsqmlnt +ntsqlmj +jqntslm + +saxdlkjwvyctqenrio +wqnvsoyaextcilkrjd +krdqwevyliojxcntas +ywlnkcafdoirsvjxetq + +ryae +yaq +ya +ya +ya + +epvy +nvyqu +vnxy +oyvh + +kschegfmla +lgfmscaehk +gshfalcemk +lcgemshkfa +mkgaselhctf + +bfxqtegnoismrk +mnuivtxasgbjqyfkp +mkxgrnltfiqbhsw + +s +s +s + +zoe +eoz +oze +eoz + +q +kuprd +gvmbn +vctx +oi + +nbrjveycdlw +jyhfcwnglerv + +vkoxqwfhubrcsnme +bqkexhovswmntfrc + +aidoznexygkjlqs +neysaiudmoqklgxzc + +ypsn +eyp +yp +iyp + +gol +olg + +rypjohwvxkisnldatuzfb +btpxvolknwdhuryiafjsz +vkahgbsitwdoyjplfruznx + +mipqtk +nikqpvu + +kztifpne +yzit +rigtz +zait + +jxgvt +gfjoky +kvygh +dmwgqsrcp +ounalgyze + +nypvuiseqtjwxchlbfogdamzr +apqnbzhwmjldotfsvexruicyg +bpyjzomwahcrgsutlefxkqdivn + +qumcbsvlpthfwyda +hagwiucnvfdypqlzs + +tog +otg +gfto +gto + +ctp +uda + +vlbi +swmiujf + +xbi +upsdbi +bizr + +ltw +we +wzavnymh +iw +wfe + +caqjdphelmtvyfbxo +acxmtljedhoqbsfyp + +fyqthpe +bmrceljqy +eyqt + +frjdhuyqsgon +krouhsfgydnj + +ltopekjnacgbms +elngjotmpsca +splcgnatmoej +egjctspmlaon +jtealcmpongs + +fvsmiotkb +fbnupmcsxd +fmkvjysb +qbksmywrtf + +mklqnp +mqnlk +mwqnlke + +jykqrlaocvunfpix +rcymsnwuafdtvgbqoieh + +c +c +ct +c + +mlv +lyfpq +vsli +vrdwl + +srtaq +nuptlr + +hcfjdaqwo +qmoefalzdh + +zxyksijbeahgvc +xgvjhsczeyikba +yxickjesbhgavz +sjvgibeczxhkay +hvgizjmaxsybcke + +wjmypxi +jipmx +pjmix +bjivamxp + +dytnalmqkbpruef +qplfuynbdaertm +rbnetqdupamlwyf + +e +e +m +p +e + +b +eb +b +b +b + +yieovwqukxcnbfjpdg +qjvunkgywpfoidbxec +jupowqfbiknvdgeycx +dqeicgjfpxonbukwvy +gociquxvjbfdwnpkye + +lwrch +huosc + +somiywgdbf +fbmvdwgzsy +ufrltkydsnwm + +epvfduyh +vfpeyuhd +epdchvyuf +udeohyvpf +evhpyufd + +b +b + +szfgmlxwd +eapoqydvi + +puedtjkqbwfznhvycxrolamsgi +cvqeyszrwdfnkutjihxmlapbgo +nfdpoukvizgctxwmeaqjrhlbys + +nuf +je +uieq +ctodh +sbx + +psrwqlgd +lrwdqgpzs + +qheijmngzsrdawbvucolxpy +vhqnlcouibjdarzxpmeygs +edlixjhrquamovnpbsgycz + +jkphyr +urycxn + +snbcyoe +nuewpy + +gbnsoirkwyhp +iogsqbkymwp +fzbwkeyutdxp + +w +w +w + +jsbp +bjsp +jspb + +jfbdpv +pfjvb + +wfhvsjloznb +gmupxcnrakelfsvzqd + +dbsuoriacgnwxtzveyhqfkmp +adwcifzvsgnkphyburtexomq +wzbkmsdpfrhiaqxyecuonvgt +athzyrgbwckvomqudsnexfip +vidbhyqesancrzugkxfopwmt + +nl +ln +nl +osnl + +iewcxgqtf +gtwmfieqc +icfvqwyhadgkn +qcgwerfli + +wyj +jy +atycnje +qyjg +yzjsg + +ivjwfeuz +jvcw +mbhvwj +rswvhjd + +zmjlpeia +eimrlpzaj +jmealyqpi + +zgkf +gkz + +zuosdlvkxm +tlxskcvpumo +kuyomrxlvs +uvosxmldyk + +yuilcqhgmazts +swhvdcigltmakzuy +stojxiflyghnazcpum +gkhqtyciuwszmal + +nzhlyu +hngc +ngcah +anch +nvkhj + +xhfvwbkn +nahwxfo +fhgnwx +dmfuxnht + +vbhpedluncftoxys +cydfsolpejhbntux + +vkilx +pvxskd + +hvwuecgs +guvwcsh +sgrwculmvhb +wcpznuqsvghi +vhwcsulg + +ndfapjlztc +npoacfjtld + +jzd +xaulvyksp +zeh + +ck +ck +ck +kc + +kiroh +rh + +euxdrkvtfbqon +ytfvurxwheokqn + +sirznatbxkghm +skaiqzrmhnx +ztgmhrsikanx +hksxmairnez +ywdiracnfsuzhjxmpk + +bacgwvmxrdfne +pdcofwbza +cfqdwuptzabo + +dqmp +dqpm +qvmpd + +kczxnlerm +vqrzjmf + +qmuorwspx +dywcxarilegkh + +gqzph +qhapozk +zhqp + +fastkjnl +jsnafkt +jfnacskt + +fxgpiadjrvhs +smfwbejadh +hjmfyaods +fzdqsjham +hlcbyfjkaunsdt + +dqlevpahscoyi +iypldavhsqoce +clhvyaisoepdq +eayqiosdlpvch +epodliqvhcsay + +nhxbmlqv +qylkhmnxvbj +xbnlvqmh +vxmbhqln +lbvhxsqmn + +exrtdq +tderq +djretq + +lwqj +jmwlr +zbswtx + +pxi +ipx +ixp +xip + +vgfscwrqzdojxhe +xfvqhzsjecgownd +qdopyzjwegfsxchv +gosqeckhvzdjfxw +gszxpfveocjhqmdw + +gvlyuiscaewfpx +gfwjtapuoynvqzi + +ycsdnbzjoki +wfpvogmqhautlx + +tbjliqdfzgny +zjwilpghqdyekc + +yftcnao +ncfytaio +conyfta + +yslactbwhjfvnomiue +mbyiavojlwtunces +eontumvircsalbjwy +jguvcxylitsbmwenazo +bayolijwqcevpmsktdun + +ynmki +ykinm +inymk +iykmn +yimnk + +vzjnpybg +vjqfyno +rnvity + +ilxkjhcfpdmeb +hwdjleirc +aiulechdj +dljiwehc + +rptom +ife +nuli +yized + +loe +eg + +fprtvcgkwnasljebhm +nvbltrckumfhpgjew +grpuefzknmblovjw +bjwgykpinqlemrd +mrlegnjwbkp + +xtquyrjnszl +ysrqzj +zsqyjpr + +ft +fjt +ft +tf + +ejli +l +l +rl + +lwgrihbdvno +ydbrvhgolniw +rivdongwhlb +ndhbrgwilov +dwvrnlhbgio + +fc +fc +cqfo +fc +fc + +nhaoi +nioha +osijah + +hgrec +gchre +cehrg + +higmvfbtjre +ikhxjbrefvq +brjiefhvl +ivfeqblhrj +hrkifjvbe + +vsgqmibordtznkl +dehupjlcxtsrnfawy + +t +crfi + +nrai +hjcmpzla +dveria + +krp +achvofx +kbp + +vfdzhuskanm +lhucb +uh + +qu +uqj +quh +qu + +tokmzyuxjsbvic +zegday + +wqfxlhyapcdtv +vctalwmjdpqyfh + +nqge +vneiqt +hqvfenwj +nksqcrlmde +vqgbone + +f +w +w +f +oq + +qziwcdjyepvhn +wvypijednqzc + +uwjflbhoq +dwxublig + +c +lc +ec +c +txcjrkd + +cglvpyadf +rqfvgaplc +kgpatsxuelvh +oapgvliwc + +ln +st +bs + +sfra +dskrnf +mzhjrfpx + +phu +uph +uph +hpu +phu + +pcxhvbf +hxbtyk + +jdzsaiwbphmftqxrlngcyoe +mqbrsplojgyheznxcdtfwia +pitajxzhsonwygrfblecmqd +nyliauzgfbcprewhdtjmsxoq +taxnylhvgjqewcksfpmzdbior + +h +c +om + +ruplsfnhyjqigwkzexbtoc +newjivhyckdagob +ywocjmnkbghie + +jdrtpbvohaxy +dnjxyrfsv + +lq +nsulxvmhj +l +lk + +fdsxhvqaiblt +fihykrdlsoaqx +laqgpznecjiuxfsdhmw + +capkzueqjmdv +ckdvymqazu +fklcmdbuxqarzv +zkcsvmqhiadgeu +jotqkuzndvciwam + +lzqbrgkp +grvpntoz +ozwvpg +suefagcp +pkjygd + +zbangyoqjlkdevrxti +gzniebarjloykqtdxv + +xviqehycstgjladuoznfwp +odwplyiqnxghutezcvsj +ersxgqtcjouvdiznlyhwp +cpshuoijtxvelqynwmdgz + +tnzkdmgqci +mqkzgydtijn +mtikzqdng + +d +ad +d + +k +iof + +otkvualrqdsixf +nkhwid +dbkiwpj +ikd +ekziydgm + +wjvgqsxinfburh +wxgqsurjvflnhbi + +hebmgftkpcq +owektbpfhqcmg +egtfbpckhmdq +qmcetgpfkhb + +exukswmlgznjoqhvabid +dkgmeoahtxpzflnwru + +lf +fl +lf +fle + +zblhfjqpr +rzp +uprzo + +wmktipjq +twmikp +jmtwikyp +azcempwtkiv +itkmpw + +qwodjmelanykpxuh +weqnajoxmupklyihd +pjodermlyuknwxhqa +mqbaoxylgdshtnjpwuvkfe +lnaxijmwqhukodpye + +azxw +xazw +zwax +wafqztx +zaxw + +ydzmvpskfjiqneluabgtrw +vyfdpqrkbistwlaxzjum +ukortizjvdwhlpafycmqsb + +cno +y +no +y +bqe + +zlcotxyhfeij +xtlvhifkszoj + +kczqegopj +qupzjod + +hpclqaktjmbnyxw +iqphxcamk + +rebc +qcbra +brc +crb + +flkoiavp +aduhjeqtyrmzkn +cslwgfaokp + +qmnzcjb +bmeqzjsc +jxochgfbmwzvq +zqcbmja + +deyifvsxw +evdyw +edbhzyuqv + +xmhknbcwdaztvl +mruslxozyangpj +xgszalnm +aoqmleunizxs + +eh +he +eh +nxeh +eh + +cjbx +jxsub + +yusezdlpgxtm +dyrkmstuegpx +pdxmyeutvkjsrhgaw + +ruz +rzu +zur +zru + +wgbdctzlsmh +peglstyhcd +adtqlhcgvs +tylndgrcujhsbx +odltpshecg + +ylntchparijwfo +wtrjpiaohylcf +wlfyvrehcutapgko + +tkbpfhjzravmquxewgl +goxphazbfvrqkijlwtm +mkrbzqphvawtyjfxilg +plhcnwgqmrxfvdzabjkt + +pfhtlqawckegij +wjpaksdctfghlo + +jqctpgrvu +qkvgjuprtc +vutcqpgrj +gpruvjtcq +gvqprujct + +dkevisf +kfei +mlukicwfje + +nsoyjcwzife +spnocteji + +cfuzsbtvdkq +rcasmqzkpdxuo +drxzwqckus +zqsrndeukxic + +vkgpbz +zkpvg +zkvpg + +eqhpyasvnumzgclitofjw +ofsgpaijzqmtvcuwhlbe +ujiewctamfxqdghslpvzo +qivnwtlfcmpgaeouhjzs + +lfahbowz +ryxcwtvs +mytucdivw + +lqetdskgyznojharxvufpwimbc +kpcoqugdvxibftjmywzslnreh +mxjgcinhobeldrwfukyvptqsz + +jxhc +fjsqglzwhu +mhcj +hecj + +ihdsbckn + +siponk +sikonp +psinkfo + +qbvdrutoan +qbcftunvoi +qvkoxzbtushny +qtwojubnv + +eu +u +xtujdms +ehu + +jkqdoner +eyxnkuaoqfg +kqenxmyo + +wk +wk +ykw +kw +kw + +gvrebwq +erkflnbjhagv +givrybues +itpvegsrbz + +hlykfbqnexots +tqhgfonkzeyxsbl +qkcybxtsnloefh +fxalqkntsuobyech +hvyjefkbitrqoplwxns + +paxu +parnkxu +pxua +xupa +uxpa + +ytzjokcqlmviha +sykbmizchvq +aocvizymhkq +ivhkcqlzym +iayelkzqmtchv + +aekxzstuc +czetkxsau +zqpakexsuct +zuxtacske +kuszetcax + +czlkiprvydnmsoxqwajgb +byszdijkplawcvnm +ikmwandcjzlvybsp +nbvwlikjscdmpzay + +fpuxqtigly +hpuqkfxigyt +tifpygqkux +uygqftwpxi + +gvdwnrefpj +nwgapvedr +egdvwnrp +xshwezgipdvr + +joefgnu +tknuhvfy + +rjo +rpjyos +rjo +roj +jro + +zxvatmfbujgryinokwehsc +xjzdusehibgtvncmkflyao + +fpnkyo +nopfky +kpnyof +ponkfy +tnpfoyk + +mevhflgowbkqdjutrzys +qrgmkeohvstnbwfdjluy + +pejhrgwtmcny +hjangqtbprsmwe +umiegvdprwtznhj +nhgptresjwlm + +ohgmls +othljm +jmhtlso +mhxlcnp + +dtufxjrbq +rdfjxtqbu +qjtdufbrx + +iexvaok +kexu +xkje +xkfe + +dpursykgo +ugkrsqpody +sokpgyrdnu +kwsuoyrpdg +sovjiydkagmuptbrhcf + +mwxcqs +mcwxqs +mwxqsc +tcswmxq + +cqatfowbvmirly +woibncaylqgvsf + +bico +izdt +tiz + +af +fkq +f +fyb +f + +wxftpjclsrhm +sdzuvanek + +jr +rjp +rj + +zhpknlosiadcfbjweuqvy +ulbkhapqzisefdyonjc + +oivjy +djvwbofy +kvlqyxrj +bsivdyjf + +kifcamqwgy +amfkgicyq +miygkcafq + +egslifrtvcnhk +vymgiprjzcxasbqn + +gji +g +oar +jgk + +gxtkohsqcvmrjzie +jfghvuxokznqwsdmarcl + +xvlnpjdar +vldnopxaj +dtnpsayjvlc +dgjvalnmp +mfnvjdpal + +mnaxd +xmda +kdaxm + +szpeac +ezpsac +aesxpcz + +vgpldyruqmfbsehzkxjwa +wrxmvtqgyjsdazlkbofeuhc +ablmzyevqgswfnxkdrphuj + +aoedxnzjqsbyihtpkcfuwl +dsbeyathwxjupozlqncikf + +mwzkrnhp +okqj + +s +s + +erjyvcwhuitdaogsnfb +dculesyjotbwhavfirn +swfbohtjdciaurenyv +ubsvfamrjoynwchitdke + +yb +yb +by + +pbrhzvjcsgeylfxt +sjcyezvxfgbhtplr + +rphvaxw +zhjapvrxw +xahvwspr +lpdqrvwahmx + +rpmild +vlrpswnb +ylrezfpi +pbraslm +utxgqhpjkorl + +pizbmcxreftywhdq +pqyezcxtidgmhfrw +ixrctphwqydzfme +fxdhpyctwrinmazqe +pctzyrhdiqwmxef + +wasjdyzgfu +zfdyujgwsa +wbyzjgadufs +afzswydguj + +zqanmksjruhx +qljaunzmkrshx +jrxqsmzknhua +rjazknumxqhs +kuzqxhjmasrn + +virdpbztchkgo +hdiopebvzaw + +ziwscmotk +jwmas + +h +h +h +h +h + +qhywbkuvnst +zmynwxvufqarkbeht + +onfvrqxa +xrvqnofa +fiuarnvoxq +qvzafonrx +fqvxebnaolr + +kmfulryg +bkswufgylmr +myulgjrfk +gouyxrlkmf + +skerjmgbvtcphdzafniyxo +ljybizemsvhokxrdcagptnf + +oyt +hytx +mdtyjrslkczu +bvyto + +mpwv +acvbp + +m +ftz + +kvtmidlngo +edznioyvkx +kofvirdn diff --git a/2020/days/06/test_day6.py b/2020/days/06/test_day6.py new file mode 100644 index 0000000..9e080a4 --- /dev/null +++ b/2020/days/06/test_day6.py @@ -0,0 +1,55 @@ +#! /usr/bin/env python3 + +import pathlib +import pytest +import day6 as aoc + +PUZZLE_DIR = pathlib.Path(__file__).parent + +#these test fixtures setup the test, mainly by reading the filename into a string in this simple case. +@pytest.fixture +def example1(): + puzzle_input = (PUZZLE_DIR / "example1").read_text().strip() + return aoc.parse(puzzle_input) + +@pytest.fixture +def example2(): + puzzle_input = (PUZZLE_DIR / "example2").read_text().strip() + return aoc.parse(puzzle_input) + +# @pytest.mark.skip(reason="Not implemented") +def test_parse_example1(example1): + """Test that input is parsed properly""" + assert example1 == [ + [ + ['a', 'b', 'c'] + ], + [ + ['a'], + ['b'], + ['c'] + ], + [ + ['a', 'b'], + ['a', 'c'] + ], + [ + ['a'], + ['a'], + ['a'], + ['a'] + ], + [ + ['b'] + ] + ] + +# @pytest.mark.skip(reason="Not implemented") +def test_part1_example1(example1): + """Test part 1 on example input""" + assert aoc.part1(example1) == 11 + +# @pytest.mark.skip(reason="Not implemented") +def test_part2_example2(example1): + """Test part 2 on example input""" + assert aoc.part2(example1) == 6 diff --git a/2020/main.py b/2020/main.py new file mode 100644 index 0000000..10e37c7 --- /dev/null +++ b/2020/main.py @@ -0,0 +1,6 @@ +def main(): + print("Hello from 2020!") + + +if __name__ == "__main__": + main() diff --git a/2020/pyproject.toml b/2020/pyproject.toml new file mode 100644 index 0000000..919e855 --- /dev/null +++ b/2020/pyproject.toml @@ -0,0 +1,9 @@ +[project] +name = "AOC-2020" +version = "0.1.0" +description = "Advent of code 2020 in python." +readme = "README.md" +requires-python = ">=3.13" +dependencies = [ + "pytest>=9.0.3", +] diff --git a/2020/template/template.py b/2020/template/template.py new file mode 100755 index 0000000..853407c --- /dev/null +++ b/2020/template/template.py @@ -0,0 +1,31 @@ +#! /usr/bin/env python3 + +import pathlib +import sys +import re +from dataclasses import dataclass +from pprint import pprint + +def parse(puzzle_input: str): + """Parse input""" + +def part1(data): + """Solve part 1""" + +def part2(data): + """Solve part 2""" + +def solve(puzzle_input): + """Solve the puzzle for the given input""" + data = parse(puzzle_input) + solution1 = part1(data) + solution2 = part2(data) + + return solution1, solution2 + +if __name__ == "__main__": + for path in sys.argv[1:]: + print(f"{path}:") + puzzle_input = pathlib.Path(path).read_text().strip() + solutions = solve(puzzle_input) + print("\n".join(str(solution) for solution in solutions)) diff --git a/2020/template/test_template.py b/2020/template/test_template.py new file mode 100644 index 0000000..d5a24ce --- /dev/null +++ b/2020/template/test_template.py @@ -0,0 +1,33 @@ +#! /usr/bin/env python3 + +import pathlib +import pytest +import template as aoc + +PUZZLE_DIR = pathlib.Path(__file__).parent + +#these test fixtures setup the test, mainly by reading the filename into a string in this simple case. +@pytest.fixture +def example1(): + puzzle_input = (PUZZLE_DIR / "example1").read_text().strip() + return aoc.parse(puzzle_input) + +@pytest.fixture +def example2(): + puzzle_input = (PUZZLE_DIR / "example2").read_text().strip() + return aoc.parse(puzzle_input) + +@pytest.mark.skip(reason="Not implemented") +def test_parse_example1(example1): + """Test that input is parsed properly""" + assert example1 == ... + +@pytest.mark.skip(reason="Not implemented") +def test_part1_example1(example1): + """Test part 1 on example input""" + assert aoc.part1(example1) == ... + +@pytest.mark.skip(reason="Not implemented") +def test_part2_example2(example2): + """Test part 2 on example input""" + assert aoc.part2(example2) == ... diff --git a/2020/uv.lock b/2020/uv.lock new file mode 100644 index 0000000..cfb30db --- /dev/null +++ b/2020/uv.lock @@ -0,0 +1,75 @@ +version = 1 +revision = 3 +requires-python = ">=3.13" + +[[package]] +name = "aoc-2020" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "pytest" }, +] + +[package.metadata] +requires-dist = [{ name = "pytest", specifier = ">=9.0.3" }] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "iniconfig" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, +] + +[[package]] +name = "packaging" +version = "26.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/df/de/0d2b39fb4af88a0258f3bac87dfcbb48e73fbdea4a2ed0e2213f9a4c2f9a/packaging-26.1.tar.gz", hash = "sha256:f042152b681c4bfac5cae2742a55e103d27ab2ec0f3d88037136b6bfe7c9c5de", size = 215519, upload-time = "2026-04-14T21:12:49.362Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7a/c2/920ef838e2f0028c8262f16101ec09ebd5969864e5a64c4c05fad0617c56/packaging-26.1-py3-none-any.whl", hash = "sha256:5d9c0669c6285e491e0ced2eee587eaf67b670d94a19e94e3984a481aba6802f", size = 95831, upload-time = "2026-04-14T21:12:47.56Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + +[[package]] +name = "pygments" +version = "2.20.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, +] + +[[package]] +name = "pytest" +version = "9.0.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c", size = 1572165, upload-time = "2026-04-07T17:16:18.027Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9", size = 375249, upload-time = "2026-04-07T17:16:16.13Z" }, +] diff --git a/2022/.gitignore b/2022/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/2022/.gitignore @@ -0,0 +1 @@ +/target diff --git a/2022/Cargo.lock b/2022/Cargo.lock new file mode 100644 index 0000000..e2cfc24 --- /dev/null +++ b/2022/Cargo.lock @@ -0,0 +1,197 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "aoc_libs" +version = "0.1.0" + +[[package]] +name = "day01" +version = "0.1.0" + +[[package]] +name = "day02" +version = "0.1.0" + +[[package]] +name = "day03" +version = "0.1.0" + +[[package]] +name = "day04" +version = "0.1.0" +dependencies = [ + "once_cell", + "regex", +] + +[[package]] +name = "day05" +version = "0.1.0" +dependencies = [ + "once_cell", + "regex", +] + +[[package]] +name = "day06" +version = "0.1.0" + +[[package]] +name = "day07" +version = "0.1.0" +dependencies = [ + "once_cell", + "regex", + "thiserror", +] + +[[package]] +name = "day08" +version = "0.1.0" + +[[package]] +name = "day09" +version = "0.1.0" +dependencies = [ + "aoc_libs", + "once_cell", + "regex", +] + +[[package]] +name = "day10" +version = "0.1.0" +dependencies = [ + "aoc_libs", + "nom", +] + +[[package]] +name = "memchr" +version = "2.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "proc-macro2" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "syn" +version = "2.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "template" +version = "0.1.0" +dependencies = [ + "aoc_libs", +] + +[[package]] +name = "thiserror" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" diff --git a/2022/Cargo.toml b/2022/Cargo.toml new file mode 100644 index 0000000..47faac1 --- /dev/null +++ b/2022/Cargo.toml @@ -0,0 +1,21 @@ +[workspace] +members = [ + "template", + "aoc_libs", + "days/*", +] +default-members = [ "days/*", "aoc_libs" ] +resolver = "2" + +[workspace.package] +version = "0.1.0" +authors = ["Gabriel Venberg"] +edition = "2021" +description = "advent of code 2022 in rust" + +[workspace.dependencies] +aoc_libs = {path = "./aoc_libs"} +regex = "1" +once_cell = "1.16" +thiserror = "1.0" +nom = "7.1" diff --git a/2022/aoc_libs/Cargo.toml b/2022/aoc_libs/Cargo.toml new file mode 100644 index 0000000..63d082f --- /dev/null +++ b/2022/aoc_libs/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "aoc_libs" +version.workspace = true +authors.workspace = true +edition.workspace = true +description.workspace = true diff --git a/2022/aoc_libs/src/lib.rs b/2022/aoc_libs/src/lib.rs new file mode 100644 index 0000000..2111939 --- /dev/null +++ b/2022/aoc_libs/src/lib.rs @@ -0,0 +1 @@ +pub mod points; diff --git a/2022/aoc_libs/src/points.rs b/2022/aoc_libs/src/points.rs new file mode 100644 index 0000000..74a92c6 --- /dev/null +++ b/2022/aoc_libs/src/points.rs @@ -0,0 +1,211 @@ +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Hash)] +pub struct Point { + pub x: isize, + pub y: isize, +} + +impl Point { + /// converts a point (representing a point on a 4 quadrant grid with positive xy in the + /// top-right) into a upoint (representing a point on a 1 quadrant grid with the origin in the + /// top-left corner). Returns none if the resulting point would have either number negative. + pub fn to_upoint(self, zero_coord: &UPoint) -> Option { + Some(UPoint { + x: zero_coord.x.checked_add_signed(self.x)?, + y: zero_coord.y.checked_add_signed(-self.y)?, + }) + } +} + +impl std::ops::Add for Point { + type Output = Point; + + fn add(self, rhs: Self) -> Self::Output { + Self { + x: self.x + rhs.x, + y: self.y + rhs.y, + } + } +} + +impl std::ops::AddAssign for Point { + fn add_assign(&mut self, rhs: Self) { + *self = *self + rhs + } +} + +impl std::ops::Sub for Point { + type Output = Point; + + fn sub(self, rhs: Self) -> Self::Output { + Self { + x: self.x - rhs.x, + y: self.y - rhs.y, + } + } +} + +impl std::ops::SubAssign for Point { + fn sub_assign(&mut self, rhs: Self) { + *self = *self - rhs + } +} + +impl std::ops::Neg for Point { + type Output = Point; + + fn neg(self) -> Self::Output { + Point { + x: -self.x, + y: -self.y, + } + } +} + +/// an unsigned point in 2d space +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct UPoint { + pub x: usize, + pub y: usize, +} + +impl UPoint { + /// converts a upoint (representing a point on a 1 quadrant grid with the origin in the + /// top-left corner) into a point( representing a point on a 4 quadrant grid with positive xy + /// in the top-right) + pub fn to_point(self, zero_coord: &UPoint) -> Point { + Point { + x: -(zero_coord.x as isize - self.x as isize), + y: zero_coord.y as isize - self.y as isize, + } + } +} + +impl std::ops::Add for UPoint { + type Output = UPoint; + + fn add(self, rhs: Self) -> Self::Output { + Self { + x: self.x + rhs.x, + y: self.y + rhs.y, + } + } +} + +impl std::ops::AddAssign for UPoint { + fn add_assign(&mut self, rhs: Self) { + *self = *self + rhs + } +} + +impl std::ops::Sub for UPoint { + type Output = UPoint; + + fn sub(self, rhs: Self) -> Self::Output { + Self { + x: self.x - rhs.x, + y: self.y - rhs.y, + } + } +} + +impl std::ops::SubAssign for UPoint { + fn sub_assign(&mut self, rhs: Self) { + *self = *self - rhs + } +} + +/// A matrix that allows negative co-oordinates. Will panic if referencing out of bounds, just like +/// a normal 2d array. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct FourQuadrantMatrix { + matrix: [[T; X]; Y], + max_point: Point, + min_point: Point, + zero_coord: UPoint, +} + +impl FourQuadrantMatrix<{ X }, { Y }, T> +where + T: Copy, + T: Default, +{ + /// generates a new FourQuadrantMatrix with a given zero point (the point in the underlying 2d + /// array considered to be (0,0)) + pub fn new(zero_coord: UPoint) -> FourQuadrantMatrix<{ X }, { Y }, T> { + FourQuadrantMatrix { + matrix: [[T::default(); X]; Y], + max_point: UPoint { x: X - 1, y: 0 }.to_point(&zero_coord), + min_point: UPoint { x: 0, y: Y - 1 }.to_point(&zero_coord), + zero_coord, + } + } + + pub fn zero_coord(&self) -> UPoint { + self.zero_coord + } + + pub fn min_point(&self) -> Point { + self.min_point + } + + pub fn max_point(&self) -> Point { + self.max_point + } + + /// makes sure a point is in bounds and if not, brings it in bounds. + pub fn bound_point(&self, point: &mut Point) { + if point.x > self.max_point.x { + point.x = self.max_point.x + } + + if point.y > self.max_point.y { + point.y = self.max_point.y + } + + if point.x < self.min_point.x { + point.x = self.min_point.x + } + + if point.y < self.min_point.y { + point.y = self.min_point.y + } + } + + /// checks if the point is in bounds. + pub fn is_in_bounds(&self, point: &Point) -> bool { + point.x <= self.max_point.x + && point.y <= self.max_point.y + && point.x >= self.min_point.x + && point.y >= self.min_point.y + } + /// fills the matrix with the Ts default value. + pub fn reset_matrix(&mut self) { + self.matrix = [[T::default(); X]; Y]; + } +} + +impl std::ops::IndexMut for FourQuadrantMatrix<{ X }, { Y }, T> { + fn index_mut(&mut self, index: Point) -> &mut Self::Output { + let upoint = index + .to_upoint(&self.zero_coord) + .expect("would result in negative unsigned coordinate!"); + &mut self.matrix[upoint.y][upoint.x] + } +} + +impl std::ops::Index for FourQuadrantMatrix<{ X }, { Y }, T> { + type Output = T; + + fn index(&self, index: Point) -> &Self::Output { + let upoint = index + .to_upoint(&self.zero_coord) + .expect("would result in negative unsigned coordinate!"); + &self.matrix[upoint.y][upoint.x] + } +} + +impl From> for [[T; X]; Y] { + fn from(value: FourQuadrantMatrix<{ X }, { Y }, T>) -> Self { + value.matrix + } +} diff --git a/2022/days/01/Cargo.toml b/2022/days/01/Cargo.toml new file mode 100644 index 0000000..ead9da8 --- /dev/null +++ b/2022/days/01/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "day01" +authors.workspace = true +description.workspace = true +version.workspace = true +edition.workspace = true diff --git a/2022/days/01/src/input.txt b/2022/days/01/src/input.txt new file mode 100644 index 0000000..448e913 --- /dev/null +++ b/2022/days/01/src/input.txt @@ -0,0 +1,2255 @@ +6758 +5199 +10292 +8812 +3527 +10178 +1340 +2824 + +62522 + +22990 + +6730 + +7255 +3210 +3003 +8296 +8799 +7655 +10312 + +18837 +19882 +5386 +15891 + +4203 +36288 + +1586 +2295 +4981 +2109 +2284 +5814 +4823 +5492 +1524 +5286 +2147 +2952 +4783 +4814 +3042 + +8474 +4059 +14465 +13390 + +4623 +2150 +7545 +7833 +3686 +2095 +3336 +5030 +7648 +4087 +4482 + +31278 +29863 + +1228 +4851 +2706 +1692 +3200 +3521 +5200 +3755 +3922 +5181 +5561 +5162 +5280 +2460 + +1083 +4432 +4938 +4303 +6304 +3746 +3527 +3141 +3198 +4980 +4395 + +8218 +3954 +1396 +2147 +7924 +4650 +4483 +6610 +4799 +3973 + +3401 +4111 +7798 +5181 +8418 +5014 +5975 +7916 +7788 +1864 + +8547 +13217 +9699 +5701 +11040 +2943 + +6214 +3287 +4137 +6773 +2593 +4776 +1687 +2821 +7240 +3681 +1185 +6578 + +7850 +6697 +4844 +2325 +1834 +6812 +3380 +2302 +2531 +4959 + +5275 +1883 +6919 +2865 +7943 +7718 +9494 +7957 + +28727 +22865 + +3064 +4279 +2649 +12521 + +10169 +16383 +3301 +12707 + +3533 +2280 +9232 +10618 +1488 +7616 +4334 +7847 + +4322 +1215 +3514 +5513 +3469 +5472 +3658 +1096 +3410 +1607 +5482 +3015 +5234 +2488 + +1306 +8067 +3375 +4064 +2943 +6158 +3911 +7766 +2493 +4897 +6551 + +10694 +13319 + +10862 +2483 +8522 +4509 +5021 +8789 +6152 + +7824 +23812 +6740 + +6548 +2116 +14900 + +3470 +1825 +2865 +4691 +4729 +4263 +4899 +4855 +3732 +4439 +5023 +1291 +3121 +5322 + +6529 + +5141 +2353 +8515 +9815 +9541 +10389 +1114 +1373 + +11924 +11446 +20373 + +37249 + +5749 +2968 +5300 +5405 +7280 +6161 +4298 +7104 +7140 +3405 +5754 + +4763 +11364 +7492 +5630 +15978 + +3622 +2185 +12718 +2466 +5015 +11302 + +65579 + +5450 +6455 + +5721 +1939 +8537 +7075 +1317 +1805 +1701 +4578 +8435 +1718 + +10692 +6581 +3068 +9013 +1741 +4654 +2159 +5340 + +4981 +6327 +6931 +3024 +1263 +4313 +6793 +2818 +6727 +2245 +4524 +5825 + +10156 +11779 +1694 +7495 +1615 +8872 +11840 + +7323 +7184 +4094 +3989 +1820 +2141 +7277 +3208 +2064 +7765 +5764 + +2796 +3030 +2783 +3426 +5581 +1659 +2369 +2784 +5284 +4110 +1157 +3129 +6088 +2215 +3503 + +20991 +1521 + +1601 +4869 +9195 +1835 +5402 +2721 +1128 +1991 +9336 + +2557 +6635 +6981 +6296 +5278 +3077 +7679 +5764 +2359 +2467 +6705 + +2594 +2611 +3189 +1436 +1510 +1341 +8213 +8525 +5447 +2045 + +3812 +2106 +6216 +3236 +7169 +5840 +4770 +1724 +1061 +5062 +7990 + +5722 +4372 +3524 +1561 +3417 +5807 +3969 +3635 +3067 +3469 +4393 +1705 +4897 +4307 +2663 + +28920 +3093 + +12949 +9070 +9161 +3530 +6651 + +12010 +1783 +21165 + +4667 +3553 +6938 +5433 +3244 +1082 +7305 +7262 +6577 +1987 +2256 + +4933 +1802 +1315 +1303 +1722 +2688 +6103 +2749 +1478 +4994 +4369 +5074 +5655 +2827 +3232 + +1101 +2284 +4349 +4868 +3264 +3227 +1786 +5233 +6054 +6144 +3533 +1841 +1721 +4775 + +16514 + +7282 +7260 +2423 +1738 +4498 +5570 +3862 +3979 +3845 +4313 +3249 +5639 + +7910 +9862 +7476 +9103 +2851 +3634 +8641 +7369 + +8574 +1439 +1442 +12337 +1387 +7777 + +18060 + +10287 +1924 +4066 +12275 +14094 + +4797 +5061 +2701 +1391 +6617 +5870 +4999 +4150 +2881 +2667 +2461 +1978 +1058 + +12911 +7290 +9442 +2875 +5812 + +13016 +4985 +2517 +9758 +11215 + +2845 +11805 +6418 +8128 +1604 + +9643 +6574 +6804 +3575 +9226 +6276 +1406 +4493 +8104 + +11616 +7196 +5685 +1267 +3281 +1250 +7666 + +9654 +8646 +7144 +2790 +7583 +2681 +1799 +5301 +1714 + +30086 +23066 + +10205 +7316 +1550 +4056 +2627 +10056 + +9912 +1615 +1584 +2963 +1347 +9336 +8310 +8728 + +2436 +4741 +6665 +5239 +5737 +4252 +1954 +4916 +5341 +7475 +5909 +5012 + +4897 +8580 +5122 +1865 +8318 +5369 +2334 +5629 +7058 + +14621 +2969 +15900 +14828 +2997 + +7051 +3305 +7848 +7947 +3961 +3206 +5175 +7055 +3182 +5838 +1954 + +6614 +3086 +7740 +6624 +4106 +7195 + +3815 +4858 +3460 +1427 +5685 +5865 +4790 +6660 +1510 +5685 +2790 +5112 + +13626 +1665 +16722 +9598 + +15870 + +3453 +8531 +9997 +8590 +5833 +7896 +8524 + +6783 +5931 +3245 +4327 +5496 +5017 +2136 +3899 +3875 +2904 +5023 +3173 +3227 + +4241 +4693 +1164 +1877 +5541 +5017 +3433 +3333 +4734 +3639 +1724 +2439 +1673 +4362 + +6479 +3259 +3496 +6125 +1147 +3181 +3948 +5746 +3019 +1924 + +6250 +26443 + +4901 +6813 +6581 +3144 +1525 +6629 +3254 +6542 +1156 +6663 +3856 +4083 +1598 + +7932 +8717 +9657 +1873 +2727 +2052 +2376 + +6455 +13127 +3540 +8038 +6601 +2249 + +6226 +5251 +3416 +5941 +7336 +5668 +4139 +1459 +2529 +7538 + +6899 +4680 +10277 +2515 +16361 + +23283 +2647 + +1272 +3462 +6817 +3795 +4973 +6750 +2340 +7379 +3873 +1832 +7935 + +4808 +4018 +11801 +7092 +8312 +9718 +6693 + +7285 +7822 +7063 +2854 +7844 +1121 +4362 +4685 +5360 +7140 +6796 + +17114 +20195 +9330 + +19378 +27739 + +16288 +15298 +13251 +5444 +10856 + +7616 +6108 +3420 +9201 +3422 +4312 +4388 +3008 +9551 + +1255 +7803 +1598 +3892 +6954 +7936 +8078 +5261 +2057 +2914 + +7497 +10296 +2343 +10020 +1171 +3092 +2333 + +1492 +4718 +4267 +10309 +7919 +7080 +1012 +9981 + +17367 +1357 +16269 +7775 + +13641 +3004 +13280 + +6205 +3003 +1634 +4608 +2759 +6324 +4372 +4833 +6565 +2865 +7345 +3719 + +4268 +2071 +2155 +4408 +4869 +2634 +1329 +2075 +4276 +4032 +2129 +5181 +2594 +2102 +2281 + +2486 +7483 +6748 +4017 +5926 +3507 +4666 +3837 + +8082 +13626 +12247 +5622 +13565 + +7911 +1180 +1854 +5795 +7017 +6873 +7728 +5055 +5207 +7810 +7474 + +3459 +5418 +1420 +5028 +6793 +4851 +2885 +2263 +2734 +4868 +6596 +1434 +5440 + +3368 +3541 +5756 +3039 +4234 +2632 +6031 +5613 +4769 +1538 +4898 +5128 +4848 + +2817 +3013 +2260 +4714 +6461 +3262 +3924 +4083 +2487 +4221 +5311 +4274 +5591 +1625 + +8756 +8549 +9481 +7994 +7775 +6951 +5276 +7598 +9126 + +11749 +7152 +14494 + +14395 +7799 +16109 +14178 + +24404 +4941 + +5326 +9070 +3951 +1404 +6513 +9155 +5981 +3880 +1476 + +12661 +10966 + +3517 +7760 +4724 +6891 +1447 +3337 +3903 +7382 +7067 +1771 +1184 + +3556 +13458 +12699 +12330 +13534 +11244 + +10818 +31380 + +17968 +3978 +17994 + +9486 +6163 +1748 +3765 +7191 +1461 +2062 +8169 +9167 + +3111 +4378 +3560 +6292 +5521 +2132 +5071 +4519 +1977 +6587 + +11961 +2119 +11633 +10970 +4089 +7390 +6481 + +4350 +5261 +4801 +1584 +1531 +5034 +5917 +4136 +6668 +5364 +3814 +3873 +4437 + +2568 +2449 +5582 +1857 +6143 +5457 +4396 +3723 +2885 +2428 +2790 +4173 +1726 +5687 + +21758 + +32901 + +4313 +12688 +14465 +1073 +6568 + +2295 +3872 +5979 +3014 +1408 +1865 +2937 +4231 +5076 +2544 +3270 +2673 +6060 +4292 +1073 + +5340 +10378 +10445 +11874 +8275 +8558 +1558 + +3652 +9630 +15612 +18471 + +5856 +4627 +4762 +6094 +5266 +2970 +1230 +6292 +5083 +4557 +6158 +5841 +6321 +3672 + +4531 +2204 +4583 +4426 +4310 +6136 +5577 +4765 +6882 +1300 +2979 +6754 +4241 + +3266 +6610 +2322 +12666 +11874 +10495 + +7493 +2468 +2710 +6550 +7383 +4442 +3692 +8168 + +4381 +3648 +4270 +3016 +4178 +3066 +1736 +5402 +4995 +1980 +5438 +5256 +4804 +4854 +2585 + +4096 +4397 +4061 +3811 +2537 +3296 +1877 +4267 +2760 +3682 +5949 +3713 +3365 +4135 +1310 + +30319 + +7244 +6071 +1234 +6387 +1980 +1935 +3431 +6474 +6601 +1652 + +10125 +11599 + +4436 +3242 +6077 +6707 +1582 +6648 +3345 +5812 +1635 +2782 +2514 +2608 + +9244 +1348 +5019 +2059 +9226 +2546 +5130 +8902 +7779 + +10030 +10749 +3690 +8769 +9835 +7216 +2132 + +6105 +1205 +1860 +3190 +5815 +1424 +2611 +1230 +4491 +1731 +5804 +2863 +1816 +3694 + +4791 +6491 +3292 +3310 +2223 +4296 +6323 +3414 +1462 +6799 +3276 +4435 +5554 + +2859 +2854 +1127 +4179 +6233 +6219 +5955 +3139 +2457 +3854 +5071 +4887 +4190 +4469 + +67818 + +7880 +6503 +4931 +5813 +1692 +2126 +6300 +8743 +4983 +2182 + +1882 +5752 +6369 +1996 +2955 +5978 +6087 +5123 +2587 +2000 +4973 +2214 +5118 +3178 + +10807 +9780 +8468 +2157 +1021 +8078 +4848 + +3400 +1666 +6908 +10199 +1685 +4979 + +2250 +5672 +2505 +9061 +5514 +8895 +4958 +8274 +7707 + +15083 +2359 +23052 + +6279 +1563 +4247 +4593 +4844 +5335 +7024 +7324 +5904 +1016 +3394 +3382 + +2965 +2673 +3329 +1833 +1222 +1789 +1027 +6268 +4404 +1031 +1407 +4510 +4047 +1972 + +4423 +8018 +4991 +7190 +7061 +6223 +5972 +2864 +5674 + +1559 +1850 +4117 +1495 +2604 +2243 +1498 +4936 +2970 +4109 +1252 +6416 +5293 +3319 + +5577 +4032 +3528 +6140 +5994 +2811 +3247 +7297 +5776 +3863 +4240 +3973 + +9884 +8267 + +3047 +4053 +2400 +4246 +3193 +2309 +4014 +1369 +1437 + +10529 +2975 +3033 +10601 +13985 + +12323 +9086 +2903 +7243 +8351 +12729 + +13982 +7013 +7500 +11098 +9206 + +11963 +3055 +9862 +2601 +13991 + +66684 + +6171 +1924 +1569 +3761 +4616 +5565 +3644 +1817 +4029 +2333 +1934 +2492 +6161 + +2802 +1498 +3232 +7475 +5503 +4913 +6759 +8657 +4445 + +18324 +19871 + +6287 +4271 +7871 +1097 +1932 +5980 +5376 +7824 +4911 +4751 +6453 + +8374 +3293 +7175 +8288 +1217 +4831 +1514 +6681 +2596 +6199 + +32039 + +1235 +2206 +6429 +4880 +5463 +6814 +1530 +3544 +4685 +3169 +6752 +5854 +6764 + +6115 +6039 +6519 +6414 +4558 +5214 +4411 +2882 +6006 +5117 +5321 +2059 + +2431 +5892 +1839 +5352 +3295 +2768 +4788 +5271 +1503 +1173 +4691 +4906 +4346 +1043 + +5172 +5976 +6248 +4288 +3851 +8543 +4189 +4396 + +10361 +14864 +18037 + +7381 +5180 +1829 +3624 +3144 +3962 +5923 +4356 +1477 +3153 +2891 +5196 + +3143 +3180 +4428 +3418 +6243 +3480 +1151 +4262 +4958 +4641 +3823 +1469 +2149 + +3702 +4159 +3799 +4639 +5703 +2425 +4579 +2397 +2814 +3959 +3987 +3088 +2982 +2338 +3432 + +7256 +16171 +12417 +11290 +13105 + +2594 +5105 +6253 +4743 +4251 +6439 +3370 +5662 +2763 +3147 +6366 +4537 +6279 +6104 + +7926 +3430 +2206 +4334 +5226 +1817 +2404 +2587 +8020 +1849 + +1257 +6091 +2485 +6366 +3184 +4775 +5987 +3473 +5761 +1905 +3742 +5478 +5343 + +3336 +5819 +2617 +2756 +5602 +3921 +4660 +5041 +1471 +2297 +5575 +1473 +6059 +3111 +5789 + +2647 +6183 +5004 +2750 +2772 +1964 +4453 +2132 +3181 +2916 +1804 +4666 +1215 +6354 + +1449 +1539 +3005 +3167 +1712 +6222 +6007 +4141 +1481 +6198 +4476 +3850 +3885 +5880 + +1833 +5557 +3185 +6117 +3456 +2789 +4576 +1439 +3212 +5223 +2687 +2368 +3270 +4629 +4716 + +10123 +6686 +12658 + +6838 +4415 +10796 +6040 +3065 +1832 +11624 + +69368 + +5469 +8816 +7624 +13506 + +8923 +1621 +10042 + +6113 +9373 +9212 +7054 +3193 +6588 +7743 +4224 +4983 + +1911 +1589 +2667 +3095 +3768 +5898 +4574 +3456 +3281 +4176 +1591 +3383 +5063 + +1378 +5923 +9019 +4379 +2932 +3918 +9631 + +7851 +6466 +2388 +13209 +7613 +2396 + +3015 +1119 +4172 +2459 +3872 +5912 +4012 +2894 +2765 +1950 +4147 +4523 +2504 +4691 +2038 + +4472 +5029 +3599 +6237 +8566 +3508 +7995 +3756 +6631 +3625 + +16549 +15550 +22868 + +7356 +11800 +8330 +14503 +9470 + +1306 +1960 +6574 +7234 +3841 +1006 +4156 +2019 +6187 +2494 +7475 +5916 + +8894 +9358 +9666 +8711 +10140 +11205 + +8123 +19317 +11676 +7989 + +7610 +3163 +9789 +6331 +6998 +7288 +4632 +5340 + +7105 +15276 +22300 + +11919 +6212 +5062 + +18496 +10383 +10695 +4206 + +8127 +2277 +10392 +1337 +2779 +5380 +3881 +6556 + +5514 +6678 +2324 +4686 +3807 +4785 +3972 + +1488 +3662 +4866 +2687 +3519 +2605 +5189 +5313 +4112 +2559 +1887 +5656 +5931 +1816 + +9949 +11409 +8427 +15008 +2241 + +1942 +1004 +1070 +5860 +4932 +4055 +2922 +5129 +1232 +4940 +5270 +1023 +5323 +2002 +2727 + +48445 + +6687 +4155 +2999 +3348 + +5347 +4592 +1463 +3080 +3520 +5283 +3166 +2945 +2891 +1100 +5372 +5797 +3060 +5748 +5592 + +8132 +3941 +7625 +4458 +2714 +7390 +4305 +1612 +6707 + +2105 +2880 +6683 +6257 +6472 +1371 +3493 +1542 +4431 +5003 +3276 +2205 +3417 + +6421 +4279 +1213 +6274 +3757 +6856 +3244 +1554 +2716 +1854 +1924 +3769 +6344 + +1081 +2601 +2607 +6042 +1967 +2924 +4656 +6462 +1747 +4278 +6384 +4427 +5074 +6454 + +6344 +13912 +15708 +1335 +5433 + +5862 +7799 +3707 +9404 +10527 +10543 +6428 + +2009 +17261 +13328 + +10389 +9214 +9189 +8747 +12720 +9443 + +7162 +2362 +3837 +8891 +2098 +8577 +9063 +3336 +5023 + +1322 +12214 +5387 +9804 +9542 +6149 + +1997 +6709 +6614 +5116 +6691 +5904 +5563 +2437 +4442 +7346 +5749 +7194 + +5836 +15439 +9020 +9124 + +6761 +4892 +5956 +2500 +6879 +1980 +1908 +1705 +6157 +4559 +5776 +1235 +3077 + +10155 +8529 +7837 +7027 +7897 +6504 +4192 +7193 + +9711 +17664 +4069 +10400 + +24373 +20215 + +2155 +9371 +9201 +5590 +9806 +13380 + +7716 +1116 +6106 +2703 +2403 +3549 +3740 +6658 +4769 + +13954 +36130 + +1767 +7955 +5622 +5077 +2512 +8206 +4501 +2917 +9336 + +1601 +23493 +16981 + +3719 +2266 +1982 +4557 +3198 +3815 +5006 +2587 +4173 +2965 +2658 +4890 +5723 +4231 + +19350 + +19637 +13784 +21672 + +17040 +29745 + +2037 +7872 +5766 +7919 +1382 +9398 +3197 + +11570 +12560 +6206 +12642 +3275 + +1535 +6685 +5587 +12955 +12197 + +2980 +15784 +12178 +12996 + +7928 +8780 +7528 +5428 +8181 +8527 +5229 +3850 +2012 +2975 + +30992 +26372 + +4384 +2425 +2332 +1309 +3899 +3062 +4825 +1428 +1116 +3635 +1669 +1922 +5941 +4378 +2742 + +1961 +4243 +4443 +3070 +5786 +3638 +6330 +2461 +1612 +4572 +3551 +3831 +3263 +6173 + +2759 +3889 +5197 +4293 +2957 +6305 +3797 +1465 +4674 +5659 +5258 +3775 +4436 +2260 + +5141 +8383 +6249 +9982 +4848 +2675 +4232 +8974 + +11489 +11733 +9990 +4150 +4533 +3032 +1044 + +62338 + +3645 +5406 +4672 +3889 +5799 +5760 +4356 +5557 +4120 +2771 +3399 +5292 +3640 +3989 +6047 + +4629 +6897 +4312 +2108 +5301 +1122 +1893 +5508 +3414 +2180 +4254 diff --git a/2022/days/01/src/main.rs b/2022/days/01/src/main.rs new file mode 100644 index 0000000..8998253 --- /dev/null +++ b/2022/days/01/src/main.rs @@ -0,0 +1,14 @@ +mod parse; +mod part1; +mod part2; + +fn main() { + let _input = include_str!("./input.txt"); + let _structured_input = parse::parse(_input); + + println!("Part One"); + println!("Result: {}", part1::part1(&_structured_input)); + + println!("Part Two"); + println!("Result: {}", part2::part2(&_structured_input)); +} diff --git a/2022/days/01/src/parse.rs b/2022/days/01/src/parse.rs new file mode 100644 index 0000000..790aba8 --- /dev/null +++ b/2022/days/01/src/parse.rs @@ -0,0 +1,48 @@ +#[derive(Debug, PartialEq, Eq)] +pub struct Elf(pub Vec); + +pub fn parse(input: &str) -> Vec { + input + .trim() + .split("\n\n") + .map(|group| { + Elf(group + .split('\n') + .map(|line| line.parse().unwrap()) + .collect()) + }) + .collect::>() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse() { + let input = "1000 +2000 +3000 + +4000 + +5000 +6000 + +7000 +8000 +9000 + +10000"; + assert_eq!( + parse(input), + vec![ + Elf(vec![1000, 2000, 3000]), + Elf(vec![4000]), + Elf(vec![5000, 6000]), + Elf(vec![7000, 8000, 9000]), + Elf(vec![10000]) + ] + ); + } +} diff --git a/2022/days/01/src/part1.rs b/2022/days/01/src/part1.rs new file mode 100644 index 0000000..b2d1150 --- /dev/null +++ b/2022/days/01/src/part1.rs @@ -0,0 +1,27 @@ +use crate::parse; + +pub fn part1(input: &[parse::Elf]) -> usize { + input + .iter() + .map(|elf| elf.0.iter().sum::()) + .max() + .unwrap() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part1() { + let input = vec![ + parse::Elf(vec![1000, 2000, 3000]), + parse::Elf(vec![4000]), + parse::Elf(vec![5000, 6000]), + parse::Elf(vec![7000, 8000, 9000]), + parse::Elf(vec![10000]), + ]; + + assert_eq!(part1(&input), 24000); + } +} diff --git a/2022/days/01/src/part2.rs b/2022/days/01/src/part2.rs new file mode 100644 index 0000000..e8bf977 --- /dev/null +++ b/2022/days/01/src/part2.rs @@ -0,0 +1,27 @@ +use crate::parse; + +pub fn part2(input: &[parse::Elf]) -> usize { + let mut input = input + .iter() + .map(|elf| elf.0.iter().sum::()) + .collect::>(); + input.sort_unstable(); + input[input.len() - 3..].iter().sum() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part2() { + let input = vec![ + parse::Elf(vec![1000, 2000, 3000]), + parse::Elf(vec![4000]), + parse::Elf(vec![5000, 6000]), + parse::Elf(vec![7000, 8000, 9000]), + parse::Elf(vec![10000]), + ]; + assert_eq!(part2(&input), 45000); + } +} diff --git a/2022/days/02/Cargo.toml b/2022/days/02/Cargo.toml new file mode 100644 index 0000000..17738f9 --- /dev/null +++ b/2022/days/02/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "day02" +authors.workspace = true +description.workspace = true +version.workspace = true +edition.workspace = true diff --git a/2022/days/02/src/input.txt b/2022/days/02/src/input.txt new file mode 100644 index 0000000..1930858 --- /dev/null +++ b/2022/days/02/src/input.txt @@ -0,0 +1,2500 @@ +C Z +C Z +A X +A X +B Z +B Z +B Z +A Z +B X +A X +A X +A X +C Z +C Z +C X +A X +A X +A X +C Z +B Z +C Z +A Y +B Z +A X +C Y +A X +A X +C Y +C Z +A Y +B Z +A X +C Y +B Z +B Z +B Z +A X +C X +C X +B Z +A X +C Z +A X +B Z +A Y +C X +A X +C Z +C Z +B Z +C Y +C X +C X +C X +C X +A Y +C Y +C Z +C Y +A X +C Y +A X +B Z +A Y +C X +A X +B Y +A X +C X +C X +C Z +A X +C X +A X +C X +B Z +A Z +B Y +B Z +B Z +A X +C Y +B X +A X +A X +B Z +A X +C X +C Z +C Z +A X +C Z +C Z +C Z +C X +C Z +A X +B Z +B Y +C Z +B Z +B Z +A X +B Z +C Y +C Z +A X +A Y +C Z +A X +B Y +C Y +C Z +A X +C Y +C X +A X +C X +A X +C Z +A X +C Y +A Y +C Z +C X +C Y +C Y +A Y +A Y +C Y +C Y +A Y +A X +C Z +C Z +C X +C X +C Z +A Y +C Z +C Z +A Y +A Y +B Z +A X +B Z +C Y +B Z +C Z +C Y +C Y +B Y +C X +A X +A X +A X +A Y +A X +C Z +C Z +C Z +A X +B Z +A X +B Z +C Y +C Z +A Y +C Y +A X +A X +C Z +B X +C Z +C Z +B Z +B Z +B Z +C Z +C X +C Z +A X +B Z +C Z +C X +A X +A Y +B Y +A X +B Z +A X +C Z +C Z +C X +B Z +C Z +C Z +C X +A X +A X +B Y +C Y +C Z +B Y +A X +B Z +A X +B X +B Z +C X +C X +C Y +C X +B Y +B Z +C X +A Y +C X +C Y +A X +C Z +C Z +C X +B Z +A Y +B Z +A Y +B X +A X +C Z +B Z +C X +C X +C X +A X +C X +B Z +C Z +B Y +B Z +A X +A X +C Z +B Z +A X +A Z +C Y +B Z +C X +C Z +A Y +C X +A X +A X +A Y +B Z +A X +B Z +A Y +B X +C X +C Y +A X +C Z +B X +C Z +C X +C X +C Z +A X +B Z +C Z +C X +C Z +B Y +A X +C X +C Y +A X +C Z +A X +B Z +C X +C X +B Z +C Z +C Z +C Y +A X +C Z +C X +A X +C Y +C Z +C Z +C Y +B Y +B Z +A X +B Y +C X +A X +A X +C Y +C Z +B Z +C X +C X +B Z +C Z +A X +A Y +A X +C Y +A Y +B Y +A X +A X +C X +C X +B Z +A Y +B Z +C Z +A X +A Y +A X +C X +A X +C Z +B Y +C Z +A X +B Z +C Z +C Z +A X +A X +B Z +B Z +B Z +A X +C X +A X +A X +C Y +C Y +C X +C X +A X +A Y +B Y +C Z +C Z +B Y +C X +C Z +A Y +C X +C Z +C X +B Z +C Y +C Z +C X +C Y +C Z +B Z +C Z +B Z +A X +B Y +B Y +C Z +B Z +C X +C Z +C Z +C Z +B Y +B Z +C Z +B Y +A X +A X +C X +A X +C X +A X +B Z +A X +A X +A X +C Z +A Y +A X +C Z +C X +A X +C X +A X +B Z +C Z +C Z +C Z +A X +A X +C Z +A X +B Z +C X +C Z +C Y +B Z +A X +B Z +A X +A Z +B Y +B Z +B Z +B Z +A Y +C Z +A X +B Y +C X +B X +B Z +C X +B Y +C Z +A X +C X +B Z +A X +B Z +A X +A X +B Y +C Y +C X +C X +C Z +A X +C Z +A X +B Y +C X +C Y +B Y +B Y +A Y +C X +A Y +C Z +C Y +A X +C Z +C Z +B Z +A X +A X +A X +A X +B Z +C Z +C X +C X +C Z +A X +B Z +B Y +C Y +A Y +C X +B Z +A Y +B Z +C Z +B Z +C X +A X +B Z +A X +A Y +C Y +B Z +B Z +C X +C Z +C Z +C Z +A X +B Z +A Y +A X +C Y +A Y +B Z +A Y +C Z +A Y +A Y +C X +A X +B Z +A Y +B Z +C X +A X +B Y +B Z +C Z +C Z +B Z +A X +A X +B Y +C Z +C Y +B Z +C Z +A Y +A X +C X +C Z +A X +A X +A Z +C X +C X +B X +B Z +A Y +C X +A Y +C X +C Z +A Y +B Z +A X +B X +A Y +C X +C Y +A Y +C X +B Y +C Y +A X +B Z +A X +C Z +A X +A X +C Z +C Z +B X +C X +A Y +B Z +C Z +A X +A X +C Z +C Y +A X +C X +C Z +C Y +C X +C Y +C X +C Z +C Z +B Z +A X +A Y +B Z +A X +B Z +C X +B Y +A X +A X +A X +A X +B Z +C Z +B Z +B Y +C Z +C X +C Z +C X +B Z +C Z +A X +C Z +C Z +A Y +C X +A X +B Z +A X +B Z +B Y +A X +A X +A X +A Y +C Z +A X +B Y +A Y +B Y +C Y +A X +A X +C Y +A X +C Z +B Z +C X +C Z +A X +B Z +C Z +B Z +B Z +B Z +C X +C Z +A X +A Y +C X +C Z +B Z +B Y +C Z +B Y +B Z +C Z +A Y +B Z +C X +C Y +A X +B Y +A X +C Z +C X +C Z +A X +C X +B Z +B X +C Z +B Z +A Y +A X +A Y +C Z +C Y +A X +B X +A Z +C Y +C X +C Y +C X +C Y +B Z +C X +B Y +C Z +C Y +B Z +A Y +B Y +C Z +C X +B Z +A Y +C Z +C Z +C Z +C Y +C X +C X +B Y +C Z +A Y +C Z +C X +B Y +C X +B Z +B Z +B Z +B Z +C Y +C Z +C X +B X +C Z +C Z +C Z +C X +B Y +B Z +C X +A X +C Y +B X +C X +C X +C Z +A X +A X +B Z +B Z +A X +C Z +A X +A Y +C X +B X +C Y +C Y +A X +A X +C Z +C Z +B Y +B Y +B Z +C X +A X +A Z +C Z +B Y +C Y +C X +C Y +B Z +C X +A X +A X +C Z +C Y +B X +C Z +B Z +A X +C X +A Y +C Y +C Z +B Z +C Z +A X +C Y +B Z +C Y +B X +C Z +C Z +A X +A X +C X +C Z +C X +C Y +C Z +A Y +C X +C Z +B Y +B Y +C Z +A X +C Y +A X +C X +C X +B Y +C Z +C Z +A X +A Y +C Z +B Z +C Y +A X +A X +C Z +C Z +A X +C Z +C Z +B Z +B Z +A X +A Y +A X +C Z +C X +A X +B X +C Z +C Z +B Y +A X +B Z +C X +C Z +C Z +C Z +C X +A Y +A X +A Y +A X +A Y +C Z +C Z +B Z +B Y +A X +B Z +C Z +C X +C Y +C Z +A X +C Y +B Y +B Z +C Z +B Y +C X +C Z +B Y +B Z +B Y +C X +C Z +C X +C Z +B Y +B Z +C X +A X +A Y +B Z +B Y +A X +A X +C Z +A X +A X +C X +A X +C Z +C X +A X +B X +A Y +C X +A X +C Y +A X +C Z +A X +A X +C Z +A X +A X +C Z +A X +B Y +B Z +A X +C X +A X +C X +B Z +C Y +A Y +C Z +B Z +A X +C X +A X +B Y +C X +B Y +B Z +A X +B Z +C X +B Z +A X +A X +C X +A X +C X +A Y +C Z +A X +B Y +B Z +C Z +C Z +A X +C Y +B Z +C X +B Z +B Z +C Z +A X +C X +C X +A Y +A X +C Z +B Z +A X +B X +A X +B Z +B Z +C Z +B Y +C Z +A X +C Z +C Z +C Z +C X +A X +A X +C Y +B Y +C Z +B Y +A X +B Z +A Y +C Y +B Y +C Z +C X +C X +A X +B Y +A X +A X +C Z +C X +C Y +A X +A X +A X +C X +B Z +B Y +A X +B Y +C X +C Z +B Z +A X +C X +C Z +B Y +A X +C Z +B Z +B Z +A X +B Y +A X +B Y +C Z +C Z +B Z +C Z +C Y +A X +B Z +C Z +A Y +C Z +B Z +B Z +C Z +B Y +C Z +C Z +B Z +A Y +C X +C Y +B Z +C X +C Z +A X +A X +C Y +A Z +C Z +C X +B Z +B Z +C Y +A X +A Y +C Z +A X +A X +B Z +A X +C X +C X +B X +B X +A Z +B Y +A X +A Y +C Z +A X +A X +B Z +B Z +C Y +A X +C Y +C Z +A Y +C Y +B X +C X +A X +B Z +A X +A X +A X +A X +A X +B X +A X +C Z +B Z +B Z +B X +A X +C Z +B Z +C Z +C Z +C Y +A X +C Y +C Y +C Z +A Y +C Z +A X +C X +C Z +A X +A Y +C Z +C X +A X +C X +B Y +C Z +B Z +A X +C Y +B Z +B Y +A X +C Z +A X +B Z +C Z +C Y +C Z +A X +A X +B Z +B Y +A X +C X +C Y +B X +C Z +A Y +C X +B Y +B Z +A Y +C Y +C Z +C Z +C X +A X +A X +C X +C X +C Z +C X +C X +B X +B Z +B Z +C X +C Z +C X +A X +A X +A X +C Z +C Y +B Z +C X +C X +A X +C X +C Y +A X +B Y +A X +C Z +C Z +B Z +A X +A X +A X +B Z +C X +A X +B Y +B Z +C X +B Y +C X +B Y +C Z +B X +A X +A X +B Z +A X +A X +A X +B Z +A X +C Z +C X +C Z +A X +C Y +C Y +C Z +C Z +C Z +A X +C Z +C X +C Z +C Z +A X +B Z +C X +C Y +B X +B Z +B Z +A X +C Y +B Y +C Z +B Z +C Z +C X +A Z +C Z +B X +C X +C Z +C Z +C X +C Z +C Z +A X +B Z +C Z +C X +A X +B Z +C Y +C Y +B Y +C X +A X +A X +C Z +B Z +C X +C X +C X +B Y +C Z +B X +C X +C Z +A X +A X +C Z +C Z +C X +C X +C Z +A X +C Z +C X +C Z +C Z +A X +C Z +A X +A X +A X +B Z +A X +B Z +C Z +C Z +A X +C Z +C Z +B Z +C Z +A Y +C X +A X +A X +C X +A X +C X +C X +A Y +B Y +C Z +B Z +C X +B Y +C Y +C X +C Z +A X +C Y +B Z +B Y +A X +B Y +B Y +A X +C X +C X +A X +A Y +C Y +B Z +A X +B Z +A Y +B Y +C Z +C Z +C Z +A Y +B Y +B Y +C Z +B Z +C Z +A X +C Y +A X +B Y +B Z +C X +C Y +A X +B Z +B Z +A X +B Z +C Y +A X +C X +C Z +C Z +A X +C Y +A X +C X +C X +B Z +B Y +A X +C Y +B Z +B Y +A X +C Z +A X +B Y +A X +A X +A X +C X +A X +C Z +B Z +C Z +A X +A X +B Y +C X +C Y +C Z +A X +C Z +B Z +A X +B Z +A X +B Y +B Z +C Z +C Z +C Y +C X +A X +C Z +A Y +A X +B Z +B Y +A X +C X +C Z +B Z +A X +C Z +C X +C Y +A X +A X +C Z +A X +A X +C X +C X +A X +C X +C Z +A X +A X +C Y +A Y +B Z +C X +C X +B Y +B Z +A X +B Z +C Z +C Z +A Y +C Y +C Z +A X +C Z +A X +C Y +C X +B X +B Z +A X +A X +B Z +A X +C X +C X +A Y +A X +A X +C Y +B Z +A X +B Y +C X +B Z +C Y +B Y +A X +C Z +B Y +B Z +A X +B Y +C X +C Z +A X +B Z +A X +C Y +C Z +A X +A X +C Y +C Y +C X +A Y +C Z +B Z +A X +A Y +C Z +C Z +C Z +C Z +B Y +A Y +A X +A X +C X +A X +B Y +C Z +B Z +A Y +C X +C X +A Y +A X +A X +C X +C Z +C X +A X +A Y +C X +C Z +C X +A X +A X +C Z +C X +A X +C X +C Z +A X +A X +C Z +B Y +A X +C Z +C Y +C Z +C Z +B X +B Z +B X +A X +C Z +B X +C Z +A X +C Z +A Y +A Z +B Z +C X +A X +A X +A X +A X +A X +C Z +A X +B X +A Y +A X +C X +A X +A Y +A Y +B Y +C X +A Y +A X +C Z +C Z +C Y +B Z +C X +C Z +A Y +C X +C Y +C X +A X +B Y +C Z +C Z +A X +C Z +B Z +B Z +C X +C X +A X +B Y +C X +C X +A X +C Z +B Y +C Y +C Z +A X +B Z +C Z +B Y +C X +A X +B Y +B Z +A X +C Y +B Z +C Z +C X +A X +C X +A X +B Y +C X +A X +C Y +B Z +B Z +B Z +C Y +A X +A X +A Y +C Z +B X +B Z +A X +A X +C X +A X +C X +A X +C X +A X +A X +A X +A Y +A Y +B Y +A X +B Y +A X +B Y +B Z +B Y +A Y +C Z +C Z +C Z +C Z +A X +C Z +C X +C Y +C Z +B Z +B Z +B Z +C Y +C Z +B Z +C X +A Y +A X +C X +C Y +A Y +B Y +C X +C X +B Y +C Z +A X +C X +C X +C X +C X +C X +C X +B Z +C Y +A X +A X +B Y +B Z +A X +C X +C Z +A X +B X +B Z +C Y +B Z +C Z +C Y +A X +C Z +B Y +C X +A X +A Y +A X +C X +A Y +A Y +C Z +B Z +C Z +C X +C Y +B Y +A X +C X +C Z +B Y +A X +B X +B Z +C Z +B Z +B Z +A X +A Y +A X +A X +B Z +C Z +A X +A Y +C Z +C Z +C Y +A X +B Z +C X +C X +A Y +A X +C X +C Y +C Z +C Y +C X +A X +B Z +C Y +B Z +C X +A X +A X +C X +C Z +C Y +C Y +A X +A Y +C Z +A Y +B Y +C Y +A Y +C Z +B Y +C X +A X +B Z +C Z +A X +A X +B Z +C X +B Z +C Z +C Z +A Y +A X +C X +A X +B Z +C X +A X +A X +B Y +A Z +B Z +C X +C Z +C X +C Z +C X +A X +C Z +B Y +C Y +C Z +A X +C Z +A X +A Z +A X +A X +C Z +A X +B Z +C X +B Z +A X +C X +A X +C X +C Z +B Z +A Y +C Y +C Z +C Z +C X +C Z +A X +A X +B Y +B Z +C Y +B Z +A Y +A X +A X +B Z +B X +A X +B Y +B Z +C X +A X +A X +C Z +B Y +C X +B Y +A Y +A Z +A X +B Y +C X +C Z +C Z +C Y +C Z +A X +B X +C X +A Y +A X +C Z +C Y +C X +B Z +A X +C X +C Z +A X +C Z +A X +C X +C X +A Y +C Z +A X +C X +C Z +C Y +A X +A Y +A Y +C Z +C X +A X +C Z +A Y +A Y +A X +B Z +C Z +B Y +C Z +B Y +C X +C Z +B Y +A X +A X +B Z +A X +C Z +A X +A X +B Y +A X +B Z +A Y +A X +A Y +C Z +B Z +A X +B X +B Y +B Z +A X +A Z +B Y +B Z +C X +B Z +A X +B Z +C Z +B Y +C X +A X +A Y +B Y +A Y +C X +C X +B Y +A Y +B Z +C Z +B Z +A Y +A X +B Z +B Z +A Y +C Z +C Z +B Z +C X +B Z +B Y +B Z +B Z +A X +A X +C X +C Z +B Z +A X +B Z +C Y +C Z +A Z +A X +A X +C Z +A X +C Z +C Z +C Z +B Z +A X +A Y +B X +A X +A X +A X +C Z +B X +B X +A X +C Z +A X +B X +A X +A X +B Z +A X +C Z +C Y +A X +B Z +A X +C Z +B Z +A X +A X +B Y +B Y +C Y +A X +B Z +C Y +A X +C Z +B Z +A X +C Z +B Z +C X +B X +B Z +C Z +A X +B Z +A X +A X +A X +A X +C Z +B Z +B Y +C Z +A X +C Z +A X +C X +C X +A X +B Y +C X +B Z +A Y +C Y +B Z +C Y +C X +A X +B Z +C X +B Y +A X +A Y +B Y +B Y +A X +C X +C Z +B Z +A Y +A X +B Y +C X +B Z +B X +C Y +B X +C X +B Y +C X +A X +C Z +B Z +B Y +B Y +A X +A X +A Z +B Z +B Z +C X +C Y +A Y +C Z +C X +A X +C Z +C X +B Z +A Y +B Z +C Z +B Z +B Z +C X +B Z +C X +C X +B Z +A X +B Y +B Z +A X +C X +A X +C Y +A X +C X +B X +C Z +C Y +C Z +B Z +C X +A X +A X +A Y +C Z +C Y +A Y +C Z +B Z +C Z +C Y +A X +A X +C X +C Z +C Z +A Z +C Z +A X +B Z +C X +C Z +A X +B Z +C X +A X +A Y +B Y +C X +A X +A X +C X +C Y +B Z +C X +A X +C X +B Z +B Y +A Y +C Z +A X +C Z +C Z +A X +C Y +B Z +A Y +B Y +B Y +A X +A X +C X +C X +B Y +C Z +C Z +C Z +C X +C Y +C Z +B Z +C Z +A Y +C Z +A X +B Z +B Y +B Z +A X +A X +A X +A X +C X +C Z +B Z +C X +B Z +C Z +A X +C X +C Z +B Y +A X +C X +A X +B Z +B Z +A X +A X +B Y +C Y +C Y +C X +A X +B Z +C Y +B Z +A Y +B Y +B Y +A X +B Z +A X +C X +C Z +A X +B Z +A Y +C Y +B Z +C Z +C Y +A X +C Y +A X +C X +B Z +C X +A X +C Z +A X +B Y +B Z +C X +C Y +B X +A X +B Z +A X +B Y +C X +C X +C Y +C Y +C X +B Y +C Z +C X +B Z +B Y +C X +A Y +C Z +C Z +C X +B X +B Y +A X +A X +C Z +C X +C Y +A X +C Y +A Y +C Z +C X +A X +C Z +C X +A X +B X +C X +C X +C X +B Y +B Z +C X +C Z +A Y +B Y +C X +C X +A X +B Z +C Z +A X +C Y +C Z +A Y +B Z +C X +C Z +A X +C Z +B Z +B Y +B Z +A X +C X +A Y +C X +C Z +B Y +C Y +C Z +C Z +A X +A X +A X +C Z +B Y +C Z +A X +A X +B Z +B Y +B Z +C Z +B Z +A Y +C Y +C Z +B Y +A X +A X +C Z +B Y +C Z +A X +C X +B Y +A Y +B Z +A X +A X +A X +B Y +A X +C Z +B Y +C Z +B Y +C Z +C X +C Y +C X +A X +A X +A X +C Z +C X +C X +B Y +A Y +B Z +B X +C Z +B Y +A X +C Y +B Z +C X +A X +A X +A X +A X +C X +B Y +A X +A X +B Y +A X +B Z +C Z +A X +A X +A X +A X +B Z +A X +C Z +C X +C Y +B Z +C Z +A X +C Y +C Z +A X +A X +C X +B Z +C X +B Z +C Z +A X +A X +A Y +B Y +C Z +B Y +A X +C X +C Z +C Z +C X +A X +A X +C Z +A X +A Y +A X +A X +C Z +C X +C X +C Z +C X +A X +C Z +C Z +B Z +A Y +A Y +B Y +A X +A X +C X +C X +A X +A X +C X +C X +B Y +C Z +A X +B Y +A X +A X +A X +C X +C Y +B Z +B Y +B Z +C Z +C Z +C X +C Z +A X +B Z +A Y +C Z +B Z +A X +C Y +B Z +C Z +C Y +A X +B Y +C Z +A X +A X +A X +C Z +C Z +C X +A Y +C X +B Z +B Y +A X +C X +C X +A Y +A Y +A X +B X +B Z +B Y +B Y +A X +C Y +A X +C Z +C X +C X +C Z +B Z +B Z +C Y +C X +B Z +C Z +A Y +C Y +A X +B Z +A X +C Y +B Z +B Y +C Z +A X +A X +C Z +B Z +B Z +C Z +C Y +C Z +C Z +C X +A Y +A Y +B Z +C Z +B Y +C X +C X +A Z +C Z +A X +A X +C X +A Y +C X +A X +A X +A X +C Y +A X +B Y +A X +B Y +A X +A X +A Y +C X +C Z +A X +C X +B Y +B Z +B Z +A Y +C Z +C X +C X +B Z +B Z +C X +B Y +A X +B Y +A X +A X +C Y +B X +C X +A Z +A Z +A X +C Z +C Y +C Z +C Y diff --git a/2022/days/02/src/main.rs b/2022/days/02/src/main.rs new file mode 100644 index 0000000..aa5fb7d --- /dev/null +++ b/2022/days/02/src/main.rs @@ -0,0 +1,13 @@ +mod part1; +mod part2; +mod utilities; + +fn main() { + let _input = include_str!("./input.txt"); + + println!("Part One"); + println!("Result: {}", part1::part1(_input)); + + println!("Part Two"); + println!("Result: {}", part2::part2(_input)); +} diff --git a/2022/days/02/src/part1.rs b/2022/days/02/src/part1.rs new file mode 100644 index 0000000..8901bec --- /dev/null +++ b/2022/days/02/src/part1.rs @@ -0,0 +1,62 @@ +use crate::utilities::*; +pub fn part1(input: &str) -> usize { + parse(input).iter().map(calc_score).sum() +} + +pub fn parse(input: &str) -> Vec { + input + .lines() + .map(|line| { + let elf = match line.as_bytes()[0] { + b'A' => Play::Rock, + b'B' => Play::Paper, + b'C' => Play::Scissors, + _ => panic!("your opponent not playing defined strategy!"), + }; + let you = match line.as_bytes()[2] { + b'X' => Play::Rock, + b'Y' => Play::Paper, + b'Z' => Play::Scissors, + _ => panic!("you are not playing defined strategy!"), + }; + Strategy { elf, you } + }) + .collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part1() { + let input = "A Y +B X +C Z"; + assert_eq!(part1(input), 15); + } + + #[test] + fn test_parse() { + let input = "A Y +B X +C Z"; + assert_eq!( + parse(input), + vec![ + Strategy { + elf: Play::Rock, + you: Play::Paper + }, + Strategy { + elf: Play::Paper, + you: Play::Rock + }, + Strategy { + elf: Play::Scissors, + you: Play::Scissors + } + ] + ); + } +} diff --git a/2022/days/02/src/part2.rs b/2022/days/02/src/part2.rs new file mode 100644 index 0000000..7d82894 --- /dev/null +++ b/2022/days/02/src/part2.rs @@ -0,0 +1,87 @@ +use crate::utilities::*; + +pub enum GameResult { + Win, + Loss, + Draw, +} + +pub struct ResultStrategy { + pub elf: Play, + pub you: GameResult, +} + +pub fn part2(input: &str) -> usize { + parse(input) + .iter() + .map(gen_strategy) + .map(|strat| calc_score(&strat)) + .sum() +} + +fn gen_strategy(input: &ResultStrategy) -> Strategy { + match input.you { + GameResult::Win => Strategy { + elf: input.elf, + you: gen_win(input.elf), + }, + GameResult::Draw => Strategy { + elf: input.elf, + you: input.elf, + }, + GameResult::Loss => Strategy { + elf: input.elf, + you: gen_loss(input.elf), + }, + } +} + +fn gen_win(opponent: Play) -> Play { + match opponent { + Play::Rock => Play::Paper, + Play::Paper => Play::Scissors, + Play::Scissors => Play::Rock, + } +} + +fn gen_loss(opponent: Play) -> Play { + match opponent { + Play::Rock => Play::Scissors, + Play::Paper => Play::Rock, + Play::Scissors => Play::Paper, + } +} + +pub fn parse(input: &str) -> Vec { + input + .lines() + .map(|line| { + let elf = match line.as_bytes()[0] { + b'A' => Play::Rock, + b'B' => Play::Paper, + b'C' => Play::Scissors, + _ => panic!("your opponent not playing defined strategy!"), + }; + let you = match line.as_bytes()[2] { + b'X' => GameResult::Loss, + b'Y' => GameResult::Draw, + b'Z' => GameResult::Win, + _ => panic!("you are not playing defined strategy!"), + }; + ResultStrategy { elf, you } + }) + .collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part2() { + let input = "A Y +B X +C Z"; + assert_eq!(part2(input), 12); + } +} diff --git a/2022/days/02/src/utilities.rs b/2022/days/02/src/utilities.rs new file mode 100644 index 0000000..3ecf4eb --- /dev/null +++ b/2022/days/02/src/utilities.rs @@ -0,0 +1,36 @@ +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum Play { + Rock = 1, + Paper = 2, + Scissors = 3, +} + +#[derive(Debug, PartialEq, Eq)] +pub struct Strategy { + pub elf: Play, + pub you: Play, +} + +pub fn calc_score(input: &Strategy) -> usize { + //an enum wins if (you-elf)%3 = 1, looses if it = 2 + (match (input.you as i8 - input.elf as i8).rem_euclid(3) { + 1 => 6, + 2 => 0, + 0 => 3, + _ => unreachable!("you were {}, elf was {}", input.you as i8, input.elf as i8), + }) + input.you as usize //play enum has value corresponding to its score. +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_calc_score() { + let input = Strategy { + elf: Play::Scissors, + you: Play::Scissors, + }; + assert_eq!(calc_score(&input), 6); + } +} diff --git a/2022/days/03/Cargo.toml b/2022/days/03/Cargo.toml new file mode 100644 index 0000000..8fe85a0 --- /dev/null +++ b/2022/days/03/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "day03" +authors.workspace = true +description.workspace = true +version.workspace = true +edition.workspace = true diff --git a/2022/days/03/src/input.txt b/2022/days/03/src/input.txt new file mode 100644 index 0000000..d0ad78f --- /dev/null +++ b/2022/days/03/src/input.txt @@ -0,0 +1,300 @@ +PcPlnShmrLmBnmcwBhrmcmbHNGFGpwdFFwGNjNbGqNHH +tzQfRJfWZZztWzVtCTfRzFZjpFjNZjGLHbdHLDdjpb +CCQTzRLzvQVVfRzJfMPsnBlglgPmBgPmvSrl +RMfvbbszHTsssFPzDQPggpQJPQ +NSNcqVtLVGgDlpQBClVB +hmStGNNLhjNrpWLGSjWrZssbZTMMvTfMnThbRRTs +fTrTPGTbfftWBBmLjrJL +DqHwVMqVplDslmlZmpHVwNnShWZFdBBdjWBtWtdtWJSSLS +MNslpDvVHlwsmpQRgQgCfTTcvcRQ +pBBhRgDsMsswprBhvgRglZtFGFFRqZtZmRtNqtZPPN +TdmmzzmdZdqdGFtF +nmSccCVmSCpDCswMwl +NptqDsQtDTQzCvlzCpRlRp +jmZcndmjbZcjrmDvFMFFlwCvzFnF +jjgLVLrGcdDBNhWQTgHg +mLVhhfSMSTmMwClHGdpjDHjGdV +zPrZgJCgbsnrPtZzsCsbpRDjBRHnjGDRldRHppcG +JJrbsFrZqrgWbbqbrgWzJPNTwhTNCmmvfWCShhhmwwfm +ftgfljvgfgBTNvtggFDDGLGRDnMDzcQzncGt +VdbpbVdZwdwrsVVLRrMrDLDBGnBGcM +wmpWwWsHWBCCCPPvjvmSqlfTTmSNgN +jSqmzmmSSDRjLMLDwqjNcMMLTTflffWCCsRsTHnHVrfHWTsr +tdbgZpgBPdgGZGGFTHVpCsCVfVsJpnWl +FnPQFvbvhFFFbvBwScjhzcqSLLSzSN +bWdgrWwwFWbgzFWzrmNbdPqttChMSRnmqSPSnqtMRM +lcPJLDDPPfpMBCRJBtQtMh +lGDGjTGLLDHPPGjlPTsswsbHNFsNrFNFsrzr +VmtHfVhBLHVtlhphjZMdnQQZZqZmQDdzQQ +CPFwPWrvWgrfNgFPCMqZzMDDbznFTqqzDQ +NNPsfffPCsBLjpVltV +ssdBBJqJhlTJLsjTJqFFmnmmnnrcmpprmmmPcRlf +gqtqzSgWQWqmnRPPcNmmQM +GqbSVtGzvgvgWbZjjBhTdhBsTZBJBZ +jhNBsPDzLjsVhLSNzgvcvbcwbBWFcgtWCc +ZQQTTHHnGpMtnpdHpQJfMgrvWWFqbcWWGgrgwCCwwF +nHpmMnQQMmHpRnHRmMJnnTShPzljzjSNmSDhLsNSPtSh +GdqnBGFdlqzFnwdSCQZjZLLDZjZRvZLDVvgQ +PsptsTcftMfcTfhTghVDvvjnRNjVZnvV +WtPfJTfftJcMTrMnpccFwlCSCGFGCbCwJSbqBl +GjFLGhjRwFjNSjSdJCBBdQJddbBc +MVvMMHRzVtHlvlcQBQJHqdpQqCBC +vDgVztvvmrgrVRrMmsrsmZzZnWhGnNhGWTLfnLwTLhLTjngL +VljjQJSsrjjrCglsCjsgjVVfDLdZGMdvvGdQMzmvzcDQMc +HqPBtcpRWwtHbbFwBHZfmfpDfvffDfMfmGvM +PwHNbcwtqFqnwtNNqPNPPWBTThjhhVTCSJTThssVnSlJJV +GCccNCrrnCrpnzrnCDPcDDrvHHTBqTPhswqhPTBTTwBhTj +VfNmRtZgWWHdBdswdjZv +SmtQfgNmVFgVLVLVmrnMpcDLGCGLGDMpCp +CrdZdZmPPjrQdRPRDqDLBqBLBSWgWgLDzF +sQhTNphsVbhhhMJfhNVGqltVSzSllBzStlzFFFWB +hsMpwQhNMZmPmrwHRj +cNVpSVRpLHRLsVWWfnfsCshW +jvqjTgqZPlJZmbPPfbpswsPb +vlqdTZdtJvqdZjgqZrtRpQFtLFRQczHGzt +JJQndVQnQgTfNvGf +ljpbWbmNbDlGTvggGvZf +mpmRbMmmNDFDmScpzCsdzrnJrsCzrrnM +tNFtNFFzzjjzjBtVNZVbjZGlpSvTllpWwvnBlWGGBGCC +fPdcrrgPHrHMMMWlppGJSPwGSnGv +fmrqrhhfhdRddHrhQqQrfnLZjLtNttZjjRtzjFtRNj +sphRcpQRhfmnmfpptg +WVPlGLlSjCjSlGSHJJWZdmbmfvPmmnftbbgDdt +LJjjqVNjlnCTRcRhhsNcFF +vwwqttFjwgClRNCCvGNmZZMmJsPJjJpTdMpsZd +fBLVHHHrFnhHhnrVSTmfdPdPccTTPsMfsJ +QzVWzznzFbWNGNlt +vjMddVVmnWpdMndjvhhWfNLpfBsfLLZLBBSqqTZq +RFlrzQJPSRGzzzzgBZNsgBZTBflfgf +cQFDRHFDDGCJShCnvwVnnhCn +hgjlpRRLlPJJhTLJMDnwBndSPBNvMqnN +FGWVfZsmCbmVzrvtwCSMtMdnDMCw +VsVmVZfVQDmVFrrmzmGrHHTJgJjhHJcllglLQJRL +rrTVcTBgsjTffmfWHZTv +JLdnDlpGlGSLlpwJpHZfFvRZnWzWrHWqFH +wQDpDrdSlSCblCdwdSLlwQGBthPMsghNsVNVtCNNhNPjhs +CtCMvNhDMHfDDdffqtDtCflpJlBpvmWWJWwlpwFFvjwB +rGSbVGZrSsFJjlmBFZWp +rbbQgzVGrFVSPPGqfhftfqztNtqHtt +lMGZCGphllZDNshNNmHHND +PLwjVwJVsHmRrZZw +ffSdzjfZSjtjSjLtLLFFFGqFzznCpCnCBblQ +CqRnlzHCRWTlHPTZVQrcQtFsQFTcrQ +DfJcdBDBcftQjsrsBtjZ +JDfdGhSvNGhNfffGSfRznPvcRWcqCqmlvlcn +JPhBBBQCnCJCMhnhMZRrRZgbDgrWrNbglDgR +jLtSTwtsShwRNpRWrh +FLLSHsjGLGczvfPfJdfhddnHPC +BjHBNrWmTjFgJngbJhWd +vsGttMDtwCMQCJnqqqFJsggqdg +GFtDSwwMpTrzSSfcfm +rnWDQvpwWpDDcPjFPPHZjVDZ +CTJCRmCJcZZZHCCQ +LdlmdQJNpnLWbrfL +VdTdcVTZwCRGVGGMVmttlF +gnrsbngfgQSpBfpMBBBpSgMNNJbmGmlqGDqDNlFFJlGNFz +gprgQhgpMMMPsrRTCdPZwCwZZCRH +cHlCVGbbWHWqRNThhcNcmh +MwQDzpwdJwpBpPDQvrhShfLTTRLfLdjfNRqS +JwMBBrPsPDwQMDPPBPQJwMrvWHFbHHlgbsGnnWHnFnRGlblF +PQPjPDjRRQSFLSlgSmLlfh +zpLdBddbNCdqGbWJGWpJWWlsFsmmFpwfflFgfHwFhgmh +nJLdLVnzqqbjRctcPDQVTP +JdztScztPdSWLJLtgMbCjhvlbPRbjbMvCh +VZrqfQcFQwGVVFqfrTFTNqhljRHDMvMMGhRDRRHGbDhG +NZQNVQQpQmrZFQQFwQQVVZgBszJJgznstnmtcztdBSgs +nFHLNJzFbLJGGLMlTTRZbZRhWRTr +wVmgBBmtmwlqlWTwTM +sdvmgcPsCPPQQSMz +SccCqmQmgBmppLQmpSMjjlJzzsNPMDRbPNPlJM +VHZvwtZwhZHtdTwrVbNsljlRDlJPDhzsbN +dZwftVRftmcgpBCmBf +NTTlVlgNSflqbphFFhNbFp +wmmLmjwzwbWGLjRmtZZdhZLFtQQLQBFh +RvjbMjjvMzMWbDWwvzPjvmWSfVfsTlVVPVgTgPfVsnnnsJ +BsBsZHZNdWwsNdrzgCrMMqsjzzMC +flfhVWFmLrhQzCCh +fVbmFSpnSSmtnPZvdWbwvdvdHZ +NsZWWWWLsBZPhfsLmPhcFCCHCMMrqfqcvHMfHH +nThSllnplGlMpvFRcCqrrr +DnTwSztgzlDnVGTwztmdZhmLdJdNDshBdsWs +RBBGTFZGglMHvrtcgSdnNgjg +DmVcbmbJmwJDJzVVwzJfmfstnztvjnNjvNSpdptvzCnpjj +DsLcfLmbhVQssQJQscWRPBZZMMRLHFHZBGMG +FVvhVnhFnFhmvFhVcMBHLgcPClrqqrtqCppldrRRTppldg +QLWfDNwsQLtlrrCtDdpq +sJwZwLsGJWGGwzzWZNbWNLjQHSVhvHSnhcMFcbVmnvcchSBS +jTMNMrHBJWWDffRqfDBqfD +QmSFphtQqQmVmqVnPnPlpwgfnRnDPl +VqFmLFbLhmZhGFGmCmGtZLtJWzWHcJrNrHMccjMscMHzMZ +hGPGmbfPzbPfgdMdWGqBGQcqpp +nvFTvDrTdNZZlrjnMHHHpBBcppqq +rNlZZNLvRdRCRFFwZwhgbmSJPSmPfhfwhS +vjdbFWTtFRRvtvZZvdWJWbGjLhCcnrrrNqLNCPqchShNqc +QHQVlDsMfmmDMHDBdLdCSLnhNLNNfqCd +VQHsMDpHlzMBBwlsmMzmmlVwptvTWdvJdbvJtRTWgGFJJGtR +nSScBcnbbFSQVdBFBtWpwtvtPbTZthtTvT +pRzHpGjCDGzHGCGsThqqwZwPhCtvhTqZ +NzlzjDDpNldBFrlfFQ +qJlDlPPWppgppqPlplpfdvgnbMfGbdgCghMdCM +QWTWZcSsWbvVvTnhfC +tRFLwZrcrWzzlJmtBqlm +HMNMvvzzNcmfNmfbhs +qVcwCgjCLtWRSLsTPbmPfmTh +RtWCJgddWRtCJdWWgdBjwWWwpzMFpHGprcBGFFnGHQZHQGpF +gZgBDgDVGDGjmDZRtgjvVvtQdnLrcRcrdfdfCcnlscsJsn +WTqzqHqNzpHpwzNhMHNwWPbQCQcCLsnCrLLfcrffNflcNn +zHTwwpTPzTTwlFTFzwqzPbwZGgGZZBtmGGvGmBGZVFStFZ +znlSSzfzTcmmfcCt +PHWWGpqgPShPMwGwqJFTVtwtCVTCmTJcFc +qHqqSggLrRLBbvDDdndzRQ +WBddBQWZWWQqqQFMWfmrWsJnmVJJNDDVJGsLmHmLDN +PTgCjvCCPPPzSZGJVLsVZCHHnH +pzwtPTvzTjRTPtwSjPSzRgBbWMBfMwwZfbWrMrZFqFFM +BqDwVqdqlDlblQMf +ZcCWWcWzvJZjcPjZZZfTHfQJQHThqpMbQQJf +LPCcZcczZLgCjvPWgvstjsjmRRBdmGrdGdmSFGnFrtGmqr +CBvgQssVzfCBQSgvvvfmrlGrCtMGwthJlJtbrh +TpLqLRFpqdRpRTfNPtRmrMMtMlMMmlMJlt +PZTjqFFTHZZNZpqcVWzVvgzcWnSWfBDD +SVSTpgpVpdNbpcVdfjcNfbcJnqsltcJPvRJqRwQqlQsJls +zhWzDLmFHhmrWZmmzHJJQlnswqsvttrstQqs +zGtZFGGCmZmGGFhLBWBGGFdgVjgppMTSTgMfCNfVVSdj +CzjNJGcnzQJltPHttcPHTP +bLVsqLbLmSSVrqmdhVSmsVFFprfrFWrwTTWWWZpFPtlP +ssDsMqLqhvmvhdmdvzRCnQgRzzBjgnlNCM +TzTLzzSGRlRSjWzlWRzHGTpNhPhJPmdnNPPbhlbPbdhfPh +mBCDBVrCqVQvQMBcVcqBrBDsbtJfnZNbJndNNhthZNJfPZPs +wMCrqVvBzmzHTGLw +NbfwfZPPdVNPdBdQBcmQzrQz +nnWqHLWGFMDFDLDjsqnHLsrQGzmJczmQrgJmJGZmQrgJ +FFWRsHMHCZCWFwRwphpvlfTTpp +PclPlVZvLDNvVZSLSMvvDttmtfzFtzHqtqtzzccCFc +jrggQGhjQsTDbrbJjJQqzzCsdtzzFCdHqmBBHz +WGDgngwrQggZMNvMWPMRRV +wNgpMdMMcdSscccNcLLTbtQJtQJQltJwFtlBlzBt +HHGhrLrCvHWHCPhrWDtnBllnQbfQftGnfnBF +HvLjWCLHPZvHHHZjjrqVTTZVcppMgNNNNSpS +QQrwQmvWQjgTfvBjfffrSDcrqSqDDVLctqqcVd +GnHFnGhGplGMlHMNhzBzlLPLVcVNCPDqVNdcqLdqtV +GnMGpslMhGsRzzHzGsZFZQJTTmWfBbvfgfgJRfbwbW +MRCtSwMhvjCGtvMZDVWpVZJlVccNDlpb +gdLQFFwwLfHJWnQlcJJbWc +rdqdmqHLTLmsswsFHLFtMPRMCSSRtSjTPMPSCR +jmCCnLCLZjZjRjQTLZQhGPGhhzHhDRGRDzwzwh +stlJlrlJJcSSfSMMzPfhhGhzpwhpNwhD +rbrbBcSlWmdZWjDnTm +PNBRNnnqQRNfVfRtVVzgFLLttpSwgzzzmFFF +fcWlcbvvCFzLbwLw +rlrMrhTJhDcTTfhRNqHRQPQRQNQB +TrprpprRVVfpRpVqTVpzDdvmvbbCchhcttqcthSMdd +JlnZnFlsMBZnJHlsLsCLbSNtbNhdbbShCScm +FlZjjsHHsnQFQwTDzMRRpGRR +wHWzwCTTqJhzzvJhWHWhqJWrFsFQrrrFCfFfgjjgjprfsp +DBRmZRtZLbnRBGSBmtGSLpjBrrsfrgsTQVrVrrPrgr +DLnbcbtLtmNNmbRcGbcGmHzlThNNhqJTHdvqvWlHJh +GSNqjRcqflNLnCTTWrWn +BmwQtmtJwPwmzMwQtHtVssvrnpWTTnsTTgpVCLCs +DBBQHJJrzhzQDDfSljRfhccfcdZf +wtgtChCwzqgLzjggqtHtjFHHFcnPfdRDfZZVcPfVZZfGnfdm +vBTrRTTWGGmcTDVD +SJMbbpWslJblSSNzNsztRChzqRCj +gBHHCtVCSHMQlfFTQqCfmq +WrpdwjbwbwQGlPqSqblP +wWDncWrDDNdWNRjScScjpzvHZtBMZtJsvLVgvzssBsvs +VppWpVfmZPBlnmrGBzhttMzMpctLLcChSh +FwgLJvRdHcwMzSzjzc +QvbgdQLQgDvsqvqRHRDdDQDBWmBGBflnVbZmZmmnBBWrmW +SqShwLFCQGpDHCtZCWpW +bdHPHjTbJdsMnPHPbdjgtnBlVlBnVgtZpDBpWV +bdmPcjbjMNMvvHbTcQRNfRwRwLffwwqwNF +zdRHTpQTQHQnpnnQRHTsNNlJSJWmzJmJllNmSG +FBbRvLbFRwLqbbVgBVqqLFqJtJNcltsSGmgmGtNtgWmstm +FLhhfvvVwvjqfLRBqLVqbwqZQrTTpHMHjdrpnnDPDQCdCrpC +JgjzvbJCWgbjgGbJWjRhgNPGHHBMtqBStZZsHMSsBqtD +cfQdwQFdQQppnVVnlFLLBsBZMhqPlPMMqBSHDtHM +wnQhcnVddmdWgjvjmvRjjJ +QpcRtndvsLcVJtRSzWSlWjzSbjjWBv +qGZPqCTmGPqgGTCqHgCqZCPFWbbBNBMNBbdBMlWWrbjlMbFl +qhHDGhCmPhZHgDmDVQthttRchLwLdwcc +srpPMwlMmsrGFGswvDRhRWRDJJJchJ +fSgBbCBNnBTTgCNLTCRJhRJVWhTcVVVFFJdR +SbBnnLNZCLFQCZjnCnZFjPrzqmlMmmsrpzrlsmtt +BBsfDfsBDSWRwlLqmWCpWcllrl +nQMgMnnnhdntgMBrCdpNNLNlNqLqLl +FnQFHzPQJjJGRBGvfR +lRnVRFFlgMCRVwLgFZRnZQHWdcftHdmcJHmmMdzzfz +DGBqGQbhhBDbSBpGDBzqdNHJdtmcWdqdmtcm +bjbsBvjhSlVsPRgLQl +dDLbRdTMRJMbFRzZBfzNSjtNBzBD +PmgspqqVrppTVrvrsPhhfQwZBwNjNtNffzqqfwwN +mCcmsngrPvpVTssCVsvsPLRRJllGFlnRGbMJMWWlJJ +fGlGZHRRbwgPbZRRNCdcSWpncnQtQWlWcWpW +JrTLJgVvVLQQvtSvQncQ +JrrrmMTBVTmjBMrVjrshmJzgCfzRPCRZPGHfbwNPzbZHNH +qqqlDDZzVVnNqHDDFFFNlQpzjrTvsvzTbgJQQggjJp +cWPWcCmMfCMWdtPMhMbQQQjGGjpdvjTbjgjr +WtMSBCtCwchChMfBWtcPnNVNqZZLDRNqTRnnlwHn +mvQQnhBvhmvBmncmZBclTZTQccRFNFFdqFFgVqSRrgFrppNR +MjzJPzGPfffMCjVVjfPHLCFRNFStqrdRSdqdNGRqNptq +HDJHPjDJLfjbzfwPjCzCWWTwlmQhBnsWBvVsvBvZ +RVjcshhscQhrVjhvzjVfDNnzGtftmDHFttFGGf +qLcBCCMBJJbTdBDnNtdfnmDG +WpZgLLclTclRwgjgsrwsvj +shhhltNPcDtlNcNMcsctNtppLZvWWFLTFFZpTZDQgFLT +dRgJVzRHbqnLpTWQvLLJfp +mCVCdzqHndbqHCrVqRrmbwtNBsmPwNmScPgtPhBclw +bDDZMDrFPsrsMcsrbJZJdMMGpSzpSbwRSSRGpCHCGzlhCC +BWWNQjBLQVHhlGpSCmwj +ffwnNwfgtnNgVVwfNWBWnFsMJTJTcPFJcTFDsrJstJ +vQbQLQBpBvbvpHplHNTHWGZDngntZCQGgZhGhtjG +rqccPPmcrffRmsmCjVgnrGChChDjgW +fqRJsJMSlSzSWTbT +brsjjJPJwrJJsrRRlllNQGWQpwppCtfGGtWzGGMQ +ncBqqLTDnmLgVDZVnBDmdtVVtMzWWdMCQdpQWdVz +hDZgTSSnTzNPNFSFPF +VZVJJtWTsfTVVWsJhPWrCjzSBJlHSmjJCRlNSSlz +CqMpwccgvvgLnvLbMMRRjBNHzjmGmwNHlmlN +gLqqvpCDfVDrTfVW +CNMDGNPPNJCGbLnTffsTLT +tcBBRlrBdQrtmtWFjjbnrTjjFbjr +cTQQhcmvcBRcwDMVDZZPPCJh +mBCdgPLgZmLfGmfvGhtRQJWjtjQGQhtN +pMwrVwbwHMsqcTWQhQWzggTTWp +nnSMwrlrsmSZgvvmDd +WNSzpCzNzqzNdmqrRHrrLHFrJH +MtPfvnGMPnMcbnRtDHTRFFDrmJRQ +PcBsfPPHPGGfcSzZjNjpNZZdCs +mDCZVLDhWVSDCRvGtsGgGRHl +JjPwPNdcPnjPdcwNltHzzGmgGJzQJJRQ +dqfjnNmwmbmWrZMbMrThhB +qtBpNZFpBGFNfZNPmZPmQmHrmPPPTz +LLwJLvDvlWWLHdwDrVcCRcDVzzVVcV +sMMwvgjnMvjvnlsvNFBqfGHFqHGjtSpS +MmZZsFgwJTdTMdgmZdZRgFhDHhPQPPnRPhCrHhnnrPDD +fBcLlNNpQCDLDJJC +jSbWWlWpBpclWlWpNWlVBbWVdgwswFJmFJsGtdMggZFGbZwd +CMVQVMLLMFGRCMWQttnqqwQwhqsm +pJzlczSpPpPgmsqNhmPGDstq +gZgTccZGGpzdpjclGRVMVRFRMFvHRLRdLf +FMWMSBtStZqZWQtFtScWWSZmHPVJJVHwwlTgmgbzQwbwTJ +jhGLhdjNjsLvLsshzHJPVdVmmbzHzdHJ +jvDRNjnDNGRCzjLzZZpqnrFBSccWrMcB +zggmthDDghHvtrdgrVWfSBRwTHLWHwsBWw +PGGjpCjQnJQGJcJnnQpjFWVSsZWVLRZLBcsWSZBRWS +FGQlpnJCbqqGGRCjjnlCqGMtdNmmmvdNmmmzvhbrmgMz +TstvBTdgBhqTsdTcPlfCSrNMrNnrCNNSNNgp +HwLQwQDZzDjnDbmMhNSnmm +FZLVzLLQHRRzwWHjdPlJctlJtlsllhRs +fBtPsMDDswHvBmmVdBlSBRcGGnhVhg +LWJbrpFqpTLTTjqqNWlhnRGGSnhrcSdlRlsh +JWNbbpjJzTbNNNJNJMvmvfZHvzDsHDCsZw +LPGnPNLtwGhFFnJPfsqpVVszzpsP +TcWdvlrcWddggrDBDDdDMmWzRJqfVQZqmsfZsRQzZfZzQJ +TldWrMrDdlDCDdMTcwSLVCSShLNSwHjhGF +JGsWWWQsJmPwQWbBPmccbcbqFfMMpFDVCDFVFVCDqqfFwD +ZtLnlvLnNtvLndnCmfMVSmVCClfpVp +zTzZtjnZNLNmZvdtznntHHZJbBRGBRQWcJGbGsbsJRPQWT +MLmlMTPtQtMNlhbqbbqhflBB +rcrvjpSvScbRbBvbDBPG +ZZJzSHpzPrJzHFmMVMFmHCLNtV diff --git a/2022/days/03/src/main.rs b/2022/days/03/src/main.rs new file mode 100644 index 0000000..e4fc4b6 --- /dev/null +++ b/2022/days/03/src/main.rs @@ -0,0 +1,14 @@ +mod part1; +mod part2; +mod utilities; + +fn main() { + let _input = include_str!("./input.txt"); + let _structured_input = utilities::parse(_input); + + println!("Part One"); + println!("Result: {}", part1::part1(&_structured_input)); + + println!("Part Two"); + println!("Result: {}", part2::part2(&_structured_input)); +} diff --git a/2022/days/03/src/part1.rs b/2022/days/03/src/part1.rs new file mode 100644 index 0000000..4bffe88 --- /dev/null +++ b/2022/days/03/src/part1.rs @@ -0,0 +1,54 @@ +use crate::utilities::*; + +pub fn part1(input: &[Rucksack]) -> usize { + input + .iter() + .map(|rucksack| rucksack.0.intersection(&rucksack.1).next().unwrap()) + .map(find_char_score) + .sum() +} + +#[cfg(test)] +mod tests { + use super::*; + use std::collections::HashSet; + + #[test] + fn test_part1() { + let input = vec![ + Rucksack( + HashSet::from(['v', 'J', 'r', 'w', 'p', 'W', 't', 'w', 'J', 'g', 'W', 'r']), + HashSet::from(['h', 'c', 's', 'F', 'M', 'M', 'f', 'F', 'F', 'h', 'F', 'p']), + ), + Rucksack( + HashSet::from([ + 'j', 'q', 'H', 'R', 'N', 'q', 'R', 'j', 'q', 'z', 'j', 'G', 'D', 'L', 'G', 'L', + ]), + HashSet::from([ + 'r', 's', 'F', 'M', 'f', 'F', 'Z', 'S', 'r', 'L', 'r', 'F', 'Z', 's', 'S', 'L', + ]), + ), + Rucksack( + HashSet::from(['P', 'm', 'm', 'd', 'z', 'q', 'P', 'r', 'V']), + HashSet::from(['v', 'P', 'w', 'w', 'T', 'W', 'B', 'w', 'g']), + ), + Rucksack( + HashSet::from([ + 'w', 'M', 'q', 'v', 'L', 'M', 'Z', 'H', 'h', 'H', 'M', 'v', 'w', 'L', 'H', + ]), + HashSet::from([ + 'j', 'b', 'v', 'c', 'j', 'n', 'n', 'S', 'B', 'n', 'v', 'T', 'Q', 'F', 'n', + ]), + ), + Rucksack( + HashSet::from(['t', 't', 'g', 'J', 't', 'R', 'G', 'J']), + HashSet::from(['Q', 'c', 't', 'T', 'Z', 't', 'Z', 'T']), + ), + Rucksack( + HashSet::from(['C', 'r', 'Z', 's', 'J', 's', 'P', 'P', 'Z', 's', 'G', 'z']), + HashSet::from(['w', 'w', 's', 'L', 'w', 'L', 'm', 'p', 'w', 'M', 'D', 'w']), + ), + ]; + assert_eq!(part1(&input), 157); + } +} diff --git a/2022/days/03/src/part2.rs b/2022/days/03/src/part2.rs new file mode 100644 index 0000000..cf38cf0 --- /dev/null +++ b/2022/days/03/src/part2.rs @@ -0,0 +1,78 @@ +use crate::utilities::*; +use std::collections::HashSet; + +struct Group(HashSet, HashSet, HashSet); + +pub fn part2(input: &[Rucksack]) -> usize { + seperate_groups(input) + .iter() + .map(|group| { + //manual implementation of intersection because doing chained intersections is annoying... + group + .0 + .iter() + .filter(|c| group.1.contains(c)) + .filter(|c| group.2.contains(c)) + .next() + .unwrap() + }) + .map(find_char_score) + .sum() +} + +fn seperate_groups(input: &[Rucksack]) -> Vec { + let mut output: Vec = Vec::new(); + for group in input.chunks_exact(3) { + output.push(Group( + group[0].0.union(&group[0].1).copied().collect(), + group[1].0.union(&group[1].1).copied().collect(), + group[2].0.union(&group[2].1).copied().collect(), + )); + } + output +} + +#[cfg(test)] +mod tests { + use super::*; + use std::collections::HashSet; + + #[test] + fn test_part2() { + let input = vec![ + Rucksack( + HashSet::from(['v', 'J', 'r', 'w', 'p', 'W', 't', 'w', 'J', 'g', 'W', 'r']), + HashSet::from(['h', 'c', 's', 'F', 'M', 'M', 'f', 'F', 'F', 'h', 'F', 'p']), + ), + Rucksack( + HashSet::from([ + 'j', 'q', 'H', 'R', 'N', 'q', 'R', 'j', 'q', 'z', 'j', 'G', 'D', 'L', 'G', 'L', + ]), + HashSet::from([ + 'r', 's', 'F', 'M', 'f', 'F', 'Z', 'S', 'r', 'L', 'r', 'F', 'Z', 's', 'S', 'L', + ]), + ), + Rucksack( + HashSet::from(['P', 'm', 'm', 'd', 'z', 'q', 'P', 'r', 'V']), + HashSet::from(['v', 'P', 'w', 'w', 'T', 'W', 'B', 'w', 'g']), + ), + Rucksack( + HashSet::from([ + 'w', 'M', 'q', 'v', 'L', 'M', 'Z', 'H', 'h', 'H', 'M', 'v', 'w', 'L', 'H', + ]), + HashSet::from([ + 'j', 'b', 'v', 'c', 'j', 'n', 'n', 'S', 'B', 'n', 'v', 'T', 'Q', 'F', 'n', + ]), + ), + Rucksack( + HashSet::from(['t', 't', 'g', 'J', 't', 'R', 'G', 'J']), + HashSet::from(['Q', 'c', 't', 'T', 'Z', 't', 'Z', 'T']), + ), + Rucksack( + HashSet::from(['C', 'r', 'Z', 's', 'J', 's', 'P', 'P', 'Z', 's', 'G', 'z']), + HashSet::from(['w', 'w', 's', 'L', 'w', 'L', 'm', 'p', 'w', 'M', 'D', 'w']), + ), + ]; + assert_eq!(part2(&input), 70); + } +} diff --git a/2022/days/03/src/utilities.rs b/2022/days/03/src/utilities.rs new file mode 100644 index 0000000..e192d61 --- /dev/null +++ b/2022/days/03/src/utilities.rs @@ -0,0 +1,93 @@ +use std::collections::HashSet; +#[derive(Debug, PartialEq, Eq)] +pub struct Rucksack(pub HashSet, pub HashSet); + +pub fn parse(input: &str) -> Vec { + input + .lines() + .map(|line| { + let (first, second) = line.split_at(line.len() / 2); + Rucksack(first.chars().collect(), second.chars().collect()) + }) + .collect() +} + +pub fn find_char_score(input: &char) -> usize { + if input.is_uppercase() { + *input as usize - 38 + } else { + *input as usize - 96 + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_find_char_score() { + static CHARS: [char; 52] = [ + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', + 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', + 'Z', + ]; + + for character in CHARS { + println!("{}", character); + assert_eq!( + find_char_score(&character), + CHARS.iter().position(|c| *c == character).unwrap() + 1 + ) + } + } + + #[test] + fn test_parse() { + let input = "vJrwpWtwJgWrhcsFMMfFFhFp +jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL +PmmdzqPrVvPwwTWBwg +wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn +ttgJtRGJQctTZtZT +CrZsJsPPZsGzwwsLwLmpwMDw"; + assert_eq!( + parse(input), + vec![ + Rucksack( + HashSet::from(['v', 'J', 'r', 'w', 'p', 'W', 't', 'w', 'J', 'g', 'W', 'r']), + HashSet::from(['h', 'c', 's', 'F', 'M', 'M', 'f', 'F', 'F', 'h', 'F', 'p']) + ), + Rucksack( + HashSet::from([ + 'j', 'q', 'H', 'R', 'N', 'q', 'R', 'j', 'q', 'z', 'j', 'G', 'D', 'L', 'G', + 'L' + ]), + HashSet::from([ + 'r', 's', 'F', 'M', 'f', 'F', 'Z', 'S', 'r', 'L', 'r', 'F', 'Z', 's', 'S', + 'L' + ]) + ), + Rucksack( + HashSet::from(['P', 'm', 'm', 'd', 'z', 'q', 'P', 'r', 'V']), + HashSet::from(['v', 'P', 'w', 'w', 'T', 'W', 'B', 'w', 'g']) + ), + Rucksack( + HashSet::from([ + 'w', 'M', 'q', 'v', 'L', 'M', 'Z', 'H', 'h', 'H', 'M', 'v', 'w', 'L', 'H', + ]), + HashSet::from([ + 'j', 'b', 'v', 'c', 'j', 'n', 'n', 'S', 'B', 'n', 'v', 'T', 'Q', 'F', 'n', + ]) + ), + Rucksack( + HashSet::from(['t', 't', 'g', 'J', 't', 'R', 'G', 'J',]), + HashSet::from(['Q', 'c', 't', 'T', 'Z', 't', 'Z', 'T',]) + ), + Rucksack( + HashSet::from(['C', 'r', 'Z', 's', 'J', 's', 'P', 'P', 'Z', 's', 'G', 'z',]), + HashSet::from(['w', 'w', 's', 'L', 'w', 'L', 'm', 'p', 'w', 'M', 'D', 'w',]) + ), + ] + ); + } +} diff --git a/2022/days/04/Cargo.toml b/2022/days/04/Cargo.toml new file mode 100644 index 0000000..fe84f67 --- /dev/null +++ b/2022/days/04/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "day04" +authors.workspace = true +description.workspace = true +version.workspace = true +edition.workspace = true + +[dependencies] +once_cell.workspace = true +regex.workspace = true diff --git a/2022/days/04/src/input.txt b/2022/days/04/src/input.txt new file mode 100644 index 0000000..0f2f19d --- /dev/null +++ b/2022/days/04/src/input.txt @@ -0,0 +1,1000 @@ +23-33,24-65 +10-24,23-88 +71-92,18-71 +2-2,10-95 +24-26,25-66 +19-93,36-99 +12-99,5-13 +13-88,14-94 +4-85,5-84 +78-88,79-87 +13-82,13-83 +3-98,3-99 +27-69,28-89 +24-47,23-66 +43-48,29-49 +2-99,2-98 +3-77,21-65 +10-90,89-93 +64-75,63-75 +97-99,1-97 +48-65,49-64 +18-26,25-28 +85-86,26-85 +82-89,69-83 +21-93,93-98 +73-79,46-81 +33-52,32-51 +1-99,99-99 +11-36,34-40 +31-88,32-89 +9-19,18-35 +9-84,83-83 +34-82,4-83 +33-33,24-33 +34-83,83-90 +11-86,10-86 +48-48,3-50 +8-92,9-91 +16-38,15-37 +4-84,5-93 +70-75,41-79 +40-48,47-92 +37-41,52-89 +3-3,4-91 +27-77,27-77 +64-90,33-52 +28-40,9-64 +2-73,3-95 +17-94,7-75 +6-71,7-71 +11-69,10-70 +4-40,4-40 +9-54,30-44 +92-93,4-92 +62-63,63-67 +7-34,16-34 +54-55,31-54 +12-90,11-91 +11-13,12-53 +10-73,9-64 +13-18,13-84 +6-82,16-81 +52-78,18-53 +22-82,23-74 +90-91,3-90 +92-93,70-93 +18-44,19-45 +20-20,20-67 +31-93,76-93 +25-86,86-86 +6-73,5-94 +75-84,74-86 +50-51,50-51 +56-86,57-86 +18-81,13-18 +3-9,8-93 +31-36,34-34 +19-88,18-87 +10-95,54-79 +83-85,66-86 +32-68,31-49 +14-97,12-99 +42-42,42-53 +27-32,28-69 +96-98,15-96 +25-49,25-48 +71-81,15-92 +19-83,15-19 +14-99,6-14 +52-90,53-94 +5-98,85-96 +18-30,10-15 +4-86,4-98 +54-55,30-78 +85-99,62-86 +10-99,10-98 +4-96,5-95 +6-59,7-18 +6-86,1-7 +28-85,5-84 +3-82,2-82 +73-92,87-87 +2-3,2-89 +4-5,4-8 +21-96,69-97 +89-90,4-89 +28-79,29-80 +35-58,40-48 +96-96,3-97 +17-27,16-96 +7-99,8-94 +26-92,25-92 +17-24,17-25 +44-44,40-47 +57-64,57-65 +60-91,59-79 +23-79,22-71 +34-37,31-70 +22-60,22-59 +44-99,98-98 +9-57,49-55 +61-64,33-62 +15-68,4-15 +53-55,34-55 +13-13,9-15 +2-43,3-81 +17-56,16-99 +1-4,3-92 +76-77,73-83 +2-97,2-96 +44-45,44-55 +8-89,8-97 +23-73,22-88 +23-90,79-93 +23-87,86-91 +3-45,17-44 +7-99,8-98 +92-97,14-92 +85-89,59-90 +7-8,7-89 +5-90,49-89 +28-30,29-63 +38-61,38-60 +32-98,5-75 +22-87,71-76 +5-85,5-88 +16-96,18-88 +39-51,40-90 +21-21,19-23 +22-55,15-56 +1-75,35-59 +13-84,12-85 +11-83,23-27 +11-98,11-97 +35-92,34-92 +8-96,8-30 +48-72,33-60 +9-83,10-82 +97-97,10-98 +5-7,9-98 +1-44,3-43 +7-85,8-85 +12-32,12-52 +1-86,86-86 +3-63,4-63 +3-83,83-91 +74-88,38-74 +92-95,6-98 +11-19,10-20 +6-94,7-94 +39-90,38-42 +60-92,61-92 +43-94,44-98 +23-98,22-99 +31-41,27-32 +9-79,9-78 +63-64,11-64 +82-82,83-98 +78-79,77-78 +19-63,4-27 +26-62,27-44 +91-91,91-93 +16-94,31-93 +23-25,24-99 +78-79,11-78 +30-30,29-31 +34-85,35-84 +4-78,4-5 +42-84,43-85 +39-87,40-86 +49-84,50-84 +67-67,7-67 +38-38,62-67 +2-83,3-82 +14-33,32-68 +18-76,17-75 +68-77,68-76 +4-97,53-73 +53-97,54-96 +53-55,54-98 +35-95,75-83 +2-3,2-78 +3-97,15-96 +26-87,26-92 +4-10,9-48 +3-89,22-96 +10-85,10-84 +1-93,2-2 +24-37,37-62 +32-68,48-53 +33-96,95-97 +9-26,14-31 +16-66,13-14 +85-86,78-85 +65-82,64-81 +5-85,31-49 +47-88,59-91 +34-71,70-76 +14-14,14-14 +45-46,45-97 +63-73,63-64 +16-54,17-53 +87-88,51-87 +20-79,19-98 +3-96,2-95 +86-86,60-86 +82-82,67-82 +12-35,11-35 +15-31,26-52 +1-2,1-99 +3-96,2-2 +91-97,11-92 +41-89,42-96 +62-64,41-65 +54-54,16-55 +28-41,40-97 +15-89,89-90 +50-71,55-70 +30-66,30-93 +89-92,84-89 +25-27,26-84 +59-91,60-91 +4-11,4-98 +5-48,10-44 +53-80,77-79 +20-21,10-20 +14-86,14-85 +32-70,33-69 +94-94,26-95 +5-57,5-97 +38-50,38-92 +48-50,49-51 +13-98,12-98 +90-95,24-88 +90-94,67-91 +1-11,10-91 +48-59,59-91 +26-68,31-55 +15-56,21-57 +6-69,7-69 +6-8,5-95 +32-93,33-94 +13-73,14-42 +1-4,3-98 +30-62,29-62 +57-64,61-99 +12-27,11-46 +28-99,98-98 +7-83,8-92 +56-77,56-76 +30-89,31-51 +69-83,37-72 +11-78,11-65 +61-61,60-62 +38-65,65-66 +20-44,21-97 +39-76,40-75 +10-94,11-93 +33-90,89-96 +23-77,22-78 +63-86,62-73 +42-81,35-43 +34-91,34-55 +12-97,4-13 +1-98,1-97 +23-72,24-73 +14-99,13-99 +17-97,18-96 +65-85,14-66 +68-77,67-69 +8-96,9-9 +28-57,29-56 +14-26,14-26 +6-72,6-72 +49-49,1-48 +4-65,65-65 +53-92,54-91 +48-87,15-48 +51-54,20-72 +65-75,64-64 +4-92,3-93 +42-70,30-98 +15-71,14-15 +29-62,28-63 +6-92,6-93 +37-84,83-83 +1-99,23-98 +23-82,24-88 +2-60,61-74 +3-5,17-93 +50-63,51-62 +51-55,52-52 +30-82,5-83 +5-77,4-42 +44-99,3-99 +18-81,5-18 +2-32,32-32 +50-59,58-87 +23-30,24-40 +70-70,9-71 +40-62,49-62 +2-29,1-3 +48-69,48-49 +48-48,47-93 +5-42,17-41 +11-95,12-92 +9-66,8-65 +32-84,33-84 +16-69,15-99 +12-96,9-12 +69-91,68-70 +14-69,15-81 +96-99,50-96 +35-62,35-61 +6-22,22-60 +20-76,73-74 +4-21,4-22 +22-30,21-76 +5-90,1-6 +82-96,82-95 +18-31,19-71 +29-56,50-59 +11-21,1-61 +15-76,30-81 +1-1,2-83 +11-90,90-91 +40-90,40-41 +68-83,68-83 +25-81,25-81 +87-88,22-87 +31-65,32-64 +17-90,16-90 +11-65,11-12 +35-60,36-93 +5-93,4-94 +28-29,27-75 +12-38,37-45 +39-46,32-44 +12-89,12-97 +4-54,52-52 +5-94,94-94 +30-31,29-31 +18-82,74-76 +80-80,59-81 +3-65,54-54 +20-31,19-23 +82-87,32-82 +41-41,41-42 +6-6,6-81 +2-98,98-98 +84-94,6-95 +29-89,28-92 +27-30,28-34 +5-86,4-86 +32-96,50-96 +28-93,69-90 +75-75,27-82 +9-30,30-36 +76-76,61-77 +74-80,11-74 +48-61,48-60 +64-98,64-99 +83-87,5-88 +23-25,25-98 +55-55,39-55 +5-36,5-36 +45-57,46-85 +4-86,3-85 +19-58,20-58 +25-83,14-26 +27-74,27-27 +17-18,17-45 +81-88,62-84 +84-96,21-85 +3-81,1-2 +54-93,1-94 +1-1,3-66 +69-78,49-78 +47-93,47-93 +13-13,13-66 +18-78,18-73 +11-20,15-18 +52-99,51-99 +2-57,1-58 +9-97,10-97 +80-80,24-80 +33-77,34-47 +68-75,67-73 +20-95,19-95 +4-99,5-98 +8-85,7-85 +42-80,66-82 +22-47,31-47 +22-26,24-24 +4-98,38-44 +92-94,92-95 +82-92,71-94 +6-10,1-5 +3-92,1-92 +72-76,71-74 +6-69,7-69 +25-75,26-66 +15-51,15-63 +14-99,14-98 +7-89,6-70 +58-66,62-85 +7-11,15-23 +42-62,42-63 +1-4,4-91 +1-3,3-97 +49-79,48-80 +15-95,16-77 +6-99,5-99 +6-79,8-27 +47-69,46-68 +20-21,24-96 +13-71,60-92 +69-94,36-69 +66-86,33-67 +34-47,34-47 +4-4,4-93 +22-68,68-68 +42-90,43-90 +74-74,74-94 +3-72,3-62 +63-75,64-67 +16-48,7-48 +2-89,3-99 +2-98,3-97 +41-94,42-95 +45-93,44-98 +16-18,17-64 +69-70,47-69 +2-93,93-94 +65-94,66-95 +54-56,55-57 +5-92,2-92 +48-92,28-45 +67-68,48-67 +7-12,6-8 +7-8,6-8 +94-99,16-95 +13-49,14-48 +25-48,48-48 +6-51,7-18 +46-83,15-97 +34-57,34-58 +16-89,9-17 +41-74,41-42 +13-32,13-97 +90-99,99-99 +7-99,7-98 +78-79,63-78 +4-98,64-79 +49-75,50-80 +40-75,40-52 +14-72,6-14 +5-91,91-91 +27-55,27-27 +20-22,27-37 +35-71,34-96 +2-52,1-1 +3-87,2-87 +2-70,36-69 +38-90,39-89 +67-79,67-80 +5-77,77-78 +26-32,2-34 +10-43,43-85 +55-84,84-85 +24-59,24-58 +43-49,44-48 +60-81,59-80 +52-91,91-92 +44-62,42-63 +3-96,3-97 +29-45,30-45 +64-92,6-93 +89-96,4-90 +71-91,71-90 +50-64,60-63 +49-88,49-89 +18-98,18-90 +30-74,72-77 +32-88,4-76 +22-58,22-23 +5-71,5-18 +8-90,7-98 +4-78,4-79 +54-87,54-55 +3-91,3-92 +14-92,89-91 +41-95,42-42 +74-75,53-77 +12-90,3-12 +5-50,3-51 +27-67,66-68 +10-42,24-38 +20-79,20-81 +10-78,78-97 +26-47,35-46 +34-82,34-63 +2-94,3-98 +19-87,19-87 +4-42,6-90 +13-49,12-14 +75-75,3-76 +55-70,54-56 +86-92,85-93 +31-38,28-46 +7-90,6-91 +33-72,32-50 +22-46,45-99 +45-53,46-51 +90-91,6-90 +13-87,14-45 +41-95,14-42 +90-95,76-95 +51-70,15-89 +15-49,25-95 +15-15,15-98 +20-88,14-33 +2-67,67-70 +88-93,78-96 +77-91,53-84 +53-88,52-98 +24-96,25-25 +40-40,26-40 +3-15,9-25 +35-99,36-97 +61-61,4-62 +5-95,6-6 +52-56,52-95 +22-30,23-23 +40-44,43-63 +13-16,5-14 +18-90,89-89 +5-88,4-88 +78-83,82-82 +6-80,1-1 +15-31,14-32 +13-96,13-13 +68-76,68-69 +56-67,67-90 +24-92,92-93 +16-29,17-90 +2-99,1-90 +12-75,1-13 +21-91,20-90 +1-99,11-97 +94-94,25-95 +2-91,3-92 +95-95,2-95 +2-99,1-97 +28-98,27-29 +6-26,2-67 +20-58,19-71 +32-87,49-86 +13-57,14-56 +2-55,11-44 +13-61,12-61 +33-81,80-80 +39-91,41-44 +40-93,39-47 +83-95,40-93 +20-79,24-78 +52-93,6-94 +96-96,3-97 +44-55,36-87 +43-44,13-43 +19-99,19-98 +6-17,17-97 +91-99,88-91 +31-51,52-77 +1-97,1-2 +26-86,26-87 +50-53,40-81 +40-89,89-93 +78-83,1-79 +9-89,8-73 +6-38,7-21 +19-20,18-21 +97-97,35-97 +28-57,20-28 +3-86,86-87 +53-53,2-52 +59-99,60-99 +75-84,76-95 +20-93,21-94 +29-29,29-30 +34-92,15-58 +11-58,11-59 +11-11,10-98 +19-77,77-77 +38-56,38-71 +83-86,12-88 +8-73,5-6 +5-7,7-93 +18-79,19-72 +4-99,2-2 +5-82,5-81 +24-37,37-95 +11-63,9-12 +6-99,7-98 +92-92,91-91 +58-91,2-95 +23-98,24-59 +2-90,3-89 +54-71,1-81 +22-98,48-97 +14-49,13-76 +5-52,6-89 +6-88,76-86 +3-85,6-97 +87-94,86-88 +30-46,31-45 +63-95,9-97 +19-94,94-98 +71-75,72-74 +48-89,49-89 +27-52,52-54 +21-99,41-94 +5-96,3-5 +40-69,38-40 +74-99,73-98 +6-31,22-85 +13-76,12-75 +29-74,29-74 +10-86,11-86 +40-41,33-40 +63-94,29-94 +55-85,55-55 +14-20,18-19 +52-78,1-79 +92-96,7-92 +12-89,14-57 +32-49,49-82 +36-63,43-62 +20-94,41-93 +79-95,7-97 +5-60,5-22 +29-93,28-93 +18-68,18-67 +12-37,13-36 +12-64,12-46 +1-99,2-2 +61-92,61-82 +14-16,15-68 +68-83,67-77 +24-93,93-93 +33-99,32-33 +93-93,11-94 +27-37,26-37 +7-31,6-31 +1-45,2-67 +5-99,5-99 +20-21,18-22 +22-89,23-88 +53-58,53-56 +48-91,48-86 +11-11,10-12 +33-50,50-81 +11-47,7-20 +51-71,71-72 +15-89,15-88 +6-90,2-15 +7-88,18-91 +4-98,4-98 +9-19,3-19 +29-58,57-83 +16-34,15-33 +13-50,12-89 +17-60,17-17 +90-94,91-98 +52-77,52-76 +97-99,5-97 +42-86,53-76 +4-7,19-56 +23-63,2-41 +15-43,43-44 +19-23,22-97 +47-48,45-49 +31-73,32-73 +57-72,21-38 +54-97,53-96 +2-29,3-64 +53-79,13-77 +63-77,4-63 +94-94,4-95 +5-44,4-98 +5-99,4-98 +31-96,32-96 +44-89,43-90 +1-63,2-63 +31-60,8-32 +48-88,55-62 +36-85,35-85 +7-98,97-97 +3-52,4-99 +19-57,1-20 +65-96,66-97 +61-95,43-62 +4-94,93-93 +14-97,58-96 +26-46,6-47 +79-96,81-95 +30-88,30-87 +27-97,26-96 +24-88,24-25 +27-95,28-51 +22-24,23-76 +40-44,44-52 +4-37,3-38 +6-7,4-8 +22-24,16-25 +59-73,58-73 +2-14,3-40 +20-65,65-65 +58-87,58-86 +99-99,26-98 +10-17,16-91 +52-71,59-70 +3-87,2-87 +22-95,95-96 +55-55,10-54 +52-84,82-96 +5-82,81-81 +9-95,7-7 +53-88,88-90 +5-6,5-63 +11-68,10-85 +8-12,10-11 +40-92,43-49 +19-35,20-34 +44-46,45-85 +10-25,12-26 +63-85,54-80 +10-97,91-94 +41-50,40-42 +7-72,8-71 +1-15,12-92 +22-93,54-99 +82-94,30-83 +7-89,6-89 +6-69,5-7 +8-25,24-24 +8-47,8-47 +21-25,24-92 +81-81,81-86 +6-15,44-68 +82-82,34-82 +29-86,2-87 +37-54,20-57 +56-97,1-96 +65-65,6-65 +4-81,5-82 +78-85,37-78 +18-99,19-97 +31-97,34-96 +41-58,40-77 +11-96,10-97 +18-35,7-24 +5-75,3-74 +2-53,15-47 +9-17,9-85 +20-26,21-26 +23-70,67-68 +23-72,23-73 +36-81,9-93 +25-76,25-26 +77-77,46-77 +78-98,78-87 +91-91,14-92 +22-92,21-93 +3-3,3-87 +99-99,61-99 +18-28,19-29 +44-45,19-44 +17-60,11-17 +35-97,36-36 +58-58,11-58 +24-62,23-63 +18-56,55-81 +7-31,8-30 +60-61,1-65 +8-99,7-31 +2-4,5-6 +4-93,48-92 +2-87,1-98 +3-75,3-4 +1-53,53-54 +57-73,57-68 +11-60,2-61 +51-70,43-52 +4-33,3-34 +29-68,67-68 +75-86,28-71 +4-84,3-83 +12-96,51-96 +30-98,71-94 +54-62,60-62 +13-66,14-86 +14-42,12-43 +47-69,48-69 +58-89,86-96 +27-96,27-95 +6-66,6-16 +2-30,1-37 +27-91,27-38 +46-52,45-49 +9-64,8-75 +53-92,54-93 +35-91,35-72 +66-91,91-97 +46-81,49-81 +3-90,1-3 +53-54,52-56 +4-92,3-5 +42-84,42-77 +1-3,2-95 +8-73,9-90 +17-69,16-70 +9-20,2-10 +97-99,96-97 +1-86,2-91 +17-66,9-95 +9-10,9-97 +19-40,39-54 +5-94,5-91 +33-33,18-34 +2-3,2-3 +22-66,21-84 +37-90,37-81 +6-93,6-93 +64-81,65-78 +57-59,57-67 +69-94,68-68 +39-97,38-98 +74-79,71-79 +2-80,41-80 +5-91,28-89 +1-97,2-97 +24-61,25-94 +76-81,76-97 +48-56,48-49 +25-81,7-12 +42-99,41-41 +45-60,46-59 +19-85,57-84 +8-8,7-98 +14-53,13-54 +17-82,69-84 +73-86,24-90 +78-80,6-78 +2-76,3-26 +1-33,33-89 +12-48,48-75 +25-87,21-88 +22-68,22-71 +2-91,1-91 +59-79,7-60 +6-70,4-4 +47-94,27-94 +23-50,10-49 +2-85,2-83 +2-96,7-96 +21-93,22-92 +27-67,28-67 +32-38,32-33 +15-94,93-94 +36-74,36-37 +33-84,43-83 +5-98,2-2 +1-93,2-92 +37-97,42-70 +81-82,21-81 +14-94,13-15 +5-45,4-87 +44-96,45-95 +2-7,6-14 +14-73,25-77 +83-83,84-99 +13-62,21-73 +91-98,22-91 +19-96,86-93 +5-78,6-77 +3-97,4-98 +8-54,17-83 +9-94,10-10 +36-96,35-37 +8-93,7-98 +48-60,48-61 +17-97,9-18 +73-87,74-88 +19-63,19-63 +21-73,20-74 +1-89,26-89 +44-50,48-55 +43-70,70-71 +5-14,6-63 +23-82,22-94 +20-67,18-94 +36-52,47-51 +10-84,9-83 +18-96,18-71 +3-64,4-65 +4-7,6-89 +62-89,73-99 +4-92,3-5 +3-62,45-59 +9-98,10-97 +12-80,12-89 +14-15,18-85 +7-18,6-23 +14-70,15-24 +24-52,21-78 +63-92,32-93 +47-91,42-48 +16-91,91-95 +31-66,30-65 +52-91,5-91 +85-85,11-86 +22-69,68-68 +11-58,10-21 +47-76,42-47 +63-64,43-66 +17-29,4-66 +19-19,18-86 +33-70,33-70 +33-38,32-38 +3-5,4-99 +14-55,13-55 +4-48,4-4 +80-96,79-98 +99-99,5-29 +48-72,49-72 +5-91,3-92 +10-25,10-26 +9-11,10-28 +29-39,28-38 +19-55,55-56 +1-14,1-2 +21-81,21-81 +32-89,38-86 +31-79,31-39 +66-72,67-73 +3-3,2-29 +9-67,10-10 +24-96,23-25 +90-94,90-93 +91-91,7-92 +45-98,44-93 +1-76,3-75 +14-59,22-60 +12-70,4-21 +30-93,25-98 +18-30,9-19 +1-4,3-90 +9-95,9-22 +92-96,59-92 +26-67,22-25 +7-9,8-30 +74-82,82-83 +92-92,4-93 +14-76,2-63 +52-86,51-82 +11-98,10-12 +2-97,96-96 +18-91,18-99 +15-36,17-92 +14-90,13-91 +14-88,87-99 +47-92,48-92 +3-97,10-93 +9-87,80-98 +4-96,3-5 +89-99,3-89 +11-65,10-66 +4-52,52-93 +29-31,12-28 diff --git a/2022/days/04/src/main.rs b/2022/days/04/src/main.rs new file mode 100644 index 0000000..e4fc4b6 --- /dev/null +++ b/2022/days/04/src/main.rs @@ -0,0 +1,14 @@ +mod part1; +mod part2; +mod utilities; + +fn main() { + let _input = include_str!("./input.txt"); + let _structured_input = utilities::parse(_input); + + println!("Part One"); + println!("Result: {}", part1::part1(&_structured_input)); + + println!("Part Two"); + println!("Result: {}", part2::part2(&_structured_input)); +} diff --git a/2022/days/04/src/part1.rs b/2022/days/04/src/part1.rs new file mode 100644 index 0000000..c0a0c79 --- /dev/null +++ b/2022/days/04/src/part1.rs @@ -0,0 +1,27 @@ +use crate::utilities::*; + +pub fn part1(input: &[(Range, Range)]) -> usize { + input + .iter() + .filter(|tuple| tuple.0.complete_overlap(&tuple.1)) + .count() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part1() { + let input = vec![ + (Range::new(2, 4), Range::new(6, 8)), + (Range::new(2, 3), Range::new(4, 5)), + (Range::new(5, 7), Range::new(7, 9)), + (Range::new(2, 8), Range::new(3, 7)), + (Range::new(6, 6), Range::new(4, 6)), + (Range::new(2, 6), Range::new(4, 8)), + (Range::new(19, 30), Range::new(5, 18)), + ]; + assert_eq!(part1(&input), 2); + } +} diff --git a/2022/days/04/src/part2.rs b/2022/days/04/src/part2.rs new file mode 100644 index 0000000..e11c29a --- /dev/null +++ b/2022/days/04/src/part2.rs @@ -0,0 +1,27 @@ +use crate::utilities::*; + +pub fn part2(input: &[(Range, Range)]) -> usize { + input + .iter() + .filter(|tuple| tuple.0.any_overlap(&tuple.1)) + .count() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part2() { + let input = vec![ + (Range::new(2, 4), Range::new(6, 8)), + (Range::new(2, 3), Range::new(4, 5)), + (Range::new(5, 7), Range::new(7, 9)), + (Range::new(2, 8), Range::new(3, 7)), + (Range::new(6, 6), Range::new(4, 6)), + (Range::new(2, 6), Range::new(4, 8)), + (Range::new(19, 30), Range::new(5, 18)), + ]; + assert_eq!(part2(&input), 4); + } +} diff --git a/2022/days/04/src/utilities.rs b/2022/days/04/src/utilities.rs new file mode 100644 index 0000000..b5fda5a --- /dev/null +++ b/2022/days/04/src/utilities.rs @@ -0,0 +1,79 @@ +use once_cell::sync::Lazy; +use regex::Regex; +#[derive(Debug, PartialEq, Eq)] +pub struct Range { + start: u16, + end: u16, +} + +impl Range { + pub fn new(start: u16, end: u16) -> Self { + Self { + start: start.min(end), + end: end.max(start), + } + } + + pub fn any_overlap(&self, other: &Self) -> bool { + self.start <= other.end && self.end >= other.start + } + + pub fn calc_overlap(&self, other: &Self) -> Range { + let overlap_start = self.start.min(other.start); + let overlap_end = self.end.max(other.end); + Range::new(overlap_start, overlap_end) + } + + pub fn complete_overlap(&self, other: &Self) -> bool { + self.calc_overlap(other) == *self || self.calc_overlap(other) == *other + } +} + +static PARSE_REGEX: Lazy = Lazy::new(|| Regex::new(r"^(\d+)-(\d+),(\d+)-(\d+)").unwrap()); + +pub fn parse(input: &str) -> Vec<(Range, Range)> { + input + .lines() + .map(|line| { + let cap = PARSE_REGEX.captures(line).unwrap(); + ( + Range::new( + cap.get(1).unwrap().as_str().parse().unwrap(), + cap.get(2).unwrap().as_str().parse().unwrap(), + ), + Range::new( + cap.get(3).unwrap().as_str().parse().unwrap(), + cap.get(4).unwrap().as_str().parse().unwrap(), + ), + ) + }) + .collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse() { + let input = "2-4,6-8 +2-3,4-5 +5-7,7-9 +2-8,3-7 +6-6,4-6 +2-6,4-8 +19-30,5-18"; + assert_eq!( + parse(input), + vec![ + (Range::new(2, 4), Range::new(6, 8)), + (Range::new(2, 3), Range::new(4, 5)), + (Range::new(5, 7), Range::new(7, 9)), + (Range::new(2, 8), Range::new(3, 7)), + (Range::new(6, 6), Range::new(4, 6)), + (Range::new(2, 6), Range::new(4, 8)), + (Range::new(19, 30), Range::new(5, 18)), + ] + ); + } +} diff --git a/2022/days/05/Cargo.toml b/2022/days/05/Cargo.toml new file mode 100644 index 0000000..5b0385e --- /dev/null +++ b/2022/days/05/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "day05" +authors.workspace = true +description.workspace = true +version.workspace = true +edition.workspace = true + +[dependencies] +once_cell.workspace = true +regex.workspace = true diff --git a/2022/days/05/src/input.txt b/2022/days/05/src/input.txt new file mode 100644 index 0000000..f3e1ad7 --- /dev/null +++ b/2022/days/05/src/input.txt @@ -0,0 +1,514 @@ + [S] [C] [Z] +[F] [J] [P] [T] [N] +[G] [H] [G] [Q] [G] [D] +[V] [V] [D] [G] [F] [D] [V] +[R] [B] [F] [N] [N] [Q] [L] [S] +[J] [M] [M] [P] [H] [V] [B] [B] [D] +[L] [P] [H] [D] [L] [F] [D] [J] [L] +[D] [T] [V] [M] [J] [N] [F] [M] [G] + 1 2 3 4 5 6 7 8 9 + +move 3 from 4 to 6 +move 1 from 5 to 8 +move 3 from 7 to 3 +move 4 from 5 to 7 +move 1 from 7 to 8 +move 3 from 9 to 4 +move 2 from 8 to 2 +move 4 from 4 to 5 +move 2 from 5 to 1 +move 2 from 5 to 6 +move 7 from 8 to 1 +move 9 from 3 to 9 +move 11 from 6 to 5 +move 2 from 6 to 7 +move 12 from 1 to 4 +move 10 from 2 to 9 +move 2 from 3 to 9 +move 1 from 7 to 5 +move 4 from 7 to 6 +move 2 from 6 to 1 +move 5 from 1 to 6 +move 10 from 9 to 1 +move 9 from 9 to 8 +move 13 from 4 to 3 +move 7 from 6 to 2 +move 2 from 8 to 5 +move 9 from 3 to 9 +move 8 from 9 to 8 +move 4 from 8 to 4 +move 1 from 7 to 5 +move 3 from 9 to 1 +move 7 from 2 to 1 +move 1 from 3 to 1 +move 1 from 3 to 6 +move 1 from 6 to 1 +move 2 from 3 to 6 +move 5 from 4 to 1 +move 1 from 6 to 1 +move 3 from 8 to 7 +move 8 from 8 to 4 +move 3 from 5 to 4 +move 1 from 6 to 7 +move 1 from 5 to 8 +move 4 from 5 to 2 +move 7 from 5 to 8 +move 3 from 2 to 7 +move 7 from 4 to 8 +move 11 from 8 to 4 +move 15 from 4 to 1 +move 25 from 1 to 6 +move 4 from 8 to 7 +move 1 from 2 to 4 +move 11 from 6 to 4 +move 12 from 6 to 3 +move 1 from 1 to 9 +move 1 from 9 to 8 +move 16 from 1 to 3 +move 1 from 8 to 7 +move 12 from 4 to 6 +move 9 from 6 to 5 +move 3 from 6 to 5 +move 6 from 7 to 5 +move 3 from 3 to 5 +move 2 from 6 to 3 +move 11 from 5 to 8 +move 2 from 8 to 3 +move 2 from 1 to 4 +move 7 from 3 to 1 +move 2 from 4 to 6 +move 2 from 6 to 2 +move 5 from 7 to 3 +move 1 from 1 to 6 +move 1 from 1 to 8 +move 2 from 2 to 5 +move 1 from 7 to 4 +move 1 from 1 to 2 +move 10 from 3 to 5 +move 11 from 3 to 6 +move 1 from 4 to 9 +move 1 from 9 to 4 +move 1 from 4 to 2 +move 2 from 5 to 9 +move 2 from 2 to 8 +move 2 from 1 to 6 +move 2 from 1 to 2 +move 2 from 3 to 6 +move 3 from 8 to 1 +move 3 from 1 to 4 +move 7 from 8 to 3 +move 2 from 9 to 5 +move 2 from 4 to 9 +move 7 from 5 to 6 +move 2 from 8 to 6 +move 1 from 4 to 8 +move 2 from 2 to 4 +move 21 from 6 to 3 +move 10 from 5 to 7 +move 7 from 7 to 6 +move 1 from 9 to 3 +move 1 from 4 to 9 +move 1 from 9 to 4 +move 1 from 8 to 4 +move 8 from 6 to 4 +move 1 from 4 to 5 +move 1 from 5 to 8 +move 4 from 3 to 6 +move 1 from 8 to 2 +move 1 from 4 to 2 +move 2 from 7 to 3 +move 2 from 2 to 7 +move 22 from 3 to 5 +move 4 from 6 to 2 +move 2 from 6 to 9 +move 7 from 3 to 9 +move 6 from 9 to 1 +move 18 from 5 to 3 +move 2 from 5 to 4 +move 20 from 3 to 5 +move 3 from 7 to 3 +move 5 from 1 to 2 +move 11 from 5 to 7 +move 1 from 1 to 7 +move 3 from 9 to 3 +move 16 from 5 to 8 +move 7 from 8 to 7 +move 1 from 9 to 2 +move 8 from 2 to 3 +move 2 from 2 to 4 +move 3 from 3 to 1 +move 9 from 3 to 8 +move 1 from 6 to 3 +move 9 from 7 to 3 +move 3 from 1 to 8 +move 1 from 7 to 9 +move 1 from 9 to 4 +move 1 from 7 to 5 +move 10 from 4 to 5 +move 2 from 4 to 2 +move 19 from 8 to 5 +move 1 from 8 to 3 +move 4 from 3 to 5 +move 2 from 4 to 8 +move 4 from 7 to 8 +move 4 from 3 to 9 +move 4 from 7 to 6 +move 2 from 2 to 5 +move 2 from 3 to 2 +move 6 from 8 to 7 +move 1 from 8 to 4 +move 2 from 6 to 4 +move 3 from 4 to 8 +move 3 from 9 to 2 +move 4 from 7 to 8 +move 28 from 5 to 8 +move 16 from 8 to 4 +move 11 from 8 to 4 +move 3 from 3 to 4 +move 7 from 5 to 8 +move 13 from 8 to 7 +move 1 from 5 to 6 +move 1 from 6 to 7 +move 1 from 9 to 2 +move 2 from 6 to 2 +move 12 from 4 to 9 +move 4 from 4 to 1 +move 2 from 9 to 8 +move 4 from 8 to 3 +move 3 from 4 to 5 +move 4 from 4 to 1 +move 4 from 4 to 7 +move 3 from 7 to 9 +move 5 from 9 to 7 +move 7 from 2 to 3 +move 1 from 5 to 7 +move 8 from 1 to 5 +move 1 from 2 to 4 +move 11 from 3 to 1 +move 10 from 5 to 3 +move 3 from 9 to 1 +move 3 from 9 to 6 +move 5 from 1 to 6 +move 7 from 6 to 9 +move 8 from 9 to 7 +move 9 from 3 to 4 +move 1 from 6 to 9 +move 8 from 7 to 1 +move 9 from 4 to 2 +move 2 from 1 to 6 +move 3 from 2 to 6 +move 4 from 4 to 6 +move 2 from 9 to 8 +move 2 from 1 to 2 +move 1 from 3 to 8 +move 2 from 8 to 4 +move 1 from 6 to 8 +move 11 from 1 to 6 +move 1 from 1 to 5 +move 3 from 2 to 9 +move 2 from 9 to 3 +move 1 from 1 to 7 +move 2 from 4 to 9 +move 4 from 2 to 9 +move 2 from 8 to 5 +move 10 from 6 to 1 +move 2 from 5 to 6 +move 5 from 9 to 8 +move 5 from 8 to 7 +move 1 from 2 to 1 +move 7 from 1 to 2 +move 2 from 9 to 4 +move 1 from 3 to 5 +move 15 from 7 to 2 +move 8 from 6 to 3 +move 2 from 4 to 3 +move 2 from 6 to 4 +move 4 from 7 to 1 +move 4 from 7 to 5 +move 1 from 6 to 4 +move 3 from 1 to 7 +move 5 from 7 to 6 +move 4 from 7 to 5 +move 18 from 2 to 4 +move 5 from 6 to 4 +move 4 from 1 to 2 +move 8 from 3 to 8 +move 2 from 8 to 4 +move 2 from 3 to 7 +move 1 from 5 to 7 +move 3 from 8 to 4 +move 2 from 7 to 2 +move 1 from 3 to 8 +move 9 from 2 to 6 +move 2 from 8 to 6 +move 1 from 7 to 3 +move 1 from 3 to 5 +move 3 from 6 to 8 +move 1 from 8 to 5 +move 1 from 5 to 9 +move 1 from 1 to 2 +move 5 from 4 to 6 +move 10 from 6 to 2 +move 5 from 2 to 6 +move 5 from 6 to 4 +move 1 from 6 to 3 +move 6 from 4 to 6 +move 3 from 2 to 6 +move 2 from 2 to 3 +move 11 from 4 to 6 +move 1 from 9 to 5 +move 4 from 6 to 7 +move 1 from 4 to 3 +move 12 from 4 to 3 +move 1 from 8 to 6 +move 9 from 5 to 7 +move 1 from 5 to 2 +move 1 from 8 to 5 +move 1 from 4 to 9 +move 9 from 7 to 9 +move 1 from 3 to 4 +move 2 from 3 to 6 +move 2 from 5 to 6 +move 2 from 8 to 5 +move 11 from 3 to 4 +move 2 from 3 to 1 +move 1 from 2 to 3 +move 1 from 3 to 8 +move 3 from 7 to 9 +move 5 from 4 to 2 +move 2 from 5 to 8 +move 6 from 4 to 2 +move 1 from 1 to 3 +move 12 from 9 to 1 +move 6 from 1 to 6 +move 1 from 8 to 4 +move 1 from 8 to 3 +move 5 from 2 to 7 +move 2 from 3 to 9 +move 5 from 7 to 1 +move 1 from 7 to 5 +move 2 from 9 to 1 +move 14 from 1 to 7 +move 2 from 4 to 7 +move 7 from 2 to 4 +move 1 from 2 to 1 +move 1 from 1 to 3 +move 1 from 5 to 4 +move 1 from 9 to 6 +move 16 from 6 to 5 +move 2 from 5 to 4 +move 12 from 6 to 8 +move 10 from 4 to 8 +move 9 from 7 to 3 +move 4 from 7 to 6 +move 11 from 5 to 8 +move 2 from 5 to 2 +move 14 from 8 to 9 +move 1 from 5 to 1 +move 3 from 9 to 4 +move 2 from 2 to 1 +move 7 from 8 to 3 +move 6 from 3 to 5 +move 8 from 9 to 8 +move 1 from 6 to 1 +move 1 from 4 to 2 +move 4 from 3 to 8 +move 1 from 7 to 2 +move 3 from 1 to 5 +move 2 from 5 to 7 +move 3 from 9 to 2 +move 1 from 1 to 8 +move 5 from 5 to 4 +move 2 from 7 to 8 +move 4 from 2 to 5 +move 1 from 2 to 4 +move 2 from 7 to 8 +move 4 from 6 to 2 +move 6 from 5 to 3 +move 1 from 6 to 5 +move 1 from 5 to 3 +move 1 from 3 to 8 +move 8 from 8 to 3 +move 9 from 8 to 5 +move 9 from 8 to 2 +move 2 from 8 to 9 +move 2 from 3 to 8 +move 5 from 5 to 8 +move 1 from 3 to 7 +move 2 from 9 to 5 +move 7 from 2 to 4 +move 14 from 4 to 6 +move 2 from 2 to 7 +move 1 from 7 to 3 +move 1 from 7 to 9 +move 3 from 5 to 2 +move 1 from 7 to 1 +move 3 from 2 to 4 +move 7 from 8 to 2 +move 3 from 6 to 1 +move 17 from 3 to 1 +move 2 from 8 to 3 +move 6 from 2 to 7 +move 2 from 7 to 9 +move 3 from 6 to 8 +move 2 from 8 to 6 +move 4 from 2 to 1 +move 3 from 4 to 7 +move 1 from 8 to 7 +move 1 from 8 to 9 +move 1 from 4 to 2 +move 3 from 5 to 7 +move 2 from 3 to 1 +move 2 from 3 to 5 +move 5 from 7 to 4 +move 5 from 7 to 3 +move 1 from 4 to 8 +move 3 from 3 to 1 +move 6 from 1 to 3 +move 1 from 7 to 5 +move 2 from 9 to 2 +move 3 from 5 to 8 +move 1 from 8 to 1 +move 8 from 3 to 5 +move 1 from 4 to 9 +move 3 from 6 to 5 +move 3 from 6 to 3 +move 2 from 3 to 7 +move 1 from 4 to 7 +move 3 from 6 to 4 +move 2 from 7 to 2 +move 1 from 7 to 8 +move 2 from 5 to 4 +move 1 from 6 to 1 +move 7 from 4 to 7 +move 7 from 5 to 2 +move 10 from 2 to 3 +move 3 from 2 to 6 +move 3 from 8 to 1 +move 1 from 8 to 7 +move 2 from 6 to 3 +move 1 from 6 to 9 +move 4 from 7 to 5 +move 16 from 1 to 5 +move 1 from 9 to 7 +move 3 from 7 to 6 +move 11 from 5 to 6 +move 2 from 7 to 9 +move 12 from 6 to 4 +move 2 from 6 to 9 +move 6 from 3 to 2 +move 1 from 5 to 7 +move 5 from 9 to 5 +move 1 from 9 to 6 +move 4 from 3 to 7 +move 1 from 4 to 2 +move 7 from 2 to 5 +move 3 from 5 to 2 +move 6 from 5 to 6 +move 3 from 2 to 6 +move 9 from 6 to 8 +move 5 from 5 to 9 +move 5 from 7 to 1 +move 4 from 1 to 9 +move 2 from 9 to 4 +move 1 from 6 to 7 +move 9 from 4 to 1 +move 7 from 5 to 9 +move 18 from 1 to 3 +move 9 from 9 to 5 +move 8 from 8 to 2 +move 1 from 2 to 5 +move 4 from 2 to 3 +move 4 from 9 to 6 +move 1 from 4 to 8 +move 2 from 5 to 7 +move 2 from 9 to 2 +move 10 from 3 to 9 +move 5 from 5 to 9 +move 1 from 7 to 2 +move 2 from 8 to 7 +move 2 from 3 to 5 +move 2 from 9 to 1 +move 2 from 7 to 3 +move 1 from 2 to 1 +move 5 from 5 to 8 +move 1 from 2 to 1 +move 15 from 3 to 6 +move 1 from 7 to 6 +move 10 from 6 to 5 +move 1 from 7 to 8 +move 4 from 1 to 6 +move 1 from 8 to 3 +move 2 from 1 to 5 +move 3 from 8 to 1 +move 1 from 4 to 6 +move 1 from 4 to 2 +move 4 from 9 to 7 +move 6 from 5 to 7 +move 3 from 1 to 9 +move 10 from 6 to 8 +move 2 from 1 to 3 +move 8 from 7 to 9 +move 1 from 9 to 6 +move 2 from 7 to 9 +move 3 from 3 to 5 +move 1 from 2 to 6 +move 2 from 6 to 5 +move 5 from 9 to 4 +move 4 from 8 to 2 +move 1 from 1 to 3 +move 4 from 5 to 9 +move 3 from 6 to 1 +move 2 from 1 to 5 +move 3 from 5 to 2 +move 8 from 8 to 3 +move 11 from 9 to 4 +move 13 from 4 to 8 +move 2 from 9 to 2 +move 2 from 3 to 1 +move 1 from 4 to 1 +move 1 from 3 to 8 +move 2 from 6 to 9 +move 7 from 8 to 1 +move 3 from 2 to 5 +move 7 from 2 to 5 +move 3 from 4 to 6 +move 4 from 9 to 2 +move 2 from 3 to 5 +move 9 from 5 to 6 +move 5 from 2 to 7 +move 2 from 9 to 2 +move 2 from 9 to 7 +move 12 from 6 to 8 +move 5 from 5 to 7 +move 1 from 9 to 8 +move 3 from 1 to 6 +move 5 from 5 to 8 +move 6 from 1 to 9 +move 2 from 1 to 5 +move 1 from 6 to 9 +move 5 from 9 to 7 +move 2 from 5 to 8 +move 11 from 7 to 6 +move 20 from 8 to 1 +move 2 from 9 to 8 +move 4 from 7 to 6 +move 6 from 8 to 3 +move 13 from 6 to 9 +move 4 from 3 to 2 +move 4 from 6 to 3 +move 2 from 3 to 6 +move 5 from 9 to 8 +move 2 from 7 to 1 +move 2 from 6 to 9 +move 6 from 8 to 3 +move 6 from 3 to 6 +move 5 from 2 to 9 +move 22 from 1 to 3 +move 3 from 2 to 1 +move 5 from 9 to 3 +move 1 from 1 to 6 +move 3 from 6 to 2 +move 1 from 2 to 4 +move 33 from 3 to 5 +move 1 from 8 to 7 diff --git a/2022/days/05/src/main.rs b/2022/days/05/src/main.rs new file mode 100644 index 0000000..27ac4d5 --- /dev/null +++ b/2022/days/05/src/main.rs @@ -0,0 +1,14 @@ +mod part1; +mod part2; +mod utilities; + +fn main() { + let _input = include_str!("./input.txt"); + let _structured_input = utilities::parse(_input); + + println!("Part One"); + println!("Result: {:?}", part1::part1(&_structured_input)); + + println!("Part Two"); + println!("Result: {:?}", part2::part2(&_structured_input)); +} diff --git a/2022/days/05/src/part1.rs b/2022/days/05/src/part1.rs new file mode 100644 index 0000000..613a679 --- /dev/null +++ b/2022/days/05/src/part1.rs @@ -0,0 +1,48 @@ +use crate::utilities::*; + +pub fn part1(input: &(WorkArea, Vec)) -> Vec { + let (mut work_area, moves) = input.to_owned(); + for r#move in moves { + work_area.apply_move_cratemover9000(&r#move) + } + work_area + .get_stacks() + .iter() + .map(|stack| stack.last().unwrap().to_owned()) + .collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part1() { + let input = ( + WorkArea::new(vec![vec!['Z', 'N'], vec!['M', 'C', 'D'], vec!['P']]), + vec![ + Move { + to: 1, + from: 2, + number: 1, + }, + Move { + to: 3, + from: 1, + number: 3, + }, + Move { + to: 1, + from: 2, + number: 2, + }, + Move { + to: 2, + from: 1, + number: 1, + }, + ], + ); + assert_eq!(part1(&input), vec!['C', 'M', 'Z']); + } +} diff --git a/2022/days/05/src/part2.rs b/2022/days/05/src/part2.rs new file mode 100644 index 0000000..523fe2c --- /dev/null +++ b/2022/days/05/src/part2.rs @@ -0,0 +1,48 @@ +use crate::utilities::*; + +pub fn part2(input: &(WorkArea, Vec)) -> Vec { + let (mut work_area, moves) = input.to_owned(); + for r#move in moves { + work_area.apply_move_cratemover9001(&r#move) + } + work_area + .get_stacks() + .iter() + .map(|stack| stack.last().unwrap().to_owned()) + .collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part2() { + let input = ( + WorkArea::new(vec![vec!['Z', 'N'], vec!['M', 'C', 'D'], vec!['P']]), + vec![ + Move { + to: 1, + from: 2, + number: 1, + }, + Move { + to: 3, + from: 1, + number: 3, + }, + Move { + to: 1, + from: 2, + number: 2, + }, + Move { + to: 2, + from: 1, + number: 1, + }, + ], + ); + assert_eq!(part2(&input), vec!['M', 'C', 'D']); + } +} diff --git a/2022/days/05/src/utilities.rs b/2022/days/05/src/utilities.rs new file mode 100644 index 0000000..30206df --- /dev/null +++ b/2022/days/05/src/utilities.rs @@ -0,0 +1,144 @@ +use once_cell::sync::Lazy; +use regex::Regex; +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct Move { + pub to: usize, + pub from: usize, + pub number: u8, +} + +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct WorkArea { + stacks: Vec>, +} + +impl WorkArea { + pub fn new(stacks: Vec>) -> Self { + Self { stacks } + } + pub fn apply_move_cratemover9000(&mut self, action: &Move) { + for _ in 0..action.number { + let cargo = self.stacks.get_mut(action.from - 1).unwrap().pop().unwrap(); + self.stacks.get_mut(action.to - 1).unwrap().push(cargo); + } + } + pub fn apply_move_cratemover9001(&mut self, action: &Move) { + let mut crane_holder: Vec = Vec::new(); + for _ in 0..action.number { + let cargo = self.stacks.get_mut(action.from - 1).unwrap().pop().unwrap(); + crane_holder.push(cargo); + } + for cargo in crane_holder.iter().rev() { + self.stacks.get_mut(action.to - 1).unwrap().push(*cargo); + } + } + pub fn get_stacks(&self) -> &Vec> { + &self.stacks + } +} + +pub fn parse(input: &str) -> (WorkArea, Vec) { + let mut input = input.split("\n\n"); + let work_area = parse_work_area(input.next().unwrap()); + let moves = parse_moves(input.next().unwrap()); + (work_area, moves) +} + +pub fn parse_work_area(input: &str) -> WorkArea { + //decode those bottom index numbers + let index_row = input.lines().rev().next().unwrap(); + //some ascii math and array math to get the second to last char and convert it into a number. + let index_max: usize = (index_row.as_bytes()[index_row.len() - 2] - b'0') as usize; + //initalize the work area: + let mut work_area: Vec> = Vec::new(); + for _ in 0..index_max { + work_area.push(Vec::new()) + } + + //now parse the rest + for line in input.lines().rev() { + for (y, cargo_crate) in line.as_bytes().chunks(4).enumerate() { + let cargo = cargo_crate[1] as char; + //easiest way to filter out that last line is just to filter out digits. + if cargo != ' ' && !cargo.is_ascii_digit() { + work_area.get_mut(y).unwrap().push(cargo) + } + } + } + + WorkArea::new(work_area) +} + +pub fn parse_moves(input: &str) -> Vec { + static PARSE_MOVES_REGEX: Lazy = + Lazy::new(|| Regex::new(r"^move (\d+) from (\d+) to (\d+)$").unwrap()); + input + .lines() + .map(|line| { + let cap = PARSE_MOVES_REGEX.captures(line).unwrap(); + Move { + to: cap.get(3).unwrap().as_str().parse().unwrap(), + from: cap.get(2).unwrap().as_str().parse().unwrap(), + number: cap.get(1).unwrap().as_str().parse().unwrap(), + } + }) + .collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse_work_area() { + let input = " [D] +[N] [C] +[Z] [M] [P] + 1 2 3 "; + assert_eq!( + parse_work_area(input), + WorkArea::new(vec![vec!['Z', 'N'], vec!['M', 'C', 'D'], vec!['P'],],) + ) + } + + #[test] + fn test_parse() { + let input = " [D] +[N] [C] +[Z] [M] [P] + 1 2 3 + +move 1 from 2 to 1 +move 3 from 1 to 3 +move 2 from 2 to 1 +move 1 from 1 to 2"; + assert_eq!( + parse(input), + ( + WorkArea::new(vec![vec!['Z', 'N'], vec!['M', 'C', 'D'], vec!['P'],],), + vec![ + Move { + to: 1, + from: 2, + number: 1 + }, + Move { + to: 3, + from: 1, + number: 3 + }, + Move { + to: 1, + from: 2, + number: 2 + }, + Move { + to: 2, + from: 1, + number: 1 + }, + ] + ) + ); + } +} diff --git a/2022/days/06/Cargo.toml b/2022/days/06/Cargo.toml new file mode 100644 index 0000000..cbba0f4 --- /dev/null +++ b/2022/days/06/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "day06" +authors.workspace = true +description.workspace = true +version.workspace = true +edition.workspace = true diff --git a/2022/days/06/src/input.txt b/2022/days/06/src/input.txt new file mode 100644 index 0000000..a293ff0 --- /dev/null +++ b/2022/days/06/src/input.txt @@ -0,0 +1 @@ +bhzhtzzsczszsjjjzddfzdfzfjfzfbbnntnzznwzzvfvrrqmrmmdzzfqfhqhsqqpwpgwpppbtbnnstthmhrrsmmvsmmhjmjfmfsfjfnfnjjvcjjszjszjsszbznzbnzndzzmlldsdgdcddmqmfqqlcllbvllztzctzczdzttlmtlthtmhtmhmmszsllvzvdzzzsqzqbqccvfvcffzsfslfsllcglclwlvwvzzdsslggtzzgzdzmzddjljvvztttsgscsstztjztjztzvzwwthtftppnmpmmcpmmjlmjjjsfjsjppgcgwcggzffzwzbbmbrbprpqqpccfncfnffvcffsqqtzqzqwzwvzwwwbjbfbcbfblltnlnhhcthtvvzzfcfgfddlggbbshsggplglqqbrbggsvvzdvvlfvlvpvhhmggbrrnppjfjhffttfpffbdfbfvfqvvtcvvbvnnhbhhglgjgzzghhwrrtntrtwwfdfdmmcmtctftpptllzqllzflfrrgqgvgdvdfdbddprrrgccqvqnnmtmvmffpzzqggfbfnfwwqdqldqqlnqnttnbttrffnmmzwzjjtrjtrtmmqsmqmffqmfqfhhbthbhdhvdhvdvmvdmdhdshsqslldzztvvmzzdcccmbbhfhshrrrpsrrqqmdmmgdmmwdmdjdqqmcmttpgtgwgpwpprbrprhrsrllhsllprlplhppfzpffbhbccwdwbbrpbpvpqqmsspjssmbbmfmrmnrnwwgbwwbpwpjwwhqqgcqcvqccgffzpfftcffqlqjjznnlflhhlcczhzvhzhmzhmhfhnnqznntstwtggqjgjhggsvslltjlttfjjgffjzjwzzqzrrhlhzhbhphmhlmlzmzsmzmccvllgrrpbrbfbjfjttqjttdrdhhggqgddppqgpqgpgtptjptpllwccmwcmcpmcppdrrtstqqczqzvvlsltlddnvdvggcqqblqqsjqjttzhtzzszllqsqfqddqdbqddwqddfzzlczcscfsfpfdpdrpddsggcqchcfcpcssstwstwtggghvhqhzzqssjddwjwbjjsnjnfnwwglwwfnfhnnscsggzgjzzhzmmqfqsqwqrwqqqdtdcttzvvnbngbbcdbdggddnmddgzghhzgghwwbjbttlwlcctlccwwdhhrqrvrjjlglssgttpllwclwwtptwptwtvthtbhbzhbzhhrsrwwwnrwrfwfnwnhhnqqdjqjpqqwdwttzhttcdttvztzltzlzmzddrsdsfdsfftdfffmwffrjrffqrfqfsfqqqgqjggwzzrnnqfnqffdbfbtbbrpbrpbptpwttjmjjzrrhhqppdzdtdjttqwwtddjdzzmgzzhwwwdsdgssprsrgsgbbphhdpdwppnfppdqqwzzpbzzqwqpqsqhqdhqqtwwjnnmvmwvmmwwgjgzjjvcjcvcjcnjcncmmphmmvmwmwpwbbtbffhnhshgssgvgvrrbwbtbddqmqfqvvfqvqdvvdbvdbdcdfdlflmffrwwgmmttrztrrfrqrpqrrzjrjpjdpjprrnhhbhcbbcwwqlwwcssbddfrfjrfjfrjfjvvdmdtdzzlvzlzhzmhmhphchnnfqnffvccfpfbfpfqpprrmttzrzzjzmjmzjmmfvmmrzrqqdllgjlglcchssgllsbllrbrlrjlrrhhfwwsqwsstpssznzcznzqzssvtvtrrqwqvvtssgfsfhssljjnwjnjddjdggclcrrfsfhsstgtdtctfttvvsbvvbtbttcgcssjlslhlpljpppwzwnwdnngmgjjbzznwwdllrrfppshhvdhhldhdbbdbjbdjjrnjjzhzfhhsqqbqgmsbvnjsptlrsszlqfmgprvscphmqztbgtlrqvcgdzcptcqjncrdtfqnghnbmwwmcjgtjlbvqqzslgbbntrdfnvfjvfgcgngndjcspgwmpnsrqzzvzljbzlzzrwflrqqqmhsvqwbmdftnhwwzgqrlhddbbtwvbphljmstcjzvpjqwcnhlvpqvqdgvntgqzqwrlwbwvngwtqgrhznlzcvbwqmwncccjctrdzrmzjsvrmcfpjjcczhbvdfwhqvczggfmrspvprvvthvtqnsphpcsdmbrtbdqljvssdrhwjsrrlzprstpgqcbpmnpdgzgjttwcfrgjnsghmszlclgvmlsjrqfvflbnhwwphtvrnrbhdvdglcvgpzfsjpwwhtlvvdzthsrldfzhnlrblzsjjnwclqsqzgdbflhvpwcrtfbfbjcjttbjpvfgvfcswnqqwshbmqlscdzzwshfqwsvwnwzltbnrmzzhzvtwpzqcgwshpvzgtcmwrtrwctnpzbznnwqphnrgwljtrcwlqmvlndwrdrctztnmswslqmbjcmtlrmcpjvzccqszrnflqnqzttbhqlrhbmqdpscqvfgtdbnwjdcljwcbgbgjfzgrgpwqzqgbnrtpntfthhdbqmswvhnmwmszpghgjjzrbnbbfjblpstdfslmmmqfdcrhblqjqfphnldrvvfpnfrcvprjnqbzbspfpjtgqhnjbhnrwzcjvdbshhqpgrmzqpmjfmqwqvvdbddbsldwzzsrhnhsjjnvljrbwcnjrnjpmrrvfthftgptgtlpbgqffthflgftwcrqcqwqwrmrcmfrcqgmrnqjbscdcgrqlhjzthvzdgjbvpswflqcgsnlmgmvcsttsgmnqdtvwdvrndvfdcvrcwmqlmlhtrvthsndsrmnsfmdmfnpfmfhzjqmtcjzcrnsjdztztvgdtlrmbdmmstbfgpmmzthcslpvgrpgfljfgqlqhldfwvvvdvbzjtdtppbtrnqwsqztjrsjhtfrgmvsdngvsdzjgpwrldqpzdpvhljzpjvttwltdwcrhcbrgrvdrmpwvdwjchqsjfprbgtjtzggvgrgmlvvwqrjfprbbgjjqrtdfnrdffwbswbvqtqtfsrhsgrjhftqldhmcnmsnfflmdrzqdjmbqqgqsttdmtrrvfsjnccnhcpcvqtrzdjzrpwswmjvvgsgwvnmdgqwlctrlhqnsmczbwsjhmtgvdcgsndzlstcwchcztqqbtdwfvlljdvdlzljslgnzpmqvzfcvqhdzvgchffqgfwrnmwqzwgbzblpmvddlvnhglrhdnwzqwztzgjczjpwcjwmpnrnrhncfjfggrbphrjztwtfqmfjlwfhnqfftfghbnvtwgtmdzzrdrtmfrwhrrbhzmcllsgqzwzzqtgdggvzptvtdcpzmtmsfcfbjtzlbdrwhdbtdhhrgggmddnzsvjwgcdcqfppqwphfvlhmgqsznlhmgpnjvcvrwwppnphchgsrhjwjcpjggsrcwrvnllfgrmjltfzwhmbqwpwwzmrtlqcprrqztcgnghcbvzrbfptjmhtdcfhhffdbrswqpnpppnpqwtflrrmqgjzctmmvvvwzllbsfdvpqjtmvpjcpmjztscsgbdznfgcmtjzdqzwqrsvstnnvddcstzqjtnbsnlptpmbmfqmhppgnjrffqrtchgptbmwlwbwbcqqfngpbwtwdmlmdstmqwcwjtbwbbbhghgptmvhfmvqfvpwqzwnbjdhpwlgjgvprdjbnlzhnllssbpvzfzspwsscfpqtpdvtzvqncfrfrgddsdglqvpblmpcczlqfdmwzmgvrljhqtcglcvfhbdwhbttqqrjbqwhsrhrbjwmtqwqddvdggdwfsmnpbpvvgsqnvvrqntwmbzdnqpmmqtbnlsbmslpfmqjtgvbddhwvlvjtlrhqdpfnjwtbhwjwdrpgctbbrdqvbbnvgqwngrhqfvwzmlqtmhfqphnmczlbdpnbmpvwrsjbcnjnvcfgnsvlhpzdgdzgvfbgwdcrswznrggnghzssdwqvvlwftqhbnwdvghhvjlqqmcnqmvbwhrrnsswlwmwbsmpcpdzzgmcmqnzpvjpzqbwcsgdhqtqhcpbtqftvscmntsbdcbrndvlfhprpblzbjcpqhfljtvnvtgvrcgqbsgl diff --git a/2022/days/06/src/main.rs b/2022/days/06/src/main.rs new file mode 100644 index 0000000..652af02 --- /dev/null +++ b/2022/days/06/src/main.rs @@ -0,0 +1,14 @@ +mod part1; +mod part2; +mod utilities; + +fn main() { + let _input = include_str!("./input.txt"); + // let _structured_input = utilities::parse(_input); + + println!("Part One"); + println!("Result: {}", part1::part1(_input)); + + println!("Part Two"); + println!("Result: {}", part2::part2(_input)); +} diff --git a/2022/days/06/src/part1.rs b/2022/days/06/src/part1.rs new file mode 100644 index 0000000..1744504 --- /dev/null +++ b/2022/days/06/src/part1.rs @@ -0,0 +1,23 @@ +use crate::utilities::*; + +pub fn part1(input: &str) -> usize { + input + .as_bytes() + .windows(4) + .position(|x| !find_dupes_stupid(x)) + .unwrap()+4 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part1() { + assert_eq!(part1("mjqjpqmgbljsphdztnvjfqwrcgsmlb"), 7); + assert_eq!(part1("bvwbjplbgvbhsrlpgdmjqwftvncz"), 5); + assert_eq!(part1("nppdvjthqldpwncqszvftbrmjlhg"), 6); + assert_eq!(part1("nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg"), 10); + assert_eq!(part1("zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw"), 11); + } +} diff --git a/2022/days/06/src/part2.rs b/2022/days/06/src/part2.rs new file mode 100644 index 0000000..369672c --- /dev/null +++ b/2022/days/06/src/part2.rs @@ -0,0 +1,23 @@ +use crate::utilities::*; + +pub fn part2(input: &str) -> usize { + input + .as_bytes() + .windows(14) + .position(|x| !find_dupes_stupid(x)) + .unwrap()+14 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part2() { + assert_eq!(part2("mjqjpqmgbljsphdztnvjfqwrcgsmlb"), 19); + assert_eq!(part2("bvwbjplbgvbhsrlpgdmjqwftvncz"), 23); + assert_eq!(part2("nppdvjthqldpwncqszvftbrmjlhg"), 23); + assert_eq!(part2("nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg"), 29); + assert_eq!(part2("zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw"), 26); + } +} diff --git a/2022/days/06/src/utilities.rs b/2022/days/06/src/utilities.rs new file mode 100644 index 0000000..15baf44 --- /dev/null +++ b/2022/days/06/src/utilities.rs @@ -0,0 +1,19 @@ +pub fn find_dupes_stupid(slice: &[T]) -> bool { + for i in 1..slice.len() { + if slice[i..].contains(&slice[i - 1]) { + return true; + } + } + false +} + +/* #[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse() { + let input = "test"; + assert_eq!(parse(input), 0); + } +} */ diff --git a/2022/days/07/Cargo.toml b/2022/days/07/Cargo.toml new file mode 100644 index 0000000..2f988e1 --- /dev/null +++ b/2022/days/07/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "day07" +authors.workspace = true +description.workspace = true +version.workspace = true +edition.workspace = true + +[dependencies] +once_cell.workspace = true +regex.workspace = true +thiserror.workspace = true diff --git a/2022/days/07/src/file_tree.rs b/2022/days/07/src/file_tree.rs new file mode 100644 index 0000000..defa846 --- /dev/null +++ b/2022/days/07/src/file_tree.rs @@ -0,0 +1,305 @@ +use std::{ + cell::RefCell, + fmt::Display, + ops::Deref, + rc::{Rc, Weak}, +}; + +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum FileTreeError { + #[error("Directory operation on file")] + IsFile, + #[error("File operation on directory")] + IsDir, + #[error("File not found")] + FileNotFound, + #[error("File already exists")] + FileAlreadyExists, +} + +type WeakNodeRef = Weak>; + +#[derive(Debug)] +pub struct NodeRef(pub Rc>); + +impl Deref for NodeRef { + type Target = Rc>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl From>> for NodeRef { + fn from(value: Rc>) -> Self { + NodeRef(value) + } +} + +impl From for Rc> { + fn from(value: NodeRef) -> Self { + value.0 + } +} + +impl NodeRef { + pub fn add_node(&mut self, mut node: Node) -> Result { + node.set_parent(self); + self.borrow_mut().add_children(node) + } + pub fn new_dir(name: String) -> NodeRef { + NodeRef(Rc::new(RefCell::new(Node::new_dir(name)))) + } + pub fn add_file(&mut self, name: String, size: usize) -> Result { + self.add_node(Node::new_file(name, size)) + } + pub fn add_dir(&mut self, name: String) -> Result { + self.add_node(Node::new_dir(name)) + } + pub fn get_all_dirs(&self) -> Vec { + let mut ret = Vec::new(); + match &self.borrow().contents { + Contents::Size(_) => {} + Contents::Children(c) => { + ret.push(NodeRef(Rc::clone(self))); + for node in c { + ret.append(&mut node.get_all_dirs()) + } + } + }; + ret + } +} + +#[derive(Debug)] +pub struct Node { + pub name: String, + parent: Option, + contents: Contents, +} + +impl Node { + pub fn new_dir(name: String) -> Node { + Node { + name, + parent: None, + contents: Contents::Children(Vec::new()), + } + } + pub fn new_file(name: String, size: usize) -> Node { + Node { + name, + parent: None, + contents: Contents::Size(size), + } + } + pub fn get_total_size(&self) -> usize { + match &self.contents { + Contents::Size(s) => *s, + Contents::Children(c) => c.iter().map(|f| f.borrow().get_total_size()).sum(), + } + } + fn set_parent(&mut self, newparent: &NodeRef) { + self.parent = Some(Rc::downgrade(newparent)); + } + // does not set the parent, needs to be done on the NodeRef. (this is why this func isnt pub). + // takes onwership of the node to make sure its not owned by another tree. + fn add_children(&mut self, node: Node) -> Result { + match self.contents { + Contents::Size(_) => Err(FileTreeError::IsFile), + Contents::Children(ref mut c) => { + for file in c.iter() { + if file.borrow().name == node.name { + return Err(FileTreeError::FileAlreadyExists); + } + } + let rc = Rc::new(RefCell::new(node)); + c.push(NodeRef(Rc::clone(&rc))); + Ok(NodeRef(Rc::clone(&rc))) + } + } + } + pub fn remove_child_by_name(&mut self, name: &str) -> Result<(), FileTreeError> { + match self.contents { + Contents::Size(_) => Err(FileTreeError::IsFile), + Contents::Children(ref mut c) => { + for (i, file) in c.iter().enumerate() { + if file.borrow().name == name { + c.remove(i); + return Ok(()); + } + } + Err(FileTreeError::FileNotFound) + } + } + } + pub fn get_parent(&self) -> Option { + match &self.parent { + Some(w) => Some(NodeRef(w.clone().upgrade()?)), + None => None, + } + } + pub fn get_size(&self) -> Result { + match self.contents { + Contents::Size(s) => Ok(s), + Contents::Children(_) => Err(FileTreeError::IsDir), + } + } + pub fn set_size(&mut self, size: usize) -> Result<(), FileTreeError> { + match self.contents { + Contents::Size(ref mut s) => { + *s = size; + Ok(()) + } + Contents::Children(_) => Err(FileTreeError::IsDir), + } + } + pub fn get_children(&self) -> Result + '_, FileTreeError> { + match &self.contents { + Contents::Size(_) => Err(FileTreeError::IsFile), + Contents::Children(c) => Ok(c.iter().map(|n| NodeRef(Rc::clone(n)))), + } + } + pub fn get_child_by_name(&self, name: &str) -> Result { + match &self.contents { + Contents::Size(_) => Err(FileTreeError::IsFile), + Contents::Children(c) => { + for file in c.iter() { + if file.borrow().name == name { + return Ok(NodeRef(Rc::clone(file))); + } + } + Err(FileTreeError::FileNotFound) + } + } + } +} + +#[derive(Debug)] +enum Contents { + Size(usize), + Children(Vec), +} + +impl Display for NodeRef { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.borrow()) + } +} + +impl Display for Node { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "- {} {}", self.name, self.contents) + } +} + +impl Display for Contents { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Contents::Size(s) => write!(f, "(file, size = {})", s), + Contents::Children(c) => { + writeln!(f, "(dir)").expect("I have no clue how this could fail"); + for node in c { + //padding + for line in format!("{}", node).lines() { + writeln!(f, " {line}")?; + } + } + Ok(()) + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_dir_construction() { + let mut root = NodeRef::new_dir("/".to_string()); + let mut cursor = root.add_node(Node::new_dir("a".to_string())).unwrap(); + cursor = cursor.add_dir("e".to_string()).unwrap(); + cursor.add_file("i".to_string(), 584).unwrap(); + cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap(); + cursor.add_file("f".to_string(), 29116).unwrap(); + cursor.add_file("g".to_string(), 2557).unwrap(); + cursor.add_file("h.lst".to_string(), 62596).unwrap(); + cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap(); + cursor.add_file("b.txt".to_string(), 14848514).unwrap(); + cursor.add_file("c.dat".to_string(), 8504156).unwrap(); + cursor = cursor.add_dir("d".to_string()).unwrap(); + cursor.add_file("j".to_string(), 4060174).unwrap(); + cursor.add_file("d.log".to_string(), 8033020).unwrap(); + cursor.add_file("d.ext".to_string(), 5626152).unwrap(); + cursor.add_file("k".to_string(), 7214296).unwrap(); + assert_eq!(Rc::clone(root.deref()).borrow().get_total_size(), 48381165); + println!("{}", root); + } + + #[test] + fn test_size_calcs() { + let mut root = NodeRef::new_dir("/".to_string()); + let mut dirs: Vec = Vec::new(); + let mut cursor = root.add_dir("a".to_string()).unwrap(); + dirs.push(NodeRef(Rc::clone(&cursor))); + cursor = cursor.add_dir("e".to_string()).unwrap(); + dirs.push(NodeRef(Rc::clone(&cursor))); + cursor.add_file("i".to_string(), 584).unwrap(); + cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap(); + cursor.add_file("f".to_string(), 29116).unwrap(); + cursor.add_file("g".to_string(), 2557).unwrap(); + cursor.add_file("h.lst".to_string(), 62596).unwrap(); + cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap(); + cursor.add_file("b.txt".to_string(), 14848514).unwrap(); + cursor.add_file("c.dat".to_string(), 8504156).unwrap(); + cursor = cursor.add_node(Node::new_dir("d".to_string())).unwrap(); + dirs.push(NodeRef(Rc::clone(&cursor))); + cursor.add_file("j".to_string(), 4060174).unwrap(); + cursor.add_file("d.log".to_string(), 8033020).unwrap(); + cursor.add_file("d.ext".to_string(), 5626152).unwrap(); + cursor.add_file("k".to_string(), 7214296).unwrap(); + assert_eq!(Rc::clone(root.deref()).borrow().get_total_size(), 48381165); + assert_eq!(Rc::clone(dirs[0].deref()).borrow().get_total_size(), 94853); + assert_eq!(Rc::clone(dirs[1].deref()).borrow().get_total_size(), 584); + assert_eq!( + Rc::clone(dirs[2].deref()).borrow().get_total_size(), + 24933642 + ); + } + #[test] + fn test_get_all_dirs() { + let mut root = NodeRef::new_dir("/".to_string()); + let mut cursor = root.add_dir("a".to_string()).unwrap(); + cursor = cursor.add_dir("e".to_string()).unwrap(); + cursor.add_file("i".to_string(), 584).unwrap(); + cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap(); + cursor.add_file("f".to_string(), 29116).unwrap(); + cursor.add_file("g".to_string(), 2557).unwrap(); + cursor.add_file("h.lst".to_string(), 62596).unwrap(); + cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap(); + cursor.add_file("b.txt".to_string(), 14848514).unwrap(); + cursor.add_file("c.dat".to_string(), 8504156).unwrap(); + cursor = cursor.add_node(Node::new_dir("d".to_string())).unwrap(); + cursor.add_file("j".to_string(), 4060174).unwrap(); + cursor.add_file("d.log".to_string(), 8033020).unwrap(); + cursor.add_file("d.ext".to_string(), 5626152).unwrap(); + cursor.add_file("k".to_string(), 7214296).unwrap(); + let dirs = root.get_all_dirs(); + let sizes: Vec = dirs.iter().map(|d| d.borrow().get_total_size()).collect(); + println!("{:?}", sizes); + assert_eq!(Rc::clone(root.deref()).borrow().get_total_size(), 48381165); + assert_eq!( + Rc::clone(dirs[0].deref()).borrow().get_total_size(), + 48381165 + ); + assert_eq!(Rc::clone(dirs[1].deref()).borrow().get_total_size(), 94853); + assert_eq!(Rc::clone(dirs[2].deref()).borrow().get_total_size(), 584); + assert_eq!( + Rc::clone(dirs[3].deref()).borrow().get_total_size(), + 24933642 + ); + } +} diff --git a/2022/days/07/src/input.txt b/2022/days/07/src/input.txt new file mode 100644 index 0000000..efd9044 --- /dev/null +++ b/2022/days/07/src/input.txt @@ -0,0 +1,1030 @@ +$ cd / +$ ls +dir bhtvbj +dir bmlllrl +dir dhm +dir mnp +dir nwqgchw +$ cd bhtvbj +$ ls +dir dmd +dir fjblqtdp +25595 mdmtpjq.wmf +dir qhm +dir rjr +dir smtrp +dir tbdsml +$ cd dmd +$ ls +232616 ngmqbc.mdj +75367 vqqcvgts.vrc +$ cd .. +$ cd fjblqtdp +$ ls +dir czvcf +dir jnzwf +245590 lcpgtrc.dqm +141631 nwqgchw +37152 nwqgchw.ppg +80432 rbj.twt +$ cd czvcf +$ ls +dir cqzcp +dir czvcf +$ cd cqzcp +$ ls +dir bshmsns +55418 svhphd +232179 vqqcvgts.vrc +$ cd bshmsns +$ ls +243135 rbhprlgq.gbh +$ cd .. +$ cd .. +$ cd czvcf +$ ls +158882 lhfsc.lrh +266626 ntsrpn +$ cd .. +$ cd .. +$ cd jnzwf +$ ls +108142 btmz +$ cd .. +$ cd .. +$ cd qhm +$ ls +162986 bnqbdmm.dfh +dir hqbhr +201987 hwvdlfl +dir lvdrr +143900 nwcjvb +dir rgtcchh +297583 wdcsgg.cjt +$ cd hqbhr +$ ls +175196 btmz +dir fcm +221851 ngmqbc +dir qnlssvn +263872 rdzsz.grd +dir vvbgt +dir wwzwqqh +$ cd fcm +$ ls +66471 sfddtgp.flr +$ cd .. +$ cd qnlssvn +$ ls +dir czvcf +dir gngvc +75812 lbthznl.llq +182104 nwqgchw.nlq +161446 rrvwdw.nzv +dir rzssqpcj +260877 wdcsgg.cjt +$ cd czvcf +$ ls +202850 vqqcvgts.vrc +$ cd .. +$ cd gngvc +$ ls +154834 rdzsz.hst +$ cd .. +$ cd rzssqpcj +$ ls +66116 bdzdp +$ cd .. +$ cd .. +$ cd vvbgt +$ ls +288775 cpsmvwq +dir fbfddwqz +81857 jcpj.wpf +dir nwjps +49905 tlrlbg.mgz +64870 wdcsgg.cjt +131013 zbc.rhl +$ cd fbfddwqz +$ ls +100619 wdcsgg.cjt +$ cd .. +$ cd nwjps +$ ls +96526 cjrvb.tdv +$ cd .. +$ cd .. +$ cd wwzwqqh +$ ls +dir czvcf +$ cd czvcf +$ ls +256121 nrjfpjc.wcg +$ cd .. +$ cd .. +$ cd .. +$ cd lvdrr +$ ls +27488 lhfsc.lrh +$ cd .. +$ cd rgtcchh +$ ls +19285 bfdfz.rln +166070 btmz +222301 vqqcvgts.vrc +$ cd .. +$ cd .. +$ cd rjr +$ ls +dir dbb +121292 drv.ljf +dir ntbbd +228025 rphtjh.ngl +133033 wrlwdgz +$ cd dbb +$ ls +158756 btmz +130326 czvcf.trn +dir fdgh +dir grr +20181 wdcsgg.cjt +$ cd fdgh +$ ls +24629 rph.rsl +299233 wdcsgg.cjt +$ cd .. +$ cd grr +$ ls +259732 tqvvp +$ cd .. +$ cd .. +$ cd ntbbd +$ ls +dir cwwhvghw +dir hggcq +169994 jrvt.srj +dir jtzbw +dir ptr +215668 smcngpwr +dir tfshcbw +$ cd cwwhvghw +$ ls +dir czvcf +167719 dzltv +dir mdgqwdjq +265831 pcfcw.jrd +86965 qsdv +71709 tdbtjwzp.msg +dir vtbr +$ cd czvcf +$ ls +dir ntj +dir nwqgchw +dir rdzsz +202867 vqqcvgts.vrc +$ cd ntj +$ ls +214072 ntplhvnn.zpt +$ cd .. +$ cd nwqgchw +$ ls +228489 qfphslzt +15383 zfpdpds.bjt +$ cd .. +$ cd rdzsz +$ ls +dir jrvt +6415 jrvt.vjt +290773 mhfwsc.nlr +82027 wdcsgg.cjt +$ cd jrvt +$ ls +85079 mnq.jvr +$ cd .. +$ cd .. +$ cd .. +$ cd mdgqwdjq +$ ls +223814 phghj +172175 wwpvcb +$ cd .. +$ cd vtbr +$ ls +134023 frwc.dhg +26692 fvgscmns.mpj +148404 wnlgfmdr.dch +$ cd .. +$ cd .. +$ cd hggcq +$ ls +19064 btmz +200043 lswzn +dir mlrj +49427 rcwmzz.nsn +dir wjznmcw +$ cd mlrj +$ ls +10869 czvcf.fvc +277796 gprlsg.tbt +$ cd .. +$ cd wjznmcw +$ ls +43168 bzwn +dir dznz +4102 lcpgtrc.dqm +dir ltcpgcdf +228100 nwqgchw.mgc +dir tbdqsnb +dir tmzswrgt +19984 whgmsm.bjj +$ cd dznz +$ ls +59403 msqdt.mlm +$ cd .. +$ cd ltcpgcdf +$ ls +dir czvcf +10727 jgphjm.pdw +309167 nwqgchw +dir pwbt +dir qznbn +203154 ztpcdmb.rrs +$ cd czvcf +$ ls +173609 pntjz.vzq +292292 trvbpz.djc +111008 wdcsgg.cjt +107437 wjvv.hsj +265353 wsbff.pzh +$ cd .. +$ cd pwbt +$ ls +307172 jtdtlbsh +dir lgz +$ cd lgz +$ ls +dir fnlsq +$ cd fnlsq +$ ls +161356 jrvt.ljb +$ cd .. +$ cd .. +$ cd .. +$ cd qznbn +$ ls +12354 bdgvj +59582 cslzb.qnq +dir czvcf +dir psnpf +136432 vlsswwgv +99861 vqqcvgts.vrc +39898 wzllwpmr.mqc +$ cd czvcf +$ ls +dir dqnpjjrv +13244 ztcpzzr +$ cd dqnpjjrv +$ ls +233675 ngmqbc.srp +$ cd .. +$ cd .. +$ cd psnpf +$ ls +1986 lhfsc.lrh +$ cd .. +$ cd .. +$ cd .. +$ cd tbdqsnb +$ ls +170099 hbcnv.gmj +$ cd .. +$ cd tmzswrgt +$ ls +118969 btmz +dir czvcf +51649 hbb.jcb +$ cd czvcf +$ ls +163330 hhcf +159514 wdhw +22876 wtn.pnb +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd jtzbw +$ ls +55634 rdzsz.dgf +$ cd .. +$ cd ptr +$ ls +49447 wdcsgg.cjt +$ cd .. +$ cd tfshcbw +$ ls +193480 btmz +44402 sjsgfmts.dtc +115952 vqncb.ssf +$ cd .. +$ cd .. +$ cd .. +$ cd smtrp +$ ls +dir hlpzdbwp +307696 jrvt.hds +300691 lcpgtrc.dqm +dir nflt +dir qcph +dir qlrdf +$ cd hlpzdbwp +$ ls +dir czvcf +dir frzvnrb +dir jrvt +$ cd czvcf +$ ls +155141 lcpgtrc.dqm +$ cd .. +$ cd frzvnrb +$ ls +71241 btmz +dir rdzsz +dir vdb +$ cd rdzsz +$ ls +35362 jngsmcrm.pwt +$ cd .. +$ cd vdb +$ ls +239928 jrvt.nbf +16883 ngmqbc +$ cd .. +$ cd .. +$ cd jrvt +$ ls +dir lcchtcz +$ cd lcchtcz +$ ls +199091 qzsh.fst +$ cd .. +$ cd .. +$ cd .. +$ cd nflt +$ ls +219987 nwqgchw.qpf +dir rdzsz +257069 wdcsgg.cjt +$ cd rdzsz +$ ls +dir zmgf +$ cd zmgf +$ ls +dir vwcvbff +$ cd vwcvbff +$ ls +157598 qsp +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd qcph +$ ls +158708 cdj.bch +dir drdpdzj +dir jrvt +109459 lhfsc.lrh +dir ngmqbc +164488 rtnvpg +23729 vqqcvgts.vrc +115775 wdcsgg.cjt +$ cd drdpdzj +$ ls +dir ngwcr +dir pwffm +dir vcclwq +$ cd ngwcr +$ ls +76003 rqjbn +84407 vqqcvgts.vrc +$ cd .. +$ cd pwffm +$ ls +284565 rzdjrmn.jdz +$ cd .. +$ cd vcclwq +$ ls +137044 czvcf.qll +3433 nwqgchw +18027 vqqcvgts.vrc +$ cd .. +$ cd .. +$ cd jrvt +$ ls +57605 vljs +$ cd .. +$ cd ngmqbc +$ ls +217554 btmz +96485 lhfsc.lrh +dir lpcr +dir sltwgmjv +dir snll +dir tsq +218323 vqqcvgts.vrc +150009 wdcsgg.cjt +$ cd lpcr +$ ls +227650 qhfz.grc +$ cd .. +$ cd sltwgmjv +$ ls +39536 fncjl.vlr +248067 lcpgtrc.dqm +$ cd .. +$ cd snll +$ ls +70368 btmz +195228 svmdc.pcv +$ cd .. +$ cd tsq +$ ls +271904 vqqcvgts.vrc +104043 wbgwpcl +$ cd .. +$ cd .. +$ cd .. +$ cd qlrdf +$ ls +dir dqgln +dir ngmqbc +dir ntngh +$ cd dqgln +$ ls +dir qdrszjvm +$ cd qdrszjvm +$ ls +199245 lcpgtrc.dqm +$ cd .. +$ cd .. +$ cd ngmqbc +$ ls +171851 czvcf.jft +dir ngmqbc +dir qdffn +$ cd ngmqbc +$ ls +14596 jjhmhzs.dww +$ cd .. +$ cd qdffn +$ ls +dir czvcf +$ cd czvcf +$ ls +130227 jhqhd.fdz +$ cd .. +$ cd .. +$ cd .. +$ cd ntngh +$ ls +243908 bqjfjnl.pcl +112351 btmz +30167 lcpgtrc.dqm +249181 mfwcvc.zdg +dir qlhw +157482 vqqcvgts.vrc +$ cd qlhw +$ ls +267233 gfhthp.prr +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd tbdsml +$ ls +44152 btmz +143454 cpzlrsh +47848 crdvhbt.dfr +dir gvjhlqdd +171842 mgljcrw.trm +dir nqsq +dir rdzsz +$ cd gvjhlqdd +$ ls +177040 ffbm +$ cd .. +$ cd nqsq +$ ls +dir fchtl +dir jrvt +dir nsgbjwbt +dir qcz +dir vqlnqvwn +55184 wlspgz +dir wzm +dir zpw +$ cd fchtl +$ ls +193793 btmz +164089 jrvt.hzn +53839 lpv.gtg +dir qmfwds +dir sqznc +dir tdqg +dir zvd +$ cd qmfwds +$ ls +dir dqtbp +236341 lcpgtrc.dqm +101548 rdzsz.vqr +180341 wzpdq.gjr +$ cd dqtbp +$ ls +56177 hdgnthn.dff +56834 jrvt.nmg +$ cd .. +$ cd .. +$ cd sqznc +$ ls +282988 dpdfvn.spw +248737 tzfd.pfd +$ cd .. +$ cd tdqg +$ ls +251266 rdzsz.dhb +$ cd .. +$ cd zvd +$ ls +124979 ngmqbc +$ cd .. +$ cd .. +$ cd jrvt +$ ls +206684 dbbppj.sds +189832 jvst.fzr +$ cd .. +$ cd nsgbjwbt +$ ls +32810 btmz +$ cd .. +$ cd qcz +$ ls +dir bjbsl +dir brvgznjr +98771 btmz +dir gbfhz +dir ngmqbc +88248 rccpzctp.gwn +dir rdzsz +39060 tqswrdh.wfc +dir ztnv +$ cd bjbsl +$ ls +1312 rdzsz.qtl +$ cd .. +$ cd brvgznjr +$ ls +98988 lhfsc.lrh +$ cd .. +$ cd gbfhz +$ ls +96203 hgldz +28558 nwqgchw +dir qrzd +240140 wjww.hjf +$ cd qrzd +$ ls +231108 hjfcwvtq +$ cd .. +$ cd .. +$ cd ngmqbc +$ ls +dir cpjvd +dir vrbfcwc +$ cd cpjvd +$ ls +142549 btmz +dir ngmqbc +$ cd ngmqbc +$ ls +62008 vqqcvgts.vrc +$ cd .. +$ cd .. +$ cd vrbfcwc +$ ls +dir czj +$ cd czj +$ ls +48640 btmz +$ cd .. +$ cd .. +$ cd .. +$ cd rdzsz +$ ls +dir czvcf +dir fmgmgmp +dir jrvt +308389 lhfsc.lrh +dir nfdh +dir ptgsd +dir qmg +244691 vqqcvgts.vrc +$ cd czvcf +$ ls +dir fqjrb +dir jbtgpl +dir jstzjf +299095 lcpgtrc.dqm +122426 lhfsc.lrh +dir wczwphjh +219013 wdcsgg.cjt +$ cd fqjrb +$ ls +dir fpspthg +dir hdmtsv +118041 mwlsw.fvs +dir rdzsz +99976 wdcsgg.cjt +$ cd fpspthg +$ ls +280707 hmwsq +$ cd .. +$ cd hdmtsv +$ ls +102842 btmz +72949 fpzqpqb.zjp +$ cd .. +$ cd rdzsz +$ ls +36159 sjtwbsvc +$ cd .. +$ cd .. +$ cd jbtgpl +$ ls +139817 lhfsc.lrh +139333 nwqgchw.wrz +$ cd .. +$ cd jstzjf +$ ls +dir gngbnq +54929 lcpgtrc.dqm +dir pdbdwmc +$ cd gngbnq +$ ls +dir bfvsz +dir pndfrjhz +$ cd bfvsz +$ ls +283370 mdf.wvc +$ cd .. +$ cd pndfrjhz +$ ls +252824 lhfsc.lrh +$ cd .. +$ cd .. +$ cd pdbdwmc +$ ls +dir nwqgchw +dir sdmfntl +266823 vqqcvgts.vrc +$ cd nwqgchw +$ ls +dir bnfhbvmr +$ cd bnfhbvmr +$ ls +62602 lrmmtjmv +$ cd .. +$ cd .. +$ cd sdmfntl +$ ls +93365 njfgsgm.jtv +$ cd .. +$ cd .. +$ cd .. +$ cd wczwphjh +$ ls +164840 lcpgtrc.dqm +$ cd .. +$ cd .. +$ cd fmgmgmp +$ ls +292610 jglzqc.mss +dir rdzsz +dir rrrjw +$ cd rdzsz +$ ls +295660 lcpgtrc.dqm +$ cd .. +$ cd rrrjw +$ ls +dir lsc +$ cd lsc +$ ls +280045 dljtrq.tll +dir nwqgchw +$ cd nwqgchw +$ ls +162525 lhfsc.lrh +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd jrvt +$ ls +227518 pcsqv +$ cd .. +$ cd nfdh +$ ls +304769 ngmqbc.qhd +$ cd .. +$ cd ptgsd +$ ls +281593 cpfzhhd +123541 hhlhssqb.szt +250182 lcpgtrc.dqm +dir ngmqbc +229226 pppmnp +dir wntfhzqf +dir zchjnbz +$ cd ngmqbc +$ ls +202162 vqqcvgts.vrc +$ cd .. +$ cd wntfhzqf +$ ls +dir czvcf +dir rdzsz +dir wvhznt +$ cd czvcf +$ ls +250212 bzwsvd.lhc +$ cd .. +$ cd rdzsz +$ ls +244145 ngmqbc.lfb +236278 plnjrm.rgs +$ cd .. +$ cd wvhznt +$ ls +264719 czvcf.cgn +$ cd .. +$ cd .. +$ cd zchjnbz +$ ls +dir jrvt +dir msrs +dir vtrcs +$ cd jrvt +$ ls +154825 jrvt +44966 rdzsz +198819 vnnrqcbr.fjf +$ cd .. +$ cd msrs +$ ls +188969 cwbq.ltd +$ cd .. +$ cd vtrcs +$ ls +2014 jmvvq.pvn +$ cd .. +$ cd .. +$ cd .. +$ cd qmg +$ ls +dir dqfs +dir hwnbws +dir ngmqbc +$ cd dqfs +$ ls +130929 smwcjg.vjm +$ cd .. +$ cd hwnbws +$ ls +dir vsq +$ cd vsq +$ ls +196984 twlvvd.qlc +$ cd .. +$ cd .. +$ cd ngmqbc +$ ls +212410 cdzjjw +$ cd .. +$ cd .. +$ cd .. +$ cd ztnv +$ ls +167568 pwrsss +64234 rlprpl +$ cd .. +$ cd .. +$ cd vqlnqvwn +$ ls +19448 lcpgtrc.dqm +$ cd .. +$ cd wzm +$ ls +123271 lhfsc.lrh +dir ngmqbc +dir qvvvdl +$ cd ngmqbc +$ ls +dir bdjfhmvz +101745 cqg +dir ngmqbc +119605 ngmqbc.lnd +dir tnfr +dir wfzct +$ cd bdjfhmvz +$ ls +104287 jrvt.nnj +$ cd .. +$ cd ngmqbc +$ ls +88793 nwqgchw +$ cd .. +$ cd tnfr +$ ls +dir nggnpj +161400 vqqcvgts.vrc +$ cd nggnpj +$ ls +308915 btmz +81154 jjtwrbtw.bln +50902 sfppg.hvn +dir tpg +$ cd tpg +$ ls +143630 vqqcvgts.vrc +$ cd .. +$ cd .. +$ cd .. +$ cd wfzct +$ ls +71154 bzhzl.zcg +$ cd .. +$ cd .. +$ cd qvvvdl +$ ls +185898 nwqgchw.tvr +$ cd .. +$ cd .. +$ cd zpw +$ ls +167347 bcfj.lch +dir fldmgj +dir jspslmwp +199949 rdsz.dng +$ cd fldmgj +$ ls +154330 sbftm.wmt +$ cd .. +$ cd jspslmwp +$ ls +75378 jrvt.jdw +26174 mzthsl.qtv +214743 njjdqsr +29213 tsdnqwj +$ cd .. +$ cd .. +$ cd .. +$ cd rdzsz +$ ls +263486 cfjb.mfc +77949 fjnfp.lcl +262618 lcpgtrc.dqm +124555 lhfsc.lrh +dir pngmr +$ cd pngmr +$ ls +305791 fdvbthn.cvs +32332 rdjvldmt.lfw +dir rwwqsl +dir rzgv +$ cd rwwqsl +$ ls +158602 bmqnqtz +dir cvphd +dir hpb +$ cd cvphd +$ ls +119828 hfhvv.ffp +dir qbvcjq +257077 wdcsgg.cjt +$ cd qbvcjq +$ ls +dir nwqgchw +$ cd nwqgchw +$ ls +127576 lcpgtrc.dqm +$ cd .. +$ cd .. +$ cd .. +$ cd hpb +$ ls +176379 nwqgchw +166831 qhdgmsvv.bdr +$ cd .. +$ cd .. +$ cd rzgv +$ ls +56544 pngtztnf.gdt +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd bmlllrl +$ ls +270146 chqqnfpn.dfs +dir ngmqbc +dir rdzsz +70712 vqqcvgts.vrc +$ cd ngmqbc +$ ls +dir rgcrvvgj +301804 vqqcvgts.vrc +$ cd rgcrvvgj +$ ls +219577 jwrlwq +$ cd .. +$ cd .. +$ cd rdzsz +$ ls +290477 nwqgchw.rng +$ cd .. +$ cd .. +$ cd dhm +$ ls +127736 npznvgqn.bdd +59221 smmlzfj.lhh +22345 zhfpvppf.gtn +$ cd .. +$ cd mnp +$ ls +dir gdntwv +dir qlsfmcqp +dir schlsbb +$ cd gdntwv +$ ls +133571 btmz +$ cd .. +$ cd qlsfmcqp +$ ls +244176 bffzdczp.gqf +12060 cqlvm.wdd +dir jnl +14040 ldczcfl +dir nwqgchw +243637 sphmmcv +290808 wdcsgg.cjt +$ cd jnl +$ ls +252674 lcpgtrc.dqm +$ cd .. +$ cd nwqgchw +$ ls +258944 btmz +$ cd .. +$ cd .. +$ cd schlsbb +$ ls +dir fpbrwnz +dir hnrh +101456 rtqfwbl +$ cd fpbrwnz +$ ls +232867 btmz +150179 cmq.tgm +249603 jztmgg.dlb +dir mqhz +62465 wdcsgg.cjt +$ cd mqhz +$ ls +232359 rdzsz.lhj +25201 vpjbmjd.zvt +277414 vqqcvgts.vrc +$ cd .. +$ cd .. +$ cd hnrh +$ ls +dir dmghrm +290254 lcpgtrc.dqm +dir tbbp +104510 vqqcvgts.vrc +$ cd dmghrm +$ ls +16799 vqqcvgts.vrc +$ cd .. +$ cd tbbp +$ ls +14688 jrvt +45492 wdcsgg.cjt +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd nwqgchw +$ ls +21374 lhfsc.lrh +121726 wdcsgg.cjt diff --git a/2022/days/07/src/main.rs b/2022/days/07/src/main.rs new file mode 100644 index 0000000..74fa7a2 --- /dev/null +++ b/2022/days/07/src/main.rs @@ -0,0 +1,19 @@ +use std::rc::Rc; + +use crate::file_tree::NodeRef; + +mod part1; +mod part2; +mod parser; +mod file_tree; + +fn main() { + let input = include_str!("./input.txt"); + let structured_input = parser::parse(input); + + println!("Part One"); + println!("Result: {}", part1::part1(NodeRef(Rc::clone(&structured_input)))); + + println!("Part Two"); + println!("Result: {}", part2::part2(NodeRef(Rc::clone(&structured_input)))); +} diff --git a/2022/days/07/src/parser.rs b/2022/days/07/src/parser.rs new file mode 100644 index 0000000..a6e2968 --- /dev/null +++ b/2022/days/07/src/parser.rs @@ -0,0 +1,262 @@ +use std::ops::Deref; +use std::rc::Rc; + +use crate::file_tree::*; +use once_cell::sync::Lazy; +use regex::Regex; + +static IS_COMMAND_REGEX: Lazy = Lazy::new(|| Regex::new(r"^\$").unwrap()); +static PARSE_CD_REGEX: Lazy = Lazy::new(|| Regex::new(r"^\$ cd (\S*)$").unwrap()); +static PARSE_LS_ENTRY_REGEX: Lazy = + Lazy::new(|| Regex::new(r"^([[:alnum:]]*) (\S*)$").unwrap()); + +#[derive(Debug, PartialEq, Eq)] +pub enum Command { + CdRoot, + CdUp, + Cd(String), + Ls(Vec), +} +#[derive(Debug, PartialEq, Eq)] +pub enum LsEntry { + Dir(String), + File(ParseFile), +} + +#[derive(Debug, PartialEq, Eq)] +pub struct ParseFile { + size: usize, + name: String, +} + +//parses a single line +pub fn parse_to_commands(input: &str) -> Vec { + let mut ret = Vec::new(); + let mut lines = input.lines().peekable(); + while lines.peek().is_some() { + let line = lines.next().unwrap(); + if line == "$ ls" { + ret.push(Command::Ls(parse_ls(&mut lines))); + } else { + let captures = PARSE_CD_REGEX + .captures(line) + .unwrap_or_else(|| panic!("invalid line {}", line)); + + ret.push(match &captures[1] { + ".." => Command::CdUp, + "/" => Command::CdRoot, + s => Command::Cd(s.to_string()), + }) + } + } + ret +} + +fn parse_ls(lines: &mut std::iter::Peekable>) -> Vec { + let mut ret: Vec = Vec::new(); + while lines.peek().is_some() { + // if the next line is a command, then we are at the end of the ls listing. + let line = lines.peek().expect("no next line"); + if IS_COMMAND_REGEX.is_match(line) { + break; + } + let captures = PARSE_LS_ENTRY_REGEX + .captures(line) + .unwrap_or_else(|| panic!("invalid line {}", line)); + ret.push(match &captures[1] { + "dir" => LsEntry::Dir(captures[2].to_string()), + _ => LsEntry::File(ParseFile { + size: str::parse(&captures[1]).unwrap_or_else(|_| panic!("invalid line {}", line)), + name: captures[2].to_string(), + }), + }); + lines.next(); + } + ret +} + +pub fn parse(input: &str) -> NodeRef { + commands_to_tree(parse_to_commands(input)) +} + +pub fn commands_to_tree(input: Vec) -> NodeRef { + let root = NodeRef::new_dir("/".to_string()); + let mut cursor = NodeRef(Rc::clone(&root)); + for command in input { + match command { + Command::CdRoot => cursor = NodeRef(Rc::clone(&root)), + Command::CdUp => cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap(), + Command::Cd(name) => cursor = cursor.add_dir(name).unwrap(), + Command::Ls(ls) => { + for entry in ls { + match entry { + LsEntry::Dir(_) => { + //dirs dont exist until you cd into them. + } + LsEntry::File(f) => { + cursor.add_file(f.name, f.size).unwrap(); + } + }; + } + } + } + } + root +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse_to_commands() { + let input = concat!( + "$ cd /\n", + "$ ls\n", + "dir a\n", + "14848514 b.txt\n", + "8504156 c.dat\n", + "dir d\n", + "$ cd a\n", + "$ ls\n", + "dir e\n", + "29116 f\n", + "2557 g\n", + "62596 h.lst\n", + "$ cd e\n", + "$ ls\n", + "584 i\n", + "$ cd ..\n", + "$ cd ..\n", + "$ cd d\n", + "$ ls\n", + "4060174 j\n", + "8033020 d.log\n", + "5626152 d.ext\n", + "7214296 k" + ); + assert_eq!( + parse_to_commands(input), + vec![ + Command::CdRoot, + Command::Ls(vec![ + LsEntry::Dir(String::from("a")), + LsEntry::File(ParseFile { + size: 14848514, + name: String::from("b.txt") + }), + LsEntry::File(ParseFile { + size: 8504156, + name: String::from("c.dat") + }), + LsEntry::Dir(String::from("d")) + ]), + Command::Cd(String::from("a")), + Command::Ls(vec![ + LsEntry::Dir(String::from("e")), + LsEntry::File(ParseFile { + size: 29116, + name: String::from("f") + }), + LsEntry::File(ParseFile { + size: 2557, + name: String::from("g") + }), + LsEntry::File(ParseFile { + size: 62596, + name: String::from("h.lst") + }), + ]), + Command::Cd(String::from("e")), + Command::Ls(vec![LsEntry::File(ParseFile { + size: 584, + name: String::from("i") + }),]), + Command::CdUp, + Command::CdUp, + Command::Cd(String::from("d")), + Command::Ls(vec![ + LsEntry::File(ParseFile { + size: 4060174, + name: String::from("j") + }), + LsEntry::File(ParseFile { + size: 8033020, + name: String::from("d.log") + }), + LsEntry::File(ParseFile { + size: 5626152, + name: String::from("d.ext") + }), + LsEntry::File(ParseFile { + size: 7214296, + name: String::from("k") + }), + ]), + ] + ) + } + #[test] + fn test_commands_to_tree() { + let input = vec![ + Command::CdRoot, + Command::Ls(vec![ + LsEntry::Dir(String::from("a")), + LsEntry::File(ParseFile { + size: 14848514, + name: String::from("b.txt"), + }), + LsEntry::File(ParseFile { + size: 8504156, + name: String::from("c.dat"), + }), + LsEntry::Dir(String::from("d")), + ]), + Command::Cd(String::from("a")), + Command::Ls(vec![ + LsEntry::Dir(String::from("e")), + LsEntry::File(ParseFile { + size: 29116, + name: String::from("f"), + }), + LsEntry::File(ParseFile { + size: 2557, + name: String::from("g"), + }), + LsEntry::File(ParseFile { + size: 62596, + name: String::from("h.lst"), + }), + ]), + Command::Cd(String::from("e")), + Command::Ls(vec![LsEntry::File(ParseFile { + size: 584, + name: String::from("i"), + })]), + Command::CdUp, + Command::CdUp, + Command::Cd(String::from("d")), + Command::Ls(vec![ + LsEntry::File(ParseFile { + size: 4060174, + name: String::from("j"), + }), + LsEntry::File(ParseFile { + size: 8033020, + name: String::from("d.log"), + }), + LsEntry::File(ParseFile { + size: 5626152, + name: String::from("d.ext"), + }), + LsEntry::File(ParseFile { + size: 7214296, + name: String::from("k"), + }), + ]), + ]; + let tree = commands_to_tree(input); + println!("{}", tree); + assert_eq!(Rc::clone(tree.deref()).borrow().get_total_size(), 48381165) + } +} diff --git a/2022/days/07/src/part1.rs b/2022/days/07/src/part1.rs new file mode 100644 index 0000000..688f89a --- /dev/null +++ b/2022/days/07/src/part1.rs @@ -0,0 +1,37 @@ +use crate::file_tree::*; + +pub fn part1(input: NodeRef) -> usize { + let dirs = input.get_all_dirs(); + dirs.iter() + .map(|d| d.borrow().get_total_size()) + .filter(|s| *s <= 100000) + .sum() +} + +#[cfg(test)] +mod tests { + use std::{ops::Deref, rc::Rc}; + + use super::*; + + #[test] + fn test_part1() { + let mut root = NodeRef::new_dir("/".to_string()); + let mut cursor = root.add_node(Node::new_dir("a".to_string())).unwrap(); + cursor = cursor.add_dir("e".to_string()).unwrap(); + cursor.add_file("i".to_string(), 584).unwrap(); + cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap(); + cursor.add_file("f".to_string(), 29116).unwrap(); + cursor.add_file("g".to_string(), 2557).unwrap(); + cursor.add_file("h.lst".to_string(), 62596).unwrap(); + cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap(); + cursor.add_file("b.txt".to_string(), 14848514).unwrap(); + cursor.add_file("c.dat".to_string(), 8504156).unwrap(); + cursor = cursor.add_dir("d".to_string()).unwrap(); + cursor.add_file("j".to_string(), 4060174).unwrap(); + cursor.add_file("d.log".to_string(), 8033020).unwrap(); + cursor.add_file("d.ext".to_string(), 5626152).unwrap(); + cursor.add_file("k".to_string(), 7214296).unwrap(); + assert_eq!(part1(root), 95437); + } +} diff --git a/2022/days/07/src/part2.rs b/2022/days/07/src/part2.rs new file mode 100644 index 0000000..bf69baa --- /dev/null +++ b/2022/days/07/src/part2.rs @@ -0,0 +1,44 @@ +use crate::file_tree::*; + +const TOTAL_SPACE: usize = 70000000; +const NEEDED_SPACE: usize = 30000000; + +pub fn part2(input: NodeRef) -> usize { + let used_space = input.borrow().get_total_size(); + let unused_space = TOTAL_SPACE - used_space; + let space_to_free = NEEDED_SPACE - unused_space; + let dirs = input.get_all_dirs(); + dirs.iter() + .map(|d| d.borrow().get_total_size()) + .filter(|s| *s >= space_to_free) + .min() + .unwrap() +} + +#[cfg(test)] +mod tests { + use std::{ops::Deref, rc::Rc}; + + use super::*; + + #[test] + fn test_part2() { + let mut root = NodeRef::new_dir("/".to_string()); + let mut cursor = root.add_node(Node::new_dir("a".to_string())).unwrap(); + cursor = cursor.add_dir("e".to_string()).unwrap(); + cursor.add_file("i".to_string(), 584).unwrap(); + cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap(); + cursor.add_file("f".to_string(), 29116).unwrap(); + cursor.add_file("g".to_string(), 2557).unwrap(); + cursor.add_file("h.lst".to_string(), 62596).unwrap(); + cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap(); + cursor.add_file("b.txt".to_string(), 14848514).unwrap(); + cursor.add_file("c.dat".to_string(), 8504156).unwrap(); + cursor = cursor.add_dir("d".to_string()).unwrap(); + cursor.add_file("j".to_string(), 4060174).unwrap(); + cursor.add_file("d.log".to_string(), 8033020).unwrap(); + cursor.add_file("d.ext".to_string(), 5626152).unwrap(); + cursor.add_file("k".to_string(), 7214296).unwrap(); + assert_eq!(part2(root), 24933642); + } +} diff --git a/2022/days/08/Cargo.toml b/2022/days/08/Cargo.toml new file mode 100644 index 0000000..987173b --- /dev/null +++ b/2022/days/08/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "day08" +authors.workspace = true +description.workspace = true +version.workspace = true +edition.workspace = true diff --git a/2022/days/08/src/input.txt b/2022/days/08/src/input.txt new file mode 100644 index 0000000..a531013 --- /dev/null +++ b/2022/days/08/src/input.txt @@ -0,0 +1,99 @@ +002100030222341303232115221524311502200403234452204125251345024423544443305142410110142101223120110 +102030322341143330244233013052025453422005415304655426206452251310214055314024034341233110302320003 +003012203404011430120134554314552441635001641050211406204621114102021543144514102510421243314102033 +330313423002034140035001210441156554545625042262651356556544202500446121455112434243313013430141203 +331203121131230002055113430244610062654034520106363462155201210355601153542301323442223310134324300 +232201231021003254355411402310326206625011564114125202263504451451212600155351424154310240411213431 +033033333301011523544023206136145505304224325606020360006206455564513553512054354124523232201230441 +132201032234334044251334220345360402456541662253556375754662323265201641514121105025300453041111234 +314322341322104402235020206565044225363527617767574524475421763504341061551154250344125514014234344 +101323043023430543342440532324326413655657527215661116623455613664321005134300223542510253102211310 +320404242514122111525043444530625417656773117247512712444315767422412130351505513231104322032421303 +221204123205133142044056245654205231734371546616753217321556472223654044043612554152141554333102034 +340310155225452152216635634352712541366312326272262143522347111166646736001360102010220214000133002 +012404003515002416422500163244271366252711531615333437352461454777311142132000140205630042305222013 +332434552302203445503543424523327464362526657251687634745536521746523154717531643250132300541053000 +020130312425316362611130462217125425435545265467725256332777233137141524314631100051153314314343032 +112115124512002346011342433146124542356845483862756322785545283652723747276776403131622540014001524 +332354013101003031053022245431274627654677343638672643442563448782737464337546541546630431125021330 +220315320142064161406534365262377268373743527784575246325564676238816733767331345114363612344051535 +102041153526000601402325625766534543527882476653366727573448727775677146365732431425225562043130034 +350054114310533002426654125166575285757827422257872378766383267543484865317252532765440216543555512 +222440404353016144747347457368562668586285847553578732435887584463446862116134751240360645225435344 +554234546163262630313431762248876668663352436888374587856263343842526635237314231451062036605442520 +525531324662660356256614344438373575732699988366775989976447384338336827686445577222030363631240512 +055541261042533424177375756738443482846986979788978997559377679255463858237757327464422026230510130 +514123221240250442457744728347386637684953574546455344754548333793233865436751231314653541223102202 +355454250661114645144551785724753237378345375493453967559796675839837444334776625552412552302431302 +202445234333206767744653874724276586973668878949653473947686567565487325864733735677672241416513452 +445415223211061633767433865252483574744685974593334963668983745643354885658423263536531213102544202 +201405464251164654177385783224666473975674643767946648464678958969336335638578275154116223152222102 +401423140356441654745572266848965593553995667644648964747884544439493545472454437715336645303346422 +154440323240741427732867467564957336394985859766644495658985963583496399736552632162756445212536404 +441663663062661372122867364584655388977474857585778686889578799644949733463423826715534215154065204 +422036122016243651174663588693898583374968974778579585977478599643389537573534354622377452555411315 +430412403362272513348763673566578945645997454758694486758844958569786758359475575577532661126532300 +503653020441267422765353469867998339764449596776968996449777464644846938866332635583727771665263026 +006252631541331635768754753357384754988659585857956567666645975599653466655333342485345762600032403 +215205542775713732868842389885585646884858449858579777975997584997463698339932263363162431251615251 +342224450731115175762626546538955447796468885776778879697695699945446388444478355347827635732006646 +045011110226211633623658548365544498466468766878699597655897586488555435934935526883851537736604133 +440352212243431376382869634434568447654566895897796875679759667598898849334873844583742271767024403 +566632367121414762272448784755746799985759966559657989697977677955455754549393784586875275341562621 +004131167135757426882464486773699786789959957795985595559587775554479945637849747667752242212324244 +022411031432724262533554794664597446479869568767598899669969588984864457535986725263473577457413134 +036415005331162527346577487593798458668976888776888766856699598847776567686579476836656723623111342 +504001302331545267684439554776894957999788577876688969865558955547965687556849786463457244355044511 +464266074264126575276833864784546697885788878967966988678696686685576789843676844576623242451411411 +660130573642326366362654785549676574587876888769689696798799988678648554635745724364273772474666502 +413511521313437652422664948645649566979966676679778669968777776786958464356797545247763267365643645 +455033174473274564484285387995879595555686569997977698868769855686564847593489668858847744131410225 +560316675532344635443349663994499869866598568889798868967976679655597494679336978524332246567265361 +121053163342234352453837754569968465557968697766766888969966667796479457384444468264837376474515455 +604062313527642634768255846899648545559665886668966887999959659769978495794795825775373713613231451 +041031112622754332842439776736966994677888699898679988967779696758849589365579766676242256227420364 +630161363126476778455475799658545955598576568877768698668579988799596866465635488284555252726211044 +455563641427127283364758796475975894658677688789777769876667978747955677573575525588444241765111511 +256420063532645225542863884958844496596759999769769687678888788875449888945958948378756476127155054 +523256165217547362636325547686549767698957967985968987897777685866576744344388256886854362647342110 +205224606764556763544234874676659474468968576879668558856675855668779847849738247387744421321145610 +022651355615653552468486676459694744747575877656886776677858584988944678787576556747724125467333305 +526313424324717126486746644643397589664468865599858886996669788566489473798387676766873216657521426 +426530404522411762572567697375959747975669667958685679878659587764977658398697353283563215312244014 +023510245741131775436864579684699874979976567776557765866775469587757498544476554753722641656303654 +211341433442225414565332887899363678699495567888998675657659688744458493387343842346747477252626250 +406543152154335614758277748595836896786654948759999978569588555764838686653647362854723163226456101 +333640633617315535456525364849458558744656899855554897897568844446533866457545654847562377442214226 +040003053246534354438748723933365934878485997458955574785966996653353969666867276761661111124104550 +405602516206264365157378627495546935658594587869579958969686766986836687348285865231616336232000100 +304131030254233641578272475868953446545577766644956989679964489688554398956223433417637732661500540 +131164662225325441733366324345477954639475997658684766465487974699579665344326248136151472051130445 +452312154206174654138684277376889449945746954689646875777596486949365968888456226732332263263420000 +003010154551246223274282454345355673349967689986885795449989359633496728553885221437611730454554455 +131435126460017635544785754344874379695379366384573934357795398633967475353836864461424146264354142 +350154544045013352533173566257757787385448697484997454578735937499665628425542376452563635450224022 +302420224365163651765264446875287359533637498445639443969586466433384346337722662774436566624454214 +415242456321105173655733744886343826548944666338683876383973497998744488687446541256724244661531431 +155303206134314124372553618623857237346567857564464797593393675563536467777317174625640132203003240 +335521544652523624641575451785635352333587957647598535633948867838652636686573137515062356442045153 +235314500244636615342325346277256685653838226755493858683465683736283367654226655456541546644313125 +252520511531061305614364671212856473625642477732845278766573642425286572562373137446456005011330433 +241525455120116046543737642325543677623243884242534423327827446383376441727657314343125403632434002 +301045223551220356167117621755325772252845222546246588464784874685774676163655131632622146412415515 +011150133311336614251435416453632383454327534367288242328746537673543714263674263262001132354544412 +314104033000306256531666256433553535833538337463847277453476563227672715617272601302551120422305504 +104211442013141664402363645617163435245556228235337864656673626354151416721375243323635625100210424 +413422313502535362615054171511431775335574748526574728747453724472157632635263350024552502052340024 +131225301023304456424150404525765416565572272321835377167235317312551645334432406536160545434122120 +342131052232413325301451041516716541737346252413667115612642227312572433104525003114240240141232002 +244421101354005430232434420344323273421374225635551363463245561271743411452116466311034334101231020 +232404402304311415164151401553463731147111147752141732625152553615361046133341313265525232544143442 +201321033520133414312301326330253041267251614477322566645472656414545035321106361434351501123314104 +211232034442524242313453325046331353174352335422752364775746537513333534355120322320404054014303124 +224032233240430510135541652065052415154147565656231651653327511443424113100543020223335130010141400 +004110101133543440511523265424013341433043655022512172622140322434116104552043413352211021312421433 +000304433232402410151205333526613043463556021413402141634154404530112303306244402221312522221004042 +200204441020135232033032541516232550445221141520665016336536052063115335040344025054213324400312303 +300211022440310123055510053251505226452265556365100101014044645236505213550201425252404100302413231 +310312413210032422053242024243343060135340422313312403505631104430120233112324204414021331012401232 +132020341330304022053503522313342026211133610000020554213662244142551253124302245242110111033101203 diff --git a/2022/days/08/src/main.rs b/2022/days/08/src/main.rs new file mode 100644 index 0000000..644e313 --- /dev/null +++ b/2022/days/08/src/main.rs @@ -0,0 +1,16 @@ +mod part1; +mod part2; +mod utilities; + +type StructuredInput = Vec>; + +fn main() { + let input = include_str!("./input.txt"); + let structured_input = utilities::parse(input); + + println!("Part One"); + println!("Result: {}", part1::part1(&structured_input)); + + println!("Part Two"); + println!("Result: {}", part2::part2(&structured_input)); +} diff --git a/2022/days/08/src/part1.rs b/2022/days/08/src/part1.rs new file mode 100644 index 0000000..1bd15f2 --- /dev/null +++ b/2022/days/08/src/part1.rs @@ -0,0 +1,85 @@ +use crate::StructuredInput; + +pub fn part1(input: &StructuredInput) -> usize { + let mut acc: usize = 0; + for y in 0..input.len(){ + for x in 0..input[0].len(){ + if is_visible(x, y, input){ + acc+=1; + } + } + } + acc +} + +fn is_visible(x: usize, y: usize, input: &StructuredInput) -> bool { + is_visible_north(x, y, input) + || is_visible_east(x, y, input) + || is_visible_south(x, y, input) + || is_visible_west(x, y, input) +} +fn is_visible_north(x: usize, y: usize, input: &StructuredInput) -> bool { + if y == 0 { + return true; + }; + let hight = input[y][x]; + for y in 0..y { + if input[y][x] >= hight { + return false; + } + } + true +} +fn is_visible_east(x: usize, y: usize, input: &StructuredInput) -> bool { + if x == input[0].len() { + return true; + } + let hight = input[y][x]; + for x in (x + 1)..input[0].len() { + if input[y][x] >= hight { + return false; + } + } + true +} +fn is_visible_south(x: usize, y: usize, input: &StructuredInput) -> bool { + if y == input.len() { + return true; + }; + let hight = input[y][x]; + for y in (y + 1)..input.len() { + if input[y][x] >= hight { + return false; + } + } + true +} +fn is_visible_west(x: usize, y: usize, input: &StructuredInput) -> bool { + if x == input[0].len() { + return true; + } + let hight = input[y][x]; + for x in 0..x { + if input[y][x] >= hight { + return false; + } + } + true +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part1() { + let input = vec![ + vec![3, 0, 3, 7, 3], + vec![2, 5, 5, 1, 2], + vec![6, 5, 3, 3, 2], + vec![3, 3, 5, 4, 9], + vec![3, 5, 3, 9, 0], + ]; + assert_eq!(part1(&input), 21); + } +} diff --git a/2022/days/08/src/part2.rs b/2022/days/08/src/part2.rs new file mode 100644 index 0000000..963fe25 --- /dev/null +++ b/2022/days/08/src/part2.rs @@ -0,0 +1,109 @@ +use crate::StructuredInput; + +pub fn part2(input: &StructuredInput) -> usize { + let mut max: usize = 0; + for y in 0..input.len() { + for x in 0..input[0].len() { + let tree_score = tree_score(x, y, input); + if max < tree_score{ + max = tree_score; + println!("found new max with score {} at {}, {}", tree_score, x, y) + } + } + } + max +} +fn tree_score(x: usize, y: usize, input: &StructuredInput) -> usize { + trees_visible_north(x, y, input) + * trees_visible_east(x, y, input) + * trees_visible_south(x, y, input) + * trees_visible_west(x, y, input) +} +fn trees_visible_north(x: usize, y: usize, input: &StructuredInput) -> usize { + if y == 0 { + return 0; + }; + let hight = input[y][x]; + let mut trees: usize = 0; + for y in (0..y).rev() { + trees += 1; + if input[y][x] >= hight { + break + } + } + trees +} +fn trees_visible_east(x: usize, y: usize, input: &StructuredInput) -> usize { + if x == input[0].len() { + return 0; + } + let hight = input[y][x]; + let mut trees: usize = 0; + for x in (x + 1)..input[0].len() { + trees += 1; + if input[y][x] >= hight { + break + } + } + trees +} +fn trees_visible_south(x: usize, y: usize, input: &StructuredInput) -> usize { + if y == input.len() { + return 0; + }; + let hight = input[y][x]; + let mut trees: usize = 0; + for y in (y + 1)..input.len() { + trees += 1; + if input[y][x] >= hight { + break + } + } + trees +} +fn trees_visible_west(x: usize, y: usize, input: &StructuredInput) -> usize { + if x == input[0].len() { + return 0; + } + let hight = input[y][x]; + let mut trees: usize = 0; + for x in (0..x).rev() { + trees += 1; + if input[y][x] >= hight { + break + } + } + trees +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part2() { + let input = vec![ + vec![3, 0, 3, 7, 3], + vec![2, 5, 5, 1, 2], + vec![6, 5, 3, 3, 2], + vec![3, 3, 5, 4, 9], + vec![3, 5, 3, 9, 0], + ]; + assert_eq!(part2(&input), 8); + } + #[test] + fn test_trees_visible() { + let input = vec![ + vec![3, 0, 3, 7, 3], + vec![2, 5, 5, 1, 2], + vec![6, 5, 3, 3, 2], + vec![3, 3, 5, 4, 9], + vec![3, 5, 3, 9, 0], + ]; + assert_eq!(trees_visible_north(2, 3, &input), 2); + assert_eq!(trees_visible_east(2, 3, &input), 2); + assert_eq!(trees_visible_south(2, 3, &input), 1); + assert_eq!(trees_visible_west(2, 3, &input), 2); + assert_eq!(tree_score(2, 3, &input), 8); + } +} diff --git a/2022/days/08/src/utilities.rs b/2022/days/08/src/utilities.rs new file mode 100644 index 0000000..acf6673 --- /dev/null +++ b/2022/days/08/src/utilities.rs @@ -0,0 +1,26 @@ +pub fn parse(input: &str) -> Vec> { + input + .lines() + .map(|l| l.chars().map(|c| c.to_digit(10).unwrap() as u8).collect()) + .collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse() { + let input = concat!("30373\n", "25512\n", "65332\n", "33549\n", "35390\n",); + assert_eq!( + parse(input), + vec![ + vec![3, 0, 3, 7, 3], + vec![2, 5, 5, 1, 2], + vec![6, 5, 3, 3, 2], + vec![3, 3, 5, 4, 9], + vec![3, 5, 3, 9, 0] + ] + ); + } +} diff --git a/2022/days/09/Cargo.toml b/2022/days/09/Cargo.toml new file mode 100644 index 0000000..eadb393 --- /dev/null +++ b/2022/days/09/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "day09" +authors.workspace = true +description.workspace = true +version.workspace = true +edition.workspace = true + +[dependencies] +aoc_libs.workspace = true +regex.workspace = true +once_cell.workspace = true diff --git a/2022/days/09/src/input.txt b/2022/days/09/src/input.txt new file mode 100644 index 0000000..68e6657 --- /dev/null +++ b/2022/days/09/src/input.txt @@ -0,0 +1,2000 @@ +D 1 +L 2 +D 2 +L 1 +R 1 +D 1 +R 2 +U 1 +R 1 +D 2 +R 1 +L 2 +U 1 +D 2 +R 1 +L 2 +R 1 +U 2 +D 2 +L 1 +U 2 +R 2 +D 1 +R 2 +D 1 +U 2 +D 2 +L 1 +U 1 +R 1 +D 1 +U 1 +D 1 +U 2 +L 2 +R 1 +U 1 +R 2 +L 2 +U 2 +R 1 +L 1 +U 1 +L 2 +R 1 +D 1 +L 1 +D 2 +U 1 +D 1 +R 1 +L 2 +D 1 +R 2 +L 2 +U 1 +D 2 +R 2 +D 1 +U 1 +R 2 +D 1 +L 1 +U 2 +R 2 +D 1 +U 2 +R 1 +D 2 +R 1 +D 1 +U 2 +R 2 +U 1 +R 1 +U 1 +L 1 +U 2 +D 1 +R 2 +D 2 +R 2 +D 1 +L 2 +D 2 +L 1 +R 1 +U 1 +D 2 +L 2 +D 2 +L 1 +D 2 +R 1 +D 1 +R 2 +L 2 +R 2 +D 2 +R 1 +D 2 +R 2 +U 2 +L 2 +R 1 +U 1 +R 1 +U 1 +D 1 +U 1 +R 2 +L 1 +R 1 +D 2 +U 3 +R 1 +L 2 +D 1 +R 3 +U 1 +D 2 +R 1 +D 1 +R 2 +L 1 +R 2 +L 2 +D 3 +R 3 +D 1 +U 2 +D 2 +R 1 +D 2 +R 1 +L 3 +D 1 +L 1 +R 2 +D 3 +R 2 +D 3 +R 3 +L 2 +U 3 +D 3 +L 2 +R 3 +L 1 +U 1 +L 2 +D 2 +U 1 +D 2 +U 1 +D 2 +R 1 +U 1 +D 2 +U 1 +L 1 +R 2 +L 2 +D 3 +U 2 +L 3 +D 2 +U 1 +D 3 +L 1 +U 1 +D 2 +R 2 +U 1 +L 2 +D 3 +L 3 +D 3 +U 1 +R 1 +U 2 +D 1 +R 3 +L 1 +D 1 +U 3 +D 1 +L 2 +U 1 +L 3 +D 2 +L 2 +R 1 +L 3 +U 3 +R 3 +U 1 +R 2 +D 1 +L 3 +U 3 +D 3 +L 2 +D 1 +U 2 +D 2 +U 2 +R 3 +U 2 +L 1 +U 1 +R 2 +L 3 +D 3 +U 3 +R 1 +L 1 +U 1 +D 1 +U 2 +R 1 +D 3 +L 1 +R 3 +L 4 +D 3 +R 2 +U 3 +R 1 +L 4 +R 1 +L 3 +R 3 +U 2 +D 1 +L 3 +D 4 +U 4 +L 3 +U 4 +R 4 +L 1 +R 4 +D 1 +R 1 +L 3 +R 3 +L 1 +R 4 +D 2 +L 3 +D 2 +U 1 +R 3 +D 2 +L 3 +R 4 +L 3 +U 3 +D 3 +R 1 +D 2 +U 4 +L 1 +R 1 +L 4 +R 3 +U 1 +L 4 +R 1 +U 3 +R 1 +L 1 +U 3 +R 3 +U 2 +R 2 +L 4 +U 1 +R 1 +D 3 +L 2 +D 1 +L 3 +R 3 +D 3 +L 4 +U 2 +L 3 +U 4 +L 2 +U 2 +D 4 +L 3 +D 1 +U 2 +L 3 +R 4 +U 1 +L 4 +R 4 +L 3 +U 2 +D 4 +L 1 +R 3 +D 2 +L 3 +U 1 +L 3 +U 4 +R 2 +U 2 +R 1 +D 2 +L 4 +R 3 +D 2 +L 3 +U 3 +D 3 +L 1 +D 4 +R 3 +U 1 +R 3 +L 1 +U 3 +R 2 +D 3 +L 3 +U 3 +L 3 +D 5 +U 4 +L 5 +D 2 +R 1 +D 2 +U 5 +R 1 +U 2 +D 2 +R 4 +U 2 +L 3 +U 2 +R 5 +D 4 +L 3 +U 3 +D 1 +R 2 +L 3 +U 1 +R 5 +D 1 +U 2 +R 1 +U 3 +L 2 +U 5 +R 4 +D 5 +L 4 +D 4 +L 2 +U 4 +R 5 +L 1 +D 1 +R 2 +U 2 +D 5 +R 2 +U 4 +L 3 +D 2 +R 4 +L 1 +R 1 +L 2 +U 4 +D 4 +R 5 +D 3 +R 1 +D 4 +L 4 +U 5 +L 2 +U 2 +L 3 +R 4 +U 5 +L 4 +U 2 +D 1 +R 2 +U 4 +L 1 +U 3 +R 1 +U 5 +D 5 +U 4 +D 3 +L 3 +U 3 +D 2 +U 4 +R 3 +D 1 +U 5 +D 3 +R 1 +U 2 +R 1 +D 4 +R 4 +L 4 +U 1 +L 5 +R 3 +D 2 +U 2 +L 5 +R 1 +L 1 +U 3 +D 4 +R 5 +L 4 +D 5 +L 2 +U 1 +D 1 +U 3 +R 4 +D 4 +L 4 +U 3 +L 2 +D 2 +L 5 +U 1 +R 6 +U 4 +R 3 +D 2 +R 6 +D 2 +R 6 +L 3 +R 4 +L 3 +D 5 +U 2 +R 5 +L 5 +R 4 +U 6 +R 6 +D 1 +U 4 +D 4 +L 3 +D 2 +U 5 +R 2 +U 5 +D 2 +U 3 +R 2 +D 5 +R 2 +D 6 +R 1 +U 5 +D 2 +L 6 +U 2 +L 4 +R 6 +L 6 +D 6 +L 3 +D 5 +L 1 +R 5 +D 4 +L 4 +U 1 +R 3 +D 6 +R 6 +U 2 +R 4 +D 1 +R 4 +U 4 +L 6 +U 6 +D 6 +R 2 +D 2 +L 4 +R 6 +L 1 +U 5 +D 4 +U 4 +R 3 +U 1 +D 3 +R 6 +D 4 +U 5 +R 3 +D 5 +R 5 +D 4 +U 4 +D 3 +U 6 +L 1 +D 4 +U 6 +L 3 +R 3 +D 6 +U 4 +R 3 +L 3 +R 1 +D 6 +R 4 +U 2 +R 6 +L 3 +D 3 +L 4 +R 3 +L 4 +R 3 +U 4 +R 3 +D 4 +R 6 +D 2 +U 1 +D 2 +L 3 +D 4 +L 1 +D 5 +L 6 +U 4 +L 7 +R 6 +U 7 +R 7 +L 5 +D 1 +U 3 +R 6 +U 6 +R 2 +U 5 +R 4 +U 7 +R 1 +L 3 +D 7 +L 4 +D 6 +U 1 +L 1 +R 3 +D 2 +L 5 +R 1 +U 1 +L 1 +R 6 +L 6 +D 2 +U 3 +L 6 +R 6 +L 3 +D 3 +R 2 +L 1 +U 5 +R 6 +D 2 +L 5 +U 1 +D 4 +R 3 +L 6 +R 2 +L 4 +D 4 +R 5 +D 3 +R 2 +L 5 +U 7 +D 5 +L 3 +R 2 +D 5 +U 5 +D 2 +U 2 +L 2 +R 5 +L 2 +D 5 +R 3 +U 4 +R 4 +D 1 +L 6 +U 2 +R 7 +L 3 +U 4 +D 2 +R 5 +L 6 +R 7 +L 1 +U 5 +L 3 +U 7 +D 6 +R 3 +D 3 +U 7 +L 4 +R 2 +U 1 +L 1 +R 6 +D 5 +R 7 +U 4 +D 2 +R 2 +D 4 +L 1 +U 4 +D 2 +R 2 +D 5 +U 7 +D 1 +U 7 +R 3 +U 5 +L 1 +R 7 +L 2 +R 5 +U 5 +R 5 +D 4 +U 5 +L 7 +D 3 +R 5 +L 3 +R 1 +U 8 +L 4 +U 3 +D 4 +U 1 +L 2 +D 5 +L 5 +D 4 +U 3 +L 2 +R 3 +D 6 +L 4 +U 3 +R 1 +U 1 +D 3 +R 5 +D 4 +L 7 +U 7 +R 7 +L 6 +D 7 +U 5 +L 2 +U 4 +R 8 +L 4 +U 4 +R 5 +U 1 +R 1 +D 7 +R 6 +L 8 +R 1 +D 4 +U 5 +R 6 +L 3 +R 7 +L 4 +D 7 +U 8 +R 5 +D 5 +U 4 +L 3 +D 4 +U 1 +L 8 +R 8 +U 2 +L 5 +R 7 +D 5 +L 5 +D 3 +L 5 +U 4 +D 1 +U 6 +R 7 +D 5 +R 4 +D 6 +U 4 +L 5 +D 8 +U 5 +L 7 +D 1 +U 8 +R 3 +U 4 +R 5 +U 7 +R 6 +L 3 +U 4 +L 7 +R 5 +U 6 +L 2 +R 2 +U 7 +R 4 +D 2 +L 2 +D 6 +L 5 +D 5 +L 1 +R 5 +D 1 +U 5 +L 8 +R 3 +D 4 +R 2 +U 2 +L 5 +D 4 +U 7 +D 9 +R 9 +U 9 +R 3 +L 2 +D 8 +U 6 +L 1 +R 1 +D 4 +L 9 +R 9 +L 3 +U 4 +D 7 +U 9 +D 5 +R 8 +D 6 +R 9 +U 2 +R 2 +U 8 +R 5 +U 6 +L 8 +D 7 +L 2 +U 3 +R 3 +U 6 +L 5 +R 4 +D 6 +U 6 +R 6 +D 5 +U 5 +D 6 +L 4 +D 2 +U 6 +L 8 +U 3 +D 6 +U 1 +L 7 +D 6 +R 3 +D 7 +U 6 +D 4 +U 5 +R 3 +D 7 +L 5 +U 6 +L 6 +R 2 +D 7 +L 7 +U 5 +D 9 +R 6 +L 9 +R 1 +L 6 +U 5 +R 4 +U 7 +L 2 +U 5 +L 9 +U 3 +R 2 +L 5 +R 2 +U 6 +L 3 +D 7 +R 9 +D 3 +L 4 +R 2 +D 8 +L 6 +D 9 +L 5 +D 1 +R 8 +D 4 +U 5 +L 7 +D 2 +R 2 +L 7 +D 6 +L 7 +R 1 +D 4 +U 3 +D 3 +U 8 +R 8 +L 3 +D 8 +U 7 +R 4 +D 9 +L 3 +U 10 +L 4 +D 4 +R 7 +U 1 +L 10 +U 10 +R 9 +U 3 +L 3 +R 1 +D 10 +L 4 +U 9 +L 4 +U 7 +L 8 +R 7 +D 1 +U 3 +L 3 +U 2 +R 4 +U 5 +D 9 +L 5 +U 10 +L 2 +U 1 +L 7 +D 9 +L 8 +R 10 +D 7 +U 9 +L 4 +U 10 +L 3 +U 1 +D 1 +L 1 +D 6 +U 8 +R 8 +L 6 +U 9 +L 3 +U 6 +R 6 +U 3 +R 7 +U 2 +D 4 +L 4 +R 8 +D 3 +R 8 +U 2 +R 3 +D 6 +U 4 +R 9 +L 4 +D 4 +L 6 +R 2 +D 10 +L 7 +R 9 +L 7 +D 8 +R 2 +D 2 +U 9 +R 2 +U 1 +R 10 +U 1 +D 2 +U 10 +D 10 +U 5 +R 3 +U 5 +R 10 +L 3 +R 5 +U 5 +L 4 +D 3 +L 7 +D 3 +U 10 +R 7 +L 3 +D 2 +L 1 +D 1 +L 7 +R 2 +L 10 +D 6 +R 4 +L 8 +R 9 +D 5 +L 2 +D 4 +R 1 +L 4 +R 8 +D 5 +R 10 +D 1 +L 10 +D 11 +L 10 +R 4 +L 3 +D 1 +U 4 +L 9 +D 6 +U 2 +R 4 +L 2 +U 5 +D 1 +R 6 +L 5 +U 7 +D 2 +R 5 +D 9 +R 11 +U 9 +D 9 +R 2 +L 9 +D 4 +U 7 +L 10 +D 7 +U 4 +D 1 +U 4 +D 10 +L 8 +D 3 +L 8 +D 8 +R 7 +D 10 +R 5 +U 1 +L 11 +D 2 +L 11 +U 4 +L 8 +D 10 +U 3 +D 11 +R 10 +L 1 +D 2 +U 11 +L 4 +U 2 +L 6 +D 7 +R 10 +L 2 +D 7 +R 9 +U 6 +D 5 +R 9 +U 1 +D 3 +R 8 +D 7 +L 3 +D 8 +U 4 +D 4 +R 8 +L 7 +R 1 +D 3 +U 7 +D 4 +L 10 +R 1 +D 6 +R 1 +L 5 +D 2 +L 9 +R 1 +U 5 +D 4 +U 11 +L 6 +R 11 +D 11 +R 6 +U 9 +R 1 +L 5 +U 3 +R 10 +L 8 +R 6 +L 2 +R 8 +D 11 +L 5 +R 3 +L 1 +R 3 +L 8 +R 10 +U 2 +R 2 +D 7 +L 9 +U 2 +L 8 +D 3 +U 1 +L 11 +D 1 +U 6 +L 2 +R 7 +D 5 +R 1 +D 11 +U 12 +D 10 +L 11 +U 3 +D 10 +L 6 +U 3 +D 12 +R 4 +D 9 +R 2 +U 12 +R 11 +L 2 +R 7 +L 11 +U 12 +R 12 +U 1 +R 2 +D 8 +R 10 +U 2 +D 8 +U 8 +D 5 +U 10 +R 4 +U 8 +D 4 +R 8 +D 8 +R 2 +U 4 +L 10 +D 2 +L 10 +R 2 +D 9 +U 6 +L 2 +D 10 +L 2 +D 11 +R 11 +U 2 +L 6 +D 3 +U 3 +R 4 +U 9 +L 9 +R 8 +D 5 +L 9 +U 8 +L 11 +D 8 +R 12 +U 1 +D 1 +U 7 +L 11 +U 2 +L 12 +R 11 +U 8 +R 12 +U 11 +L 7 +U 5 +L 4 +R 4 +D 1 +U 6 +D 7 +U 5 +R 5 +U 10 +D 2 +R 9 +L 12 +D 9 +U 6 +L 11 +D 7 +L 6 +D 10 +L 9 +D 11 +R 7 +D 10 +L 1 +R 9 +D 10 +L 1 +U 1 +L 13 +R 10 +D 9 +L 9 +U 7 +L 10 +R 1 +U 12 +R 13 +U 8 +L 9 +U 5 +L 11 +D 11 +U 8 +R 2 +D 2 +R 7 +D 3 +L 3 +R 2 +L 6 +U 11 +L 6 +U 8 +L 11 +U 12 +L 13 +D 4 +L 8 +U 11 +D 9 +U 11 +D 10 +U 4 +D 9 +L 12 +D 6 +L 11 +U 11 +L 1 +D 6 +R 12 +U 9 +D 1 +L 4 +R 9 +L 13 +R 10 +D 9 +L 2 +R 3 +D 10 +L 13 +R 3 +L 8 +R 8 +L 1 +R 5 +L 12 +D 10 +R 6 +U 7 +R 11 +U 11 +R 10 +D 9 +R 12 +D 8 +U 6 +L 8 +D 6 +L 10 +R 2 +L 2 +D 12 +U 12 +R 11 +L 8 +U 2 +R 2 +L 11 +U 11 +L 7 +D 2 +U 2 +L 9 +D 4 +R 2 +U 7 +D 3 +R 1 +D 6 +U 13 +R 11 +D 1 +U 4 +R 9 +D 7 +L 12 +U 12 +L 10 +U 9 +L 1 +D 1 +U 6 +L 1 +D 13 +U 14 +L 2 +D 6 +U 8 +D 8 +L 9 +D 1 +R 11 +D 6 +L 8 +R 11 +U 4 +L 5 +R 5 +D 10 +U 10 +R 7 +D 7 +L 8 +U 9 +R 1 +L 5 +D 4 +L 13 +D 4 +R 14 +D 13 +R 9 +L 13 +R 7 +L 14 +R 12 +D 1 +U 8 +L 10 +U 7 +D 9 +U 7 +D 13 +L 1 +R 1 +D 14 +L 9 +U 5 +R 7 +U 2 +L 11 +D 5 +U 7 +D 1 +L 13 +U 14 +L 1 +D 3 +R 3 +D 1 +L 3 +U 4 +R 14 +U 11 +R 4 +L 13 +U 3 +R 8 +D 5 +U 8 +L 6 +R 14 +L 3 +D 2 +L 5 +U 11 +R 8 +L 11 +U 8 +D 11 +U 14 +R 14 +L 4 +D 10 +R 11 +U 1 +D 4 +U 11 +D 5 +L 5 +R 14 +U 12 +L 1 +D 4 +R 11 +L 5 +R 9 +U 9 +D 2 +U 12 +D 2 +R 8 +U 6 +L 11 +U 8 +L 6 +U 9 +L 5 +U 3 +D 10 +R 10 +D 6 +U 1 +R 13 +U 5 +R 8 +U 11 +L 11 +D 10 +R 11 +U 2 +D 3 +R 10 +D 2 +L 9 +R 7 +L 8 +U 1 +R 6 +L 3 +D 10 +U 14 +D 4 +U 7 +L 6 +R 8 +U 15 +D 14 +U 5 +D 15 +U 2 +D 4 +L 11 +U 8 +L 10 +U 15 +R 8 +U 14 +D 6 +R 9 +L 15 +R 9 +L 11 +R 3 +D 2 +U 10 +L 12 +D 2 +L 5 +D 1 +R 8 +U 7 +L 7 +D 7 +L 15 +D 11 +U 3 +L 4 +U 10 +L 14 +U 10 +D 10 +U 11 +D 1 +L 3 +R 11 +L 3 +U 10 +L 2 +D 8 +R 8 +L 12 +D 15 +U 10 +L 14 +R 4 +L 9 +R 11 +U 10 +R 7 +D 13 +U 11 +D 10 +R 3 +U 6 +R 9 +L 15 +R 11 +D 6 +R 14 +L 7 +D 7 +L 3 +D 13 +U 10 +R 14 +U 2 +D 4 +U 1 +R 1 +D 8 +R 12 +L 15 +R 4 +L 15 +U 13 +D 12 +L 8 +D 1 +R 3 +U 11 +R 3 +U 2 +R 4 +D 15 +U 4 +L 6 +D 6 +L 9 +D 2 +L 15 +R 5 +U 2 +R 7 +D 7 +U 15 +L 4 +D 7 +R 9 +D 11 +R 8 +L 4 +R 6 +L 11 +U 16 +L 10 +U 10 +L 11 +U 9 +R 8 +U 13 +R 13 +L 5 +R 8 +L 12 +U 11 +L 4 +D 10 +R 2 +U 13 +R 4 +L 15 +D 15 +L 15 +R 16 +L 7 +R 14 +D 5 +L 16 +U 6 +D 3 +L 13 +D 8 +L 11 +U 13 +L 9 +U 6 +L 4 +U 11 +R 1 +L 13 +R 11 +L 13 +R 13 +L 9 +D 15 +R 1 +L 15 +R 14 +L 14 +U 7 +L 1 +R 6 +D 16 +L 2 +R 12 +L 4 +D 12 +R 8 +U 9 +D 10 +R 1 +L 2 +D 5 +L 3 +R 15 +L 8 +D 1 +L 1 +D 8 +U 13 +R 1 +L 2 +D 1 +R 3 +L 6 +U 12 +L 4 +D 13 +U 2 +L 4 +D 10 +R 16 +D 1 +U 1 +L 11 +D 8 +L 12 +R 8 +L 5 +R 1 +D 12 +R 2 +D 7 +U 16 +D 11 +L 15 +R 4 +U 4 +D 4 +U 4 +L 17 +U 3 +D 8 +U 1 +L 1 +U 4 +L 7 +U 9 +L 13 +D 10 +L 2 +U 7 +L 13 +D 16 +U 6 +L 10 +D 16 +L 8 +U 10 +L 6 +U 16 +L 5 +U 4 +R 9 +D 12 +R 1 +U 14 +L 14 +R 16 +D 5 +L 16 +R 14 +U 10 +R 4 +U 9 +L 15 +D 4 +U 15 +L 11 +R 14 +L 10 +D 14 +L 10 +D 12 +R 2 +D 3 +R 1 +U 1 +L 17 +U 9 +D 13 +R 7 +D 7 +U 13 +D 1 +R 14 +U 10 +R 16 +L 17 +R 7 +D 17 +U 11 +L 2 +U 16 +L 8 +U 13 +R 17 +U 5 +L 7 +R 3 +D 17 +L 10 +U 9 +D 16 +R 3 +U 5 +L 15 +R 16 +D 11 +U 9 +L 3 +R 14 +D 4 +L 4 +U 12 +D 9 +U 10 +D 15 +L 12 +R 6 +D 4 +L 14 +D 5 +L 4 +U 7 +R 15 +D 6 +L 15 +U 14 +D 10 +L 3 +D 9 +L 15 +R 9 +U 1 +L 4 +D 15 +U 12 +D 9 +R 8 +D 14 +R 15 +D 7 +U 18 +L 5 +U 6 +L 6 +D 10 +L 18 +R 3 +L 11 +D 10 +L 13 +U 13 +L 13 +R 3 +L 1 +U 3 +D 7 +L 9 +R 6 +U 18 +R 18 +U 15 +R 9 +U 4 +R 12 +L 12 +D 6 +U 10 +D 13 +L 6 +R 13 +L 13 +D 12 +U 4 +D 15 +L 12 +D 10 +U 12 +R 8 +L 13 +D 11 +L 13 +U 12 +D 5 +U 12 +R 10 +L 9 +U 13 +R 7 +D 2 +L 6 +U 13 +D 15 +R 3 +U 4 +D 5 +L 2 +D 10 +U 7 +L 2 +D 5 +L 5 +D 11 +R 5 +U 18 +L 9 +D 8 +U 12 +R 3 +U 8 +R 14 +D 1 +R 4 +L 5 +D 10 +R 18 +D 2 +R 9 +L 14 +U 4 +R 15 +D 4 +R 2 +L 4 +U 13 +R 6 +U 18 +D 4 +U 7 +L 15 +D 1 +L 6 +D 3 +U 15 +L 17 +U 15 +R 14 +L 9 +U 5 +L 4 +U 13 +R 5 +D 17 +U 17 +L 15 +U 14 +R 5 +L 1 +R 9 +U 8 +R 15 +U 18 +L 12 +R 13 +D 15 +R 5 +L 11 +R 5 +U 12 +R 8 +L 6 +R 1 +L 10 +U 17 +L 16 +U 12 +L 14 +D 16 +U 13 +D 18 +L 5 +U 16 +L 11 +D 15 +U 2 +L 9 +D 5 +L 17 +D 17 +L 4 +D 4 +L 19 +R 6 +D 6 +U 18 +R 16 +U 12 +D 2 +L 4 +U 19 +R 6 +U 1 +D 15 +R 13 +U 18 +D 12 +L 9 +U 1 +R 13 +D 18 +L 4 +D 17 +L 9 +D 8 +U 3 +D 5 +R 7 +L 16 +U 3 +L 1 +D 13 +R 17 +D 8 +R 9 +U 17 +L 2 +U 17 +D 16 +L 8 +R 9 +D 7 +L 16 +R 10 +L 16 +D 10 +L 15 +U 17 +L 2 +U 10 +D 16 +R 1 +L 2 +D 4 +R 13 +L 12 +D 8 +U 10 +L 6 +D 14 +L 6 +D 11 +R 1 +D 10 +L 18 +D 12 +R 14 +L 3 +D 7 +L 12 +R 19 +U 5 +R 19 +D 3 +L 15 +U 13 diff --git a/2022/days/09/src/main.rs b/2022/days/09/src/main.rs new file mode 100644 index 0000000..5c07519 --- /dev/null +++ b/2022/days/09/src/main.rs @@ -0,0 +1,15 @@ +mod part1; +mod part2; +mod parse; +mod rope; + +fn main() { + let input = include_str!("./input.txt"); + let structured_input = parse::parse(input); + + println!("Part One"); + println!("Result: {}", part1::part1(&structured_input)); + + println!("Part Two"); + println!("Result: {}", part2::part2(&structured_input)); +} diff --git a/2022/days/09/src/parse.rs b/2022/days/09/src/parse.rs new file mode 100644 index 0000000..9c4588d --- /dev/null +++ b/2022/days/09/src/parse.rs @@ -0,0 +1,75 @@ +use once_cell::sync::Lazy; +use regex::Regex; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Direction { + Up, + Right, + Down, + Left, +} + +static PARSE_REGEX: Lazy = Lazy::new(|| Regex::new(r"^([URDL]) (\d+)$").unwrap()); + +pub fn parse(input: &str) -> Vec { + let mut ret = Vec::new(); + for line in input.lines() { + let captures = PARSE_REGEX + .captures(line) + .unwrap_or_else(|| panic!("invalid line {}", line)); + let dir = match &captures[1] { + "U" => Direction::Up, + "R" => Direction::Right, + "D" => Direction::Down, + "L" => Direction::Left, + _ => panic!("invalid direction char"), + }; + for _ in 0..captures[2] + .parse() + .unwrap_or_else(|_| panic!("invalid line {}", line)) + { + ret.push(dir) + } + } + ret +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse() { + let input = + concat!("R 4\n", "U 4\n", "L 3\n", "D 1\n", "R 4\n", "D 1\n", "L 5\n", "R 2\n",); + assert_eq!( + parse(input), + vec![ + Direction::Right, + Direction::Right, + Direction::Right, + Direction::Right, + Direction::Up, + Direction::Up, + Direction::Up, + Direction::Up, + Direction::Left, + Direction::Left, + Direction::Left, + Direction::Down, + Direction::Right, + Direction::Right, + Direction::Right, + Direction::Right, + Direction::Down, + Direction::Left, + Direction::Left, + Direction::Left, + Direction::Left, + Direction::Left, + Direction::Right, + Direction::Right, + ] + ); + } +} diff --git a/2022/days/09/src/part1.rs b/2022/days/09/src/part1.rs new file mode 100644 index 0000000..92134a6 --- /dev/null +++ b/2022/days/09/src/part1.rs @@ -0,0 +1,53 @@ +use std::collections::HashSet; + +use aoc_libs::points::Point; + +use crate::parse::Direction; +use crate::rope::Rope; + +pub fn part1(input: &Vec) -> usize { + let mut visited: HashSet = HashSet::new(); + let mut rope: Rope<2> = Rope::new(); + visited.insert(*rope.get_tail_pos()); + for direction in input { + rope.update_rope(direction); + visited.insert(*rope.get_tail_pos()); + } + visited.len() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part1() { + let input = vec![ + Direction::Right, + Direction::Right, + Direction::Right, + Direction::Right, + Direction::Up, + Direction::Up, + Direction::Up, + Direction::Up, + Direction::Left, + Direction::Left, + Direction::Left, + Direction::Down, + Direction::Right, + Direction::Right, + Direction::Right, + Direction::Right, + Direction::Down, + Direction::Left, + Direction::Left, + Direction::Left, + Direction::Left, + Direction::Left, + Direction::Right, + Direction::Right, + ]; + assert_eq!(part1(&input), 13); + } +} diff --git a/2022/days/09/src/part2.rs b/2022/days/09/src/part2.rs new file mode 100644 index 0000000..98b19fd --- /dev/null +++ b/2022/days/09/src/part2.rs @@ -0,0 +1,31 @@ +use std::collections::HashSet; + +use aoc_libs::points::Point; + +use crate::{parse::Direction, rope::Rope}; + +pub fn part2(input: &Vec) -> usize { + let mut visited: HashSet = HashSet::new(); + let mut rope: Rope<10> = Rope::new(); + visited.insert(*rope.get_tail_pos()); + for direction in input { + rope.update_rope(direction); + visited.insert(*rope.get_tail_pos()); + } + visited.len() +} + +#[cfg(test)] +mod tests { + use crate::parse::parse; + + use super::*; + + #[test] + fn test_part2() { + let input = parse(concat!( + "R 5\n", "U 8\n", "L 8\n", "D 3\n", "R 17\n", "D 10\n", "L 25\n", "U 20\n", + )); + assert_eq!(part2(&input), 36); + } +} diff --git a/2022/days/09/src/rope.rs b/2022/days/09/src/rope.rs new file mode 100644 index 0000000..8f21c71 --- /dev/null +++ b/2022/days/09/src/rope.rs @@ -0,0 +1,160 @@ +use std::fmt::Display; + +use crate::parse::Direction; +use aoc_libs::points::{Point, UPoint}; + +// L is the length of the rope in segments. +#[derive(Debug)] +pub struct Rope { + segments: [Point; L], +} + +impl Rope { + pub fn new() -> Rope { + Rope { + segments: [Point::default(); L], + } + } + + pub fn update_rope(&mut self, direction: &Direction) { + self.segments[0] += match direction { + Direction::Up => Point { x: 0, y: 1 }, + Direction::Right => Point { x: 1, y: 0 }, + Direction::Down => Point { x: 0, y: -1 }, + Direction::Left => Point { x: -1, y: 0 }, + }; + for segment in 1..self.segments.len() { + self.segments[segment] += Rope::::update_single_segment_pair( + &self.segments[segment - 1], + &self.segments[segment], + ) + } + } + + pub fn get_tail_pos(&self) -> &Point { + &self.segments[self.segments.len() - 1] + } + + // the rope segment will not move if the segment ahead of it is only at most one away, and will + // move with the following rules if it is 2 away: It moves straight towards the head if the + // head is directly up/down/left/right, and diagonally towards it if its not straight + // up/down/left/right. + fn update_single_segment_pair(head: &Point, tail: &Point) -> Point { + let delta = *head - *tail; + if delta.x.abs() > 2 || delta.y.abs() > 2 { + panic!("invalid delta ({}, {})", delta.y, delta.x) + } + match (delta.x, delta.y) { + (0, 2) => Point { x: 0, y: 1 }, + (2, 0) => Point { x: 1, y: 0 }, + (0, -2) => Point { x: 0, y: -1 }, + (-2, 0) => Point { x: -1, y: 0 }, + (1, 2) | (2, 2) | (2, 1) => Point { x: 1, y: 1 }, + (2, -1) | (2, -2) | (1, -2) => Point { x: 1, y: -1 }, + (-1, -2) | (-2, -2) | (-2, -1) => Point { x: -1, y: -1 }, + (-2, 1) | (-2, 2) | (-1, 2) => Point { x: -1, y: 1 }, + _ => Point { x: 0, y: 0 }, + } + } +} + +impl Display for Rope<{ L }> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let grid_size = (self.segments.len() * 2) - 1; + let zero_point = UPoint { + x: self.segments.len() - 1, + y: self.segments.len() - 1, + }; + + let mut grid: Vec> = Vec::with_capacity(grid_size); + for y in 0..grid_size { + grid.push(Vec::with_capacity(grid_size)); + for _ in 0..grid_size { + grid[y].push('.') + } + } + + for segment in self.segments.iter().skip(1) { + let delta = *segment - self.segments[0]; + let upoint = delta.to_upoint(&zero_point).unwrap(); + grid[upoint.y][upoint.x] = 'T' + } + + writeln!( + f, + "head is at {}, {}", + self.segments[0].x, self.segments[0].y + )?; + let upoint = Point { x: 0, y: 0 }.to_upoint(&zero_point).unwrap(); + grid[upoint.y][upoint.x] = 'H'; + + for line in grid { + let mut writeline = "".to_string(); + for char in line { + writeline.push(char) + } + writeln!(f, "{}", writeline)?; + } + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use std::collections::HashSet; + + use super::*; + + #[test] + fn test_single_segment() { + let input = [ + Direction::Right, + Direction::Right, + Direction::Right, + Direction::Right, + Direction::Up, + Direction::Up, + Direction::Up, + Direction::Up, + Direction::Left, + Direction::Left, + Direction::Left, + Direction::Down, + Direction::Right, + Direction::Right, + Direction::Right, + Direction::Right, + Direction::Down, + Direction::Left, + Direction::Left, + Direction::Left, + Direction::Left, + Direction::Left, + Direction::Right, + Direction::Right, + ]; + let mut visited: HashSet = HashSet::new(); + let mut rope: Rope<2> = Rope::new(); + visited.insert(*rope.get_tail_pos()); + println!("{}", rope); + for direction in input { + rope.update_rope(&direction); + visited.insert(*rope.get_tail_pos()); + println!("{}", rope); + } + // let mut graph = [ + // ['.', '.', '.', '.', '.', '.'], + // ['.', '.', '.', '.', '.', '.'], + // ['.', '.', '.', '.', '.', '.'], + // ['.', '.', '.', '.', '.', '.'], + // ['s', '.', '.', '.', '.', '.'], + // ]; + // for point in &visited { + // graph[4 - point.y as usize][point.x as usize] = '#'; + // } + // for line in graph { + // println!("{:?}", line) + // } + assert_eq!(visited.len(), 13) + } +} diff --git a/2022/days/10/Cargo.toml b/2022/days/10/Cargo.toml new file mode 100644 index 0000000..529f9e5 --- /dev/null +++ b/2022/days/10/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "day10" +authors.workspace = true +description.workspace = true +version.workspace = true +edition.workspace = true + +[dependencies] +aoc_libs.workspace = true +nom.workspace = true diff --git a/2022/days/10/src/crt.rs b/2022/days/10/src/crt.rs new file mode 100644 index 0000000..caf8b4a --- /dev/null +++ b/2022/days/10/src/crt.rs @@ -0,0 +1,118 @@ +use std::fmt::Display; + +use crate::machine::Machine; + +#[derive(Debug, PartialEq, Eq)] +pub struct Crt { + pub screen: [[bool; 40]; 6], +} + +impl Crt { + pub fn draw_pixel(&mut self, sprite_pos: i32, cycle: usize) { + let x_coord = (cycle - 1) % self.screen[0].len(); + if sprite_pos.abs_diff(x_coord as i32) <= 1 { + self[cycle] = true + } + } +} + +impl Default for Crt { + fn default() -> Self { + Self { + screen: [[false; 40]; 6], + } + } +} + +impl Display for Crt { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + for line in self.screen { + for char in line { + if char { + write!(f, "#")?; + } else { + write!(f, ".")?; + } + } + writeln!(f)?; + } + Ok(()) + } +} + +impl std::ops::Index for Crt { + type Output = bool; + + fn index(&self, index: usize) -> &Self::Output { + let index = index - 1; + let x = index % self.screen[0].len(); + let y = index / self.screen[0].len(); + &self.screen[y][x] + } +} + +impl std::ops::IndexMut for Crt { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + let index = index - 1; + let x = index % self.screen[0].len(); + let y = index / self.screen[0].len(); + &mut self.screen[y][x] + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_index() { + let mut input = Crt::default(); + input[1] = true; + input[40] = true; + input[41] = true; + println!("{}", input); + assert_eq!( + input, + Crt { + screen: [ + [ + true, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, true + ], + [ + true, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false + ], + [ + false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false + ], + [ + false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false + ], + [ + false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false + ], + [ + false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false + ] + ] + } + ) + } +} diff --git a/2022/days/10/src/input.txt b/2022/days/10/src/input.txt new file mode 100644 index 0000000..c26a664 --- /dev/null +++ b/2022/days/10/src/input.txt @@ -0,0 +1,139 @@ +noop +addx 12 +addx -5 +addx -1 +noop +addx 4 +noop +addx 1 +addx 4 +noop +addx 13 +addx -8 +noop +addx -19 +addx 24 +addx 1 +noop +addx 4 +noop +addx 1 +addx 5 +addx -1 +addx -37 +addx 16 +addx -13 +addx 18 +addx -11 +addx 2 +addx 23 +noop +addx -18 +addx 9 +addx -8 +addx 2 +addx 5 +addx 2 +addx -21 +addx 26 +noop +addx -15 +addx 20 +noop +addx 3 +noop +addx -38 +addx 3 +noop +addx 26 +addx -4 +addx -19 +addx 3 +addx 1 +addx 5 +addx 3 +noop +addx 2 +addx 3 +noop +addx 2 +noop +noop +noop +noop +addx 5 +noop +noop +noop +addx 3 +noop +addx -30 +addx -4 +addx 1 +addx 18 +addx -8 +addx -4 +addx 2 +noop +addx 7 +noop +noop +noop +noop +addx 5 +noop +noop +addx 5 +addx -2 +addx -20 +addx 27 +addx -20 +addx 25 +addx -2 +addx -35 +noop +noop +addx 4 +addx 3 +addx -2 +addx 5 +addx 2 +addx -11 +addx 1 +addx 13 +addx 2 +addx 5 +addx 6 +addx -1 +addx -2 +noop +addx 7 +addx -2 +addx 6 +addx 1 +addx -21 +addx 22 +addx -38 +addx 5 +addx 3 +addx -1 +noop +noop +addx 5 +addx 1 +addx 4 +addx 3 +addx -2 +addx 2 +noop +addx 7 +addx -1 +addx 2 +addx 4 +addx -10 +addx -19 +addx 35 +addx -1 +noop +noop +noop diff --git a/2022/days/10/src/machine.rs b/2022/days/10/src/machine.rs new file mode 100644 index 0000000..b148ee9 --- /dev/null +++ b/2022/days/10/src/machine.rs @@ -0,0 +1,455 @@ +use std::{collections::VecDeque, fmt}; + +use crate::crt::Crt; +use crate::parse::*; + +pub struct Machine { + instructions: VecDeque, + current_instruction: Option<(Instruction, usize)>, + cycle: usize, + x: i32, + pub crt: Crt, +} + +impl Machine { + pub fn load_program(instructions: VecDeque) -> Self { + let mut res = Machine { + instructions, + current_instruction: None, + cycle: 0, + x: 1, + crt: Crt::default(), + }; + res.fetch_next_instruction(); + res + } + + pub fn step(&mut self) -> (bool, i32) { + if self.current_instruction.is_none() { + return (false, self.x); + } + + //we return x as it was at the beginning of the cycle. + let x = self.x; + let (instruction, cycles_left) = self.current_instruction.as_mut().unwrap(); + *cycles_left -= 1; + if *cycles_left == 0 { + if let Instruction::Addx(i) = instruction { + self.x += *i + } + + self.fetch_next_instruction(); + }; + + self.cycle += 1; + self.crt.draw_pixel(x, self.cycle); + (true, x) + } + + fn fetch_next_instruction(&mut self) { + self.current_instruction = self.instructions.pop_front().map(|i| (i, i.cycles())); + } + + //returns the signal strength during the middle of the 20th cycle. + pub fn step20(&mut self) -> i32 { + for _ in 0..19 { + if !self.step().0 { + break; + } + } + self.step().1 * self.cycle as i32 + } +} + +impl fmt::Debug for Machine { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "cycle={} x={} current instruction: {:?} ({} instructions left)", + self.cycle, + self.x, + self.current_instruction, + self.instructions.len() + ) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_screen() { + let input = vec![ + Instruction::Addx(15), + Instruction::Addx(-11), + Instruction::Addx(6), + Instruction::Addx(-3), + Instruction::Addx(5), + Instruction::Addx(-1), + Instruction::Addx(-8), + Instruction::Addx(13), + Instruction::Addx(4), + Instruction::NoOp, + Instruction::Addx(-1), + Instruction::Addx(5), + Instruction::Addx(-1), + Instruction::Addx(5), + Instruction::Addx(-1), + Instruction::Addx(5), + Instruction::Addx(-1), + Instruction::Addx(5), + Instruction::Addx(-1), + Instruction::Addx(-35), + Instruction::Addx(1), + Instruction::Addx(24), + Instruction::Addx(-19), + Instruction::Addx(1), + Instruction::Addx(16), + Instruction::Addx(-11), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(21), + Instruction::Addx(-15), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(-3), + Instruction::Addx(9), + Instruction::Addx(1), + Instruction::Addx(-3), + Instruction::Addx(8), + Instruction::Addx(1), + Instruction::Addx(5), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(-36), + Instruction::NoOp, + Instruction::Addx(1), + Instruction::Addx(7), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(2), + Instruction::Addx(6), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(1), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(7), + Instruction::Addx(1), + Instruction::NoOp, + Instruction::Addx(-13), + Instruction::Addx(13), + Instruction::Addx(7), + Instruction::NoOp, + Instruction::Addx(1), + Instruction::Addx(-33), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(2), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(8), + Instruction::NoOp, + Instruction::Addx(-1), + Instruction::Addx(2), + Instruction::Addx(1), + Instruction::NoOp, + Instruction::Addx(17), + Instruction::Addx(-9), + Instruction::Addx(1), + Instruction::Addx(1), + Instruction::Addx(-3), + Instruction::Addx(11), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(1), + Instruction::NoOp, + Instruction::Addx(1), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(-13), + Instruction::Addx(-19), + Instruction::Addx(1), + Instruction::Addx(3), + Instruction::Addx(26), + Instruction::Addx(-30), + Instruction::Addx(12), + Instruction::Addx(-1), + Instruction::Addx(3), + Instruction::Addx(1), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(-9), + Instruction::Addx(18), + Instruction::Addx(1), + Instruction::Addx(2), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(9), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(-1), + Instruction::Addx(2), + Instruction::Addx(-37), + Instruction::Addx(1), + Instruction::Addx(3), + Instruction::NoOp, + Instruction::Addx(15), + Instruction::Addx(-21), + Instruction::Addx(22), + Instruction::Addx(-6), + Instruction::Addx(1), + Instruction::NoOp, + Instruction::Addx(2), + Instruction::Addx(1), + Instruction::NoOp, + Instruction::Addx(-10), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(20), + Instruction::Addx(1), + Instruction::Addx(2), + Instruction::Addx(2), + Instruction::Addx(-6), + Instruction::Addx(-11), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + ]; + let mut machine = Machine::load_program(input.into()); + //step till we cant anymore. + while machine.step().0 {} + println!("{}", machine.crt); + assert_eq!( + machine.crt, + Crt { + screen: [ + [ + true, true, false, false, true, true, false, false, true, true, false, + false, true, true, false, false, true, true, false, false, true, true, + false, false, true, true, false, false, true, true, false, false, true, + true, false, false, true, true, false, false + ], + [ + true, true, true, false, false, false, true, true, true, false, false, + false, true, true, true, false, false, false, true, true, true, false, + false, false, true, true, true, false, false, false, true, true, true, + false, false, false, true, true, true, false + ], + [ + true, true, true, true, false, false, false, false, true, true, true, true, + false, false, false, false, true, true, true, true, false, false, false, + false, true, true, true, true, false, false, false, false, true, true, + true, true, false, false, false, false + ], + [ + true, true, true, true, true, false, false, false, false, false, true, + true, true, true, true, false, false, false, false, false, true, true, + true, true, true, false, false, false, false, false, true, true, true, + true, true, false, false, false, false, false + ], + [ + true, true, true, true, true, true, false, false, false, false, false, + false, true, true, true, true, true, true, false, false, false, false, + false, false, true, true, true, true, true, true, false, false, false, + false, false, false, true, true, true, true + ], + [ + true, true, true, true, true, true, true, false, false, false, false, + false, false, false, true, true, true, true, true, true, true, false, + false, false, false, false, false, false, true, true, true, true, true, + true, true, false, false, false, false, false + ] + ] + } + ) + } + + #[test] + fn test_machine() { + let input = vec![ + Instruction::Addx(15), + Instruction::Addx(-11), + Instruction::Addx(6), + Instruction::Addx(-3), + Instruction::Addx(5), + Instruction::Addx(-1), + Instruction::Addx(-8), + Instruction::Addx(13), + Instruction::Addx(4), + Instruction::NoOp, + Instruction::Addx(-1), + Instruction::Addx(5), + Instruction::Addx(-1), + Instruction::Addx(5), + Instruction::Addx(-1), + Instruction::Addx(5), + Instruction::Addx(-1), + Instruction::Addx(5), + Instruction::Addx(-1), + Instruction::Addx(-35), + Instruction::Addx(1), + Instruction::Addx(24), + Instruction::Addx(-19), + Instruction::Addx(1), + Instruction::Addx(16), + Instruction::Addx(-11), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(21), + Instruction::Addx(-15), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(-3), + Instruction::Addx(9), + Instruction::Addx(1), + Instruction::Addx(-3), + Instruction::Addx(8), + Instruction::Addx(1), + Instruction::Addx(5), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(-36), + Instruction::NoOp, + Instruction::Addx(1), + Instruction::Addx(7), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(2), + Instruction::Addx(6), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(1), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(7), + Instruction::Addx(1), + Instruction::NoOp, + Instruction::Addx(-13), + Instruction::Addx(13), + Instruction::Addx(7), + Instruction::NoOp, + Instruction::Addx(1), + Instruction::Addx(-33), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(2), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(8), + Instruction::NoOp, + Instruction::Addx(-1), + Instruction::Addx(2), + Instruction::Addx(1), + Instruction::NoOp, + Instruction::Addx(17), + Instruction::Addx(-9), + Instruction::Addx(1), + Instruction::Addx(1), + Instruction::Addx(-3), + Instruction::Addx(11), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(1), + Instruction::NoOp, + Instruction::Addx(1), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(-13), + Instruction::Addx(-19), + Instruction::Addx(1), + Instruction::Addx(3), + Instruction::Addx(26), + Instruction::Addx(-30), + Instruction::Addx(12), + Instruction::Addx(-1), + Instruction::Addx(3), + Instruction::Addx(1), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(-9), + Instruction::Addx(18), + Instruction::Addx(1), + Instruction::Addx(2), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(9), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(-1), + Instruction::Addx(2), + Instruction::Addx(-37), + Instruction::Addx(1), + Instruction::Addx(3), + Instruction::NoOp, + Instruction::Addx(15), + Instruction::Addx(-21), + Instruction::Addx(22), + Instruction::Addx(-6), + Instruction::Addx(1), + Instruction::NoOp, + Instruction::Addx(2), + Instruction::Addx(1), + Instruction::NoOp, + Instruction::Addx(-10), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(20), + Instruction::Addx(1), + Instruction::Addx(2), + Instruction::Addx(2), + Instruction::Addx(-6), + Instruction::Addx(-11), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + ]; + let mut machine = Machine::load_program(input.into()); + + //20th + assert_eq!(machine.step20(), 420); + + machine.step20(); + //60th + assert_eq!(machine.step20(), 1140); + + machine.step20(); + //100th + assert_eq!(machine.step20(), 1800); + + machine.step20(); + //140th + assert_eq!(machine.step20(), 2940); + + machine.step20(); + //180th + assert_eq!(machine.step20(), 2880); + + machine.step20(); + //220th + assert_eq!(machine.step20(), 3960); + } +} diff --git a/2022/days/10/src/main.rs b/2022/days/10/src/main.rs new file mode 100644 index 0000000..b82e7ad --- /dev/null +++ b/2022/days/10/src/main.rs @@ -0,0 +1,16 @@ +mod part1; +mod part2; +mod parse; +mod machine; +mod crt; + +fn main() { + let input = include_str!("./input.txt"); + let structured_input = parse::parse(input); + + println!("Part One"); + println!("Result: {}", part1::part1(structured_input.clone())); + + println!("Part Two"); + println!("Result:\n{}", part2::part2(structured_input.clone())); +} diff --git a/2022/days/10/src/parse.rs b/2022/days/10/src/parse.rs new file mode 100644 index 0000000..1fdbb02 --- /dev/null +++ b/2022/days/10/src/parse.rs @@ -0,0 +1,344 @@ +use std::collections::VecDeque; + +use nom::{ + branch::alt, + bytes::complete::tag, + combinator::{all_consuming, map, value}, + sequence::preceded, + Finish, IResult, +}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Instruction { + NoOp, + Addx(i32), +} + +impl Instruction { + fn parse(i: &str) -> IResult<&str, Self> { + let noop = tag("noop"); + let addx = preceded(tag("addx "), nom::character::complete::i32); + alt((value(Self::NoOp, noop), map(addx, Self::Addx)))(i) + } + pub fn cycles(self) -> usize { + match self { + Self::NoOp => 1, + Self::Addx(_) => 2, + } + } +} + +pub fn parse(input: &str) -> VecDeque { + input + .lines() + .map(|l| all_consuming(Instruction::parse)(l).finish().unwrap().1) + .collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse() { + let input = concat!( + "addx 15\n", + "addx -11\n", + "addx 6\n", + "addx -3\n", + "addx 5\n", + "addx -1\n", + "addx -8\n", + "addx 13\n", + "addx 4\n", + "noop\n", + "addx -1\n", + "addx 5\n", + "addx -1\n", + "addx 5\n", + "addx -1\n", + "addx 5\n", + "addx -1\n", + "addx 5\n", + "addx -1\n", + "addx -35\n", + "addx 1\n", + "addx 24\n", + "addx -19\n", + "addx 1\n", + "addx 16\n", + "addx -11\n", + "noop\n", + "noop\n", + "addx 21\n", + "addx -15\n", + "noop\n", + "noop\n", + "addx -3\n", + "addx 9\n", + "addx 1\n", + "addx -3\n", + "addx 8\n", + "addx 1\n", + "addx 5\n", + "noop\n", + "noop\n", + "noop\n", + "noop\n", + "noop\n", + "addx -36\n", + "noop\n", + "addx 1\n", + "addx 7\n", + "noop\n", + "noop\n", + "noop\n", + "addx 2\n", + "addx 6\n", + "noop\n", + "noop\n", + "noop\n", + "noop\n", + "noop\n", + "addx 1\n", + "noop\n", + "noop\n", + "addx 7\n", + "addx 1\n", + "noop\n", + "addx -13\n", + "addx 13\n", + "addx 7\n", + "noop\n", + "addx 1\n", + "addx -33\n", + "noop\n", + "noop\n", + "noop\n", + "addx 2\n", + "noop\n", + "noop\n", + "noop\n", + "addx 8\n", + "noop\n", + "addx -1\n", + "addx 2\n", + "addx 1\n", + "noop\n", + "addx 17\n", + "addx -9\n", + "addx 1\n", + "addx 1\n", + "addx -3\n", + "addx 11\n", + "noop\n", + "noop\n", + "addx 1\n", + "noop\n", + "addx 1\n", + "noop\n", + "noop\n", + "addx -13\n", + "addx -19\n", + "addx 1\n", + "addx 3\n", + "addx 26\n", + "addx -30\n", + "addx 12\n", + "addx -1\n", + "addx 3\n", + "addx 1\n", + "noop\n", + "noop\n", + "noop\n", + "addx -9\n", + "addx 18\n", + "addx 1\n", + "addx 2\n", + "noop\n", + "noop\n", + "addx 9\n", + "noop\n", + "noop\n", + "noop\n", + "addx -1\n", + "addx 2\n", + "addx -37\n", + "addx 1\n", + "addx 3\n", + "noop\n", + "addx 15\n", + "addx -21\n", + "addx 22\n", + "addx -6\n", + "addx 1\n", + "noop\n", + "addx 2\n", + "addx 1\n", + "noop\n", + "addx -10\n", + "noop\n", + "noop\n", + "addx 20\n", + "addx 1\n", + "addx 2\n", + "addx 2\n", + "addx -6\n", + "addx -11\n", + "noop\n", + "noop\n", + "noop\n", + ); + assert_eq!( + parse(input), + vec![ + Instruction::Addx(15), + Instruction::Addx(-11), + Instruction::Addx(6), + Instruction::Addx(-3), + Instruction::Addx(5), + Instruction::Addx(-1), + Instruction::Addx(-8), + Instruction::Addx(13), + Instruction::Addx(4), + Instruction::NoOp, + Instruction::Addx(-1), + Instruction::Addx(5), + Instruction::Addx(-1), + Instruction::Addx(5), + Instruction::Addx(-1), + Instruction::Addx(5), + Instruction::Addx(-1), + Instruction::Addx(5), + Instruction::Addx(-1), + Instruction::Addx(-35), + Instruction::Addx(1), + Instruction::Addx(24), + Instruction::Addx(-19), + Instruction::Addx(1), + Instruction::Addx(16), + Instruction::Addx(-11), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(21), + Instruction::Addx(-15), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(-3), + Instruction::Addx(9), + Instruction::Addx(1), + Instruction::Addx(-3), + Instruction::Addx(8), + Instruction::Addx(1), + Instruction::Addx(5), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(-36), + Instruction::NoOp, + Instruction::Addx(1), + Instruction::Addx(7), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(2), + Instruction::Addx(6), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(1), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(7), + Instruction::Addx(1), + Instruction::NoOp, + Instruction::Addx(-13), + Instruction::Addx(13), + Instruction::Addx(7), + Instruction::NoOp, + Instruction::Addx(1), + Instruction::Addx(-33), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(2), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(8), + Instruction::NoOp, + Instruction::Addx(-1), + Instruction::Addx(2), + Instruction::Addx(1), + Instruction::NoOp, + Instruction::Addx(17), + Instruction::Addx(-9), + Instruction::Addx(1), + Instruction::Addx(1), + Instruction::Addx(-3), + Instruction::Addx(11), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(1), + Instruction::NoOp, + Instruction::Addx(1), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(-13), + Instruction::Addx(-19), + Instruction::Addx(1), + Instruction::Addx(3), + Instruction::Addx(26), + Instruction::Addx(-30), + Instruction::Addx(12), + Instruction::Addx(-1), + Instruction::Addx(3), + Instruction::Addx(1), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(-9), + Instruction::Addx(18), + Instruction::Addx(1), + Instruction::Addx(2), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(9), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(-1), + Instruction::Addx(2), + Instruction::Addx(-37), + Instruction::Addx(1), + Instruction::Addx(3), + Instruction::NoOp, + Instruction::Addx(15), + Instruction::Addx(-21), + Instruction::Addx(22), + Instruction::Addx(-6), + Instruction::Addx(1), + Instruction::NoOp, + Instruction::Addx(2), + Instruction::Addx(1), + Instruction::NoOp, + Instruction::Addx(-10), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(20), + Instruction::Addx(1), + Instruction::Addx(2), + Instruction::Addx(2), + Instruction::Addx(-6), + Instruction::Addx(-11), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp + ] + ); + } +} diff --git a/2022/days/10/src/part1.rs b/2022/days/10/src/part1.rs new file mode 100644 index 0000000..d69856c --- /dev/null +++ b/2022/days/10/src/part1.rs @@ -0,0 +1,191 @@ +use std::collections::VecDeque; + +use crate::{parse::*, machine::Machine}; + +pub fn part1(input: VecDeque) -> i32 { + let mut machine = Machine::load_program(input.into()); + let mut total = 0; + + //20th + total+=machine.step20(); + + machine.step20(); + //60th + total+=machine.step20(); + + machine.step20(); + //100th + total+=machine.step20(); + + machine.step20(); + //140th + total+=machine.step20(); + + machine.step20(); + //180th + total+=machine.step20(); + + machine.step20(); + //220th + total+=machine.step20(); + + total +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part1() { + let input = vec![ + Instruction::Addx(15), + Instruction::Addx(-11), + Instruction::Addx(6), + Instruction::Addx(-3), + Instruction::Addx(5), + Instruction::Addx(-1), + Instruction::Addx(-8), + Instruction::Addx(13), + Instruction::Addx(4), + Instruction::NoOp, + Instruction::Addx(-1), + Instruction::Addx(5), + Instruction::Addx(-1), + Instruction::Addx(5), + Instruction::Addx(-1), + Instruction::Addx(5), + Instruction::Addx(-1), + Instruction::Addx(5), + Instruction::Addx(-1), + Instruction::Addx(-35), + Instruction::Addx(1), + Instruction::Addx(24), + Instruction::Addx(-19), + Instruction::Addx(1), + Instruction::Addx(16), + Instruction::Addx(-11), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(21), + Instruction::Addx(-15), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(-3), + Instruction::Addx(9), + Instruction::Addx(1), + Instruction::Addx(-3), + Instruction::Addx(8), + Instruction::Addx(1), + Instruction::Addx(5), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(-36), + Instruction::NoOp, + Instruction::Addx(1), + Instruction::Addx(7), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(2), + Instruction::Addx(6), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(1), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(7), + Instruction::Addx(1), + Instruction::NoOp, + Instruction::Addx(-13), + Instruction::Addx(13), + Instruction::Addx(7), + Instruction::NoOp, + Instruction::Addx(1), + Instruction::Addx(-33), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(2), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(8), + Instruction::NoOp, + Instruction::Addx(-1), + Instruction::Addx(2), + Instruction::Addx(1), + Instruction::NoOp, + Instruction::Addx(17), + Instruction::Addx(-9), + Instruction::Addx(1), + Instruction::Addx(1), + Instruction::Addx(-3), + Instruction::Addx(11), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(1), + Instruction::NoOp, + Instruction::Addx(1), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(-13), + Instruction::Addx(-19), + Instruction::Addx(1), + Instruction::Addx(3), + Instruction::Addx(26), + Instruction::Addx(-30), + Instruction::Addx(12), + Instruction::Addx(-1), + Instruction::Addx(3), + Instruction::Addx(1), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(-9), + Instruction::Addx(18), + Instruction::Addx(1), + Instruction::Addx(2), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(9), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(-1), + Instruction::Addx(2), + Instruction::Addx(-37), + Instruction::Addx(1), + Instruction::Addx(3), + Instruction::NoOp, + Instruction::Addx(15), + Instruction::Addx(-21), + Instruction::Addx(22), + Instruction::Addx(-6), + Instruction::Addx(1), + Instruction::NoOp, + Instruction::Addx(2), + Instruction::Addx(1), + Instruction::NoOp, + Instruction::Addx(-10), + Instruction::NoOp, + Instruction::NoOp, + Instruction::Addx(20), + Instruction::Addx(1), + Instruction::Addx(2), + Instruction::Addx(2), + Instruction::Addx(-6), + Instruction::Addx(-11), + Instruction::NoOp, + Instruction::NoOp, + Instruction::NoOp, + ]; + assert_eq!(part1(input.into()), 13140) + } +} diff --git a/2022/days/10/src/part2.rs b/2022/days/10/src/part2.rs new file mode 100644 index 0000000..5c43139 --- /dev/null +++ b/2022/days/10/src/part2.rs @@ -0,0 +1,19 @@ +use std::collections::VecDeque; + +use crate::{crt::Crt, parse::*, machine::Machine}; + +pub fn part2(input: VecDeque) -> Crt { + let mut machine = Machine::load_program(input); + while machine.step().0 {}; + machine.crt +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part2() { + assert_eq!(0, 0); + } +} diff --git a/2022/template/Cargo.toml b/2022/template/Cargo.toml new file mode 100644 index 0000000..801326a --- /dev/null +++ b/2022/template/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "template" +authors.workspace = true +description.workspace = true +version.workspace = true +edition.workspace = true + +[dependencies] +aoc_libs.workspace = true diff --git a/2022/template/src/input.txt b/2022/template/src/input.txt new file mode 100644 index 0000000..e69de29 diff --git a/2022/template/src/main.rs b/2022/template/src/main.rs new file mode 100644 index 0000000..456385c --- /dev/null +++ b/2022/template/src/main.rs @@ -0,0 +1,14 @@ +mod part1; +mod part2; +mod parse; + +fn main() { + let input = include_str!("./input.txt"); + let structured_input = parse::parse(input); + + println!("Part One"); + println!("Result: {}", part1::part1(&structured_input)); + + println!("Part Two"); + println!("Result: {}", part2::part2(&structured_input)); +} diff --git a/2022/template/src/parse.rs b/2022/template/src/parse.rs new file mode 100644 index 0000000..ed7984c --- /dev/null +++ b/2022/template/src/parse.rs @@ -0,0 +1,16 @@ +pub type StructuredInput = usize; + +pub fn parse(input: &str) -> StructuredInput { + unimplemented!() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse() { + let input = concat!(); + assert_eq!(0, 0); + } +} diff --git a/2022/template/src/part1.rs b/2022/template/src/part1.rs new file mode 100644 index 0000000..bcd1611 --- /dev/null +++ b/2022/template/src/part1.rs @@ -0,0 +1,15 @@ +use crate::parse::*; + +pub fn part1(input: &StructuredInput) -> usize { + unimplemented!() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part1() { + assert_eq!(0, 0); + } +} diff --git a/2022/template/src/part2.rs b/2022/template/src/part2.rs new file mode 100644 index 0000000..687e0cf --- /dev/null +++ b/2022/template/src/part2.rs @@ -0,0 +1,15 @@ +use crate::parse::*; + +pub fn part2(input: &StructuredInput) -> usize { + unimplemented!() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part2() { + assert_eq!(0, 0); + } +} diff --git a/2023/.gitignore b/2023/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/2023/.gitignore @@ -0,0 +1 @@ +/target diff --git a/2023/Cargo.lock b/2023/Cargo.lock new file mode 100644 index 0000000..a1716b5 --- /dev/null +++ b/2023/Cargo.lock @@ -0,0 +1,184 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "aoc_libs" +version = "0.1.0" + +[[package]] +name = "collection_literals" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186dce98367766de751c42c4f03970fc60fc012296e706ccbb9d5df9b6c1e271" + +[[package]] +name = "day01" +version = "0.1.0" +dependencies = [ + "aoc_libs", + "once_cell", + "regex", +] + +[[package]] +name = "day02" +version = "0.1.0" +dependencies = [ + "aoc_libs", + "nom", +] + +[[package]] +name = "day03" +version = "0.1.0" +dependencies = [ + "aoc_libs", +] + +[[package]] +name = "day04" +version = "0.1.0" +dependencies = [ + "aoc_libs", + "collection_literals", + "nom", +] + +[[package]] +name = "day05" +version = "0.1.0" +dependencies = [ + "aoc_libs", + "nom", +] + +[[package]] +name = "day06" +version = "0.1.0" +dependencies = [ + "aoc_libs", + "nom", +] + +[[package]] +name = "day07" +version = "0.1.0" +dependencies = [ + "aoc_libs", + "itertools", +] + +[[package]] +name = "day08" +version = "0.1.0" +dependencies = [ + "aoc_libs", + "collection_literals", + "once_cell", + "regex", +] + +[[package]] +name = "day09" +version = "0.1.0" +dependencies = [ + "aoc_libs", +] + +[[package]] +name = "day11" +version = "0.1.0" +dependencies = [ + "aoc_libs", + "collection_literals", + "itertools", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "itertools" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +dependencies = [ + "either", +] + +[[package]] +name = "memchr" +version = "2.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "regex" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "template" +version = "0.1.0" +dependencies = [ + "aoc_libs", +] diff --git a/2023/Cargo.toml b/2023/Cargo.toml new file mode 100644 index 0000000..922814b --- /dev/null +++ b/2023/Cargo.toml @@ -0,0 +1,23 @@ +[workspace] +members = [ + "template", + "aoc_libs", + "days/*", +] +default-members = [ "days/*", "aoc_libs" ] +resolver = "2" + +[workspace.package] +version = "0.1.0" +authors = ["Gabriel Venberg"] +edition = "2021" +description = "advent of code 2022 in rust" + +[workspace.dependencies] +aoc_libs = {path = "./aoc_libs"} +regex = "1" +once_cell = "1.16" +thiserror = "1.0" +nom = "7.1" +collection_literals = "1.0.1" +itertools = "0.12.0" diff --git a/2023/aoc_libs/Cargo.toml b/2023/aoc_libs/Cargo.toml new file mode 100644 index 0000000..63d082f --- /dev/null +++ b/2023/aoc_libs/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "aoc_libs" +version.workspace = true +authors.workspace = true +edition.workspace = true +description.workspace = true diff --git a/2023/aoc_libs/src/distances.rs b/2023/aoc_libs/src/distances.rs new file mode 100644 index 0000000..a6219ad --- /dev/null +++ b/2023/aoc_libs/src/distances.rs @@ -0,0 +1,3 @@ +pub trait Distances{ + fn taxicab_distance(&self, other: &Self)->usize; +} diff --git a/2023/aoc_libs/src/lib.rs b/2023/aoc_libs/src/lib.rs new file mode 100644 index 0000000..b87b103 --- /dev/null +++ b/2023/aoc_libs/src/lib.rs @@ -0,0 +1,4 @@ +pub mod points; +pub mod range; +pub mod misc; +pub mod distances; diff --git a/2023/aoc_libs/src/misc.rs b/2023/aoc_libs/src/misc.rs new file mode 100644 index 0000000..20dd250 --- /dev/null +++ b/2023/aoc_libs/src/misc.rs @@ -0,0 +1,43 @@ +pub fn arr_lcm(input: &[usize]) -> usize { + input.iter().copied().reduce(lcm).unwrap_or(0) +} + +pub fn lcm(first: usize, second: usize) -> usize { + first * second / gcd(&first, &second) +} + +pub fn gcd(a: &usize, b: &usize) -> usize { + let mut a = *a; + let mut b = *b; + while b != 0 { + let tmp = b; + b = a.rem_euclid(b); + a = tmp; + } + a +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_arr_lcm() { + assert_eq!(arr_lcm(&[4, 6]), 12); + assert_eq!(arr_lcm(&[5, 2]), 10); + assert_eq!(arr_lcm(&[5, 2, 6]), 30); + assert_eq!(arr_lcm(&[5, 2, 6, 3]), 30); + } + + #[test] + fn test_lcm() { + assert_eq!(lcm(4, 6), 12); + assert_eq!(lcm(5, 2), 10); + } + + #[test] + fn test_gcd() { + assert_eq!(gcd(&8, &12), 4); + assert_eq!(gcd(&54, &24), 6); + } +} diff --git a/2023/aoc_libs/src/points.rs b/2023/aoc_libs/src/points.rs new file mode 100644 index 0000000..5dd921c --- /dev/null +++ b/2023/aoc_libs/src/points.rs @@ -0,0 +1,229 @@ +use crate::distances::Distances; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Hash)] +pub struct Point { + pub x: isize, + pub y: isize, +} + +impl Point { + /// converts a point (representing a point on a 4 quadrant grid with positive xy in the + /// top-right) into a upoint (representing a point on a 1 quadrant grid with the origin in the + /// top-left corner). Returns none if the resulting point would have either number negative. + pub fn to_upoint(self, zero_coord: &UPoint) -> Option { + Some(UPoint { + x: zero_coord.x.checked_add_signed(self.x)?, + y: zero_coord.y.checked_add_signed(-self.y)?, + }) + } +} + +impl Distances for Point { + fn taxicab_distance(&self, other: &Self) -> usize { + self.x.abs_diff(other.x) + self.y.abs_diff(other.y) + } +} + +impl std::ops::Add for Point { + type Output = Point; + + fn add(self, rhs: Self) -> Self::Output { + Self { + x: self.x + rhs.x, + y: self.y + rhs.y, + } + } +} + +impl std::ops::AddAssign for Point { + fn add_assign(&mut self, rhs: Self) { + *self = *self + rhs + } +} + +impl std::ops::Sub for Point { + type Output = Point; + + fn sub(self, rhs: Self) -> Self::Output { + Self { + x: self.x - rhs.x, + y: self.y - rhs.y, + } + } +} + +impl std::ops::SubAssign for Point { + fn sub_assign(&mut self, rhs: Self) { + *self = *self - rhs + } +} + +impl std::ops::Neg for Point { + type Output = Point; + + fn neg(self) -> Self::Output { + Point { + x: -self.x, + y: -self.y, + } + } +} + +/// an unsigned point in 2d space +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct UPoint { + pub x: usize, + pub y: usize, +} + +impl UPoint { + /// converts a upoint (representing a point on a 1 quadrant grid with the origin in the + /// top-left corner) into a point( representing a point on a 4 quadrant grid with positive xy + /// in the top-right) + pub fn to_point(self, zero_coord: &UPoint) -> Point { + Point { + x: -(zero_coord.x as isize - self.x as isize), + y: zero_coord.y as isize - self.y as isize, + } + } +} + +impl Distances for UPoint { + fn taxicab_distance(&self, other: &Self) -> usize { + self.x.abs_diff(other.x) + self.y.abs_diff(other.y) + } +} + +impl std::ops::Add for UPoint { + type Output = UPoint; + + fn add(self, rhs: Self) -> Self::Output { + Self { + x: self.x + rhs.x, + y: self.y + rhs.y, + } + } +} + +impl std::ops::AddAssign for UPoint { + fn add_assign(&mut self, rhs: Self) { + *self = *self + rhs + } +} + +impl std::ops::Sub for UPoint { + type Output = UPoint; + + fn sub(self, rhs: Self) -> Self::Output { + Self { + x: self.x - rhs.x, + y: self.y - rhs.y, + } + } +} + +impl std::ops::SubAssign for UPoint { + fn sub_assign(&mut self, rhs: Self) { + *self = *self - rhs + } +} + +/// A matrix that allows negative co-oordinates. Will panic if referencing out of bounds, just like +/// a normal 2d array. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct FourQuadrantMatrix { + matrix: [[T; X]; Y], + max_point: Point, + min_point: Point, + zero_coord: UPoint, +} + +impl FourQuadrantMatrix<{ X }, { Y }, T> +where + T: Copy, + T: Default, +{ + /// generates a new FourQuadrantMatrix with a given zero point (the point in the underlying 2d + /// array considered to be (0,0)) + pub fn new(zero_coord: UPoint) -> FourQuadrantMatrix<{ X }, { Y }, T> { + FourQuadrantMatrix { + matrix: [[T::default(); X]; Y], + max_point: UPoint { x: X - 1, y: 0 }.to_point(&zero_coord), + min_point: UPoint { x: 0, y: Y - 1 }.to_point(&zero_coord), + zero_coord, + } + } + + pub fn zero_coord(&self) -> UPoint { + self.zero_coord + } + + pub fn min_point(&self) -> Point { + self.min_point + } + + pub fn max_point(&self) -> Point { + self.max_point + } + + /// makes sure a point is in bounds and if not, brings it in bounds. + pub fn bound_point(&self, point: &mut Point) { + if point.x > self.max_point.x { + point.x = self.max_point.x + } + + if point.y > self.max_point.y { + point.y = self.max_point.y + } + + if point.x < self.min_point.x { + point.x = self.min_point.x + } + + if point.y < self.min_point.y { + point.y = self.min_point.y + } + } + + /// checks if the point is in bounds. + pub fn is_in_bounds(&self, point: &Point) -> bool { + point.x <= self.max_point.x + && point.y <= self.max_point.y + && point.x >= self.min_point.x + && point.y >= self.min_point.y + } + /// fills the matrix with the Ts default value. + pub fn reset_matrix(&mut self) { + self.matrix = [[T::default(); X]; Y]; + } +} + +impl std::ops::IndexMut + for FourQuadrantMatrix<{ X }, { Y }, T> +{ + fn index_mut(&mut self, index: Point) -> &mut Self::Output { + let upoint = index + .to_upoint(&self.zero_coord) + .expect("would result in negative unsigned coordinate!"); + &mut self.matrix[upoint.y][upoint.x] + } +} + +impl std::ops::Index + for FourQuadrantMatrix<{ X }, { Y }, T> +{ + type Output = T; + + fn index(&self, index: Point) -> &Self::Output { + let upoint = index + .to_upoint(&self.zero_coord) + .expect("would result in negative unsigned coordinate!"); + &self.matrix[upoint.y][upoint.x] + } +} + +impl From> for [[T; X]; Y] { + fn from(value: FourQuadrantMatrix<{ X }, { Y }, T>) -> Self { + value.matrix + } +} diff --git a/2023/aoc_libs/src/range.rs b/2023/aoc_libs/src/range.rs new file mode 100644 index 0000000..2906cf0 --- /dev/null +++ b/2023/aoc_libs/src/range.rs @@ -0,0 +1,118 @@ +// #[derive(Debug, PartialEq, Eq, Clone, Copy)] +// /// range that includes the start, but excludes the end. +// pub struct Range +// where +// T: PartialOrd + Ord + PartialEq + Copy, +// { +// start: T, +// end: T, +// } + +use std::ops::Range; + +pub trait RangeIntersection { + fn any_overlap(&self, other: &Self) -> bool; + fn calc_intersection(&self, other: &Self) -> Option + where + Self: std::marker::Sized; + fn complete_overlap(&self, other: &Self) -> bool; +} + +impl RangeIntersection for Range +where + T: PartialOrd + Ord + PartialEq + Copy, +{ + /// calcs whether self and other overlap at all. symettric. + fn any_overlap(&self, other: &Self) -> bool { + if self.is_empty() || other.is_empty() { + false + } else { + self.start < other.end && self.end > other.start + } + } + + /// calculates the range that is part of both ranges. + /// Returns None if the ranges do not overlap. + fn calc_intersection(&self, other: &Self) -> Option { + if self.any_overlap(other) { + Some(self.start.max(other.start)..self.end.min(other.end)) + } else { + None + } + } + + ///calcs whether self completely contains other + fn complete_overlap(&self, other: &Self) -> bool { + if self.is_empty() || other.is_empty() { + false + } else { + self.start <= other.start && self.end >= other.end + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn calc_intersection() { + let a = 1..5; + let b = 3..9; + let c = 4..6; + let d = 6..8; + let e = 1..4; + assert_eq!(a.calc_intersection(&b), Some(3..5)); + assert_eq!(b.calc_intersection(&a), Some(3..5)); + + assert_eq!(a.calc_intersection(&d), None); + assert_eq!(d.calc_intersection(&a), None); + + assert_eq!(c.calc_intersection(&b), Some(c.clone())); + assert_eq!(b.calc_intersection(&c), Some(c.clone())); + + assert_eq!(e.calc_intersection(&b), Some(3..4)); + assert_eq!(b.calc_intersection(&e), Some(3..4)); + } + + #[test] + fn test_any_overlap() { + let a = 1..5; + let b = 3..9; + let c = 4..6; + let d = 6..8; + let e = 1..4; + assert!(a.any_overlap(&b)); + assert!(b.any_overlap(&a)); + + assert!(b.any_overlap(&c)); + assert!(c.any_overlap(&b)); + + assert!(!d.any_overlap(&a)); + assert!(!a.any_overlap(&d)); + + assert!(e.any_overlap(&b)); + assert!(b.any_overlap(&e)); + + assert!(!e.any_overlap(&d)); + assert!(!d.any_overlap(&e)); + } + #[test] + fn test_complete_overlap() { + let a = 1..5; + let b = 3..9; + let c = 4..6; + let d = 6..8; + let e = 1..4; + assert!(a.complete_overlap(&a)); + + assert!(a.complete_overlap(&e)); + assert!(!e.complete_overlap(&a)); + + assert!(b.complete_overlap(&c)); + assert!(!c.complete_overlap(&b)); + + assert!(b.complete_overlap(&d)); + assert!(!d.complete_overlap(&b)); + } +} diff --git a/2023/days/01/Cargo.toml b/2023/days/01/Cargo.toml new file mode 100644 index 0000000..cc83ea4 --- /dev/null +++ b/2023/days/01/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "day01" +authors.workspace = true +description.workspace = true +version.workspace = true +edition.workspace = true + +[dependencies] +aoc_libs.workspace = true +regex.workspace = true +once_cell.workspace = true diff --git a/2023/days/01/src/input.txt b/2023/days/01/src/input.txt new file mode 100644 index 0000000..784a61c --- /dev/null +++ b/2023/days/01/src/input.txt @@ -0,0 +1,1000 @@ +eight9fhstbssrplmdlncmmqqnklb39ninejz +three656 +ppjvndvknbtpfsncplmhhrlh5 +7fjqhrhsevenlbtwoninevnmct2 +qjnbpfrztwo1 +plggqjthree49four +xpxpbsdc1 +three2six8two5 +36two +five121zvjks3 +4onefive6zsjhzvrjnsfive1 +six5vfb +5h9bnkjfivemlqkf +fnxqvsvqbzxgkfour5 +eightjzqzhrllg1oneightfck +6threeeightjzcgsnclfive7txvgsdxnt +sevenninexsjtjvcsixtnfivejhj45 +6lxpdpdnr +56cnfourgrkfzxcvpsqd +gmlqzxdxtt9five +oneninepnvtfbbcx98vmttscj64 +lptxklsh17three2 +znzzthreecmpbtc3kbmjmfxtczjhd476 +threeeight16three +cc8one +jvlmlfvcxk2zxkpxvsf +foursevenjqncdtkqxg65hcqxrssvlq +five359hlgblsthree +lbfrhccstlhrrzones2bdeight9 +nzzsixrxzvbkzlh9vxrkmnhkkkfvffzdmphx8 +ninedxxzv7vnthmltpf5tthree7seven +8ninesix8monehbvmvrvsrvsqmhmxz +four1qpntfzmqnkkcnv +gpxprxzl15five +onebprckgrrgj2 +sevenjqkc14qfkcjfs4three +4onetrsnzpsixtwo7rxkdfh +seven4kmrlprpz +33twohsevenone67 +gbzm97nineslblhnine +kchtbjlg37three +four83dmpzflg +5eight1qrd +hqdtv8vcqqrth4mvcbtgfrbtninejkrfzvbfkq +3jrrjhtt91sixfourfive +seven9four +1twospfczxstwogcrxhcrjs6 +6onetjvskhmlrcnxnmgrh +chkpkzpqnchfrplmphhncsrppmx4ftwo1six +htr7 +dlxhmzsbtthree5nine281eight +35d9 +bfhoneighthkfvgbhbqsthree4fzgbcpdgseven +tntvhfvlone1thqdfivemfrfourfour +2kxshspv6llkpsixjpfppncthree4 +two8one +fvcbsevenlkthree32tdbpfive +56nine9one8fourcpnine +xzcgvrk35shf +8smrmnsseven +4onedxlxflgfcj +1gxvgxrqxzone +gvzkmxg55twonem +4threeone9cjjrvvqx +srpnvmpgm1sixone +five5seven3twozmfmqmsstpthreessdnlmssk7 +seven1nplbftheightfourgxflgone +eightthree77kqxpppninensjqcsnkz32 +xxmdgdstkzmgfpz4 +jfdpcgvjnnbsrkvninefive45six +qqvsc1983onertkvkhjtj +mngm7threed85pq +15one4nine7hzbgvdmtwo7 +xnthree3843 +35threeninetwo3 +gmc7sgfqjkqxlpgbjkpcrbeightnine8fbhgp +ctjhrmnsevenone6xlzvtjk +14xzgsbvrleightfourseven3 +8nqxtj4ninehhvsbfxnpl +45prcggcvqpmone2tdggkfgrrvfivemcspfnf +cnoneight8rdbdjvjbseight +pvkxgtfx2hmkznp9six +8cbzksc +tbzcfourvrfsdrjx2threestxdqsdcnp +two1zkmprx +5fninenkzkclksbfourvclcdnkmrx +28four4 +two2qkxlctcndmqxm7 +sixthreekzdvkpmptvkrxpzdthree16eight3 +6six85k +72four +4one8tf1fxoneone +6twod9six2 +sixsix3onepqnjspdmxfour1 +fqqcmvgkdfnvjschmtnzplpkl1eight +fourqtrtlsix2 +5vknkpb5825ninetjzsr6 +1oneeight53eightthreeonenjk +7vbktk1onethreezhnthqhncc7xbcqmqgtg +fourfivevxfbbbtgfpbq4nine5 +four32two +foursix4jlhkzqcgg +3cbrftrphh8twoeightfoursix4 +7onegqhngfcsrrlknk97six +9prrrtgoneonekmrhxlttwo8 +2jpfqlnmrjprxbs8hhtgxg +8tmckkdlgtmzljlsq +fivedznqszq67kc7onetwo3 +pdjjdfive434jzrqngcz +ljmjtwoldvkddzpght456three +1krvcrn +hndmzcqfour75zsxrlfourthreenine +277lcjzvxhv33llzrddkb +seven8vv +2fourqhkmtdh +pvk9four +eightqqgpncmncmsjgvkpxqzdjvkqjhsninexsbkjtk6 +gvfsrxpp59 +sevenseven7three +jpcxldqbmdptnlj838rcpftjmfgonekmfltkrdlg +95threevktfour5lzntgmfbcdx +mhdzxhmfqgffjhjfh5k635three6 +6bmbrcznrbsgfzbpmnjdtt16four +rnbcjrzthree9four5 +kcjjnxc9nine4tr1seven2 +hdmpcjzvs4eight1 +7gtbjdkfnrnfive +five3qkhmtpfldvfourphfxvjssspfourtgctwo6 +cfkr8seven99zxvhxrzx +fourshjqd1six +sixceight7 +plxhflcmqsgjpn5mhsphvv +three5ninehntgrlchcnnmqx98two5 +8sixcbqlfmcq14vnlmsixlhzrq +4eight2dsdnpnsx +fivexntprmkhpronejbnbseighttfnzmkdn3six +ninejtrqtneight6rvtnqspmkjsix +jsvgpb4 +tgrtn2qsbjsjjhxnntcmmgxrfivenmchb +rtvlmjpgbhmjxsixsix3ninetwonr +4jpkgvzzcnine8one +1threefivexzcqlgpbmczvvkrcznbr +dvgf6fivezvpvvz5vvtdhqpj4 +five8threesqqzlfvl1 +oneeight7onenine1 +lngrtsrfive6fcfhmfgxrc +eightfourtwoplzjkclh6 +2six9 +threefour5 +8twopmonedgn +3eightg +onetwoktxtbhffxvnhjbmbjqrgsh29tqlkpcnine +8sixoneninetwofive7qz5 +nine5skfsmrzeight61five +four1two8zvhcfgdpsb72 +4seven2six5 +fivebsix81two9xmjq +nxnrsdsixeightgfbmmhhst2251eight +nine339ksh9seven +sixonesixjblvfqvftxpjznf5fivefour +fvnvvp6twofive25twoneg +fourthreebr8gnkmrh6llrlg2four +kjjgzq25four19 +zlsfbnfkm64five24jtqmvgjtrzggqnfive +8nkrfltkeight +eighttlzrsgbfjp8 +sevennfrmfscs8four5czrlrxhmxl +threeeightrdnqvrdd9 +7six2824 +ggteight8nine23 +twofour3sevenqvzn6one +4rdcmnhtrdfour +3j515 +onecgfhxvndbfqkcsbbksix2mbszjp95 +3tk61ltpcg +fivefourdnine1 +86vjxfmvbtqgnflmgrnp87kqsgt3 +qlcshkxbxtvflbqth5sxsxlj9zvchrgqzdmlmtmsfldb +9twothree7bfrqjgztdlmrdxzpbdnd1 +psrfcqqbs62lfhthree4 +v3dhzkznrkzfgjksgppzxgpone +svqnineqkjtfxvbff2rqkbvqctzh1n +2sqvnkmvjlqflbv1654twoeight +twoseveneight56trvvzv +5qp +cgrks12857 +ltflnbzslg8fkfourkllzh +1four9eighteight8nine6gbdv +three9eight2vcndvvkphllzkqfbvbc +2eight1fivefcmdcbdn5onedffr +jqbnzzjxjhrvdzbglgtnrgccrhxjqtnrqt9 +sixhdggzgsrr8five8zjndfskgbr2five +9dsclqonefournine +eight8qvnpcmzkgd37srgrvseven +7gzc124kninetwoseven +pnfthree46foursevenfivek +6bsvbrrfoureighttwo +sixsevenfivefhrslvvdmf2 +5eightczxjsgfjpmzdrzkg6 +rzvtzjvmdvr6five3 +six2sevennttwo +2one1 +klfour13four +8xdnmzonesevencldxvlhxmnjpcfgnqfourfive8 +8nkmkqgngfourpnddbmtvnfour3h +9154 +crddnxhhznnkcptjcxds8sixvjr7fllrj +three9dfkzjqxbxfive1fhqzmlpgtseven +seightninepjr3mjkgq3ckxzlqkkxpxdpkk +four2flfsvhlm3vnbktkhjbj +four2ndrspfq8gmseven766 +4one5two +993 +1eightworc +rzpfczninefive8 +5seven3bjrsgqdncnpbxqstqfnine23nine +one2xdstrtwovpponefngmjh5 +foursix72psvxtwocxxz81 +845vpjdhdd5four3hhv +eightthreefive828ssxktxqrsz3 +48six62two1 +5bfhqfbqsmjndthreenxlzfhlhz2 +4onehgsix75six +5zjbqr6fivefourrmfvf8 +threesixfive1qnmbv4six8vxrsjzkd +threeeightthreelxprspvcone926eight +four3phmjpmmq3one +1nvszzgtp795n +four4eighttbmzcjkfbzlvzgjnsg +nsmlqsixfiveng65jjblflfone +xzcdfpscgm869s9 +sixsixgrndhrfnpthree4 +tgtpqllvsr4rhx8nine6lgdfx +lrkf9sklkonezszgc +11fiveeightdmqldjvjfivelbqdhbpbgbtwo8 +3ndfour +293 +bfgrxvjprnine4fourbnxltjzpgnseven +622fxlbpsmm9seven9tkppzxfc +6pfkrrpdltqzghp1 +1twozfvskmlzrjpxnnj +nmhht3four2 +41threeninesixdbvrnshnmfsx21 +sevenkzvmsfpzkbx2pzfvdttjbtwo51nine +dbhjz1nine +4cbsrqdk6hzxtmld +xbvqzsltsvckzgzqgj47mdlcqjone2bbl6 +gtpmrrgrdmsfrfvrddqsbgrfmqlvnjmpd5gbxpzgcm6 +9t8ddhjgvfmtwo +2ninefivebvlgtrj4two46five +six4frshtwomqjmq +8four488 +45nxxhvbqlfivefour +eightnine36twogzqcnine +751sdpjqvtvgvznsm +863cgcg +3rhrpdgmds1 +twoonevpzhjddskcqfive3ztqxch6 +583one2four +5fczvhfqhrd39gnpmbvcnvvhsbnj9 +jthreefivezqbncdmcvhjftkpccsjzlv6three +six51 +4nineseven1861ltvljzhneight +one1kjbsm8nxsjs2mnzn +pdqkjrbxs69bgpm8six8 +8qhfhsn8tjtwofivesevenonexpjtjm +2r +fpdfcndph7sixnine3fm4two +fourl2seven5threepjonesix +8three6sjxtthree4sixfkmnthree +tscm83vpnrclcf +6onecvgfshgcnznines +pthreeqrcsgvtnpsix5 +eightvlqdjcgpzkbxcjzjhdsbvkcv2skcspgcqtpsnncxrthree +sevensixqp3 +9eighteightckpkjbn +lthree2jfncnkzcfq3 +8two64rrqprsj +twonineglpjqmkbdc7kkcz5five +threefourvrdgpzcn2 +sevenlknine4 +one346sevennkknkts +7z +32bjldfrccj9onejdgrhmtvm +five72threesevenrnfour +11sevengvjvhk +173 +fcmznseven9three9nvbbcglpjk2 +lmdjlpxbg777ggpftspzjlmh118 +sixeight9threenine4 +qsix2 +three6sixeightlbgfbdzlf8threesix +vvblfthreeeight2msjkqjjtnfpkgqgkcxthh8 +chhoneightone9lkczftxeight8 +threeninehmqddfsxjxvknvsgljp841 +1tfgk673 +4four3qcsix6dqnt +gzrgcgt9threebxprzqfmgz6rdtgkbvjv +nflvtzljs7kgbpfourcvxptsz +blgdmqtdlphtjbfsix7seven1 +eightpfdblscrtf9seven +pvkl7cbfqk8mflrxhvhgvfourthreeqrdlxhjxp +threeqbqjdhgkkfour61 +fbjgmrjhtjl2twonsq +sixthree357snkvbcr1 +79zxxsix2lvtwo5 +five51 +twothree4eight4one3 +6gsxlggspbbgsixsixsj995 +vtzdkqxksthree9fourfive +392rklpf4mfqcrtxsixfivexfcszd +one56bxzkqcsixsevenkqclbfvvh9 +8onefivetd1nine +3dsckcnqfive1sixkrc +8djmrcpzeightzkkspjq +dnbxzn6four7hsevenpsdbfgztjtckvlc +fpmrqk3 +3one71seven +qkdcshhbsshcvslhteight4tgskjnzvone +fourgtqdqxgxtqpn7jlgq1eightsj8 +1tkhxbqmdvthree7jvcqtbnsixeightwor +8nine5rvckdfqf +3hkbthreexfxtbszrcneight +1fivesixthreenine +4eightfnhzdtxkcsthree24 +55mhpsxtscpk +lbhfsnineone8 +33sixnlctccbs3 +one1jt879cthreeeightwob +1nine8ptwo +21threexffczhhv +eight113544pg +dfvlpdknmlqqf3cllbnzzbp8nlfpbqtfive +two1sfbltjbkbneight28rmzpcgn8rmkhmrjj +48zvcqcb +eightntddpqxgfkzrpcsmx68 +tdlppdpjsix59six +1lqtsxd3 +4ggpbhzhxlsxmhshkkqlqgncsjrtxfpfztdp57vntmdlrdhvjr +94grp9 +stvxsmdcflthree7gxncrthree5 +kjfbdzxztgfourrj13 +3three8dxffkzfjsevensevenseveneight +vnkhcsjfmmpsixmf9djntprkccp +nine5277 +rjktlvdfcvvkvtd8 +five9jtjhncc7 +fivenkfzczg2b +hbd2qphbcpjbjqtwo2lbsvv25 +sevenstsfoureight48bjcbsixchlrjxfh +9zghjpvlssdb +fneightwoonernrmnvvleightfour6jfmznzlsq9 +8ctvt3oneseven6zzmjzgv +xzeightwosixqxxcszqlfthree2threehpfzzzgmk1one +pcxcmnmeight2three +53lkpgqmtccnvsqfpn323 +dbfnnmcpone1sslqtnsv2ninemttk +ffjppdlpkbgmlbfivenine2bgcqdzfps +twoseveneighttwomhsztbhnzz9phsrjvnpg6nine +xfqsevenfourxk3onefivesix +one33 +4zthreexlgonevzlgxq +six9cpvrshgjzqvqslttwo +six1three4one8mdgfqc6 +cpvmpgltvpntwo855 +vroneightone8n7 +ntwoneqkdjznjfour5ppfp +bzlqxfive9onesevenhztwo76 +pt6148 +2ninegvlqckrvqzhh +sevenhr8sixgkcncfxkssfoursmgmk +tmmjbjqnine7xjtjltkksgzgthreesix +fivefive5lzpctqk7 +9fivelglghkvbnzeight29cql +7five5ninemnxzjzfrfn +786onehnfm11 +331vpeightthree3 +8fourfive87pf53four +7cqlsqtjjcfour5bdjcxrvnmdthree +15two27 +5seventwoonextsmpeighthjlcssevenone +tqfzvfzstsixqczklsd2jdjphblsvrnine5eight +4jlnqmmpvg +eightszlmmnzhjv2six +seventhree92fivelpkqvqspjsix +oneeightfiveptx4fourone +tbxcm95zzp +rfqd56 +twogkbj5phrgktgrpqqqzvhcdfzq2l2d +3slsrhqrfdcgjjpsxqcqppdkkzptbzq +six3ninesixsix +8nine9threethreeshrv48 +bvfivetwo9rfourbgtjthpdj9 +lngsxhnineone616one +sdvzzvclvkgxseven6rvncxzdrdjhhkqfcf9mlnzxntg +1zdd8 +2bnfnb1qhqfour77 +ninefourthreenine7 +four376seven +1txdvzfourkqbjkhone +34jcdcbgjlhqblsccd +nkkcdlkzscxgqjl7732nine +4nsnhsevennine1pvbsmeight +35ddqnp1h +nkmtp7 +jvrgthqv58bvthree +nzzdvhqd65rk +xvln2eightjqlfvn7cmfjbtrmc6 +six1cpfnzvzsqkvgkbkfvjxsix2 +onedzfnmndj47 +btrnfptfivetwofourxvbeightdqqt8 +vdbjckztd6 +4sevenfive72oneldjmnvjcmheightfour +one886jr +nxsvxtqtnm99onefive2xmttx3 +6threebrcrtxhgsixbrhlhnczpdbmfdgpxbcone +fjsxkdeight8gnvgnmp995 +86eightdcdfvgcv7trq +9812 +ninezgstkmnmzfzmglcfour981 +pbsqbrqgsvqrqmnjddsvrttnnlbgq932 +two2hbc +sevenzktpspbhnlgseven2ztd +svonefive57fourdmgjgzhk2fsgkczq +onexglmkkgc4 +tctceightfive2leightxzbpddbqtwo +nvzeightwojjjsftdgv56fiveeightnqpqr +395onethree6 +fk5sevenonefive +nine7four8seven +1nineqqrldthree8fptsrdpfnqnine5h +two8six958seven +dgtnb8fourgbnine +6zvhqbsthreeninesixtwonep +94cjtzhqckqxlk8 +233fiveqcfcjdfxh7two +srqchthreekztwo749 +16ldgone +zfvtspcd55fivetwo +twoonesevenonesix77 +xchhlxk9fqcqmnhddstlj +5sevenkljjjpseven9fourone +92rjbjpptmzxfjv5nine +qs6eightdgkbrlconetwo +6lv +ddqpfnxzdhhb8 +3twornpckh6ninetwo +4czdfkeightfjqtbeightgndbfourjnznxrjvzx +sixeightrqvrqvvzxqflfztxs8six1 +qxfzlbftcsixvgr2mjfpxsbfour +1mvbthree8kxgbpmc8qcnlkbknhr6 +ssfhr84 +twosixninecgxdbm3 +seven9eightwoj +pxtdmcdff3qvfkzqtftwo5 +sevenxptzflgpgt7fdmlsptx +twoglqdjtslz5 +jgjdrhcmghmlfszdfcsbl1dlbnfblrjncdl +2onetqftxthree26csixeightoneightpxt +threefoursix49 +pslnpxonec44fourninesix +two6nrgbldxz6one +lmrtwonertzlhstnvvqgz1seventwofive8 +pphxjgvhdthree1 +6qdcjd2twonetb +ninecxgvsdmmlpfxhhzfcv2threethree7rsxpdnd +5qg +66455 +vb86pxgvnzshxhthree +5vhgtwoone3 +four16 +eightxbjbzjbl1qhnhqtgq7tjtlcseven2 +zqstwo8one23three9four +71fourrnzg6 +1qmhz +fiveseven7 +fourmcqnine3sixz5 +36bfourvxbsmzqrmneightsfntqfdcgsqghpmv9 +7967 +fourtwo2four9fivekcvsf +seven9fourgcngrdbmbvhgmnkvn4 +328kkjbqpvkjg +onethree57 +72twolstbbfvstmqdtsdz1 +2fourone6three +dczthhhjqzrsfour3 +three8xqdtp6threeone +twothree8jdrpbjrxgxvkqkpbsfhglb1 +3dnkvl8 +foursix2cbkrzvlbtqqsdbcd7mkzbmzthree +99onethreezghkkj +four4rhrltfthree1 +four6fiveshd +cvdlnfkns1mlnz5 +15onezjnm4fmvdhtzsgeightseven +five6tgtlbqmkxdnmqjsn28one94 +vc3bnblfpvdxs8sixlftxr4 +cpbgvklmplj8cbnnmgzzmh1cxqvnn6 +67njgvqpgthreesbfdjcgtgvtwothree +742 +97oneninehbjzfgbdjr1vvns +mprzgsqtwo7 +stbjfour8rt +dxchvbm2onercjfggjnine9tnfxzdklhpx2 +bdtwone9fourqdlhsfmstwo +nxvcq4cgxhcn19vhkznxrbmthree +bcd1 +5tktfnjxtwo +7six12eight5bgxqjgclk +vrfgxxfivevmjllxhbcgzgqlzmnfxhpnvtjp6nine +n5eight +onefgnz1gfmblblgvl7seven +six95threeninevdmxpjvpzkpc +6eightpbjftrzthreekgptrlrrxlkhcpsmq +kvsmgkk5ndlbqrhb +xjnrxxnpxmx3 +bpgkvznj1jrlhkfive +jmh4sevenxchsh25 +fivejhtfhmrcfjfour18hmxzg5 +71vrbbbtxsjrxcxdztwo +threesevenfour7eightthreegznpcdkpqjvpklrrb +4zrjhgnmvshfour4 +2foureighteighttwoseven +cmxfqjqvtb9 +eightlzkbn91snmckvgtgjxlktlzjpp +nine9kprhsbnsjonenspsldrsf7xzxcm +ktcrnftwo1cnnbdfqbng89onerhbrjd +dvbzrrqninesixfxmxmxgfntgvkzsnqs5 +dbmfqhkxz6eight +srxftlk2fivehzhzjlgreightxxrmbqghc2 +5qdgbxd +fourthree3four9nvfivejsoneightc +6ktzrdxnnd +5seven3zlqzslrvmfj83nine +5nine6fftx2shsslcgseight5 +91two +qlkfvkdbsr1seven4 +6onemgbvthreec9three43 +fdssixnine5cvjrbcggxnhskngtd46 +three9nine49 +two2vxmghcjjjxmninemvninebl +41nine6eightthree4lgtccg +6cfivetbdjjrpz4 +lmctwone734 +eightrstfklgsdcthreehcxfnmmsc45five3 +8eight93sevenrcqtxzxgpn +foureightpsnjhmtzfr1 +ksixthree21 +2hchsgvmssmrvrtwo8 +kfpgb791sevenseven21 +fivekzzh9 +52three +fivetwoseventhreesixfour8 +8lkqlzghcnqfivefvsj +eighttwo8five +cxgj5nineg8one7pcfour +131 +two35xgxhgnjvb +gmsdkchjxvv7nkdfczxfjmvhm +1sevenfkqfour98tsjm +ninethreefour89six6 +nmqqcnhxeightmnkhsfcjlglkb5 +ninefour4eightqbfivesevenhrxsnxlv +4sevennine54six +hsqpjhjtd4rjveightnnvrhfgkzdhxknpqxr +9tgb37four +3zqrvfcpm6eightsix +twopkhshrlksevensjzlfhpfgqkfgrnq7 +frx4drhc7tzxv +ninetwoninejppfourtxmjtctsn6 +2fbbseventhree9rqtxjnsix1spcnnvmkq +eightninemfpxcbkzkj1ninelv +5fsqzdfsxp +7sixrtrbhzsfsix +5txbphrdnnine5one61 +one4zvdkkzjbfour2sntphhhzdftgqbtzxfivefive +5sevenfour6qmrpqfvqlzninefourxzsnthztc4 +x3 +946five88five +three74cvsxvsxpbrsevenfour3qh +three9xlhbjmqtwo2one +eightd4seven2vzgbhc +six1dvksgllc4eightglpfvqsfx6fourxppsclfth +tqpjtqgntfourzljvrssls77 +seveneightnineone3 +sixbk5oneone8 +threeeight1sixfour +ggmn35ksf5dlnine +six1threesevenmcvspvvz +8vlqnn7seven +4sjvkmnvone88 +twozlgjtqpczfour9lgbrsc72one +59 +lkdkdzlvrdncsixrpgqlxhdrsldxzv4seven4 +3xzq123zztzf +twoninetnfmqlhxnrfcmvpfqonenrgfvrmf7h +nsjffflgfnineg3onekzklsxcqqfivelvvzqjh +6ktvsttwothreethreetktfgnnqlrtdxjjnh6 +onetwofive2two +56ckkt7 +3lfnhbqrsk2bjnmrh +zdnh6eightsix4knfkdqbeight +746ninefive8 +vhpeightwo37fiveseventwoseven2 +8gn5fourvqsvhxsnrbbdpqhmxszdx +rkrtlbnineseven8tgz4onebtcqzb +threeseven899 +three4bzqpcjvrjthreekvblvqnszhmhtwo +2monecfvsix4kbpgbnktdpfknnd +jksgbgdnvdthree83 +onethreegltwo253two +1lgxvclgjqjeightsixjhxsrdxzl8 +hptldqz3eightsdftlshlzone +1jtlqfnk9 +154three +rlqxzteighttwo6two +eightfour29nine2mgsdnlsdbeightvbpgjtkzmm +threejbxvrzrntj311one +twolscxtkchbdqzlltg9vcqkhbb85 +plkt4jqthreeonethreeeightone +fp5hjrnqgc1five98ninegdgbh +vtwovzvdssbone2v +884kfive7ninethree +2zjbmdtgbfvjlxbj +five6three12 +nineoneeight2 +4sixrtzmjb +kcnnvqcseven25htdxx +gpvpxvz3961 +cdcsgrjjzsq2hdzrdpzsf3 +pndssrqhr5kcbspqxjxxjf +jsthk98 +3fiveseveneighttwo2 +87r3 +zfz7nsrbfzgphxfsdgkbfqnlseven92 +npkl7 +onet819seventjfg7three +four38 +xthffmldlmxxrltxv2eightjzmgngrgpvnine94nine +dgqsttxqnqljbvl34dcb +ploneightfour1sixrtwobdrbj1ppmjrdjfs +68seven9fvzpl4 +8bxnclnsljvbbkz +htbmxsg7sevenfourvlvmxhhsj +mpcsfpkthreeninehp1gs6 +3eightseven +ninebvqjrdsdtkgktmonegktp8 +xcksrtdfksmrlhrjhq823four8f +lhjsnhgqxxspg6seven +26mqgmfcone +twonine9 +4ninefive8five4 +scvkzqqnr24ninekmvh47 +8six56nineeight +mr8fourdl9seven +hfgrhgfhksdgrpgzk9vljzthree3cjkz2mxrq +fourtfhlzjrtl53nshcqrjv8one33 +five5n87dhncbkveight +lx49threeonetqtsj +seven29eightfivetwo4six +9xzqsvxbj9 +nine4674zxrctgqtk +1two4 +6eight3jghjrqzv +53lksnfcftgcgmfthreehxkeight +3sevenfjvjffpxqfivetljmbktvk9twojcl +six1lpvtsrq9zqcqlgtdbdzxrjk +418tfk4hghnxbjpk +7fivedvtvbtmvv5ptwozfgq7 +threeplkvctrgr43gjnlfour2bzh +bcfjntzmntwofiverbhsixgqvmpkj3gmclxtljj +764jbvbksgckc42vhqpfmb4 +qsq922njbtnqpsqkt +68388qp9kgmmqcv +poneightfourfivefourxfive7nine +6onethree6two86four +sevensixk45fourthreetwo +4eightfdqspzsnvrnztg +64mhll2four8 +gmdmgzcqqnghmrgdkhz1vhtwoqspfkzhctvgdg7 +bbheight7xlxbmvonesix5 +6rcfivejdvffnkd +vbclrqfj11hthrczhxdjthree9 +dvgk1nszpptjsz9knzbbtbtp +gsqpnb5nineklhn6hnrbseighteightslxs +nbnqlseven9vmlbfzv +threelnxztmlmptwopsmnntf89 +3kccrnfour +3threeeight +tccxcs9five37one +xmzpjth2frrqnbc +fivedmtplmsixeightllqbsdps941eight +8rdtsix +2threem1four9 +eightrvgxlrlsixeight22 +onefivejqvmdsck2sevensix7z +fourbxgtpqdfonenzpqxthtchxjhzlqnk24xlqtjrtn +eightshttzglmvdscttkzone74sixvkvmkdcq +kvphvtjcbjdsblbnvgxxninectcrqzsqgstwonineltrlldpvk4 +3threexmnb +fcfsttx4lnjr8twonef +sevensix2fourgpsx9nine +621hxrzxqlnnsxlb8jgj8three +one9ktfzq +mzk1onenine +779five5pc +43sqfknineninetgscnbmnxvtqdk +cgb3fmfmpgqfzstfkm +gktbmhp25eight1hbrhlzplkk +12nine6onetwoftjrjfrnxfng +fivekk1pvhhzzrvpsxtphgtwoeight4 +mdqjkbnvtddldkbtbcvrgbnhllgtwothreetrzrn8 +vbsbfvgrq5twoseven65nm +mgbseven9fournine +7sevenone3 +ttnonethp4 +zpzxktxbstxvkkqjbmrzqvm4txsfhcmlr +pjsix48fournksgvfgkvjqvktnh7 +vbbdxd2fivetwo +four2lmsixxgckxkbsix6 +fourxb4 +rphsevenxm12mstbdvtjx +8szlthkxxnb3two55 +zgjztbtxmgqzvhhnljjhtwo366335 +2eightfourfourtwo958oneightcps +two37kfkfive +jzctwonekbtqdnzblonefive6gqssflbprspdzmfzhbvlg +one8fivemmgnine1 +9sevenmmfrjs2three4xfxcnine +5chxgkpnsvmmvbgpsvrmfvh +flfbssqninenineeightzkcmvseven49 +8six44qtstjsm7nine +sixgtgjzbhb5seventhreeseveneightfqdqpvtone +seven3nine +553fqnvr +one6sixg5twofourthree +threesix25 +kkgggk4threehbhk +1fivezhmhckfmbfzkxx5six6 +6jjzjmmbddn365dpcgrrtcbkhpq7 +1xdnxgtwofivesixonenine +9bbbkthgghpmvjbpgnjfour +five2sixljg9gcjfour +zsqs8nhtgg7fourfive +4zlcjrtkpmsevennzjxfourdtwo +fourmdcnhz1vqxqh +hxknxpqdhrgqt3fivethreekmfm9 +sixsixvkczqlghfhvzclnxnxpthreenine2twonerc +2vgqs3twoktx66 +z6fourmlmmmmtczl +mhskb47 +eightsixnsk4threepdsxdsqmcp +vlsmnznscsix6sixdjhkdjprgkfive +zjmxfzpst153six2 +8ninelxfourtwo8glkxrvqphqlcsqxjvjmgf +31four +hdmpgjrkdthree1two +5eightfour75jmbs +one9twoztjpvxqrgrvnt +pgvpsqnmnnine36pfp +1pmkhmqrlsbtthreetbxhpsp +2761xfgtwo +1kqtnqjmx5 +5bcjgmrpvbpmktxnvd4533qh +67seven2 +hrseventwoqxbnggjf3gszbxxprkbjgdgjgskxclphvcrt +24twopjtcvnvhmdj +two1ninevphz +zljmbl4threetxqlgz +four69threethreenine6 +sixvhcxbnsone1ninesevenj +eighttwo67 +27btwosix +hglnkvmzp6sevendfqxbdnnhf +tjhgnpbq3four +1six68four +796mhqxm7 +seventclmhcvmljpbxvvtpcm8mnfnone22 +kqrtwone6vhlshrvx1 +5djgneightfivejfmvgmssscx +71eightsk93 +7tjxrnine63four5 +5ninechr +jgdjcxp2sgdpkvjsx696 +nineonetwokpvrxlbsevenfour145 +tpdfcqklninepqpdnzckxq4 +fourfourthreeqvlvvfourfiveeight7 +5fgkpgv97gcfslvms5 +xp7ninetwo3eighteight68 +five6pgncxqdcdr2sixseven +shzm9gqgpfpkhxnine +nrzhmcpbdhvkgftqtseven5fourfive82 +6threenineffrdsqtblfcfour4 +vvxfk438krcn4seven +ninethreeseven1 +seventwosevensixpblbldrfive1nine +8mpzjhzvjdj5zljjconeseven6gsz +fjzcmctxjxqrfdls9kkcdh594 +pgc1n +shheightwo7eightfourczdvnzhxztphrnj3 +155 +sixmdlbdxs1two7nineone +onegvmnsqvjbgcxxnine65pnvfivesix +onemfbznqjsgfive9threefdmb8gkc +2three1 +4sxtrr +brzkseventhree51khpzssjczseven4 +5xtkzzrqgjzthreeone +fourfivez48 +4vlcksgvddfvqnjctwo +fourhmrd2six1vcrgqsgnndn +dmcklfkpt63two8 +5onebqbjts2223lzftpxdhrs +three6mtvkhsone7fiveghxgxz +sixfiveone144seventhree +9kqqjmtkrb +93qsrktlmvtksix7 +cknsdxjkninehftwo7five +twosix4eightsevenonethreefcrpcp3 +three1oneeighteightbhlrlgsx +twosevenone1 +rdgcvvlth1fiveone9 +ksbkbnthree4rvtpftfctvmcfive +vnkprjzqtmsbhglqfcbfd3 +hfrqcjdcztxntvjrpjf7fivefive875 +4128plkhjjpgnxeight +6ffxpgg5threenzg628nine +3six3 +seven4rbzxgvrktq4mrrcvhgrkhsxmgtkzslzhzsrn +tfzhdgqpfoursix4zqqeightzmjhrrfourptcfxt +seven7sixfvnbnzbfive1zzqvnmxzjmnk8 +qneightwo6fourninefourseven7five +3dhqlct8fdcxxhp6hnb +six6eightthree1xdrtzk +7two1 +d87fourkrqzjfs +xglckx1two3jtnmmq1ftpmr +1sixtwo4sfourvprscvzf8 +36fiveonenineone +ncjblr43bljpgcbxpeightseven +9onetqhqfj134ftmd2dm +xjtwonepbqhkzbztrlsktkfxspbdj59bjzj17 +7nine6sktjpsxbxdq26qqqprk +twofoureight1two +fkvsfiveniner3 +nvsmcrpseven242threeqjlrs +76xrll28qhdqltt +8sixkkxrtwon9hm +5jnnqnsvfxcptrktmbpneight1 +xvcxsrdhzeightqfvh9 +3cdtz32six5bdskvjrksxjone +gbddhxbm44bsl +jxkmntkx1eightwodp +three27jlmrldnsj3 +6sixjmlgldbx61six3sixone +three2pjvbrjkdone5 +8oneightgp +nine4seven5 +tr4mmtcgvxvqfgqd6seven625 +twofive8 +26fivefdfkgtvsvvxlgrrjlxxseven +ninethreetwo34sevenfivevxzshkpzxk +jm1fbtptbkjfx529 +sixjrl98threetpxcnfive +6rnv +fourtwotwo4qhh4 +eightdldkblq1six +442two +ssix7fivefive +four4eighteightmchbppzmm +fivek8dmjsbtjvpj +five6861vzrqhbfdvsixmqsl +ctqrpzgpgcqhtwo8twoctb9five +eight4threeeight7 +one359 +pxhhkhccd6vvbnbfourgjmhzvcs98 +65qskzgm7seveng +9dcmtl8sixj6 +gtbvnth1three3zfmdfdnine9 +hpxjjcj6lkkzdv3xczkpbprcnvkfngv +foursixseven9 +xnlf6ccxzlcsixjvhkxzxfck +fivembqp369lzgrfzq +sixfourninefivesevenqgdfbmhthf6 +fxbtjfkqsmvnsrvfrbsixvzmrzdtvvxhbd5 +kbsxlq97 +52sfsqq4onesix +8leightsixtwo +hvrkcdbdxz9sixkgpp +four7three +9t6hbsjkznxchjq9zbdvkhx +7twoeightnt +4qmqlvlpk6 +xfqhf74eight +xhtpninecfpzjq74 +kfvdfkqtwoksbknptnrcqlghbfive4fiveftnnkv +vd1fourlfsfxqp +cnxpjjbklvlbrzkqgfmrkeightgbkgscbgpsix4 +sevenczftbcg24rrqdscm1nvtddt +sftwone1fourtwo42nine +2nineoneqxtmbsgrqvfivecsstrbstptwo +three2seven7qlcpqqgqdhjxbvf +kdkbmnbsxpgtpgzmtlbftmrfmcvmdghvhkxl4 +two6nine6prlzxrclq +qtwonefqchmsbtgk876three3 +6ltnntlnvtfive +4six46pcjgclkstwo6zspgq6 +341three8six +four9onetwo166rvcgtv +gbhgsnkz6eightfour6sldckhdnbg6xktdfb +one9three67 +hhvcphgxrzfjggthreeseven624 +three374tlfl2nine +vkpj3 +three1dglzmjvps57tworrqglxb +sixsix18six +nine8one1dmgmkchvpvxqpdqdpxzxpthree +mpsdqgmtllqhptwoninevrkp43 +3sixddcklgnrrj +gpskjbbchfive58six +72v8seven +4sxjvbd +dlqs87seven7zphphqfive +341mmsfdff +1lftv2 +five1three4xpt993 +92nhcncp +58eighteightgjndsmsjtpnlleighteight +9tnrsnzqzkbkseven +ffhhnvfbmsjg2six +4xtvqpsjnine4two +57ddkkkltv +nine8three +rvkmcmshxpkrxpglzt3khcfour +eightonebjqbljgmt6tfkrf73 +three36jtgml1 +fndcqgm2fournngpvlcmcrzrvsevenseven2 +f9ljpjpnkseven +cxhtfspj9mkfxdfour99 +tkgjdj4twos2four1 +5threezrccdbf6qpzxvdvmlrbmkkpzpxdrtwosix +eightrstwoxkbxvmdjgxjftfzmngsix6 +66onebrtfdpzqlone69four +three2five8hcncdsvqfx86 +7fivefbone +twovbqzfhkxgv5g7 +5lfprlrznvgtsix4xmdxvgsv7six +threethree57 +five8threetprlzmrx418kdlzddbpv +three7hqsnvrxhv68five1three7 +2sixcj651three +cvfqbfftpk3six6vdvx6eightxqsjqph3 +914 +2zq9 +kzfsevenninemjpfourhqq4jfgqvdjeight +rvgmtnjsix9hvncrblxfour176 +threeeight388three87 +twovtgshgfive7 +qseven4eight1fivejcrt +oneone7 +6fkfddtbpfbp +5six7three +1fourfiveljrmbmfpsvzzhdlh +ndqhpmjsxjgvdgv2six1qbnc +sixeightsvcgjzfmqthree98 +threeglsevenone2 +9onetwovlmzvndpts3 +six6xjfnrqbmxs7twofhcsgnm1 +42pspfbrfive +threeccbdtsrfv4drmvqcbdsix7sevenfiven +7rvgchnjfznc +sevensevenkpbggfhrhk121 +2hzvqxxtrmlxbvbclkfiveone +9fivepdpmmlkshq8kqlninefour1oneightt +5sixeightsix37 +four9sixqjbpxfgc68zcjffmjone +qkpbblqtk6fourvgvdvnsdhnktgqzhxrm +qbcvmnpxv1fivexlone4eightjlqdvbqmr +vgt35pztrjktfzz6 +tgfmjb7eight1ln8lhbpdcz +4xk56threethreeone +258kzkzrpsclmmf +dvrfk9fourtwollnsgcn +tnmphhv4 +sixtvtdptlpseven18dmrnrfgdzgcfrlczthree +llscxn2 +487eightfour73 +7skmgfpgdt69two +pbkprbzvs819threeonekjpk7brkmbqbkgroneightb +ninerfcvgpbltbljnk3 +nfzlonesmeight6gtff +tleighttdxtbhrvgk16bpkmtcvlnrhnmhz +one99 +mqtwooneeight7sevenfourht +stzmqplr8gvmxblz +five8dvdjqfmpnh3 +scjjr4twoh +nine35gzmlt +5sixfour2qxsqkpnq +kdkjqdkvgs2 diff --git a/2023/days/01/src/main.rs b/2023/days/01/src/main.rs new file mode 100644 index 0000000..a6abd96 --- /dev/null +++ b/2023/days/01/src/main.rs @@ -0,0 +1,15 @@ +mod part1; +mod part2; +mod parse; + +fn main() { + let input = include_str!("./input.txt"); + let structured_input = parse::parse(input); + + println!("Part One"); + println!("Result: {}", part1::part1(&structured_input)); + + let structured_input = parse::parse_english(input); + println!("Part Two"); + println!("Result: {}", part2::part2(&structured_input)); +} diff --git a/2023/days/01/src/parse.rs b/2023/days/01/src/parse.rs new file mode 100644 index 0000000..a91e4b5 --- /dev/null +++ b/2023/days/01/src/parse.rs @@ -0,0 +1,77 @@ +static REPLACEMENT_STRINGS: [(&str, &str); 10] = [ + ("zero", "zero0zero"), + ("one", "one1one"), + ("two", "two2two"), + ("three", "three3three"), + ("four", "four4four"), + ("five", "five5five"), + ("six", "six6six"), + ("seven", "seven7seven"), + ("eight", "eight8eight"), + ("nine", "nine9nine"), +]; + +pub fn parse_english(input: &str) -> Vec> { + input + .to_string() + .lines() + .map(|l| { + let mut ret = l.to_string(); + for (string, replacement) in REPLACEMENT_STRINGS.iter() { + ret = ret.replace(string, replacement) + } + ret + }) + .map(|l| l.chars().filter(|c| c.is_ascii_digit()).collect()) + .collect() +} + +pub fn parse(input: &str) -> Vec> { + input + .lines() + .map(|l| l.chars().filter(|c| c.is_ascii_digit()).collect()) + .collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse() { + let input = concat!("1abc2\n", "pqr3stu8vwx\n", "a1b2c3d4e5f\n", "treb7uchet\n",); + assert_eq!( + parse(input), + vec![ + vec!['1', '2',], + vec!['3', '8',], + vec!['1', '2', '3', '4', '5'], + vec!['7'] + ] + ); + } + #[test] + fn test_english() { + let input = concat!( + "two1nine\n", + "eightwothree\n", + "abcone2threexyz\n", + "xtwone3four\n", + "4nineeightseven2\n", + "zoneight234\n", + "7pqrstsixteen\n", + ); + assert_eq!( + parse_english(input), + vec![ + vec!['2', '1', '9',], + vec!['8', '2', '3',], + vec!['1', '2', '3',], + vec!['2', '1', '3', '4'], + vec!['4', '9', '8', '7', '2'], + vec!['1', '8', '2', '3', '4'], + vec!['7', '6'], + ] + ); + } +} diff --git a/2023/days/01/src/part1.rs b/2023/days/01/src/part1.rs new file mode 100644 index 0000000..4ff4b81 --- /dev/null +++ b/2023/days/01/src/part1.rs @@ -0,0 +1,27 @@ +pub fn part1(input: &[Vec]) -> usize { + input + .iter() + .map(|s| { + let mut string = String::new(); + string.push_str(&s.first().unwrap().to_string()); + string.push_str(&s.last().unwrap().to_string()); + string.parse::().unwrap() + }) + .sum() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part1() { + let input = vec![ + vec!['1', '2'], + vec!['3', '8'], + vec!['1', '2', '3', '4', '5'], + vec!['7'], + ]; + assert_eq!(part1(&input), 142); + } +} diff --git a/2023/days/01/src/part2.rs b/2023/days/01/src/part2.rs new file mode 100644 index 0000000..5d8ad68 --- /dev/null +++ b/2023/days/01/src/part2.rs @@ -0,0 +1,30 @@ +pub fn part2(input: &[Vec]) -> usize { + input + .iter() + .map(|s| { + let mut string = String::new(); + string.push_str(&s.first().unwrap().to_string()); + string.push_str(&s.last().unwrap().to_string()); + string.parse::().unwrap() + }) + .sum() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part2() { + let input = vec![ + vec!['2', '1', '9'], + vec!['8', '2', '3'], + vec!['1', '2', '3'], + vec!['2', '1', '3', '4'], + vec!['4', '9', '8', '7', '2'], + vec!['1', '8', '2', '3', '4'], + vec!['7', '6'], + ]; + assert_eq!(part2(&input), 281); + } +} diff --git a/2023/days/02/Cargo.toml b/2023/days/02/Cargo.toml new file mode 100644 index 0000000..3facc9f --- /dev/null +++ b/2023/days/02/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "day02" +authors.workspace = true +description.workspace = true +version.workspace = true +edition.workspace = true + +[dependencies] +aoc_libs.workspace = true +nom.workspace = true diff --git a/2023/days/02/src/input.txt b/2023/days/02/src/input.txt new file mode 100644 index 0000000..e0ad712 --- /dev/null +++ b/2023/days/02/src/input.txt @@ -0,0 +1,100 @@ +Game 1: 3 blue, 7 green, 10 red; 4 green, 4 red; 1 green, 7 blue, 5 red; 8 blue, 10 red; 7 blue, 19 red, 1 green +Game 2: 6 red, 10 green; 11 green, 4 red; 16 green, 2 blue; 7 green, 5 blue, 4 red; 17 green, 1 red, 1 blue +Game 3: 5 red, 9 blue, 1 green; 5 red; 11 red, 2 green, 8 blue; 2 green, 6 blue +Game 4: 2 red, 5 green; 2 blue, 3 red, 3 green; 3 red, 2 blue; 8 green, 2 red +Game 5: 12 red, 13 blue; 13 blue, 2 green, 9 red; 9 blue, 1 red; 2 green, 12 blue; 1 green, 1 red, 11 blue +Game 6: 4 blue, 11 red; 4 red; 1 green, 7 red; 1 green, 1 blue; 8 blue, 10 red; 1 green, 2 blue, 8 red +Game 7: 7 blue, 15 red, 1 green; 5 green, 17 red, 7 blue; 5 blue, 1 green; 11 blue, 2 green, 17 red; 14 green, 9 red, 2 blue; 6 blue, 19 red +Game 8: 13 green; 5 green; 3 blue, 9 green, 1 red; 4 red, 11 green, 4 blue +Game 9: 4 green, 1 red, 1 blue; 4 green, 7 blue, 7 red; 9 blue, 4 red; 2 blue, 8 red, 5 green; 6 blue, 2 green; 5 red, 5 green, 10 blue +Game 10: 1 green, 5 blue, 3 red; 4 green, 9 red, 3 blue; 11 red, 2 green, 5 blue; 3 green, 1 blue, 2 red; 6 red, 2 blue +Game 11: 2 red, 6 green, 12 blue; 2 red, 9 blue, 1 green; 12 green, 3 blue +Game 12: 1 red, 1 blue, 12 green; 6 green, 2 red, 1 blue; 6 red, 6 green, 1 blue; 3 green, 6 red +Game 13: 5 red, 19 green, 3 blue; 6 red, 7 blue, 11 green; 8 blue, 6 red; 3 blue, 4 green, 4 red; 8 red, 15 green, 5 blue; 5 blue, 2 red, 10 green +Game 14: 5 blue, 9 green; 4 green, 6 blue; 14 green, 1 red, 4 blue; 3 blue, 3 green; 2 green; 5 blue, 7 green, 1 red +Game 15: 5 red, 8 blue; 9 blue, 3 red; 5 red, 1 green, 16 blue; 1 blue, 3 red, 2 green; 5 red, 2 green, 10 blue +Game 16: 6 blue, 9 green, 10 red; 8 blue, 9 red, 14 green; 7 green, 1 blue, 1 red; 8 red, 5 green, 8 blue; 10 red, 5 blue, 14 green; 7 blue, 11 red, 3 green +Game 17: 12 blue, 12 red, 6 green; 14 green, 17 blue, 4 red; 11 blue, 1 red, 13 green +Game 18: 7 blue, 2 green, 4 red; 1 blue, 2 green, 4 red; 2 red, 17 blue +Game 19: 3 red, 9 green; 8 red, 2 blue, 2 green; 3 blue, 15 green, 11 red; 18 green, 3 red, 1 blue +Game 20: 5 green, 5 red, 16 blue; 8 blue, 6 green, 4 red; 10 red, 11 blue; 5 red, 5 blue, 5 green +Game 21: 1 red, 3 blue, 14 green; 6 red, 6 blue, 17 green; 12 green, 17 blue, 3 red; 15 green, 1 red, 19 blue; 3 red, 18 blue, 4 green +Game 22: 15 blue; 11 blue, 2 red, 1 green; 1 green, 7 red; 1 red, 18 blue, 1 green; 16 blue; 3 red, 6 blue +Game 23: 11 blue, 6 green, 4 red; 9 green, 11 red, 8 blue; 5 green, 5 red, 2 blue; 11 green, 4 blue, 11 red; 3 green, 9 blue, 2 red +Game 24: 7 green, 2 red; 8 red, 1 blue, 15 green; 3 red, 6 green, 6 blue +Game 25: 9 blue, 9 green; 3 green, 7 blue, 1 red; 6 green, 1 red, 1 blue; 6 green, 1 red, 1 blue +Game 26: 1 green, 15 blue, 1 red; 1 red, 12 blue, 1 green; 16 blue; 5 red, 11 green, 14 blue; 6 green, 4 red, 14 blue +Game 27: 14 red, 9 green; 11 red, 5 green, 6 blue; 1 red, 6 blue, 9 green +Game 28: 6 green, 1 blue, 9 red; 1 green, 9 red; 7 red; 11 red, 1 blue, 2 green; 8 red, 10 green; 6 green, 1 blue, 5 red +Game 29: 1 red, 19 blue, 3 green; 9 blue, 1 red; 8 green, 17 blue; 11 blue, 4 green +Game 30: 7 blue; 5 blue, 1 red, 1 green; 3 blue, 1 red +Game 31: 9 red, 2 green, 1 blue; 5 red, 1 green, 3 blue; 2 green, 7 red; 2 green, 12 red +Game 32: 1 red, 1 blue, 17 green; 14 blue, 10 green, 6 red; 12 green, 11 blue, 3 red +Game 33: 2 red, 1 green, 3 blue; 7 blue, 4 green; 1 red, 3 green, 5 blue +Game 34: 9 blue, 1 green, 9 red; 12 blue, 2 green, 12 red; 3 blue, 12 red; 2 green, 14 blue, 11 red; 10 red, 12 blue +Game 35: 6 blue, 2 red; 5 blue; 6 green, 9 blue, 3 red; 3 green, 1 red, 2 blue +Game 36: 9 blue, 4 green, 6 red; 2 red, 4 green; 7 red, 3 green; 6 green, 2 blue; 3 red, 4 blue, 3 green; 3 green, 4 red, 16 blue +Game 37: 2 green, 8 red, 4 blue; 3 red, 4 blue, 2 green; 5 blue, 3 green; 9 blue, 15 green; 5 red, 11 green, 7 blue +Game 38: 12 red, 1 blue; 10 red, 3 green, 2 blue; 7 blue, 3 green, 8 red; 14 red, 2 green +Game 39: 16 green, 2 red, 17 blue; 6 red, 4 green, 13 blue; 7 blue, 1 green, 4 red; 2 green, 3 blue; 12 green, 6 red, 17 blue; 5 red, 2 blue, 6 green +Game 40: 3 green, 4 blue, 2 red; 2 green, 3 red; 6 blue, 2 red, 6 green; 5 green; 3 blue, 1 red, 5 green +Game 41: 13 green, 11 red; 3 green, 2 red, 1 blue; 1 blue, 3 green, 9 red; 12 red, 11 green; 9 red, 1 green; 9 green, 4 red +Game 42: 4 green, 2 blue; 6 blue, 10 green; 13 blue, 3 red, 6 green; 11 blue, 17 green; 8 blue, 5 red +Game 43: 10 green, 2 blue, 10 red; 3 red, 3 blue, 5 green; 10 green, 11 red, 4 blue; 5 green; 7 green, 13 red, 2 blue +Game 44: 4 red, 1 blue, 5 green; 1 blue, 8 red, 3 green; 11 red, 1 green, 1 blue; 2 green, 12 red, 1 blue; 1 blue, 12 red; 14 red, 3 green +Game 45: 4 green, 5 red, 7 blue; 10 red, 8 green, 3 blue; 12 blue, 1 green, 13 red; 1 red, 3 blue, 7 green +Game 46: 5 blue, 13 red; 15 red, 3 green, 17 blue; 8 red, 2 green, 1 blue; 1 green, 7 red, 16 blue; 4 blue, 10 red +Game 47: 2 red, 3 green; 2 blue, 9 red, 15 green; 7 green, 4 red; 3 blue, 13 red, 9 green +Game 48: 11 green, 4 red, 9 blue; 1 blue, 7 green; 4 blue, 4 red; 4 red, 4 blue, 2 green; 9 green, 2 blue, 2 red +Game 49: 10 green, 6 blue; 2 blue, 5 green, 1 red; 5 green, 4 blue; 11 green, 3 red, 3 blue +Game 50: 2 red, 15 green, 1 blue; 8 green, 7 blue; 4 blue, 8 green; 7 blue, 17 green; 5 blue, 6 green, 2 red; 16 green, 2 red, 1 blue +Game 51: 3 green, 5 blue, 1 red; 11 red, 9 blue, 8 green; 3 red, 8 green, 7 blue; 1 red, 9 blue, 6 green; 4 green, 1 red, 3 blue; 8 green, 7 red +Game 52: 1 green, 2 blue, 10 red; 8 green, 1 blue, 2 red; 7 red, 8 green +Game 53: 2 red, 6 green; 1 green, 4 blue; 12 green, 19 blue; 11 blue, 1 green; 4 green, 20 blue; 7 blue, 9 green, 1 red +Game 54: 2 blue, 2 green, 2 red; 13 red, 1 green, 6 blue; 9 blue, 1 green, 18 red; 11 red, 16 blue; 15 red, 3 green, 13 blue +Game 55: 5 green, 5 blue, 9 red; 8 red, 11 blue, 7 green; 6 green, 2 red, 10 blue; 6 red, 6 blue, 9 green; 11 green, 14 blue, 4 red +Game 56: 8 blue, 14 green; 3 red, 8 green, 3 blue; 14 green, 1 red, 13 blue; 8 green, 3 red; 8 blue, 11 green, 1 red; 8 blue, 10 green, 2 red +Game 57: 7 blue, 7 red; 11 green, 5 blue, 2 red; 14 green, 8 blue; 5 blue, 2 red, 17 green; 12 green, 3 red; 7 red, 7 blue, 9 green +Game 58: 3 blue, 4 red, 1 green; 2 green, 3 red; 1 red, 2 green, 4 blue; 4 green, 4 red, 2 blue +Game 59: 6 red, 4 blue, 5 green; 6 blue, 6 red; 1 red; 8 blue, 1 red +Game 60: 4 blue, 9 green, 11 red; 12 green, 3 red, 9 blue; 7 green, 1 blue; 14 green, 11 blue, 11 red +Game 61: 12 green; 9 green, 9 red; 12 red, 18 blue, 8 green; 16 red, 10 blue, 3 green; 6 green, 15 red, 3 blue; 13 green +Game 62: 2 green, 3 red, 12 blue; 12 blue, 12 green, 12 red; 1 red, 12 blue, 5 green; 7 red, 9 blue, 13 green; 1 blue, 3 red, 10 green; 2 blue, 8 red, 17 green +Game 63: 10 green, 7 blue, 4 red; 3 blue, 6 green, 2 red; 4 green, 10 red, 6 blue; 16 blue, 5 red, 4 green +Game 64: 11 red, 1 green, 6 blue; 12 red, 3 green; 6 green, 5 blue, 2 red; 4 green, 9 blue, 11 red; 5 blue, 8 green, 8 red; 9 green, 11 blue +Game 65: 4 blue, 12 red; 1 green, 3 blue, 12 red; 1 green, 3 blue, 13 red; 2 red; 12 red +Game 66: 4 red, 3 green, 3 blue; 2 blue, 4 red; 10 red, 6 blue, 3 green +Game 67: 7 red, 2 blue, 5 green; 3 green, 5 red, 18 blue; 16 red, 5 green, 13 blue; 16 red, 5 blue, 2 green +Game 68: 11 blue, 2 red; 1 green, 3 blue, 8 red; 16 red, 1 green, 17 blue; 4 red, 1 green, 11 blue; 3 red +Game 69: 1 green, 9 red, 12 blue; 12 red; 11 blue; 1 green +Game 70: 1 green, 18 blue, 16 red; 3 green, 15 red, 7 blue; 3 blue, 3 green, 10 red; 1 blue, 3 green, 10 red +Game 71: 3 red, 12 blue, 8 green; 18 green, 12 blue, 5 red; 2 blue, 7 red; 11 blue, 9 green; 5 blue, 7 red, 19 green; 2 red, 1 blue, 13 green +Game 72: 8 red, 6 blue, 3 green; 2 green, 13 blue, 15 red; 5 green, 8 blue, 2 red; 5 red, 12 blue, 3 green +Game 73: 3 blue, 13 green; 7 red, 3 green; 10 red, 2 blue, 1 green +Game 74: 3 red; 2 red, 1 blue, 7 green; 10 green, 3 blue, 1 red; 6 green, 1 blue; 11 green, 4 blue +Game 75: 8 blue, 2 green, 4 red; 19 blue, 2 green; 1 red, 18 blue, 3 green; 3 red, 5 green, 18 blue +Game 76: 3 green, 2 red, 2 blue; 3 blue, 6 green, 1 red; 1 green, 3 blue; 1 blue, 1 green +Game 77: 4 green, 7 red, 13 blue; 18 blue; 4 blue, 9 red, 1 green; 2 green, 16 blue, 9 red +Game 78: 2 green, 5 blue, 11 red; 2 blue, 3 red, 1 green; 4 green, 6 blue, 6 red +Game 79: 9 blue, 1 green, 3 red; 1 green, 2 red, 4 blue; 5 red, 4 green, 10 blue; 1 red, 9 blue, 4 green +Game 80: 8 red, 5 green, 7 blue; 15 red, 6 blue, 8 green; 8 blue, 14 red, 7 green; 3 blue, 2 green, 20 red; 10 red, 8 blue, 1 green; 7 green, 11 red, 9 blue +Game 81: 7 red, 1 blue, 5 green; 5 green, 10 blue, 9 red; 8 blue, 2 green, 7 red +Game 82: 1 green, 6 blue, 14 red; 7 blue, 2 green; 7 blue, 17 red, 3 green +Game 83: 2 red, 19 blue, 2 green; 5 red, 5 blue, 2 green; 2 red, 4 blue, 1 green +Game 84: 1 blue, 1 red, 12 green; 11 blue, 6 red, 13 green; 10 red, 8 blue, 8 green; 14 blue, 15 red; 19 blue, 10 green, 17 red; 11 red, 7 green +Game 85: 16 blue, 12 red, 8 green; 13 red, 3 green; 1 red, 16 blue, 10 green +Game 86: 5 green, 8 blue, 3 red; 8 green, 9 red, 13 blue; 4 green, 1 red, 12 blue; 13 red, 15 blue, 5 green +Game 87: 1 green, 16 red; 10 red, 2 green, 2 blue; 16 red, 5 blue; 1 blue, 2 green +Game 88: 3 blue, 1 green; 1 red, 2 green, 13 blue; 5 blue, 2 green, 1 red +Game 89: 9 blue, 2 red, 1 green; 10 blue; 5 blue, 1 green +Game 90: 8 red, 2 blue, 5 green; 2 red, 2 green, 2 blue; 1 blue, 8 green, 10 red; 11 green, 1 blue; 10 green, 4 red, 3 blue +Game 91: 14 blue, 9 red; 5 green, 5 red, 11 blue; 7 green, 4 blue, 12 red; 8 red, 6 green, 10 blue +Game 92: 2 green, 2 blue, 12 red; 2 green, 1 blue, 14 red; 14 red, 2 blue, 6 green; 11 red, 6 green, 2 blue; 11 green, 12 red, 2 blue +Game 93: 4 green, 7 blue, 3 red; 1 green, 12 blue, 1 red; 8 blue, 7 green, 2 red; 3 red, 9 blue, 2 green +Game 94: 13 green, 9 blue; 9 blue, 1 red, 8 green; 12 green, 1 red, 8 blue; 1 red, 9 green; 1 red, 5 blue, 14 green +Game 95: 7 blue, 14 red; 9 blue, 17 red; 2 blue, 1 green, 4 red +Game 96: 11 blue, 2 green, 3 red; 3 blue, 12 red, 3 green; 4 green, 11 red, 1 blue +Game 97: 9 red, 5 green, 2 blue; 12 red, 1 blue, 11 green; 7 green, 4 red, 2 blue; 1 blue, 6 red, 10 green +Game 98: 5 green, 5 red, 11 blue; 1 red, 10 blue, 7 green; 8 red, 1 blue, 7 green; 8 green, 11 red, 2 blue; 4 red, 5 blue, 2 green; 10 green, 5 red, 9 blue +Game 99: 3 green, 7 red, 4 blue; 9 red, 13 blue, 2 green; 3 red, 2 green, 11 blue; 5 red, 6 blue, 3 green; 8 blue, 5 green, 6 red; 6 green, 13 red, 1 blue +Game 100: 9 green, 7 blue; 1 green, 3 red, 4 blue; 15 red, 9 green; 3 blue, 6 red, 13 green; 2 red, 11 blue, 12 green diff --git a/2023/days/02/src/main.rs b/2023/days/02/src/main.rs new file mode 100644 index 0000000..456385c --- /dev/null +++ b/2023/days/02/src/main.rs @@ -0,0 +1,14 @@ +mod part1; +mod part2; +mod parse; + +fn main() { + let input = include_str!("./input.txt"); + let structured_input = parse::parse(input); + + println!("Part One"); + println!("Result: {}", part1::part1(&structured_input)); + + println!("Part Two"); + println!("Result: {}", part2::part2(&structured_input)); +} diff --git a/2023/days/02/src/parse.rs b/2023/days/02/src/parse.rs new file mode 100644 index 0000000..17a33c4 --- /dev/null +++ b/2023/days/02/src/parse.rs @@ -0,0 +1,294 @@ +use nom::{ + branch::alt, + bytes::complete::tag, + character::{self}, + combinator::map, + multi::separated_list1, + sequence::{preceded, terminated}, + IResult, +}; + +#[derive(Debug, PartialEq, Eq)] +pub struct Handful { + pub red: u8, + pub green: u8, + pub blue: u8, +} + +impl Handful { + pub fn is_possible_given_contents(&self, contents: &Handful) -> bool { + contents.red >= self.red && contents.green >= self.green && contents.blue >= self.blue + } + + pub fn power(&self) -> usize { + self.red as usize * self.green as usize * self.blue as usize + } +} + +#[derive(Debug, PartialEq, Eq)] +pub struct Game { + pub id: u8, + pub handfuls: Vec, +} + +impl Game { + fn parse(input: &str) -> IResult<&str, Self> { + let (input, id) = Self::parse_game_id(input)?; + let (input, handfuls) = separated_list1(tag("; "), Self::parse_handful)(input)?; + Ok((input, Game { id, handfuls })) + } + + fn parse_game_id(input: &str) -> IResult<&str, u8> { + terminated( + preceded(tag("Game "), nom::character::complete::u8), + tag(": "), + )(input) + } + + fn parse_colour_set(input: &str) -> IResult<&str, Colour> { + let red = terminated(character::complete::u8, tag(" red")); + let green = terminated(character::complete::u8, tag(" green")); + let blue = terminated(character::complete::u8, tag(" blue")); + alt(( + map(red, Colour::Red), + map(green, Colour::Green), + map(blue, Colour::Blue), + ))(input) + } + + fn parse_handful(input: &str) -> IResult<&str, Handful> { + let (input, colours) = separated_list1(tag(", "), Self::parse_colour_set)(input)?; + let mut red = 0; + let mut green = 0; + let mut blue = 0; + for colour in colours { + match colour { + Colour::Red(n) => red = n, + Colour::Green(n) => green = n, + Colour::Blue(n) => blue = n, + } + } + Ok((input, Handful { red, green, blue })) + } + + pub fn is_possible_given_contents(&self, contents: &Handful) -> bool { + self.handfuls + .iter() + .all(|h| h.is_possible_given_contents(contents)) + } + + pub fn min_contents(&self) -> Handful { + Handful { + red: self.handfuls.iter().map(|g| g.red).max().unwrap_or(0), + green: self.handfuls.iter().map(|g| g.green).max().unwrap_or(0), + blue: self.handfuls.iter().map(|g| g.blue).max().unwrap_or(0), + } + } +} + +#[derive(Debug, PartialEq, Eq)] +enum Colour { + Red(u8), + Green(u8), + Blue(u8), +} + +pub fn parse(input: &str) -> Vec { + input.lines().map(|l| Game::parse(l).unwrap().1).collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse() { + let input = concat!( + "Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green\n", + "Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue\n", + "Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red\n", + "Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red\n", + "Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green\n", + ); + assert_eq!( + parse(input), + vec![ + Game { + id: 1, + handfuls: vec![ + Handful { + red: 4, + green: 0, + blue: 3 + }, + Handful { + red: 1, + green: 2, + blue: 6 + }, + Handful { + red: 0, + green: 2, + blue: 0 + } + ] + }, + Game { + id: 2, + handfuls: vec![ + Handful { + red: 0, + green: 2, + blue: 1 + }, + Handful { + red: 1, + green: 3, + blue: 4 + }, + Handful { + red: 0, + green: 1, + blue: 1 + } + ] + }, + Game { + id: 3, + handfuls: vec![ + Handful { + red: 20, + green: 8, + blue: 6 + }, + Handful { + red: 4, + green: 13, + blue: 5 + }, + Handful { + red: 1, + green: 5, + blue: 0 + } + ] + }, + Game { + id: 4, + handfuls: vec![ + Handful { + red: 3, + green: 1, + blue: 6 + }, + Handful { + red: 6, + green: 3, + blue: 0 + }, + Handful { + red: 14, + green: 3, + blue: 15 + } + ] + }, + Game { + id: 5, + handfuls: vec![ + Handful { + red: 6, + green: 3, + blue: 1 + }, + Handful { + red: 1, + green: 2, + blue: 2 + } + ] + } + ] + ); + } + + #[test] + fn test_game_parsing() { + let input = "Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green"; + assert_eq!( + Game::parse(input).unwrap(), + ( + "", + Game { + id: 1, + handfuls: vec![ + Handful { + blue: 3, + red: 4, + green: 0 + }, + Handful { + red: 1, + green: 2, + blue: 6 + }, + Handful { + green: 2, + blue: 0, + red: 0 + }, + ] + } + ) + ) + } + + #[test] + fn test_parse_handful() { + assert_eq!( + Game::parse_handful("10 blue, 53 red, 3 green").unwrap(), + ( + "", + Handful { + red: 53, + green: 3, + blue: 10 + } + ) + ); + assert_eq!( + Game::parse_handful("15 green, 53 red").unwrap(), + ( + "", + Handful { + red: 53, + green: 15, + blue: 0 + } + ) + ); + } + + #[test] + fn test_parse_colour_set() { + assert_eq!( + Game::parse_colour_set("5 red").unwrap(), + ("", Colour::Red(5)) + ); + assert_eq!( + Game::parse_colour_set("10 blue").unwrap(), + ("", Colour::Blue(10)) + ); + assert_eq!( + Game::parse_colour_set("123 green").unwrap(), + ("", Colour::Green(123)) + ); + } + + #[test] + fn test_parse_game_id() { + assert_eq!(Game::parse_game_id("Game 2: ").unwrap(), ("", 2)); + assert_eq!(Game::parse_game_id("Game 100: ").unwrap(), ("", 100)); + assert_eq!(Game::parse_game_id("Game 15: ").unwrap(), ("", 15)); + } +} diff --git a/2023/days/02/src/part1.rs b/2023/days/02/src/part1.rs new file mode 100644 index 0000000..b29b7b4 --- /dev/null +++ b/2023/days/02/src/part1.rs @@ -0,0 +1,121 @@ +use crate::parse::*; + +pub fn part1(input: &[Game]) -> usize { + let contents = Handful { + red: 12, + green: 13, + blue: 14, + }; + input + .iter() + .filter(|g| g.is_possible_given_contents(&contents)) + .map(|g| g.id as usize) + .sum() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part1() { + let input = vec![ + Game { + id: 1, + handfuls: vec![ + Handful { + red: 4, + green: 0, + blue: 3, + }, + Handful { + red: 1, + green: 2, + blue: 6, + }, + Handful { + red: 0, + green: 2, + blue: 0, + }, + ], + }, + Game { + id: 2, + handfuls: vec![ + Handful { + red: 0, + green: 2, + blue: 1, + }, + Handful { + red: 1, + green: 3, + blue: 4, + }, + Handful { + red: 0, + green: 1, + blue: 1, + }, + ], + }, + Game { + id: 3, + handfuls: vec![ + Handful { + red: 20, + green: 8, + blue: 6, + }, + Handful { + red: 4, + green: 13, + blue: 5, + }, + Handful { + red: 1, + green: 5, + blue: 0, + }, + ], + }, + Game { + id: 4, + handfuls: vec![ + Handful { + red: 3, + green: 1, + blue: 6, + }, + Handful { + red: 6, + green: 3, + blue: 0, + }, + Handful { + red: 14, + green: 3, + blue: 15, + }, + ], + }, + Game { + id: 5, + handfuls: vec![ + Handful { + red: 6, + green: 3, + blue: 1, + }, + Handful { + red: 1, + green: 2, + blue: 2, + }, + ], + }, + ]; + assert_eq!(part1(&input), 8); + } +} diff --git a/2023/days/02/src/part2.rs b/2023/days/02/src/part2.rs new file mode 100644 index 0000000..78f0457 --- /dev/null +++ b/2023/days/02/src/part2.rs @@ -0,0 +1,112 @@ +use crate::parse::*; + +pub fn part2(input: &[Game]) -> usize { + input.iter().map(|g| g.min_contents().power()).sum() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part2() { + let input = vec![ + Game { + id: 1, + handfuls: vec![ + Handful { + red: 4, + green: 0, + blue: 3, + }, + Handful { + red: 1, + green: 2, + blue: 6, + }, + Handful { + red: 0, + green: 2, + blue: 0, + }, + ], + }, + Game { + id: 2, + handfuls: vec![ + Handful { + red: 0, + green: 2, + blue: 1, + }, + Handful { + red: 1, + green: 3, + blue: 4, + }, + Handful { + red: 0, + green: 1, + blue: 1, + }, + ], + }, + Game { + id: 3, + handfuls: vec![ + Handful { + red: 20, + green: 8, + blue: 6, + }, + Handful { + red: 4, + green: 13, + blue: 5, + }, + Handful { + red: 1, + green: 5, + blue: 0, + }, + ], + }, + Game { + id: 4, + handfuls: vec![ + Handful { + red: 3, + green: 1, + blue: 6, + }, + Handful { + red: 6, + green: 3, + blue: 0, + }, + Handful { + red: 14, + green: 3, + blue: 15, + }, + ], + }, + Game { + id: 5, + handfuls: vec![ + Handful { + red: 6, + green: 3, + blue: 1, + }, + Handful { + red: 1, + green: 2, + blue: 2, + }, + ], + }, + ]; + assert_eq!(part2(&input), 2286); + } +} diff --git a/2023/days/03/Cargo.toml b/2023/days/03/Cargo.toml new file mode 100644 index 0000000..7eca856 --- /dev/null +++ b/2023/days/03/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "day03" +authors.workspace = true +description.workspace = true +version.workspace = true +edition.workspace = true + +[dependencies] +aoc_libs.workspace = true diff --git a/2023/days/03/src/input.txt b/2023/days/03/src/input.txt new file mode 100644 index 0000000..690b2fd --- /dev/null +++ b/2023/days/03/src/input.txt @@ -0,0 +1,140 @@ +....................................18..........889.270.....748.280...997.................617..............622........763............476.... +...529......434.....191..489...717...@.....................&....................939*7.....*....................606............760....*...... +....*...473....*221................$........182......812........493.84....793..........794.......589..407..41...*.....................68.... +..380.................553..559..105.....749.............*..........*.........*.............-968....@.....*..*....908..603................... +.........................................#...600.........441..#833...490....366.........................225..488........&...456.........224. +........288=......896*469..........831..........*....................*..............#...@.146.......*.............790#......%...194....@.... +..730.........................250+......./......359....=.462..............138...#.49..713.-........342...604*676.........=.....*.........418 +....*....907.......526................274...........346.....*.876..........-..725.............376......................541...600.....366*... +.....747...*..........*......56$...10........422........-.86.....*.......................728./............*................................. +.........486.........349............*..........=......696....$.............850&......906*......831.....539.195.........202.................. +..............592.............................................592....+.847.......676......365..=......................*........469.%........ +.542............*...............385....60.................329......657..@......=..*....&...........355.........=....52.........*....352..... +.............994......937...................45.....48........*..............835...791..654....................75.............523............ +...................&..............269.486.....+...*......&....954.........#........................246&...&..............203......693....... +.....262..........920...248.454......*...........289...822.........530...569..............................256.......929....*......*......... +........%............../.........................................../..............+..57.@............616=...........*...462...198.757....... +...............65........=.........764*.....$581.727........62.......4.....796..280......444.807...............174@.20................512... +.........877....*...687..187.522.......853..........*321.....*........*345...........513.....=.......849..........................@....*.... +.........*...635......*........=..............................380...........77...44*..*................#......*......484.....65.886......... +.....153.........@.&.....320........96..619....510......221.............139..*........957..977......20.....232.20......&.....*.............. +......*...397*.610..479...*....=....%.....*.......*.............839.......*................*............*.................144........#554... +..510...................927.....384........714...286....................799.....733.........832......815.187.....*....470................... +........892..................................................645.427.............%......562...................133.442....*906............... +.........=..........803............577.......%.....447..185.........*957.637*97..............132...............................83.258@..$... +...........=55......+....+...435.......930...143.............475................./..............#......................=..675...%......709.. +777....................841..*...........*......................*........*.........859...../...............640%..955..903.*.................. +..............639/...........803.829.....877........#.........716....873....387.........857..837.................*.......390................ +.................................*...............994......................%....*.............&.......749.........718.174.....138..697...463. +.....................697...873#.435......*141...........914*656....@......414..981.....541.......%....*...+.#.........*......&....+......... +.....................*................544.......524.............446.......................+.397..486....603.463......497.................... +.........161........412....273..218..............*..80............................708.......=....................899........+......-........ +............*..435*.........-..$.........666..401.....*897.214..472..499............*...955......................@...867....607.491..43@.... +666%.851..653......44...............152....................*....@.....*..........294.....*...313...237....580............................... +............................989....*.....954.....69.....488../.......90.495*..........697....*.......*.....*..686.......=.......594*981..... +.....104..#...................=.....773...$../.....*396.....959.............272...........433........889.821.....*759.469................... +.......*..865.318.@812........................267...............969.............................758........................913........646... +......132......*.........*699......+...............+.......126......468.....651............424........270.765.....53...965.*...19........... +..............725.....449.......337..187........862.............553*........*....=282.28....*........*....*........*.....%.779..&....218*... +.....744...36.....203.......452.......%..846........&......................................811..501..342...891.....776...................395 +.................$.....567&...@..689.......%.......619..392.........847#..#.....236*833............*.........................408............ +............./.....732............*........................*..............568................375..561..-270..111....=..565.................. +...........801............221....336...493....263..81*.....981...........................449*....................809......*239...........686 +...................+.........*87......*..........#....510...........20*684.../..387.....................................*...........132..... +.......674......&..364...........734.141.854*290...........................572.*......878...929.141.#.......526...919.646..*..........*..... +..............980...............*...............................500...229......876....*..............220.....*.....*........809......522.... +394....374......................194......660.....172..............&.....*...........774...................367......452..952................. +.......*...................918/............*.....*.......220........776.542..............843..857....560.................................... +........728.......@951.668.........651......589.857.........../.....*.........354....509.......@........*.................+.....151......... +......-......262.........#.....*95...................878./...563.642.............#.......................586........638..933....=........... +504.454.......*............540..........524..........*...531...........942...................632@.830.........302..-................%....... +.........498..357..........*....&..........%.......340.........925.......*....623.707.479............*36....%........+.....659*149.401.117.. +34..................608.....156.747...602@...............................748..*....*..$............*.........565.....93................*.... +........426.................................60.938...........................615.328.....818....143.118..................*.@...........916.. +...............547..............25*32.......*..*.......64..-813..........405.........802...*............188............246.236.............. +652................*426...................74.....822...*.................*...533....*....764..............*....................%............ +....920.64......437......598....738..#..............+..44...625...*....879......*..879.......668.#.......509...385..123....677..553.62...... +....*....+.783..........*..........*.552...534...............*.....312........=.........@...-....819............#..-..........*............. +....779.......&....21..582......264.........*.............564...............561........811...........................943....68..$........... +.....................&.....................915.472*918.................848.......943.........803....................*..........386.......... +...........................62........668..........................*801.*.........*...............878.......212....613....................... +.......208.......302..313*...*........*...........&.717........237.....11.........551.569.................*...............717............... +...742*......886*.........15.402....806...84...527.....*....=................650......*.....56.....401...276......964......-.....@.......... +..........................................*.........411...277.722.337.........*.....915.252*........*................+..........356....553.. +.......*...2.........406...............922.....=605............*............403......................316..........84.......%..........=..... +.......385.+....%893........200............150...........420.548.......+111...........70............................*675.895................ +...........................+.......198-...@.........532...........23..........349#....*......#...............................920.........844 +.....#.....387/.............................31..638..*....580.....#...........................397..720..........161...+.......*..628....*... +......816..............669....36..#393..848..........884.+...........&676.....876*341...565%.......*..........*....#...914...356..-..210.... +...............646........&..$.........*...................542....................................370......686.567.......................... +............../....94................414......18.............................861....*.....878..........24@.............875=.693*320..864.989 +...................*.........665..............*...595..........201......738..+...784..187....*237..../..............................*....... +......236-.......126.....641*..../............486.*.....638.............................*.%.......242....*153....+.........63.837.723.41.... +...........35....................114...............661....-....534.........626*......796..28..........579......367..78.929...*.............. +......108.........271*144.........................................*............5.....................................*.*.......669.533..704. +.........*635................#..@947.......290.....544.............707...................465..632.....771...181........471.380*......*...... +.....114..........89$.....699...........=....*........=.....416...........................&.....$......$..........365...............131..... +.......-.............................410....64......*.........*.........&....684.....15.....317...340*..............*....................... +.........26.609........152........................94.498.....26......671.......*.221*..........*......718...824.....56...........915........ +..218..............707*.......786.....839................790.....192.........181......836....287..............%.......................-..... +......937.722...............%.........*...378$...........*.........@.449..............%............226...........&...........428.......341.. +.795....*...&..185..405.....60.121....159.......275...996............*....981.....710........363...%...528....-.888....*641...*....880...... +...-..806.......*.....*......................@.....#......545..467...289..*.........*....681..........*.....86......326.......664.&......... +.............221.....142...860+....933..653..291......52&../..*............300.%...811...*.................................................. +......................................-....*.....861.........149...............673......762........./284..588..................%.....316.... +..373......290..............................665.....*................&.............&552.....51.............=.......105.......162.......*.... +...-........*.....388........%...772....................=...57....163..932..41...............*...693.116*......#.....*..............434..... +......*489...248..*........395...=.....................676..#..........*...................835...........570.199..678....................... +780...............713................952...479...379..................83.554.........919.......486..980...............984.$468.....720...... +..........66..-.....................*.......*....*...........................380%.....$.........*..........899*..118..............*......... +............*..694........382....793.........668.92.....747.......49.....&..........#.....284...462....303........*....518......50.....798.. +...*146..642.......@880...*............79=.............*.....93....&...885...785..780.......*..........=...-.....663..................*..... +533...........996.........352..................619%...200......+......................142....408....=....634............379*491.588@..183... +........$127........970...............902..........................943.649............$..........909.........619............................ +................-..*....640............*.......-459..#.....446......&.....*.934.....#....313............/....*........509...473..901....132. +..........*..415..805..*.....786.....12...............863...*...........674....$...296.....&...474......281...326.......&....*......$....... +........909...........136.......@.........645................961................................/...250...............$................*554. +...*.........589....................253..../...166.....&429.........96......568*684.%186...............*958........678..............466..... +.759............*96..........658.......*......*...............105...-....................428.............................=...73............. +......54*...................+......168.592..536.=................*8...671........753+.......*.................74........564....*............ +.304.....728..764................=...*...........804.575....266........*.....................94......27.316....=.-644.*.......209...485..... +.....997.......*.........#....792...855.................#......*169...496./615........683.......225.*..................474............$.395. +............573....206.477...................*158..........702....................298../......*...=..100....................714.........*... +448...............*..................769...27........691..$.......178....675......*........980.28...............*727...%.....@...201.545.... +............223...561..........261.....*.............*................+...........610.250....................496......408..........*........ +....@775.....*............&.....@....195..........303..+.............141..865..............629..+....659...................855*....958...... +...........407........92...22................493......605..................@..........477...*....160...................743.....163.......... +......................../......*......602@......=..+.......*....668$..245................*...731..........69.....213.....*........./....%... +................213*........903.75..........64......945...221.........+.......740........739..........393*...301*......562...../...53...4... +...164&.....145.....580.......................*................425........900......828*............................*........536............. +...............*.....................91....185..................../....................85.................414...890.204..................... +....772............422..*.351...218..................584................263...849...............*...639*.....*.............................. +.......*307...897...*..28.*........*.*49.......300....=../72...........%......*.....544......974..@.....214...55.......347.............914.. +901............*..67......840...343.........................................447....*...............400...................*.................. +.......684..498.........*......................544...347..+........493.............612..........59.........741..........593.........416*.... +..........*........369.577........690...770....*......*..983.*160....#.................623*248.#......437..*........258.................275. +....+...603....+...*............./......*...913....609.................823........................62.%....83...........&.................... +....538.....356..=..117......-.........556................................*..............920.......*...............746...................... +................483.......197...................&....................231...210......92....*.....982..&......199....$........848.$.....$..... +...370..413.........$.............*............556........325...902@....$..........@...182..........933................*.....&...829.402.... +......*..%...........524.131..134..163.....185...............*...............................756........282&.774......822................... +....340....373...*...............*...........*....649.20....289....799..549.939.....120..........61............*..345.......778...550.267... +............&...699......&319..170...492....61.....*.......................*.....+.................*.........345.....@........*...+......... +534.............................................144..849.......174......*........219.....$......140...476..................970.............. +.../....681............444.....819$...................*..=305../.....413.95...............589.................229...235................644.. +...........-.....28.......*403................&....548.............&...........17..........................33..........+........962......... +373..........500....%429.....................291........*....881.296.....163*....*..............796...585....&.............802..*.......138. +................*..................983&................809.....*.............417.999....$.......*...............633.........*...322....*.... +......907..$921.............665...........731...............903.........................638..662..............-..........495.........130.9.. +.........*......168............&..353.....-..........639.........#...........349......................660....914...570...................... +...%......695..*....679...........=..........$...958.+.....494..369..........*...........................*44........*.........964......548.. +...826.........268..*.....675..............136....-...................650.964....728.823.403..................842.983..........*......*..... +...................328................................519.....210.......................*....143.....*46....../.................241..55..... +.......855$...199.......526.....849...764*294..........#.....*.....280..........261.885.........#.434...................610................. +...............=...............+...................498.......936......*..831.......*.......&...........462.939+..439.......*845.....443..... +.....@360.842......986%.902-.....21.307....234*......*...324.......505....*.............315..............*.............................*.... +..........*....................*.*....*..............42..*................474...../919................50.674..713................./..27..... +........249....291...........448.622..228.......308.........189...............629........-...................*............594..127......782. +..................*173..817.....................*.......91.....*..#................*649...492...400.........17...878.....*..........950..... +...32.674......-........%.....402/...........610..%.....*.....549..853...........96.................=.............*....779.......@.......... +.............885.................................600.456...........................................679.............16.........392.....841... diff --git a/2023/days/03/src/main.rs b/2023/days/03/src/main.rs new file mode 100644 index 0000000..456385c --- /dev/null +++ b/2023/days/03/src/main.rs @@ -0,0 +1,14 @@ +mod part1; +mod part2; +mod parse; + +fn main() { + let input = include_str!("./input.txt"); + let structured_input = parse::parse(input); + + println!("Part One"); + println!("Result: {}", part1::part1(&structured_input)); + + println!("Part Two"); + println!("Result: {}", part2::part2(&structured_input)); +} diff --git a/2023/days/03/src/parse.rs b/2023/days/03/src/parse.rs new file mode 100644 index 0000000..81469aa --- /dev/null +++ b/2023/days/03/src/parse.rs @@ -0,0 +1,560 @@ +use std::{iter, ops::Range}; + +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct PartNumber { + pub number: usize, + pub x: Range, + pub y: usize, +} + +impl PartNumber { + fn is_adjacent_to_symbol(&self, symbol: &Symbol) -> bool { + (self.x.start.saturating_sub(1)..=self.x.end).contains(&symbol.x) + && (self.y.saturating_sub(1)..=self.y + 1).contains(&symbol.y) + } + + pub fn is_ajacent_to_any_symbol(&self, symbols: &[Symbol]) -> bool { + symbols + .iter() + .any(|symbol| self.is_adjacent_to_symbol(symbol)) + } +} + +#[derive(Debug, PartialEq, Eq)] +pub struct Symbol { + pub x: usize, + pub y: usize, + pub char: char, +} + +impl Symbol { + fn ajacent_part_numbers(&self, part_numbers: &[PartNumber]) -> Vec { + part_numbers + .iter() + .filter(|pn| pn.is_adjacent_to_symbol(self)) + .map(|pn| pn.number) + .collect() + } + pub fn gear_ratio(&self, part_numbers: &[PartNumber]) -> Option { + if self.char != '*' { + return None; + } + let ajacent_parts = self.ajacent_part_numbers(part_numbers); + if ajacent_parts.len() != 2{ + return None; + } + Some(ajacent_parts.iter().product()) + } +} + +pub type StructuredInput = (Vec, Vec); + +pub fn parse(input: &str) -> StructuredInput { + let mut part_numbers = vec![]; + let mut symbols = vec![]; + for (y, line) in input.lines().enumerate() { + let mut length: usize = 0; + let mut number: Option = None; + for (x, char) in line.chars().chain(iter::once('.')).enumerate() { + if let Some(digit) = char.to_digit(10) { + length += 1; + // this essentially 'shifts' the number left if it already exists. + number = number.map_or(Some(digit as usize), |n| Some(n * 10 + digit as usize)) + } else { + if char != '.' { + symbols.push(Symbol { x, y, char }) + } + // if number is not none, we must have just 'left' a number. + if let Some(number) = number { + part_numbers.push(PartNumber { + number, + x: (x - length)..x, + y, + }) + } + number = None; + length = 0; + } + } + } + (part_numbers, symbols) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_gear_ratio() { + let partnums = vec![ + PartNumber { + number: 467, + x: 0..3, + y: 0, + }, + PartNumber { + number: 114, + x: 5..8, + y: 0, + }, + PartNumber { + number: 35, + x: 2..4, + y: 2, + }, + PartNumber { + number: 633, + x: 6..9, + y: 2, + }, + PartNumber { + number: 617, + x: 0..3, + y: 4, + }, + PartNumber { + number: 58, + x: 7..9, + y: 5, + }, + PartNumber { + number: 592, + x: 2..5, + y: 6, + }, + PartNumber { + number: 755, + x: 6..9, + y: 7, + }, + PartNumber { + number: 664, + x: 1..4, + y: 9, + }, + PartNumber { + number: 598, + x: 5..8, + y: 9, + }, + ]; + let symbols = vec![ + Symbol { + x: 3, + y: 1, + char: '*', + }, + Symbol { + x: 6, + y: 3, + char: '#', + }, + Symbol { + x: 3, + y: 4, + char: '*', + }, + Symbol { + x: 5, + y: 5, + char: '+', + }, + Symbol { + x: 3, + y: 8, + char: '$', + }, + Symbol { + x: 5, + y: 8, + char: '*', + }, + ]; + assert_eq!(symbols[0].gear_ratio(&partnums), Some(467*35)); + assert_eq!(symbols[1].gear_ratio(&partnums), None); + } + + #[test] + fn test_num_ajacent_parts() { + let partnums = vec![ + PartNumber { + number: 467, + x: 0..3, + y: 0, + }, + PartNumber { + number: 114, + x: 5..8, + y: 0, + }, + PartNumber { + number: 35, + x: 2..4, + y: 2, + }, + PartNumber { + number: 633, + x: 6..9, + y: 2, + }, + PartNumber { + number: 617, + x: 0..3, + y: 4, + }, + PartNumber { + number: 58, + x: 7..9, + y: 5, + }, + PartNumber { + number: 592, + x: 2..5, + y: 6, + }, + PartNumber { + number: 755, + x: 6..9, + y: 7, + }, + PartNumber { + number: 664, + x: 1..4, + y: 9, + }, + PartNumber { + number: 598, + x: 5..8, + y: 9, + }, + ]; + let symbols = vec![ + Symbol { + x: 3, + y: 1, + char: '*', + }, + Symbol { + x: 6, + y: 3, + char: '#', + }, + Symbol { + x: 3, + y: 4, + char: '*', + }, + Symbol { + x: 5, + y: 5, + char: '+', + }, + Symbol { + x: 3, + y: 8, + char: '$', + }, + Symbol { + x: 5, + y: 8, + char: '*', + }, + ]; + assert_eq!(symbols[0].ajacent_part_numbers(&partnums), [467, 35]); + assert_eq!(symbols[1].ajacent_part_numbers(&partnums), [633]); + } + + #[test] + fn test_is_ajacent_to_symbol() { + let partnums = vec![ + PartNumber { + number: 467, + x: 0..3, + y: 0, + }, + PartNumber { + number: 114, + x: 5..8, + y: 0, + }, + PartNumber { + number: 35, + x: 2..4, + y: 2, + }, + PartNumber { + number: 633, + x: 6..9, + y: 2, + }, + PartNumber { + number: 617, + x: 0..3, + y: 4, + }, + PartNumber { + number: 58, + x: 7..9, + y: 5, + }, + PartNumber { + number: 592, + x: 2..5, + y: 6, + }, + PartNumber { + number: 755, + x: 6..9, + y: 7, + }, + PartNumber { + number: 664, + x: 1..4, + y: 9, + }, + PartNumber { + number: 598, + x: 5..8, + y: 9, + }, + ]; + let symbols = vec![ + Symbol { + x: 3, + y: 1, + char: '*', + }, + Symbol { + x: 6, + y: 3, + char: '#', + }, + Symbol { + x: 3, + y: 4, + char: '*', + }, + Symbol { + x: 5, + y: 5, + char: '+', + }, + Symbol { + x: 3, + y: 8, + char: '$', + }, + Symbol { + x: 5, + y: 8, + char: '*', + }, + ]; + assert!(partnums[0].is_adjacent_to_symbol(&symbols[0])); + assert!(!partnums[0].is_adjacent_to_symbol(&symbols[1])); + assert!(partnums[3].is_adjacent_to_symbol(&symbols[1])); + } + + #[test] + fn test_is_ajacent_to_any_symbol() { + let partnums = vec![ + PartNumber { + number: 467, + x: 0..3, + y: 0, + }, + PartNumber { + number: 114, + x: 5..8, + y: 0, + }, + PartNumber { + number: 35, + x: 2..4, + y: 2, + }, + PartNumber { + number: 633, + x: 6..9, + y: 2, + }, + PartNumber { + number: 617, + x: 0..3, + y: 4, + }, + PartNumber { + number: 58, + x: 7..9, + y: 5, + }, + PartNumber { + number: 592, + x: 2..5, + y: 6, + }, + PartNumber { + number: 755, + x: 6..9, + y: 7, + }, + PartNumber { + number: 664, + x: 1..4, + y: 9, + }, + PartNumber { + number: 598, + x: 5..8, + y: 9, + }, + ]; + let symbols = vec![ + Symbol { + x: 3, + y: 1, + char: '*', + }, + Symbol { + x: 6, + y: 3, + char: '#', + }, + Symbol { + x: 3, + y: 4, + char: '*', + }, + Symbol { + x: 5, + y: 5, + char: '+', + }, + Symbol { + x: 3, + y: 8, + char: '$', + }, + Symbol { + x: 5, + y: 8, + char: '*', + }, + ]; + assert!(partnums[0].is_ajacent_to_any_symbol(&symbols)); + assert!(!partnums[1].is_ajacent_to_any_symbol(&symbols)); + assert!(partnums[2].is_ajacent_to_any_symbol(&symbols)); + assert!(partnums[3].is_ajacent_to_any_symbol(&symbols)); + assert!(partnums[4].is_ajacent_to_any_symbol(&symbols)); + assert!(!partnums[5].is_ajacent_to_any_symbol(&symbols)); + assert!(partnums[6].is_ajacent_to_any_symbol(&symbols)); + assert!(partnums[7].is_ajacent_to_any_symbol(&symbols)); + assert!(partnums[8].is_ajacent_to_any_symbol(&symbols)); + assert!(partnums[9].is_ajacent_to_any_symbol(&symbols)); + } + + #[test] + fn test_parse() { + let input = concat!( + "467..114..\n", + "...*......\n", + "..35..633.\n", + "......#...\n", + "617*......\n", + ".....+.58.\n", + "..592.....\n", + "......755.\n", + "...$.*....\n", + ".664.598..\n", + ); + assert_eq!( + parse(input), + ( + vec![ + PartNumber { + number: 467, + x: 0..3, + y: 0 + }, + PartNumber { + number: 114, + x: 5..8, + y: 0 + }, + PartNumber { + number: 35, + x: 2..4, + y: 2 + }, + PartNumber { + number: 633, + x: 6..9, + y: 2 + }, + PartNumber { + number: 617, + x: 0..3, + y: 4 + }, + PartNumber { + number: 58, + x: 7..9, + y: 5 + }, + PartNumber { + number: 592, + x: 2..5, + y: 6 + }, + PartNumber { + number: 755, + x: 6..9, + y: 7 + }, + PartNumber { + number: 664, + x: 1..4, + y: 9 + }, + PartNumber { + number: 598, + x: 5..8, + y: 9 + } + ], + vec![ + Symbol { + x: 3, + y: 1, + char: '*' + }, + Symbol { + x: 6, + y: 3, + char: '#' + }, + Symbol { + x: 3, + y: 4, + char: '*' + }, + Symbol { + x: 5, + y: 5, + char: '+' + }, + Symbol { + x: 3, + y: 8, + char: '$' + }, + Symbol { + x: 5, + y: 8, + char: '*' + } + ] + ) + ); + } +} diff --git a/2023/days/03/src/part1.rs b/2023/days/03/src/part1.rs new file mode 100644 index 0000000..6e6f6ff --- /dev/null +++ b/2023/days/03/src/part1.rs @@ -0,0 +1,106 @@ +use crate::parse::*; + +pub fn part1(input: &StructuredInput) -> usize { + input + .0 + .iter() + .filter(|pn| pn.is_ajacent_to_any_symbol(&input.1)) + .map(|pn| pn.number) + .sum() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part1() { + let input = ( + vec![ + PartNumber { + number: 467, + x: 0..3, + y: 0, + }, + PartNumber { + number: 114, + x: 5..8, + y: 0, + }, + PartNumber { + number: 35, + x: 2..4, + y: 2, + }, + PartNumber { + number: 633, + x: 6..9, + y: 2, + }, + PartNumber { + number: 617, + x: 0..3, + y: 4, + }, + PartNumber { + number: 58, + x: 7..9, + y: 5, + }, + PartNumber { + number: 592, + x: 2..5, + y: 6, + }, + PartNumber { + number: 755, + x: 6..9, + y: 7, + }, + PartNumber { + number: 664, + x: 1..4, + y: 9, + }, + PartNumber { + number: 598, + x: 5..8, + y: 9, + }, + ], + vec![ + Symbol { + x: 3, + y: 1, + char: '*', + }, + Symbol { + x: 6, + y: 3, + char: '#', + }, + Symbol { + x: 3, + y: 4, + char: '*', + }, + Symbol { + x: 5, + y: 5, + char: '+', + }, + Symbol { + x: 3, + y: 8, + char: '$', + }, + Symbol { + x: 5, + y: 8, + char: '*', + }, + ], + ); + assert_eq!(part1(&input), 4361); + } +} diff --git a/2023/days/03/src/part2.rs b/2023/days/03/src/part2.rs new file mode 100644 index 0000000..e07bad3 --- /dev/null +++ b/2023/days/03/src/part2.rs @@ -0,0 +1,105 @@ +use crate::parse::*; + +pub fn part2(input: &StructuredInput) -> usize { + input + .1 + .iter() + .filter_map(|symbol| symbol.gear_ratio(&input.0)) + .sum() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part2() { + let input = ( + vec![ + PartNumber { + number: 467, + x: 0..3, + y: 0, + }, + PartNumber { + number: 114, + x: 5..8, + y: 0, + }, + PartNumber { + number: 35, + x: 2..4, + y: 2, + }, + PartNumber { + number: 633, + x: 6..9, + y: 2, + }, + PartNumber { + number: 617, + x: 0..3, + y: 4, + }, + PartNumber { + number: 58, + x: 7..9, + y: 5, + }, + PartNumber { + number: 592, + x: 2..5, + y: 6, + }, + PartNumber { + number: 755, + x: 6..9, + y: 7, + }, + PartNumber { + number: 664, + x: 1..4, + y: 9, + }, + PartNumber { + number: 598, + x: 5..8, + y: 9, + }, + ], + vec![ + Symbol { + x: 3, + y: 1, + char: '*', + }, + Symbol { + x: 6, + y: 3, + char: '#', + }, + Symbol { + x: 3, + y: 4, + char: '*', + }, + Symbol { + x: 5, + y: 5, + char: '+', + }, + Symbol { + x: 3, + y: 8, + char: '$', + }, + Symbol { + x: 5, + y: 8, + char: '*', + }, + ], + ); + assert_eq!(part2(&input), 467835); + } +} diff --git a/2023/days/04/Cargo.toml b/2023/days/04/Cargo.toml new file mode 100644 index 0000000..50a0b68 --- /dev/null +++ b/2023/days/04/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "day04" +authors.workspace = true +description.workspace = true +version.workspace = true +edition.workspace = true + +[dependencies] +aoc_libs.workspace = true +nom.workspace = true +collection_literals.workspace = true diff --git a/2023/days/04/src/input.txt b/2023/days/04/src/input.txt new file mode 100644 index 0000000..3320b6d --- /dev/null +++ b/2023/days/04/src/input.txt @@ -0,0 +1,193 @@ +Card 1: 17 15 5 75 36 13 16 66 92 39 | 13 92 16 5 87 78 15 94 21 48 30 62 70 41 3 39 22 17 77 58 75 52 83 34 24 +Card 2: 72 64 18 5 58 94 25 59 75 51 | 34 17 48 75 25 8 2 94 64 29 33 92 73 12 51 38 27 4 1 60 31 85 59 18 5 +Card 3: 71 16 97 6 68 38 82 93 33 24 | 31 75 7 99 10 70 79 61 5 80 1 33 58 30 22 48 73 72 50 16 56 4 98 43 3 +Card 4: 68 80 44 96 43 20 11 18 85 48 | 96 99 38 29 36 28 77 68 47 70 98 80 63 65 11 12 43 3 54 92 18 90 58 16 51 +Card 5: 27 61 28 60 50 59 43 96 85 9 | 3 45 14 55 39 6 93 82 96 31 70 22 8 98 88 46 72 9 79 28 23 81 87 15 30 +Card 6: 32 69 24 83 40 39 19 42 17 11 | 68 26 28 71 22 50 64 20 53 82 7 36 58 78 73 51 6 48 97 30 99 61 84 34 5 +Card 7: 99 14 25 95 31 62 1 65 59 30 | 8 9 58 73 6 2 44 11 43 4 34 70 78 90 16 24 23 39 30 69 74 59 91 84 42 +Card 8: 88 48 85 67 73 33 96 57 47 86 | 35 17 85 97 46 50 77 23 4 31 76 34 12 59 14 42 72 64 44 96 90 65 73 69 88 +Card 9: 99 17 38 77 73 71 59 86 11 97 | 60 14 19 4 6 78 51 48 87 36 88 66 30 13 94 45 97 69 62 40 47 32 7 77 57 +Card 10: 82 35 83 64 60 84 67 62 24 77 | 93 32 7 12 84 24 94 43 65 44 17 45 38 62 80 95 77 26 73 28 91 57 60 55 4 +Card 11: 9 95 29 15 88 33 58 49 83 45 | 31 38 55 62 86 60 21 97 74 53 94 19 40 50 77 26 63 43 3 52 85 8 73 35 42 +Card 12: 54 33 34 57 29 64 40 30 3 11 | 78 86 92 70 91 93 32 79 12 13 97 63 28 66 77 85 51 36 35 3 4 23 30 11 42 +Card 13: 16 49 93 29 96 23 64 57 3 42 | 56 11 53 20 72 67 26 5 4 63 8 70 97 52 6 81 62 80 12 98 33 35 77 84 58 +Card 14: 20 32 49 55 63 74 33 51 66 40 | 43 29 70 48 61 13 96 73 67 27 15 6 46 56 45 30 97 76 1 77 12 26 39 78 42 +Card 15: 65 67 7 43 83 36 24 46 16 29 | 76 12 69 27 26 71 84 11 22 86 33 63 50 49 14 40 6 4 47 34 90 21 19 74 97 +Card 16: 78 43 11 21 53 35 86 85 27 68 | 98 43 53 66 52 62 21 91 81 69 93 76 73 86 17 31 27 40 85 12 68 83 65 36 71 +Card 17: 52 55 3 69 20 96 57 67 10 38 | 91 16 3 30 52 34 78 71 55 36 48 89 79 20 37 69 67 57 18 68 46 10 25 38 96 +Card 18: 23 46 90 44 85 19 49 30 8 43 | 72 34 75 48 74 33 88 41 78 65 98 60 3 19 26 63 69 83 89 21 66 5 37 53 58 +Card 19: 69 24 83 60 59 45 51 74 93 34 | 45 83 1 8 28 60 27 38 81 36 69 24 73 90 88 59 93 16 98 34 74 48 10 61 51 +Card 20: 41 83 4 44 28 90 16 69 86 88 | 7 41 28 4 5 73 97 30 70 88 69 2 38 55 86 60 14 83 16 90 15 49 78 44 27 +Card 21: 41 61 99 59 48 8 26 92 19 85 | 35 17 49 14 94 6 29 43 55 88 63 26 13 53 66 67 8 32 18 24 7 70 86 96 38 +Card 22: 57 29 37 75 42 88 68 67 92 18 | 8 6 54 77 75 18 68 26 67 87 92 31 72 29 37 21 42 17 88 93 84 57 9 63 66 +Card 23: 70 3 75 17 64 68 53 45 23 10 | 27 7 59 68 97 72 64 30 61 29 86 45 63 53 17 3 44 87 23 75 70 10 15 4 43 +Card 24: 89 81 36 9 73 27 31 8 77 11 | 14 71 9 87 47 39 26 29 24 74 42 58 17 51 19 68 32 46 52 78 64 12 35 45 72 +Card 25: 82 3 92 95 29 14 52 41 15 98 | 21 17 51 55 77 34 72 59 78 30 5 58 92 4 85 15 91 75 26 53 25 94 7 90 22 +Card 26: 51 55 33 59 66 42 43 92 85 96 | 2 66 92 24 50 33 63 96 54 51 13 1 42 98 73 88 57 84 94 7 93 78 59 43 55 +Card 27: 19 80 30 31 15 4 65 13 66 29 | 93 75 36 26 5 14 21 49 97 43 96 54 45 57 25 55 71 95 1 27 60 61 9 59 34 +Card 28: 57 79 99 54 72 18 33 34 87 1 | 56 99 55 17 87 80 72 79 88 31 38 63 42 33 10 23 76 4 67 21 98 68 93 57 65 +Card 29: 85 26 24 34 21 35 49 92 89 73 | 70 39 73 44 67 50 43 63 4 82 14 64 22 25 2 41 8 36 89 10 54 79 87 40 6 +Card 30: 21 33 62 4 57 9 50 49 95 13 | 12 84 86 49 26 42 20 37 30 57 44 96 62 6 4 65 15 59 60 73 19 28 89 39 55 +Card 31: 7 61 76 92 70 15 45 71 98 20 | 4 33 26 63 73 52 7 3 62 60 89 28 86 55 45 90 41 83 74 31 48 27 11 65 72 +Card 32: 9 35 67 79 85 46 14 42 84 45 | 63 51 64 5 81 70 36 47 33 30 54 83 85 34 35 32 1 79 7 96 82 28 3 89 91 +Card 33: 76 48 44 64 41 62 4 25 11 8 | 15 22 10 80 59 82 89 81 2 57 31 25 50 34 53 39 86 19 47 95 23 30 88 91 51 +Card 34: 17 12 86 82 70 16 19 11 42 57 | 78 49 72 18 25 35 58 81 26 6 84 87 67 60 61 13 53 56 4 14 90 11 29 34 33 +Card 35: 16 65 64 28 25 50 73 95 20 10 | 6 4 12 77 41 98 2 74 29 15 52 91 83 49 14 40 69 88 82 22 21 89 9 70 90 +Card 36: 68 38 59 63 30 32 14 97 77 17 | 6 23 49 75 12 76 58 22 74 29 24 48 56 54 41 26 69 90 70 93 66 42 78 33 60 +Card 37: 49 37 88 55 20 95 11 86 53 18 | 53 95 18 80 25 2 88 17 11 20 22 63 45 70 55 37 86 81 28 61 47 74 49 79 48 +Card 38: 82 38 13 70 48 52 91 6 46 47 | 6 91 78 43 16 48 61 29 80 92 82 13 44 90 9 87 40 54 52 46 58 38 70 65 47 +Card 39: 82 50 67 89 49 18 24 93 98 76 | 95 61 1 91 52 86 89 53 38 98 44 67 50 49 33 66 21 18 93 82 60 76 40 24 19 +Card 40: 15 34 17 87 51 5 98 26 71 99 | 15 40 70 98 96 1 45 14 94 28 39 87 56 51 89 17 77 64 26 5 99 71 83 27 34 +Card 41: 1 98 55 28 10 14 57 62 88 96 | 96 52 8 34 88 41 73 23 16 43 98 45 55 97 1 14 28 10 62 81 33 57 32 53 99 +Card 42: 98 75 42 34 59 41 11 69 45 44 | 28 98 54 65 41 51 16 49 45 60 44 69 82 37 67 46 34 71 78 61 50 43 38 90 85 +Card 43: 42 98 96 75 68 2 23 36 37 40 | 93 59 36 33 16 68 24 42 13 75 53 2 6 86 1 98 23 70 89 5 37 40 96 84 39 +Card 44: 44 31 83 28 66 80 84 17 73 65 | 39 73 95 33 74 66 31 28 17 2 65 12 84 91 83 15 22 44 53 90 29 56 80 57 69 +Card 45: 13 90 67 40 48 54 52 53 64 9 | 17 57 67 65 45 30 95 96 3 18 52 90 7 98 21 73 8 92 59 75 5 13 6 76 64 +Card 46: 95 21 68 93 77 40 47 48 20 31 | 74 90 43 4 41 40 24 72 2 56 88 44 38 45 15 29 79 46 17 39 75 42 69 92 49 +Card 47: 25 87 64 94 99 47 29 34 89 23 | 29 25 99 58 94 7 33 6 34 36 76 5 39 64 56 87 17 52 47 50 89 16 91 23 69 +Card 48: 37 75 82 29 91 2 85 23 76 80 | 23 33 80 85 89 46 94 15 2 43 51 62 91 79 37 76 29 56 40 26 9 63 75 82 31 +Card 49: 99 80 21 7 14 27 24 13 76 70 | 36 32 16 28 30 37 73 59 42 47 40 29 19 84 18 23 79 44 93 45 87 62 60 69 65 +Card 50: 89 87 92 61 59 58 90 24 70 22 | 3 81 53 61 55 82 52 85 66 44 74 98 6 56 33 13 63 25 65 67 47 26 35 27 64 +Card 51: 65 15 62 72 92 57 1 87 55 86 | 1 47 49 98 93 38 53 68 96 59 11 4 52 84 86 94 51 13 95 29 65 16 91 45 54 +Card 52: 3 72 69 39 77 36 55 13 56 95 | 35 61 77 36 40 65 64 13 58 27 55 12 94 66 42 37 5 78 62 84 56 39 69 95 48 +Card 53: 78 57 27 16 17 55 59 56 73 40 | 65 31 20 18 64 89 44 52 92 11 62 76 13 48 72 79 94 8 82 77 5 74 30 46 98 +Card 54: 22 17 28 78 59 87 52 47 41 2 | 74 94 38 25 58 89 20 99 71 14 86 95 10 63 18 35 24 67 85 80 7 50 6 33 72 +Card 55: 78 83 54 87 55 68 77 38 34 48 | 87 23 51 75 83 86 43 93 18 34 53 56 76 72 29 27 45 85 89 36 65 84 19 88 39 +Card 56: 50 89 10 79 86 37 27 16 56 54 | 2 59 91 50 8 39 90 46 37 36 27 15 10 9 85 92 83 35 45 74 19 61 63 17 96 +Card 57: 50 39 84 22 17 73 57 77 80 85 | 8 57 15 74 38 83 32 67 99 28 63 16 30 49 75 26 55 48 47 91 33 14 62 21 20 +Card 58: 63 26 97 45 9 24 65 66 59 14 | 42 81 39 62 45 46 23 49 98 34 72 64 17 11 96 15 6 88 78 93 20 33 66 95 37 +Card 59: 46 91 3 4 70 21 2 13 19 10 | 95 56 84 16 66 7 91 11 69 89 87 29 60 47 37 40 15 55 38 80 20 81 23 64 18 +Card 60: 32 65 89 23 54 36 49 18 26 78 | 16 11 14 20 76 33 72 45 94 87 85 2 74 99 3 67 57 37 75 96 82 95 73 77 52 +Card 61: 41 42 4 27 89 64 80 28 35 92 | 97 50 88 13 19 45 49 42 85 36 4 92 29 80 77 47 91 27 46 89 68 16 35 11 28 +Card 62: 30 27 17 63 59 11 78 74 75 57 | 88 57 5 61 1 56 24 99 10 39 48 15 89 82 95 9 45 71 54 83 3 28 27 98 91 +Card 63: 86 91 21 10 84 47 83 62 90 35 | 11 16 90 10 31 84 36 74 89 5 35 47 21 40 62 63 77 67 65 83 91 86 70 85 44 +Card 64: 39 55 92 80 17 2 66 97 33 70 | 92 22 85 6 88 4 46 57 71 40 89 15 49 48 66 11 93 28 37 5 30 23 27 98 43 +Card 65: 62 94 36 40 23 61 34 46 47 63 | 6 44 23 74 97 96 62 94 61 46 93 34 47 31 87 54 26 67 56 40 27 81 63 99 36 +Card 66: 64 45 78 34 32 29 62 84 90 28 | 42 6 80 66 10 13 41 55 50 40 72 90 25 24 93 98 46 73 52 14 61 86 49 89 71 +Card 67: 9 89 2 82 42 8 78 90 59 7 | 69 55 58 2 95 78 43 26 11 75 50 22 44 4 9 59 82 68 19 32 63 49 35 42 45 +Card 68: 72 9 87 26 17 43 58 8 45 74 | 8 85 9 7 73 21 92 74 28 5 33 25 50 60 26 1 65 78 24 69 87 19 46 58 67 +Card 69: 51 69 81 71 32 59 85 29 39 5 | 68 16 31 47 29 86 50 62 98 14 22 80 56 91 35 49 51 21 36 67 52 6 15 48 58 +Card 70: 67 1 31 29 16 71 69 54 15 11 | 91 49 76 87 14 13 58 23 19 20 82 48 98 79 66 35 38 22 67 96 43 55 52 92 12 +Card 71: 73 20 52 53 61 17 87 78 82 37 | 28 21 95 74 77 58 25 84 68 75 47 49 9 18 65 51 63 12 56 50 98 23 57 69 90 +Card 72: 39 66 35 93 62 28 9 13 56 30 | 29 1 39 54 10 33 40 99 91 65 16 28 37 23 77 43 61 64 11 55 69 85 63 47 78 +Card 73: 9 10 84 56 6 14 54 36 94 61 | 89 33 88 23 87 46 47 31 55 29 69 90 11 65 19 84 35 2 32 95 80 12 3 7 50 +Card 74: 59 27 84 1 11 63 39 57 62 65 | 41 75 83 51 13 91 93 79 66 23 70 86 16 52 26 50 72 5 48 80 74 47 38 97 8 +Card 75: 38 65 93 30 12 64 31 10 37 81 | 8 76 72 3 52 89 32 60 73 40 85 55 49 43 45 42 83 58 61 47 86 67 82 94 50 +Card 76: 26 83 4 70 88 7 50 34 36 76 | 64 49 4 77 83 39 34 50 79 24 22 6 70 85 7 75 80 26 38 36 68 63 29 17 88 +Card 77: 31 97 45 39 24 5 87 26 75 15 | 38 36 10 57 39 8 45 74 24 94 31 17 25 27 92 75 60 87 12 26 69 15 70 63 7 +Card 78: 44 21 15 91 62 67 47 24 95 90 | 26 1 62 42 71 43 91 95 59 37 16 3 56 14 21 15 17 87 86 51 39 19 46 36 4 +Card 79: 67 84 14 87 21 22 91 17 88 72 | 92 82 94 31 85 54 55 93 46 35 77 67 74 96 36 50 68 19 3 40 15 69 72 6 49 +Card 80: 11 36 90 64 51 31 83 30 18 69 | 36 86 90 43 8 3 65 49 31 78 30 18 79 52 51 88 80 63 24 77 16 1 13 83 55 +Card 81: 47 2 72 59 87 30 58 68 63 61 | 55 49 42 39 99 94 50 72 90 54 29 37 21 41 48 8 82 7 63 30 62 70 87 26 14 +Card 82: 22 17 64 40 89 67 83 71 43 50 | 89 12 52 32 42 78 38 3 51 26 2 67 96 81 77 13 48 7 73 28 62 1 82 22 24 +Card 83: 53 4 35 89 23 36 8 92 32 49 | 35 52 92 73 23 64 80 32 53 4 65 20 42 31 8 39 89 95 62 44 45 77 36 68 49 +Card 84: 86 48 90 55 79 57 31 40 3 74 | 85 67 62 4 33 23 60 43 19 14 32 34 6 56 59 9 87 47 54 26 88 66 65 41 11 +Card 85: 82 66 31 3 87 19 89 57 59 8 | 15 8 31 58 53 22 89 59 63 96 40 85 3 82 35 33 49 30 75 87 66 64 83 57 19 +Card 86: 22 4 55 97 13 54 65 51 86 9 | 11 73 5 63 36 23 27 13 15 75 22 85 38 99 54 44 32 41 12 47 82 51 8 77 17 +Card 87: 27 91 1 77 75 8 76 99 88 85 | 55 46 50 2 4 27 54 10 89 3 14 91 22 75 13 77 8 6 76 69 44 19 88 1 99 +Card 88: 54 96 19 2 73 48 50 82 18 23 | 95 12 16 73 35 48 60 31 50 98 19 17 32 47 2 55 44 93 11 41 23 82 74 9 51 +Card 89: 91 89 35 65 33 19 94 76 77 45 | 99 32 96 64 31 44 45 80 71 51 83 97 21 5 20 35 40 93 39 54 29 56 23 70 66 +Card 90: 31 87 35 2 89 24 59 13 4 15 | 18 87 65 59 71 31 98 26 68 96 3 13 80 36 25 47 2 4 7 37 92 83 73 23 58 +Card 91: 28 85 49 44 87 17 56 74 25 53 | 96 23 18 27 17 72 84 29 32 85 91 86 62 94 55 49 37 56 28 59 78 88 25 1 30 +Card 92: 1 94 54 67 51 21 79 6 93 5 | 9 51 13 91 68 59 19 41 76 20 57 55 54 72 48 21 83 95 44 56 71 80 28 85 25 +Card 93: 53 86 2 60 56 18 21 22 63 59 | 79 86 73 9 32 80 7 76 26 63 48 17 90 36 91 31 69 50 49 87 37 43 92 10 55 +Card 94: 91 59 76 78 48 56 7 51 52 97 | 36 15 31 62 65 64 34 79 92 53 29 60 9 3 75 26 14 46 59 35 85 52 2 77 67 +Card 95: 59 49 67 43 82 13 19 7 58 69 | 5 65 21 86 4 3 64 72 51 94 73 88 78 98 28 85 29 96 36 1 97 37 89 62 58 +Card 96: 95 88 64 65 12 15 3 50 44 79 | 53 72 74 60 22 7 75 19 10 3 49 23 33 29 57 31 82 84 16 37 32 21 77 28 47 +Card 97: 3 85 7 2 51 27 67 32 46 9 | 60 45 11 49 13 62 76 56 63 1 37 96 20 55 24 89 31 50 19 10 6 72 30 38 54 +Card 98: 25 92 5 7 90 2 84 79 34 65 | 30 20 86 33 63 84 65 92 38 5 43 12 2 73 98 81 82 94 51 25 88 75 54 22 15 +Card 99: 59 57 36 90 26 81 15 78 49 2 | 81 26 91 47 77 46 65 59 90 57 72 99 2 98 15 5 78 36 49 63 45 9 16 92 64 +Card 100: 18 9 41 19 57 82 73 48 62 2 | 41 42 3 82 73 83 91 48 94 96 20 9 19 90 45 54 13 67 62 44 37 51 18 2 57 +Card 101: 56 35 62 52 89 60 19 71 15 50 | 60 21 39 71 45 64 73 25 80 54 50 13 6 20 1 51 42 93 92 87 96 61 16 77 40 +Card 102: 40 33 78 80 79 47 57 3 17 64 | 85 17 94 78 20 47 58 3 37 40 68 75 81 79 21 64 97 70 80 33 8 57 95 35 4 +Card 103: 99 22 60 2 93 8 46 50 90 79 | 46 2 67 62 30 93 50 99 79 8 33 34 81 98 90 78 60 92 42 80 28 89 22 16 74 +Card 104: 93 3 98 99 1 90 20 70 67 91 | 98 85 78 51 26 71 10 92 90 35 94 66 21 1 70 18 13 93 8 91 5 4 50 33 15 +Card 105: 63 86 21 98 76 18 35 7 23 41 | 88 86 53 89 31 67 55 82 3 35 18 32 76 42 23 98 7 27 79 41 14 71 83 6 93 +Card 106: 71 48 3 34 73 72 85 76 69 66 | 66 7 22 76 65 25 46 69 96 34 3 35 14 45 21 23 36 5 17 60 98 71 33 93 59 +Card 107: 49 42 7 79 31 18 97 45 6 36 | 6 43 18 51 1 39 36 76 92 88 59 26 45 5 73 7 97 55 44 21 31 49 82 42 79 +Card 108: 48 16 51 41 23 59 65 80 89 26 | 1 75 35 5 80 2 51 23 45 16 30 44 26 89 64 65 91 11 59 48 69 21 77 93 41 +Card 109: 70 63 17 48 93 67 59 22 16 89 | 28 48 22 16 79 56 21 19 89 62 67 4 17 64 49 63 59 93 60 70 1 7 43 94 81 +Card 110: 89 87 31 97 33 7 66 96 24 37 | 5 8 53 71 99 96 88 74 39 20 62 67 11 64 70 47 37 95 77 86 27 61 97 89 60 +Card 111: 27 48 31 61 39 80 81 36 87 12 | 80 43 5 12 84 67 70 91 8 39 10 48 61 27 86 16 54 22 40 90 9 36 87 44 81 +Card 112: 20 22 17 89 26 55 43 49 75 30 | 51 58 71 28 29 15 26 8 99 48 61 4 54 75 13 46 78 68 86 22 56 20 33 69 65 +Card 113: 18 40 34 27 32 15 65 19 60 87 | 32 34 60 90 24 92 51 2 91 35 27 14 15 93 88 75 48 58 65 97 87 63 94 55 56 +Card 114: 46 19 51 7 25 85 30 73 31 27 | 40 25 90 58 2 12 59 68 8 9 88 21 63 46 37 51 52 75 84 89 93 3 20 87 80 +Card 115: 70 81 83 98 66 69 72 44 1 45 | 30 40 13 80 55 77 7 85 97 18 78 53 59 31 9 45 6 21 16 63 65 27 33 49 90 +Card 116: 89 46 58 68 38 59 13 85 28 92 | 59 81 23 86 18 6 73 78 11 74 48 40 13 97 27 52 38 9 16 47 26 29 54 60 14 +Card 117: 43 38 54 63 44 95 4 64 25 57 | 43 44 94 58 54 51 56 21 6 89 30 31 8 11 46 53 5 79 16 72 90 76 67 49 34 +Card 118: 47 72 23 74 29 37 45 69 89 40 | 27 79 36 40 10 87 92 41 22 1 90 21 57 28 38 53 82 32 43 70 19 96 97 4 47 +Card 119: 11 81 28 95 53 51 90 33 8 68 | 88 74 49 27 58 57 97 4 34 2 18 22 29 99 66 28 55 7 94 41 24 60 5 14 1 +Card 120: 9 67 89 55 59 96 15 90 37 54 | 70 98 77 71 6 95 34 60 48 18 69 72 36 35 22 27 76 83 30 99 80 63 12 47 82 +Card 121: 63 50 70 62 14 22 97 65 5 53 | 24 99 55 58 47 87 77 37 5 19 83 33 42 40 45 54 46 62 28 81 95 85 23 57 49 +Card 122: 40 80 69 62 14 73 47 87 91 37 | 16 47 37 93 40 91 34 17 36 98 69 60 15 49 90 92 80 87 14 62 82 4 25 56 73 +Card 123: 51 36 72 40 53 99 69 8 96 24 | 93 74 54 8 52 59 3 57 69 85 31 72 44 89 23 9 2 27 71 48 35 17 19 96 28 +Card 124: 14 75 17 70 48 82 93 39 99 98 | 66 55 6 33 34 32 25 65 20 86 90 87 93 46 42 89 24 43 23 30 64 94 62 61 5 +Card 125: 36 96 78 58 75 87 25 28 76 52 | 7 47 46 13 3 90 35 18 53 60 30 78 74 77 33 58 22 57 80 63 92 87 76 93 70 +Card 126: 75 30 35 7 63 65 13 42 78 26 | 30 71 35 26 6 42 90 63 12 36 75 9 7 96 67 93 18 2 25 77 94 47 99 62 60 +Card 127: 7 40 79 33 52 3 21 1 71 5 | 44 14 19 29 56 25 34 41 64 12 93 70 66 94 54 97 58 59 18 27 77 17 15 38 88 +Card 128: 99 87 2 95 67 33 73 52 22 23 | 65 91 97 11 34 36 56 38 79 52 82 22 26 83 12 1 95 9 23 99 81 42 92 27 86 +Card 129: 98 68 59 25 58 27 20 23 38 46 | 97 91 59 41 70 18 36 38 46 42 58 48 53 60 81 75 83 23 15 86 89 68 69 39 88 +Card 130: 85 72 65 71 14 25 22 53 12 28 | 67 9 27 94 96 30 86 83 4 59 91 79 7 60 31 39 36 77 23 38 40 51 84 16 57 +Card 131: 6 77 45 51 48 46 21 52 84 62 | 70 74 83 39 26 27 86 96 56 33 79 18 76 34 22 32 68 59 35 66 38 71 3 20 88 +Card 132: 66 80 84 9 59 23 64 44 71 36 | 63 49 73 62 68 48 80 32 99 29 24 61 40 35 20 1 57 58 15 92 87 18 47 71 67 +Card 133: 19 94 9 45 91 35 36 60 34 26 | 72 47 82 86 88 69 6 17 7 8 21 78 90 9 12 24 85 28 15 31 98 76 35 10 39 +Card 134: 8 79 4 31 6 88 7 57 40 23 | 66 74 93 26 98 54 87 82 48 63 19 11 68 3 85 88 80 25 15 64 99 77 47 71 43 +Card 135: 86 31 63 82 83 78 19 55 20 73 | 36 98 68 52 99 8 39 60 70 80 64 41 92 91 62 85 27 32 9 97 22 46 34 23 81 +Card 136: 57 94 7 14 49 18 80 67 85 25 | 59 28 82 38 40 5 64 69 41 70 23 91 56 32 6 71 12 75 22 98 11 16 79 37 54 +Card 137: 60 88 68 93 6 98 16 17 7 62 | 59 78 54 41 98 1 66 13 71 68 45 60 70 19 96 93 77 99 95 42 55 21 30 86 7 +Card 138: 17 93 77 84 65 31 60 7 45 76 | 7 45 60 42 9 25 65 77 16 70 93 34 37 12 76 17 84 40 49 74 96 88 31 54 79 +Card 139: 15 68 80 74 33 50 57 93 78 16 | 95 96 50 71 16 99 17 58 83 72 4 80 98 11 41 63 73 62 33 37 26 70 24 29 93 +Card 140: 74 32 6 69 33 13 85 82 80 87 | 62 66 98 20 67 77 86 31 2 9 18 39 92 28 59 45 4 87 84 46 6 99 80 85 27 +Card 141: 42 52 60 31 22 99 49 61 43 72 | 55 61 81 65 97 31 60 23 6 70 62 80 58 72 56 43 98 96 87 42 53 63 52 99 45 +Card 142: 5 72 15 50 65 28 87 94 96 37 | 62 38 37 23 65 80 67 96 50 72 8 60 46 28 33 94 13 52 15 1 32 78 14 43 5 +Card 143: 57 65 29 27 41 55 94 56 73 49 | 55 84 57 56 27 72 93 41 33 28 88 75 94 51 76 98 26 32 49 36 7 44 63 20 97 +Card 144: 31 20 97 50 17 67 80 91 78 95 | 76 16 26 38 48 90 32 93 5 68 56 78 25 87 85 40 97 12 21 96 47 10 49 75 36 +Card 145: 36 58 11 92 51 32 76 39 80 62 | 6 62 37 83 40 94 81 36 2 69 45 91 8 95 78 55 27 70 22 73 53 13 67 64 63 +Card 146: 25 28 30 81 1 51 49 59 10 48 | 20 9 66 36 50 65 78 27 87 88 7 94 63 97 39 14 67 71 76 11 60 93 13 15 61 +Card 147: 18 21 81 36 33 19 99 88 24 78 | 16 19 5 40 55 12 90 44 67 20 59 71 51 32 93 2 15 22 54 87 26 92 89 49 96 +Card 148: 84 78 26 66 35 31 10 3 32 57 | 73 30 6 27 43 76 58 63 29 19 92 41 93 70 46 16 38 53 11 77 68 21 18 33 12 +Card 149: 3 20 48 92 4 37 68 54 61 42 | 64 24 23 97 65 73 1 39 14 99 51 36 2 46 30 87 79 19 49 38 52 53 40 90 88 +Card 150: 64 45 47 50 19 69 39 48 56 3 | 93 70 65 37 58 32 57 5 35 10 72 18 51 36 44 31 46 34 11 1 97 8 92 86 23 +Card 151: 29 55 30 72 6 78 56 70 36 10 | 49 28 64 13 1 24 51 5 62 17 43 48 91 38 89 59 18 54 44 86 79 46 9 53 58 +Card 152: 40 68 80 77 81 50 79 13 67 1 | 79 43 60 15 86 49 67 85 66 13 40 12 48 6 82 14 37 1 80 23 65 72 96 73 84 +Card 153: 67 29 26 94 28 52 35 69 8 81 | 35 98 78 94 11 95 87 37 42 93 82 58 4 43 47 1 19 54 3 64 7 22 27 36 74 +Card 154: 4 45 27 92 75 31 93 54 16 83 | 45 81 67 92 1 61 93 59 37 20 54 55 63 6 44 29 33 27 70 31 24 51 58 75 19 +Card 155: 17 75 37 60 72 96 40 95 3 10 | 51 58 60 40 24 2 84 37 72 41 45 78 6 28 74 64 3 75 97 89 10 96 95 83 17 +Card 156: 78 54 82 93 16 77 50 46 69 29 | 89 21 6 82 38 80 44 40 76 74 18 90 83 59 42 33 57 53 1 73 94 20 35 37 63 +Card 157: 51 24 57 3 87 90 35 27 77 34 | 12 11 7 2 84 75 6 40 23 86 91 4 32 78 83 76 48 80 8 53 98 16 38 97 79 +Card 158: 86 29 64 32 66 61 20 75 8 27 | 5 61 4 8 66 99 20 32 25 96 64 45 51 19 75 29 6 13 27 91 2 86 55 33 12 +Card 159: 59 64 39 53 10 74 35 89 84 15 | 25 1 39 49 23 90 84 61 91 30 35 76 68 24 64 6 83 15 40 54 87 98 10 52 2 +Card 160: 7 86 13 48 73 70 47 91 39 93 | 47 56 65 41 30 93 87 73 27 91 18 86 62 63 50 32 48 77 16 7 54 22 49 43 34 +Card 161: 71 95 97 94 34 37 50 98 60 28 | 78 64 99 45 40 93 31 28 24 17 56 49 18 3 25 34 59 82 97 91 68 85 75 1 96 +Card 162: 20 76 42 79 77 19 6 90 69 48 | 23 17 20 92 4 72 66 52 69 2 97 75 57 78 95 94 88 61 1 80 59 10 91 84 11 +Card 163: 63 61 5 81 67 8 30 33 2 51 | 50 53 35 67 61 84 37 97 79 49 39 34 45 17 76 41 86 81 42 14 30 38 18 8 13 +Card 164: 95 85 44 84 60 64 24 57 48 65 | 34 33 8 16 99 5 19 30 55 21 81 98 67 88 36 90 35 4 28 43 61 62 52 13 70 +Card 165: 88 31 3 71 61 37 35 51 38 76 | 42 19 63 31 40 11 56 1 27 97 22 74 79 6 4 49 35 37 45 32 93 46 52 34 24 +Card 166: 93 29 1 76 94 87 10 25 68 81 | 8 80 58 62 66 93 39 75 77 30 29 63 31 19 92 18 34 67 33 35 97 44 89 40 71 +Card 167: 48 3 58 31 26 47 66 51 35 5 | 84 33 45 90 83 9 51 68 49 29 18 50 86 25 6 34 93 82 39 24 98 23 96 89 69 +Card 168: 36 95 30 50 22 29 25 64 35 5 | 79 56 54 1 70 12 7 42 76 99 90 15 61 55 23 81 93 60 49 26 88 40 89 58 2 +Card 169: 65 35 39 95 71 16 1 6 7 34 | 59 57 27 48 97 17 87 30 75 41 19 55 99 93 54 98 86 2 81 31 4 25 69 22 39 +Card 170: 84 78 94 24 11 40 60 50 33 91 | 11 78 24 55 46 67 65 52 66 69 14 91 33 1 23 60 45 40 50 34 84 16 94 70 62 +Card 171: 38 48 45 3 11 28 43 58 4 74 | 41 21 96 58 94 97 45 95 91 28 3 43 69 70 4 99 25 48 64 38 74 86 98 11 7 +Card 172: 73 29 25 36 78 93 21 76 55 32 | 34 42 55 64 29 35 13 77 76 94 75 32 89 38 33 25 73 21 20 36 52 92 30 41 17 +Card 173: 81 61 78 38 98 2 82 51 13 21 | 82 17 51 73 8 35 77 36 68 38 26 76 2 88 53 98 9 86 97 18 95 13 21 31 45 +Card 174: 26 71 44 62 58 34 94 6 63 56 | 94 30 35 65 93 49 21 31 33 36 58 34 76 62 16 44 63 26 71 64 56 90 9 6 43 +Card 175: 48 28 15 21 81 27 25 12 36 32 | 75 61 62 92 54 24 7 23 45 89 96 67 46 57 5 47 14 30 4 90 52 72 63 76 98 +Card 176: 72 22 84 56 28 15 44 62 55 12 | 30 11 24 62 52 56 84 73 38 55 22 31 36 15 72 12 28 88 51 91 44 60 26 95 89 +Card 177: 53 85 34 5 38 82 93 51 30 28 | 80 5 28 53 70 31 63 85 89 44 7 51 33 43 93 30 34 46 49 82 26 24 69 38 54 +Card 178: 65 14 66 63 85 86 89 30 84 32 | 92 24 76 86 38 56 82 84 66 89 42 32 63 43 14 65 79 99 70 85 80 6 97 83 61 +Card 179: 85 59 18 22 15 29 2 55 16 10 | 91 48 16 15 74 75 44 77 62 58 22 88 40 34 54 55 30 2 29 18 45 51 76 79 10 +Card 180: 45 13 56 71 79 75 86 16 95 32 | 30 91 39 85 79 35 5 12 4 90 53 95 47 1 75 15 9 3 50 45 10 32 22 24 13 +Card 181: 47 13 85 45 98 21 78 68 80 27 | 64 46 42 85 82 60 8 47 69 91 15 33 52 7 95 34 86 53 40 49 27 76 63 26 78 +Card 182: 78 84 43 31 86 90 13 83 7 29 | 51 64 67 82 39 87 49 93 69 12 29 36 47 84 18 96 77 10 91 92 60 16 53 81 88 +Card 183: 28 78 55 47 42 63 49 25 76 33 | 35 15 41 37 49 50 69 70 87 88 73 77 30 6 97 61 7 38 98 1 32 48 99 47 16 +Card 184: 96 39 9 10 41 91 42 89 8 55 | 94 53 33 12 81 88 42 87 39 1 92 10 98 26 48 29 72 54 96 91 47 13 78 83 68 +Card 185: 62 93 55 27 14 24 52 1 9 48 | 58 62 35 88 45 46 24 82 12 27 77 25 10 81 6 60 71 41 52 37 50 48 28 80 75 +Card 186: 90 95 45 20 89 88 34 55 25 2 | 89 31 34 8 86 5 91 90 25 84 45 81 24 65 60 64 19 94 49 55 75 20 47 44 61 +Card 187: 43 2 16 46 75 68 71 15 45 9 | 30 7 14 37 44 48 65 62 99 89 87 75 10 69 56 78 25 76 59 1 39 23 79 70 68 +Card 188: 67 81 88 51 13 5 61 45 27 10 | 35 39 80 10 30 27 38 3 36 22 52 7 40 49 45 79 9 63 42 13 96 31 23 78 98 +Card 189: 9 6 93 60 97 95 81 94 15 35 | 95 28 17 2 52 47 5 3 86 57 59 81 21 23 41 80 34 51 53 70 68 62 83 74 22 +Card 190: 65 67 94 63 74 34 48 36 27 20 | 1 91 37 3 49 16 18 7 31 53 25 96 68 88 90 95 27 6 19 58 66 45 73 26 32 +Card 191: 33 50 17 66 25 78 56 26 93 58 | 24 27 1 28 84 63 8 54 12 39 10 17 65 51 68 37 43 85 42 38 7 96 92 2 71 +Card 192: 4 6 53 67 24 7 31 98 51 64 | 23 89 13 77 22 40 20 88 21 44 49 41 93 64 15 56 50 62 57 80 3 82 70 48 18 +Card 193: 77 56 76 24 35 51 22 43 31 34 | 86 38 36 63 58 91 87 73 66 67 61 95 28 16 42 39 41 9 83 37 59 97 92 5 6 diff --git a/2023/days/04/src/main.rs b/2023/days/04/src/main.rs new file mode 100644 index 0000000..456385c --- /dev/null +++ b/2023/days/04/src/main.rs @@ -0,0 +1,14 @@ +mod part1; +mod part2; +mod parse; + +fn main() { + let input = include_str!("./input.txt"); + let structured_input = parse::parse(input); + + println!("Part One"); + println!("Result: {}", part1::part1(&structured_input)); + + println!("Part Two"); + println!("Result: {}", part2::part2(&structured_input)); +} diff --git a/2023/days/04/src/parse.rs b/2023/days/04/src/parse.rs new file mode 100644 index 0000000..42ceee1 --- /dev/null +++ b/2023/days/04/src/parse.rs @@ -0,0 +1,128 @@ +use std::collections::BTreeSet; + +use nom::{ + bytes::complete::tag, + multi::{many1, separated_list1}, + sequence::{preceded, terminated}, + IResult, +}; + +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct Card { + pub id: usize, + pub winning_numbers: BTreeSet, + pub numbers: BTreeSet, + pub multiplier: usize, +} + +impl Card { + pub fn parse(input: &str) -> IResult<&str, Card> { + let mut game_id = terminated( + preceded( + preceded(tag("Card"), many1(tag(" "))), + nom::character::complete::u8, + ), + preceded(tag(":"), many1(tag(" "))), + ); + let mut number_list = separated_list1(many1(tag(" ")), nom::character::complete::u8); + let seperator = preceded(tag(" |"), many1(tag(" "))); + let (input, id) = game_id(input)?; + let (input, winning_numbers) = number_list(input)?; + let (input, numbers) = preceded(seperator, number_list)(input)?; + let winning_numbers: BTreeSet = winning_numbers.into_iter().collect(); + let numbers: BTreeSet = numbers.into_iter().collect(); + Ok(( + input, + Card { + id: id as usize, + winning_numbers, + numbers, + multiplier: 1, + }, + )) + } + + pub fn num_matches(&self) -> usize { + self.numbers.intersection(&self.winning_numbers).count() + } +} + +pub fn parse(input: &str) -> Vec { + input.lines().map(|l| Card::parse(l).unwrap().1).collect() +} + +#[cfg(test)] +mod tests { + use super::*; + use collection_literals::collection; + + #[test] + fn test_parse() { + let input = concat!( + "Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53\n", + "Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19\n", + "Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1\n", + "Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83\n", + "Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36\n", + "Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11\n", + ); + assert_eq!( + parse(input), + vec![ + Card { + id: 1, + winning_numbers: collection! {17, 41, 48, 83, 86}, + numbers: collection! {6, 9, 17, 31, 48, 53, 83, 86}, + multiplier: 1, + }, + Card { + id: 2, + winning_numbers: collection! {13, 16, 20, 32, 61}, + numbers: collection! {17, 19, 24, 30, 32, 61, 68, 82}, + multiplier: 1, + }, + Card { + id: 3, + winning_numbers: collection! {1, 21, 44, 53, 59}, + numbers: collection! {1, 14, 16, 21, 63, 69, 72, 82}, + multiplier: 1, + }, + Card { + id: 4, + winning_numbers: collection! {41, 69, 73, 84, 92}, + numbers: collection! {5, 51, 54, 58, 59, 76, 83, 84}, + multiplier: 1, + }, + Card { + id: 5, + winning_numbers: collection! {26, 28, 32, 83, 87}, + numbers: collection! {12, 22, 30, 36, 70, 82, 88, 93}, + multiplier: 1, + }, + Card { + id: 6, + winning_numbers: collection! {13 , 18, 31, 56, 72}, + numbers: collection! {10, 11, 23, 35, 36, 67, 74, 77}, + multiplier: 1, + } + ] + ); + } + + #[test] + fn test_card_parse() { + let input = "Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53"; + assert_eq!( + Card::parse(input).unwrap(), + ( + "", + Card { + id: 1, + winning_numbers: collection! {41, 48, 83, 86, 17}, + numbers: collection! {83, 86, 6, 31, 17, 9, 48, 53}, + multiplier: 1, + } + ) + ) + } +} diff --git a/2023/days/04/src/part1.rs b/2023/days/04/src/part1.rs new file mode 100644 index 0000000..3b00101 --- /dev/null +++ b/2023/days/04/src/part1.rs @@ -0,0 +1,65 @@ +use crate::parse::*; + +pub fn part1(input: &[Card]) -> usize { + input + .iter() + .map(|c| { + let len = c.num_matches(); + if len >= 1 { + 2_usize.pow((len - 1).try_into().unwrap()) + } else { + 0 + } + }) + .sum() +} + +#[cfg(test)] +mod tests { + use collection_literals::collection; + + use super::*; + + #[test] + fn test_part1() { + let input = vec![ + Card { + id: 1, + winning_numbers: collection! {17, 41, 48, 83, 86}, + numbers: collection! {6, 9, 17, 31, 48, 53, 83, 86}, + multiplier: 1, + }, + Card { + id: 2, + winning_numbers: collection! {13, 16, 20, 32, 61}, + numbers: collection! {17, 19, 24, 30, 32, 61, 68, 82}, + multiplier: 1, + }, + Card { + id: 3, + winning_numbers: collection! {1, 21, 44, 53, 59}, + numbers: collection! {1, 14, 16, 21, 63, 69, 72, 82}, + multiplier: 1, + }, + Card { + id: 4, + winning_numbers: collection! {41, 69, 73, 84, 92}, + numbers: collection! {5, 51, 54, 58, 59, 76, 83, 84}, + multiplier: 1, + }, + Card { + id: 5, + winning_numbers: collection! {26, 28, 32, 83, 87}, + numbers: collection! {12, 22, 30, 36, 70, 82, 88, 93}, + multiplier: 1, + }, + Card { + id: 6, + winning_numbers: collection! {13 , 18, 31, 56, 72}, + numbers: collection! {10, 11, 23, 35, 36, 67, 74, 77}, + multiplier: 1, + }, + ]; + assert_eq!(part1(&input), 13); + } +} diff --git a/2023/days/04/src/part2.rs b/2023/days/04/src/part2.rs new file mode 100644 index 0000000..b45077d --- /dev/null +++ b/2023/days/04/src/part2.rs @@ -0,0 +1,65 @@ +use crate::parse::*; + +pub fn part2(input: &[Card]) -> usize { + let mut stack: Vec = input.to_vec(); + for i in 0..stack.len() { + let matches = stack[i].num_matches(); + if matches >= 1 { + //+1 because we want 3 matches to give the num 1,2,3 + for advance in 1..(matches+1){ + stack[i+advance].multiplier+=stack[i].multiplier + } + } + } + stack.iter().map(|c| c.multiplier).sum() +} + +#[cfg(test)] +mod tests { + use collection_literals::collection; + + use super::*; + + #[test] + fn test_part2() { + let input = vec![ + Card { + id: 1, + winning_numbers: collection! {17, 41, 48, 83, 86}, + numbers: collection! {6, 9, 17, 31, 48, 53, 83, 86}, + multiplier: 1, + }, + Card { + id: 2, + winning_numbers: collection! {13, 16, 20, 32, 61}, + numbers: collection! {17, 19, 24, 30, 32, 61, 68, 82}, + multiplier: 1, + }, + Card { + id: 3, + winning_numbers: collection! {1, 21, 44, 53, 59}, + numbers: collection! {1, 14, 16, 21, 63, 69, 72, 82}, + multiplier: 1, + }, + Card { + id: 4, + winning_numbers: collection! {41, 69, 73, 84, 92}, + numbers: collection! {5, 51, 54, 58, 59, 76, 83, 84}, + multiplier: 1, + }, + Card { + id: 5, + winning_numbers: collection! {26, 28, 32, 83, 87}, + numbers: collection! {12, 22, 30, 36, 70, 82, 88, 93}, + multiplier: 1, + }, + Card { + id: 6, + winning_numbers: collection! {13 , 18, 31, 56, 72}, + numbers: collection! {10, 11, 23, 35, 36, 67, 74, 77}, + multiplier: 1, + }, + ]; + assert_eq!(part2(&input), 30); + } +} diff --git a/2023/days/05/Cargo.toml b/2023/days/05/Cargo.toml new file mode 100644 index 0000000..be6bf75 --- /dev/null +++ b/2023/days/05/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "day05" +authors.workspace = true +description.workspace = true +version.workspace = true +edition.workspace = true + +[dependencies] +aoc_libs.workspace = true +nom.workspace = true diff --git a/2023/days/05/src/input.txt b/2023/days/05/src/input.txt new file mode 100644 index 0000000..3d50c1c --- /dev/null +++ b/2023/days/05/src/input.txt @@ -0,0 +1,252 @@ +seeds: 432986705 28073546 1364097901 88338513 2733524843 234912494 3151642679 224376393 485709676 344068331 1560394266 911616092 3819746175 87998136 892394515 435690182 4218056486 23868437 848725444 8940450 + +seed-to-soil map: +748585809 2125564114 88980459 +1317392128 775565564 217595062 +1218610825 676784261 98781303 +954230685 2235762425 141777617 +2920242079 4081180892 51765553 +2972007632 3159586797 16102841 +0 2377540042 17565155 +2834452876 3712797875 58062179 +2892515055 2917079842 6424918 +3327351062 3175689638 162608005 +673338549 647264576 29519685 +1197392973 2214544573 21217852 +738232750 116664417 10353059 +2988110473 2429807442 71556277 +17565155 334379348 277510712 +1700771639 228674051 105705297 +3059666750 4132946445 162020851 +1806476936 993160626 588628261 +1096008302 127289380 101384671 +622123656 1908836676 50942989 +3221687601 3338297643 28028532 +2408505336 3770860054 310320838 +4175210607 3039830108 119756689 +3326652416 3039131462 698646 +2898939973 2408505336 21302106 +673066645 127017476 271904 +3489959067 3382623558 330174317 +702858234 611890060 35374516 +4086270124 2562002619 88940483 +837566268 0 116664417 +1534987190 1959779665 165784449 +2718826174 2923504760 115626702 +3249716133 3366326175 16297383 +3820133384 2650943102 266136740 +3266013516 2501363719 60638900 +295075867 1581788887 327047789 + +soil-to-fertilizer map: +2018515973 2192795257 82329405 +3722326327 3015971185 249665840 +3046459770 3689390318 25519185 +3971992167 3265637025 40217941 +3071978955 3453653215 203407731 +0 443504340 17965088 +584437096 1722124969 470670288 +1055107384 744431503 164966659 +1489299099 461469428 282962075 +2321848831 2380372526 153650776 +2100845378 269225056 174279284 +3487660258 2648616968 234666069 +3275386686 3305854966 147798249 +1772261174 1172578553 246254799 +4012210108 2883283037 132688148 +3423184935 4138946628 64475323 +4144898256 2321848831 58523695 +538253726 1418833352 46183370 +1220074043 0 269225056 +17965088 909398162 263180391 +2590093273 3657060946 32329372 +281145479 1465016722 257108247 +2622422645 3714909503 424037125 +2475499607 2534023302 114593666 + +fertilizer-to-water map: +3731805434 353192162 37567806 +926873139 889685769 255250442 +3170336676 695153543 194532226 +679924479 451681440 193671776 +3009343704 3081959489 160992972 +1242360754 3579359343 278026518 +1861131448 2500688596 20068354 +4028837903 4006213119 266129393 +1182123581 3242952461 60237173 +3877550443 645353216 49800327 +2223776164 1371077033 341527178 +3364868902 2566566565 36440100 +1773121333 0 76664401 +264823995 2444756861 55931735 +3929841219 3857385861 27802851 +2166799431 1712604211 56976733 +873596255 1769580944 53276884 +645696746 3047731756 34227733 +3927350770 3955153621 2490449 +3769373240 177937131 108177203 +0 3314535348 264823995 +1942121274 3885188712 69964909 +1881199802 390759968 60921472 +1849785734 3303189634 11345714 +3401309002 2855740726 104355610 +2079164011 2960096336 87635420 +544424016 76664401 101272730 +2565303342 2520756950 45809615 +1520387272 2603006665 252734061 +2012086183 286114334 67077828 +2611112957 1822857828 398230747 +320755730 2221088575 223668286 +3505664612 1144936211 226140822 +4006213119 4272342512 22624784 + +water-to-light map: +62780592 544346201 30115959 +2740764032 1352944740 34082945 +377487729 807592920 35446631 +1316419610 1454554942 34907962 +986581913 756881718 50711202 +4167758628 3240047125 127208668 +818809239 1222506283 58684750 +3649838514 2036598113 6212644 +127663629 0 10715051 +3023280854 1435387310 19167632 +663070842 10715051 124076893 +2774846977 2422700597 37614763 +1812617371 2460315360 5121443 +1640337506 1864318248 172279865 +2986755724 1316419610 36525130 +2023334670 2467203928 540327060 +1159184084 248462172 14557802 +1037293115 152894449 95567723 +0 134791944 18102505 +18102505 712203631 44678087 +465375803 972369801 197695039 +2576394916 3007530988 65274194 +92896551 1281191033 34767078 +3656051158 4289142647 5824649 +412934360 1170064840 52441443 +3417303830 3873138614 84580361 +787147735 263019974 31661504 +1817738814 2042810757 205595856 +1285160111 843039551 30798000 +2563661730 3123136764 12733186 +138378680 305237152 239109049 +3648071389 2465436803 1767125 +1132860838 574462160 26323246 +888049663 873837551 98532250 +3626039273 3072805182 22032116 +3530183657 4193287031 95855616 +1404769450 3957718975 235568056 +3042448486 1489462904 374855344 +2641669110 1387027685 48359625 +877493989 294681478 10555674 +3501884191 3094837298 28299466 +1351327572 3186605247 53441878 +2690028735 3135869950 50735297 +2812461740 2248406613 174293984 +3661875807 3367255793 505882821 +1173741886 600785406 111418225 + +light-to-temperature map: +964570004 989608620 226759942 +2204148775 2545437438 20646474 +233260112 338444213 39032265 +958191857 332066066 6378147 +2318799855 914518254 75090366 +4247140372 3146297568 47826924 +2224795249 1216368562 94004606 +2871022952 1310373168 80313918 +1400254919 233260112 98805954 +445493256 487550555 149554087 +2576473348 3962746668 294549604 +3535295748 2775008885 371288683 +1499060873 377476478 110074077 +272292377 2215619580 173200879 +3347481948 1867953550 157067409 +4161267146 3794452372 85873226 +3504549357 2184873189 30746391 +1759636962 1780717197 87236353 +2951336870 2388820459 6114967 +1191329946 2566083912 208924973 +1884544339 3880325598 82421070 +595047343 3431307858 363144514 +2393890221 731935127 182583127 +4001414916 2025020959 159852230 +2957451837 1390687086 390030111 +1846873315 4257296272 37671024 +1966965409 3194124492 237183366 +1609134950 2394935426 150502012 +3906584431 637104642 94830485 + +temperature-to-humidity map: +1406768592 2335526312 13344484 +666958498 1862550129 472976183 +558853371 843618476 74696086 +1168798622 129171378 168640618 +1713291209 297811996 183431863 +1993628008 635748116 152317885 +2560263686 2849350774 11516524 +32266442 1212766321 287276323 +2571780210 3319898101 11192927 +375095240 995599149 183758131 +2661986290 2353962919 50829838 +3252020768 4280298713 14668583 +1337439240 1793220777 69329352 +3419718116 3502299739 574454544 +2353962919 2650392505 198958269 +633549457 1179357280 33409041 +2582973137 4076754283 50515665 +319542765 788066001 55552475 +1896723072 32266442 96904936 +1420113076 1500042644 293178133 +3006421020 2404792757 245599748 +2842554807 3331091028 163866213 +2633488802 2990605977 28497488 +2300450150 947178503 48420646 +3266689351 4127269948 153028765 +2145945893 481243859 154504257 +3994172660 3019103465 300794636 +1139934681 918314562 28863941 +2712816128 2860867298 129738679 +2552921188 3494957241 7342498 + +humidity-to-location map: +897459980 3171885613 268595078 +506368722 1864971513 13322696 +1166055058 2803961444 53745388 +2572095034 667166679 114420176 +687118932 1725187165 139784348 +2478398695 0 14138781 +3427672233 370325921 251085897 +3888215738 3612891343 82449665 +1674720770 1530101168 79955344 +3970665403 925512154 2812137 +519691418 2452425610 167427514 +3884704963 3168374838 3510775 +826903280 2381868910 70556700 +2399774019 349568762 20757159 +2972099388 3465151802 147739541 +1754676114 131614075 217954687 +2865104023 3440480691 24671111 +2206760431 932309368 77882935 +2284643366 1610056512 115130653 +2492537476 14138781 35151040 +2527688516 3695341008 44406518 +3119838929 781586855 143925299 +2732270071 2857706832 132833952 +1599442846 2728683520 75277924 +3263764228 3995626854 27783181 +0 2990540784 177834054 +2686515210 621411818 45754861 +2420531178 2670816003 57867517 +1219800446 1010192303 191374197 +3678758130 3789680021 205946833 +3973477540 3739747526 49932495 +1972630801 2014419033 234129630 +3291547409 1878294209 136124824 +2889775134 49289821 82324254 +1411174643 2619853124 50962879 +1466122599 2248548663 133320247 +177834054 1201566500 328534668 +1462137522 928324291 3985077 diff --git a/2023/days/05/src/main.rs b/2023/days/05/src/main.rs new file mode 100644 index 0000000..456385c --- /dev/null +++ b/2023/days/05/src/main.rs @@ -0,0 +1,14 @@ +mod part1; +mod part2; +mod parse; + +fn main() { + let input = include_str!("./input.txt"); + let structured_input = parse::parse(input); + + println!("Part One"); + println!("Result: {}", part1::part1(&structured_input)); + + println!("Part Two"); + println!("Result: {}", part2::part2(&structured_input)); +} diff --git a/2023/days/05/src/parse.rs b/2023/days/05/src/parse.rs new file mode 100644 index 0000000..f2592d0 --- /dev/null +++ b/2023/days/05/src/parse.rs @@ -0,0 +1,543 @@ +use std::ops::Range; + +use nom::{ + bytes::complete::tag, + character::complete::{alpha1, multispace0}, + multi::{count, many1, separated_list1}, + sequence::{delimited, preceded, terminated}, + IResult, +}; + +pub type SeedRange = Range; + +#[derive(Debug, PartialEq, Eq)] +pub struct Map { + pub from: String, + pub to: String, + pub ranges: Vec, +} + +impl Map { + pub fn map_ranges(&self, seeds: SeedRange) -> Vec { + let mut unprocessed_seeds = vec![seeds]; + let mut processed_seeds = Vec::new(); + //using this instead of a for loop so that we can continue to push new stuff onto the + //unprocessed queue + while let Some(seed) = unprocessed_seeds.pop() { + //find map with intersection with seed + let map_to_apply = self + .ranges + .iter() + .find(|&map_range| !map_range.intersection_with_seed(&seed).is_empty()); + + let Some(map_to_apply) = map_to_apply else { + //if no mapping to do, consider seed processed + processed_seeds.push(seed); + continue; + }; + + let map_end = map_to_apply.src_start + map_to_apply.len; + let offset = map_to_apply.dest_start as i64 - map_to_apply.src_start as i64; + let intersection = map_to_apply.intersection_with_seed(&seed); + + processed_seeds.push(Range { + start: (intersection.start as i64 + offset) as u64, + end: (intersection.end as i64 + offset) as u64, + }); + + //add the part before the map range back to the queue + if seed.start < map_to_apply.src_start { + unprocessed_seeds.push(Range { + start: seed.start, + end: intersection.start, + }) + }; + + //add the part after the map range back to the queue + if seed.end > map_end { + unprocessed_seeds.push(Range { + start: intersection.end, + end: seed.end, + }) + }; + } + processed_seeds + } + + pub fn map(&self, src: u64) -> u64 { + for range in &self.ranges { + if range.is_applicable(&src) { + return range.map(src); + } + } + src + } + fn parse(input: &str) -> IResult<&str, Self> { + let (input, (from, to)) = delimited(multispace0, Self::parse_to_from, multispace0)(input)?; + let (input, ranges) = many1(MapRange::parse)(input)?; + Ok((input, Map { from, to, ranges })) + } + fn parse_to_from(input: &str) -> IResult<&str, (String, String)> { + let (input, from) = alpha1(input)?; + let (input, to) = terminated(preceded(tag("-to-"), alpha1), tag(" map:\n"))(input)?; + Ok((input, (from.to_string(), to.to_string()))) + } +} + +#[derive(Debug, PartialEq, Eq)] +pub struct MapRange { + pub dest_start: u64, + pub src_start: u64, + pub len: u64, +} + +impl MapRange { + fn intersection_with_seed(&self, seed: &SeedRange) -> SeedRange { + seed.start.max(self.src_start)..seed.end.min(self.src_start + self.len) + } + + fn is_applicable(&self, src: &u64) -> bool { + self.src_start <= *src && *src < (self.src_start + self.len) + } + + fn map(&self, src: u64) -> u64 { + if self.is_applicable(&src) { + let offset = src - self.src_start; + self.dest_start + offset + } else { + src + } + } + + fn parse(input: &str) -> IResult<&str, Self> { + let number = delimited(multispace0, nom::character::complete::u64, multispace0); + let (input, numbers) = count(number, 3)(input)?; + Ok(( + input, + MapRange { + dest_start: numbers[0], + src_start: numbers[1], + len: numbers[2], + }, + )) + } +} + +fn parse_input(input: &str) -> IResult<&str, (Vec, Vec)> { + let (input, seeds) = preceded( + tag("seeds: "), + separated_list1(tag(" "), nom::character::complete::u64), + )(input)?; + let (input, maps) = many1(Map::parse)(input)?; + Ok((input, (seeds, maps))) +} + +pub fn parse(input: &str) -> (Vec, Vec) { + parse_input(input).unwrap().1 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_map_range() { + let tested = Map { + from: "seed".to_string(), + to: "soil".to_string(), + ranges: vec![ + MapRange { + dest_start: 50, + src_start: 98, + len: 2, + }, + MapRange { + dest_start: 52, + src_start: 50, + len: 48, + }, + ], + }; + let input: SeedRange = 40..120; + assert_eq!( + tested.map_ranges(input), + vec![ + 50..52, + 100..120, + 52..100, + 40..50 + ] + ) + } + + #[test] + fn test_intersection_with_seed() { + let tested = MapRange { + dest_start: 52, + src_start: 50, + len: 48, + }; + let input: SeedRange = 80..120; + assert_eq!(tested.intersection_with_seed(&input), 80..98); + let input: SeedRange = 40..60; + assert_eq!(tested.intersection_with_seed(&input), 50..60); + let input: SeedRange = 55..79; + assert_eq!(tested.intersection_with_seed(&input), 55..79); + let input: SeedRange = 40..120; + assert_eq!(tested.intersection_with_seed(&input), 50..98); + } + + #[test] + fn test_map() { + let tested = Map { + from: "seed".to_string(), + to: "soil".to_string(), + ranges: vec![ + MapRange { + dest_start: 50, + src_start: 98, + len: 2, + }, + MapRange { + dest_start: 52, + src_start: 50, + len: 48, + }, + ], + }; + let input = [79, 14, 55, 13]; + let output = input.map(|i| tested.map(i)); + assert_eq!(output, [81, 14, 57, 13]) + } + + #[test] + fn test_is_appliccable() { + let tested = MapRange { + dest_start: 50, + src_start: 98, + len: 2, + }; + assert!(tested.is_applicable(&99)); + assert!(!tested.is_applicable(&100)); + assert!(!tested.is_applicable(&97)); + } + + #[test] + fn test_range_map() { + let tested = MapRange { + dest_start: 52, + src_start: 50, + len: 48, + }; + assert_eq!(tested.map(79), 81); + assert_eq!(tested.map(100), 100); + } + + #[test] + fn test_map_parse() { + let input = concat!("seed-to-soil map:\n", "50 98 2\n", "52 50 48\n", "\n",); + assert_eq!( + Map::parse(input).unwrap(), + ( + "", + Map { + from: "seed".to_string(), + to: "soil".to_string(), + ranges: vec![ + MapRange { + dest_start: 50, + src_start: 98, + len: 2 + }, + MapRange { + dest_start: 52, + src_start: 50, + len: 48 + }, + ] + }, + ) + ) + } + + #[test] + fn test_range_parse() { + assert_eq!( + MapRange::parse("50 98 2\n").unwrap(), + ( + "", + MapRange { + dest_start: 50, + src_start: 98, + len: 2, + } + ) + ); + assert_eq!( + MapRange::parse("0 15 37\n").unwrap(), + ( + "", + MapRange { + dest_start: 0, + src_start: 15, + len: 37, + } + ) + ) + } + + #[test] + fn test_parse_to_from() { + assert_eq!( + Map::parse_to_from("seed-to-soil map:\n").unwrap(), + ("", ("seed".to_string(), "soil".to_string())) + ); + assert_eq!( + Map::parse_to_from("hello-to-world map:\n").unwrap(), + ("", ("hello".to_string(), "world".to_string())) + ); + } + + #[test] + fn test_parse_input() { + let input = concat!( + "seeds: 79 14 55 13\n", + "\n", + "seed-to-soil map:\n", + "50 98 2\n", + "52 50 48\n", + "\n", + "soil-to-fertilizer map:\n", + "0 15 37\n", + "37 52 2\n", + "39 0 15\n", + ); + assert_eq!( + parse_input(input).unwrap(), + ( + "", + ( + vec![79, 14, 55, 13], + vec![ + Map { + from: "seed".to_string(), + to: "soil".to_string(), + ranges: vec![ + MapRange { + dest_start: 50, + src_start: 98, + len: 2 + }, + MapRange { + dest_start: 52, + src_start: 50, + len: 48 + }, + ] + }, + Map { + from: "soil".to_string(), + to: "fertilizer".to_string(), + ranges: vec![ + MapRange { + dest_start: 0, + src_start: 15, + len: 37 + }, + MapRange { + dest_start: 37, + src_start: 52, + len: 2 + }, + MapRange { + dest_start: 39, + src_start: 0, + len: 15 + }, + ] + } + ] + ) + ) + ); + } + + #[test] + fn test_parse() { + let input = concat!( + "seeds: 79 14 55 13\n", + "\n", + "seed-to-soil map:\n", + "50 98 2\n", + "52 50 48\n", + "\n", + "soil-to-fertilizer map:\n", + "0 15 37\n", + "37 52 2\n", + "39 0 15\n", + "\n", + "fertilizer-to-water map:\n", + "49 53 8\n", + "0 11 42\n", + "42 0 7\n", + "57 7 4\n", + "\n", + "water-to-light map:\n", + "88 18 7\n", + "18 25 70\n", + "\n", + "light-to-temperature map:\n", + "45 77 23\n", + "81 45 19\n", + "68 64 13\n", + "\n", + "temperature-to-humidity map:\n", + "0 69 1\n", + "1 0 69\n", + "\n", + "humidity-to-location map:\n", + "60 56 37\n", + "56 93 4\n", + ); + assert_eq!( + parse(input), + ( + vec![79, 14, 55, 13], + vec![ + Map { + from: "seed".to_string(), + to: "soil".to_string(), + ranges: vec![ + MapRange { + dest_start: 50, + src_start: 98, + len: 2 + }, + MapRange { + dest_start: 52, + src_start: 50, + len: 48 + } + ] + }, + Map { + from: "soil".to_string(), + to: "fertilizer".to_string(), + ranges: vec![ + MapRange { + dest_start: 0, + src_start: 15, + len: 37 + }, + MapRange { + dest_start: 37, + src_start: 52, + len: 2 + }, + MapRange { + dest_start: 39, + src_start: 0, + len: 15 + } + ] + }, + Map { + from: "fertilizer".to_string(), + to: "water".to_string(), + ranges: vec![ + MapRange { + dest_start: 49, + src_start: 53, + len: 8 + }, + MapRange { + dest_start: 0, + src_start: 11, + len: 42 + }, + MapRange { + dest_start: 42, + src_start: 0, + len: 7 + }, + MapRange { + dest_start: 57, + src_start: 7, + len: 4 + } + ] + }, + Map { + from: "water".to_string(), + to: "light".to_string(), + ranges: vec![ + MapRange { + dest_start: 88, + src_start: 18, + len: 7 + }, + MapRange { + dest_start: 18, + src_start: 25, + len: 70 + } + ] + }, + Map { + from: "light".to_string(), + to: "temperature".to_string(), + ranges: vec![ + MapRange { + dest_start: 45, + src_start: 77, + len: 23 + }, + MapRange { + dest_start: 81, + src_start: 45, + len: 19 + }, + MapRange { + dest_start: 68, + src_start: 64, + len: 13 + } + ] + }, + Map { + from: "temperature".to_string(), + to: "humidity".to_string(), + ranges: vec![ + MapRange { + dest_start: 0, + src_start: 69, + len: 1 + }, + MapRange { + dest_start: 1, + src_start: 0, + len: 69 + } + ] + }, + Map { + from: "humidity".to_string(), + to: "location".to_string(), + ranges: vec![ + MapRange { + dest_start: 60, + src_start: 56, + len: 37 + }, + MapRange { + dest_start: 56, + src_start: 93, + len: 4 + } + ] + } + ] + ) + ); + } +} diff --git a/2023/days/05/src/part1.rs b/2023/days/05/src/part1.rs new file mode 100644 index 0000000..9dc17f5 --- /dev/null +++ b/2023/days/05/src/part1.rs @@ -0,0 +1,156 @@ +use crate::parse::*; + +pub fn part1(input: &(Vec, Vec)) -> usize { + let mut seeds = input.0.clone(); + for map in &input.1 { + seeds = seeds.into_iter().map(|s| map.map(s)).collect() + } + *seeds.iter().min().unwrap() as usize +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part1() { + let input = ( + vec![79, 14, 55, 13], + vec![ + Map { + from: "seed".to_string(), + to: "soil".to_string(), + ranges: vec![ + MapRange { + dest_start: 50, + src_start: 98, + len: 2, + }, + MapRange { + dest_start: 52, + src_start: 50, + len: 48, + }, + ], + }, + Map { + from: "soil".to_string(), + to: "fertilizer".to_string(), + ranges: vec![ + MapRange { + dest_start: 0, + src_start: 15, + len: 37, + }, + MapRange { + dest_start: 37, + src_start: 52, + len: 2, + }, + MapRange { + dest_start: 39, + src_start: 0, + len: 15, + }, + ], + }, + Map { + from: "fertilizer".to_string(), + to: "water".to_string(), + ranges: vec![ + MapRange { + dest_start: 49, + src_start: 53, + len: 8, + }, + MapRange { + dest_start: 0, + src_start: 11, + len: 42, + }, + MapRange { + dest_start: 42, + src_start: 0, + len: 7, + }, + MapRange { + dest_start: 57, + src_start: 7, + len: 4, + }, + ], + }, + Map { + from: "water".to_string(), + to: "light".to_string(), + ranges: vec![ + MapRange { + dest_start: 88, + src_start: 18, + len: 7, + }, + MapRange { + dest_start: 18, + src_start: 25, + len: 70, + }, + ], + }, + Map { + from: "light".to_string(), + to: "temperature".to_string(), + ranges: vec![ + MapRange { + dest_start: 45, + src_start: 77, + len: 23, + }, + MapRange { + dest_start: 81, + src_start: 45, + len: 19, + }, + MapRange { + dest_start: 68, + src_start: 64, + len: 13, + }, + ], + }, + Map { + from: "temperature".to_string(), + to: "humidity".to_string(), + ranges: vec![ + MapRange { + dest_start: 0, + src_start: 69, + len: 1, + }, + MapRange { + dest_start: 1, + src_start: 0, + len: 69, + }, + ], + }, + Map { + from: "humidity".to_string(), + to: "location".to_string(), + ranges: vec![ + MapRange { + dest_start: 60, + src_start: 56, + len: 37, + }, + MapRange { + dest_start: 56, + src_start: 93, + len: 4, + }, + ], + }, + ], + ); + assert_eq!(part1(&input), 35); + } +} diff --git a/2023/days/05/src/part2.rs b/2023/days/05/src/part2.rs new file mode 100644 index 0000000..49b915f --- /dev/null +++ b/2023/days/05/src/part2.rs @@ -0,0 +1,168 @@ +use crate::parse::*; + +pub fn part2(input: &(Vec, Vec)) -> usize { + let mut seeds = convert_seeds_to_ranges(&input.0); + for map in &input.1{ + seeds = seeds.into_iter().flat_map(|s|{ + map.map_ranges(s) + }).collect(); + }; + seeds.iter().map(|s| s.start).min().unwrap() as usize +} + +fn convert_seeds_to_ranges(seeds: &[u64]) -> Vec { + seeds.chunks(2).map(|c| c[0]..(c[0] + c[1])).collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_convert_seeds_to_ranges() { + let input = [79, 14, 55, 13]; + assert_eq!(convert_seeds_to_ranges(&input), vec![79..93, 55..68]) + } + + #[test] + fn test_part2() { + let input = ( + vec![79, 14, 55, 13], + vec![ + Map { + from: "seed".to_string(), + to: "soil".to_string(), + ranges: vec![ + MapRange { + dest_start: 50, + src_start: 98, + len: 2, + }, + MapRange { + dest_start: 52, + src_start: 50, + len: 48, + }, + ], + }, + Map { + from: "soil".to_string(), + to: "fertilizer".to_string(), + ranges: vec![ + MapRange { + dest_start: 0, + src_start: 15, + len: 37, + }, + MapRange { + dest_start: 37, + src_start: 52, + len: 2, + }, + MapRange { + dest_start: 39, + src_start: 0, + len: 15, + }, + ], + }, + Map { + from: "fertilizer".to_string(), + to: "water".to_string(), + ranges: vec![ + MapRange { + dest_start: 49, + src_start: 53, + len: 8, + }, + MapRange { + dest_start: 0, + src_start: 11, + len: 42, + }, + MapRange { + dest_start: 42, + src_start: 0, + len: 7, + }, + MapRange { + dest_start: 57, + src_start: 7, + len: 4, + }, + ], + }, + Map { + from: "water".to_string(), + to: "light".to_string(), + ranges: vec![ + MapRange { + dest_start: 88, + src_start: 18, + len: 7, + }, + MapRange { + dest_start: 18, + src_start: 25, + len: 70, + }, + ], + }, + Map { + from: "light".to_string(), + to: "temperature".to_string(), + ranges: vec![ + MapRange { + dest_start: 45, + src_start: 77, + len: 23, + }, + MapRange { + dest_start: 81, + src_start: 45, + len: 19, + }, + MapRange { + dest_start: 68, + src_start: 64, + len: 13, + }, + ], + }, + Map { + from: "temperature".to_string(), + to: "humidity".to_string(), + ranges: vec![ + MapRange { + dest_start: 0, + src_start: 69, + len: 1, + }, + MapRange { + dest_start: 1, + src_start: 0, + len: 69, + }, + ], + }, + Map { + from: "humidity".to_string(), + to: "location".to_string(), + ranges: vec![ + MapRange { + dest_start: 60, + src_start: 56, + len: 37, + }, + MapRange { + dest_start: 56, + src_start: 93, + len: 4, + }, + ], + }, + ], + ); + assert_eq!(part2(&input), 46); + } +} diff --git a/2023/days/06/Cargo.toml b/2023/days/06/Cargo.toml new file mode 100644 index 0000000..e9b596f --- /dev/null +++ b/2023/days/06/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "day06" +authors.workspace = true +description.workspace = true +version.workspace = true +edition.workspace = true + +[dependencies] +aoc_libs.workspace = true +nom.workspace=true diff --git a/2023/days/06/src/input.txt b/2023/days/06/src/input.txt new file mode 100644 index 0000000..578cc39 --- /dev/null +++ b/2023/days/06/src/input.txt @@ -0,0 +1,2 @@ +Time: 40 81 77 72 +Distance: 219 1012 1365 1089 diff --git a/2023/days/06/src/main.rs b/2023/days/06/src/main.rs new file mode 100644 index 0000000..f7ec879 --- /dev/null +++ b/2023/days/06/src/main.rs @@ -0,0 +1,15 @@ +mod part1; +mod part2; +mod parse; + +fn main() { + let input = include_str!("./input.txt"); + let structured_input = parse::parse(input); + + println!("Part One"); + println!("Result: {}", part1::part1(&structured_input)); + + let structured_input = parse::part2_parse(input); + println!("Part Two"); + println!("Result: {}", part2::part2(structured_input)); +} diff --git a/2023/days/06/src/parse.rs b/2023/days/06/src/parse.rs new file mode 100644 index 0000000..b99a455 --- /dev/null +++ b/2023/days/06/src/parse.rs @@ -0,0 +1,148 @@ +use nom::{ + bytes::complete::tag, + character::complete::multispace0, + multi::separated_list1, + sequence::{preceded, terminated}, + IResult, +}; + +#[derive(Debug, PartialEq, Eq)] +pub struct Race { + pub time: u64, + pub record: u64, +} + +impl Race { + // pub fn distance_given_charge_time(&self, charge_time: u64) -> u64 { + // if charge_time <= self.time { + // charge_time * (self.time - charge_time) + // } else { + // 0 + // } + // } + + pub fn num_ways_to_win(&self) -> u64 { + // since distance = charge(time-charge), + // we can rearrange into charge^2-(time)charge + distance = 0. + // if we set distance to record+1 (the min distance needed to win), we can use the quadratic formula, where + // a=1 + // also notice that the upper and lower bound of charge times always sums up to + // the total time, so we can compute the lower bound from the upper bound. + // (too lazy to prove this...) + let b = -(self.time as f64); + let c = (self.record + 1) as f64; + let upper_bound = ((-b + (b.powi(2) - 4.0 * c).sqrt()) / 2.0).floor() as u64; + let lower_bound = self.time - upper_bound; + println!( + "upper bound is {}, lower bound is {}", + upper_bound, lower_bound + ); + // off by one because if your upper and lower bounds are the same, there is 1 way to win. + upper_bound - lower_bound + 1 + } +} + +pub fn parse(input: &str) -> Vec { + let times: IResult<&str, Vec> = terminated( + preceded( + preceded(tag("Time:"), multispace0), + separated_list1(multispace0, nom::character::complete::u64), + ), + multispace0, + )(input); + let (input, times) = times.unwrap(); + let distances: IResult<&str, Vec> = terminated( + preceded( + preceded(tag("Distance:"), multispace0), + separated_list1(multispace0, nom::character::complete::u64), + ), + multispace0, + )(input); + let (input, distances) = distances.unwrap(); + assert_eq!(input, ""); + times + .into_iter() + .zip(distances) + .map(|r| Race { + time: r.0, + record: r.1, + }) + .collect() +} + +pub fn part2_parse(input: &str) -> Race { + let mut string = input.to_string(); + string.retain(|c| c != ' '); + let time: IResult<&str, u64> = terminated( + preceded(tag("Time:"), nom::character::complete::u64), + multispace0, + )(&string); + let (input, time) = time.unwrap(); + let distance: IResult<&str, u64> = terminated( + preceded(tag("Distance:"), nom::character::complete::u64), + multispace0, + )(input); + let (input, distance) = distance.unwrap(); + assert_eq!(input, ""); + Race { + time, + record: distance, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_num_ways_to_win() { + let input = Race { time: 7, record: 9 }; + assert_eq!(input.num_ways_to_win(), 4); + let input = Race { + time: 15, + record: 40, + }; + assert_eq!(input.num_ways_to_win(), 8); + let input = Race { + time: 30, + record: 200, + }; + assert_eq!(input.num_ways_to_win(), 9); + let input = Race { + time: 71530, + record: 940200, + }; + assert_eq!(input.num_ways_to_win(), 71503); + } + + #[test] + fn test_parse_part2() { + let input = concat!("Time: 7 15 30\n", "Distance: 9 40 200\n",); + assert_eq!( + part2_parse(input), + Race { + time: 71530, + record: 940200 + } + ); + } + + #[test] + fn test_parse() { + let input = concat!("Time: 7 15 30\n", "Distance: 9 40 200\n",); + assert_eq!( + parse(input), + vec![ + Race { time: 7, record: 9 }, + Race { + time: 15, + record: 40 + }, + Race { + time: 30, + record: 200 + }, + ] + ); + } +} diff --git a/2023/days/06/src/part1.rs b/2023/days/06/src/part1.rs new file mode 100644 index 0000000..bcc6675 --- /dev/null +++ b/2023/days/06/src/part1.rs @@ -0,0 +1,26 @@ +use crate::parse::*; + +pub fn part1(input: &[Race]) -> u64 { + input.iter().map(|r| r.num_ways_to_win()).product() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part1() { + let input = vec![ + Race { time: 7, record: 9 }, + Race { + time: 15, + record: 40, + }, + Race { + time: 30, + record: 200, + }, + ]; + assert_eq!(part1(&input), 288); + } +} diff --git a/2023/days/06/src/part2.rs b/2023/days/06/src/part2.rs new file mode 100644 index 0000000..2ccc0d1 --- /dev/null +++ b/2023/days/06/src/part2.rs @@ -0,0 +1,16 @@ +use crate::parse::*; + +pub fn part2(input: Race) -> u64 { + input.num_ways_to_win() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part2() { + let input = Race{ time: 71530, record: 940200 }; + assert_eq!(part2(input), 71503); + } +} diff --git a/2023/days/07/Cargo.toml b/2023/days/07/Cargo.toml new file mode 100644 index 0000000..3c8d1de --- /dev/null +++ b/2023/days/07/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "day07" +authors.workspace = true +description.workspace = true +version.workspace = true +edition.workspace = true + +[dependencies] +aoc_libs.workspace = true +itertools.workspace = true diff --git a/2023/days/07/src/input.txt b/2023/days/07/src/input.txt new file mode 100644 index 0000000..356ce59 --- /dev/null +++ b/2023/days/07/src/input.txt @@ -0,0 +1,1000 @@ +536K8 291 +3T3T3 802 +5872Q 265 +K98Q4 232 +292A9 349 +825JJ 785 +68K48 521 +94A44 358 +J8JJ3 490 +7KJA8 510 +K786T 501 +QQ968 560 +8Q58J 395 +JAAJA 308 +8T7TA 2 +T5T56 216 +6Q877 398 +949QT 406 +AKJ93 400 +JK22J 414 +6AA6A 384 +68666 820 +99A99 72 +8884J 273 +97888 881 +7727T 421 +T3A43 942 +QTQTT 429 +44J29 244 +QKKKQ 537 +KK99K 51 +3333A 307 +A8AJA 721 +J7297 731 +544Q7 770 +73337 562 +226Q6 34 +5A666 857 +Q88J4 460 +97724 586 +ATA77 444 +42TTT 930 +76667 193 +43443 538 +K9994 927 +488K8 153 +33223 798 +T999A 831 +3983T 819 +227JJ 977 +79999 924 +2AQ93 778 +QQQQ4 573 +TQTQJ 367 +8A8AA 68 +44J24 279 +Q6AAQ 74 +JAQK4 709 +J355T 867 +J6666 773 +6AA63 593 +88485 626 +66965 368 +88JKJ 412 +T4T7T 467 +2A2A2 482 +77Q8Q 95 +6Q685 178 +KJ7Q3 812 +5892A 536 +837K7 266 +TQQ44 165 +QQJ73 868 +7A779 494 +77776 231 +8K264 504 +55552 900 +4AQK8 425 +QJQQ5 257 +3222T 945 +92299 603 +AK799 751 +7T5Q9 209 +88J8J 484 +TAJA9 992 +TT2TT 962 +A477A 864 +859JA 995 +J3A7A 156 +99977 580 +J5522 391 +Q6464 465 +85888 515 +7J272 954 +K6T6T 461 +TT797 534 +8Q48K 990 +69898 342 +Q979J 332 +666TT 840 +82522 793 +J888K 730 +4JJ8K 667 +AK893 415 +2992J 622 +Q74QQ 591 +9AQJ6 195 +9TT9T 409 +66JQ6 735 +33A7J 60 +5QA89 643 +49A99 327 +97JJ9 131 +2K86J 1000 +66557 320 +65666 117 +AQQQQ 362 +639K9 727 +T9996 418 +7J773 167 +J2883 666 +683Q8 697 +2T228 984 +J2332 250 +8J882 258 +47T38 397 +QQQ44 130 +73ATQ 53 +94494 685 +8263J 157 +5A228 89 +56456 462 +KK2KK 48 +9QQKK 448 +Q8878 470 +82J77 294 +35735 952 +84838 387 +9K2AT 592 +AJ999 815 +99J99 539 +KKKK8 443 +77969 674 +55556 65 +TTJJA 738 +KK4K4 599 +5J5K6 162 +88555 797 +9J89K 411 +K58K5 47 +TJQ2T 477 +2A324 401 +66K66 854 +668T6 822 +9J9K9 579 +93AQ6 662 +J7693 755 +JT63A 430 +55536 242 +698K8 369 +54544 211 +884A4 161 +4J999 713 +47466 800 +9T57K 519 +34TT4 883 +44JJ4 476 +99272 789 +76862 432 +7TT4Q 378 +3K724 918 +A6JT5 931 +885J5 380 +38888 636 +J55J9 687 +AJ4QJ 627 +372AT 681 +9QQ3Q 253 +3A433 334 +AQTK6 936 +44QQ4 825 +J2J77 309 +8T88A 858 +39323 393 +T4994 428 +259K6 208 +66A6A 568 +2K8K2 966 +423KJ 587 +42884 263 +977T9 363 +K33K3 493 +726T4 782 +T5396 948 +82833 878 +3636J 873 +72572 640 +2975T 670 +5Q57Q 832 +TK39A 506 +JTK9T 916 +5333T 968 +TQKQK 183 +3JAJ2 631 +5Q5Q5 191 +35Q3A 351 +J5AT5 823 +77747 249 +3QQQ4 399 +7J3KA 427 +K77J7 52 +946Q5 112 +T996Q 464 +7J757 876 +A9AKA 483 +JQK82 238 +6J45K 641 +AAAAQ 453 +4AAAA 704 +23A95 512 +23Q57 979 +75777 347 +27QK9 806 +K5K76 126 +KTTKT 79 +76945 522 +J7793 442 +7865T 433 +53Q2K 481 +Q5Q99 339 +5T2JJ 124 +93353 928 +99JAT 673 +85T96 839 +A7777 49 +TTT65 898 +J6234 618 +99594 891 +448J8 748 +2J55T 722 +59575 164 +45745 4 +5TT53 35 +QJ36A 469 +57752 502 +QQQ5Q 222 +72QQ4 13 +846AQ 611 +96JKT 102 +AJ672 693 +3754J 774 +8499Q 321 +A6K4A 93 +6724Q 694 +J88T8 174 +77A7J 548 +28828 671 +58J3J 886 +77J5J 389 +3KQKK 747 +96J9A 149 +94326 360 +A84J7 644 +AKAK8 116 +47724 498 +646A9 988 +QAQ9Q 39 +37Q77 635 +83J84 98 +3J6T6 316 +898AT 542 +TT33Q 872 +A4544 610 +465K8 540 +J229J 921 +QQQ77 86 +A393A 413 +A5T2T 894 +9TA33 264 +33354 459 +6Q44A 471 +23479 168 +78T77 875 +88T8T 902 +9KKKK 479 +23TQJ 612 +2A789 333 +35444 827 +J3T7Q 620 +78JQA 870 +KKKJK 816 +98888 114 +55755 240 +9JKTQ 972 +99786 436 +53JQ4 714 +365Q6 695 +A99JQ 684 +78Q48 297 +4J777 245 +778A3 795 +9TJ99 869 +66249 394 +63663 550 +8A82A 111 +88829 577 +6Q66Q 454 +5552A 608 +99JT7 340 +75376 169 +5QKKQ 843 +KQ49Q 582 +8934K 981 +64374 452 +7727Q 784 +5Q57K 500 +Q2277 525 +T423A 27 +2Q3K3 69 +8K2A7 554 +6KJ9Q 201 +68T45 455 +Q8989 318 +75A76 656 +88K29 563 +JQ268 396 +33777 653 +6J746 715 +89889 913 +7KJT6 85 +58437 26 +3J374 440 +A344A 96 +K3377 760 +422K2 892 +77676 219 +4844J 893 +86665 243 +J35K4 261 +6JJ66 669 +T8484 908 +J9A38 909 +K2689 57 +T4444 472 +TJ37T 301 +A44J4 210 +4Q3A6 306 +746T8 826 +88TTT 765 +T695J 761 +22255 783 +Q8KKJ 808 +86323 561 +58A64 997 +8888J 214 +KJKTK 595 +68484 235 +7QT7Q 617 +39J39 159 +JJ8J8 682 +4T57J 233 +AJ99A 81 +Q28T6 488 +3J2J9 706 +6A356 382 +AJA77 300 +26424 889 +QAA99 584 +897K7 28 +Q29A6 71 +TT366 144 +42898 767 +77A7A 247 +2KT23 941 +72229 555 +3245A 381 +7AQT6 434 +22AAJ 845 +333AJ 926 +A4777 897 +22772 298 +J3838 225 +34K5A 734 +AQ7Q9 423 +T27TJ 33 +T5352 417 +326K6 851 +83J73 754 +454J4 594 +K7KK7 70 +AKQT3 964 +44834 907 +94889 724 +J3J87 91 +Q26T5 955 +8Q888 370 +KK96K 277 +82826 344 +64696 492 +K553T 456 +8Q84Q 445 +TTT37 110 +9999Q 707 +A3282 719 +5KKKK 865 +2AA3A 325 +93993 239 +QQQAA 58 +289TK 824 +9595J 691 +954K2 326 +38AA5 63 +A37Q4 66 +TT7JT 230 +K44K4 982 +T8725 910 +KK5K9 986 +22J2J 290 +75Q69 353 +4444J 998 +2AK24 764 +K958K 138 +69999 78 +K66J6 686 +4TTT8 978 +99J88 466 +4Q28K 794 +K5Q68 198 +9J452 862 +66868 885 +Q5248 148 +Q2522 675 +AK576 523 +83KJT 376 +29A98 659 +35535 850 +54225 228 +85K55 634 +5394T 152 +4QQ42 814 +JAKAK 999 +ATTT8 632 +42K2K 650 +AKAK7 701 +TK653 588 +222TT 404 +Q7777 11 +9449Q 629 +A8K82 949 +33335 207 +KA6AQ 204 +Q4AQT 435 +63638 757 +A78TK 446 +7327Q 938 +JJJJJ 571 +TKKKK 505 +9474A 184 +A5T8K 55 +9QQ2A 286 +66669 969 +32992 692 +55J55 431 +AJTTT 810 +JQ369 365 +QJAKA 312 +3959Q 786 +AKKAK 528 +Q2Q28 25 +AKQKQ 678 +2266A 94 +234K5 246 +AA8AA 136 +64626 474 +2Q676 287 +TA33J 163 +K9KKT 468 +A345J 664 +JJ2JJ 920 +9KKJK 564 +JK6J8 278 +279Q2 408 +TJ777 683 +8KJ63 507 +2AAA2 917 +99499 274 +3AQ52 64 +JJJJ8 217 +77878 589 +KQ4A7 101 +8AQA5 186 +T5555 379 +TJT88 267 +8K888 129 +22KKT 292 +AAAQK 215 +26Q3J 170 +76679 192 +J9333 717 +JT99T 828 +A9887 503 +22922 139 +JKKJ4 759 +88J78 45 +94KKQ 637 +TT32K 280 +K45K4 752 +23244 348 +5K743 690 +8AQA8 566 +5JJAA 863 +TT8A3 50 +A6776 103 +3Q3Q3 108 +A95J3 106 +ATTAT 145 +83AJT 38 +JQJQQ 218 +66Q74 84 +77875 424 +J844J 597 +27Q8K 172 +8QQQ5 357 +52QJJ 991 +66555 965 +393T9 495 +7453T 766 +K65KK 441 +8A78A 223 +33635 92 +4K244 533 +95955 337 +659Q2 329 +7JQQK 372 +9A99A 605 +7JKAK 100 +923T7 652 +74444 939 +39776 529 +5T79T 710 +26662 275 +9TT8T 226 +7K22K 837 +37829 609 +773JJ 29 +QAAJA 335 +8TTTT 996 +AJAA2 352 +47559 552 +46AJJ 957 +55K55 8 +J267K 30 +594A6 788 +6JQ67 657 +44QK3 76 +88448 558 +7777K 601 +J9J99 663 +88833 585 +K26K2 700 +Q63JT 676 +28525 392 +777JJ 237 +4KK8J 346 +66366 166 +AKKK2 744 +AK7AJ 711 +KAAAA 288 +A5757 132 +29835 107 +754A4 805 +JQKA7 187 +Q88KJ 151 +439KT 82 +93J99 343 +66683 654 +28227 882 +JJ555 366 +JJ992 17 +4TAKA 416 +Q7T43 677 +778J8 109 +J6662 386 +38TTT 31 +53Q3Q 821 +JJ66J 648 +44A4A 80 +TTTT4 852 +88887 311 +52K74 177 +77746 310 +KA444 787 +66266 42 +99JQ9 660 +Q3A9K 590 +6636J 113 +4Q234 855 +J377Q 289 +99992 313 +9Q985 547 +J6959 959 +6K3AJ 905 +355A5 884 +6K5Q2 426 +36KKJ 83 +87777 749 +84A9T 572 +2KKJ2 105 +4J446 385 +Q3333 901 +8535Q 912 +T8868 638 +39999 842 +2Q7JQ 296 +T7Q6K 614 +37357 613 +T422T 647 +K6TTQ 943 +37686 565 +Q99A9 439 +59J99 624 +85A3T 628 +T3T25 438 +K2T72 874 +TTJTT 324 +4JK42 405 +T6T26 625 +3JKKT 205 +JKKJK 227 +87J74 725 +KKKK3 518 +KQ8A9 768 +AAAA9 736 +542TK 847 +33363 268 +989KK 77 +64T9K 771 +38KJK 578 +7333J 137 +TT3T6 746 +86766 419 +KKKKQ 817 +AJTK5 642 +5TK55 37 +KQT6Q 62 +K66Q6 480 +QQ449 958 +KQK44 803 +226K6 141 +Q8Q8Q 762 +84448 877 +95977 14 +Q266A 947 +47K93 374 +574T6 835 +57888 732 +QAK34 769 +67699 388 +9A9AA 373 +QQ23Q 809 +J4QKQ 12 +6666T 350 +J838T 922 +7A775 23 +73433 526 +32255 792 +T3J3J 75 +K656K 741 +K9447 556 +QJQ9Q 801 +4J545 32 +4JK87 314 +7K7KT 173 +TT9A2 739 +6QQ6A 698 +67JA6 546 +3J94T 929 +588AQ 248 +JKA44 950 +33878 983 +54484 569 +7777J 447 +T4JA2 811 +77495 919 +K3T33 606 +AK7AA 903 +KQ96T 229 +7QTJQ 545 +Q453T 776 +TTT3T 190 +JAKKT 450 +K9J94 985 +72787 520 +5QJ86 848 +9QQ9Q 202 +2TTJT 383 +23A33 703 +KT2KT 781 +88333 181 +95299 236 +J889A 356 +Q7336 302 +A2AJQ 175 +68TAJ 976 +T6J33 176 +T97K9 914 +363K6 281 +A2579 975 +67897 203 +555JT 147 +KT2T2 777 +J2524 541 +5K238 19 +55JA5 128 +ATA22 20 +2J222 364 +57T7T 860 +45922 276 +99A96 544 +K7KKK 689 +4278A 322 +78QQQ 234 +999TQ 602 +7J989 299 +6J468 3 +5K445 887 +64A57 559 +JK2TQ 221 +6A323 87 +QQ5Q6 607 +4448Q 271 +T3333 937 +74477 402 +99TT9 284 +J83J8 696 +AK99K 600 +2AT62 473 +88755 119 +QQ2QQ 796 +K85K2 543 +4K4J4 818 +JTQ2Q 407 +TT767 56 +67376 956 +59656 726 +K8KJ8 830 +55JTT 933 +333A7 194 +234T8 527 +74ATA 146 +7777T 799 +JA33A 596 +K7444 575 +3676J 973 +76227 104 +5TJKT 646 +868K8 630 +A6TAA 422 +JQK55 43 +548Q5 829 +4JK9Q 557 +J88AA 154 +9JQ76 403 +75899 61 +QQQTT 361 +27664 517 +A58JA 123 +32A32 514 +J3AJK 953 +55558 961 +366Q3 99 +22QQ2 772 +64646 633 +693KA 143 +66A76 21 +384KQ 475 +Q88Q8 142 +922KK 980 +3K33J 345 +AATAT 866 +93T5Q 598 +24222 716 +6K6A6 449 +3JQ3Q 135 +AJ855 888 +8QT46 260 +5Q7TK 895 +2J2K2 615 +55955 293 +539T5 9 +TJTJT 158 +QQ2J2 341 +QJQQ6 915 +K24K9 121 +TTTT6 390 +35533 906 +4TKAQ 904 +K22KQ 241 +Q422Q 688 +JJ333 804 +K8K5J 745 +44662 896 +4A93J 763 +4QJQ9 720 +Q4J36 256 +44T47 853 +QQQQ3 67 +8539T 661 +555Q5 496 +99696 516 +K7K97 5 +QQ677 923 +J892Q 679 +T4T47 649 +8A888 699 +79228 665 +898Q7 328 +5JKQJ 934 +K27K8 790 +799T2 196 +J2JTT 639 +4Q872 993 +5494Q 672 +68Q88 122 +82KK6 497 +QQ64T 775 +4J55Q 120 +KKKK4 524 +K8KK2 371 +6J6J4 478 +6QQQQ 743 +25QJQ 259 +9Q33Q 574 +999K9 750 +K4Q2K 463 +KT7TT 974 +2Q82K 621 +T77QA 833 +J6656 723 +AJ596 487 +A9Q98 206 +2A4K5 485 +9929J 377 +J59K6 336 +9JQ58 10 +JQQ66 46 +KK77A 220 +8K88K 570 +76T7J 185 +986T7 807 +44TJT 836 +J8662 283 +93457 619 +5K5A6 269 +K92T7 15 +3J295 16 +A5556 951 +J4KAA 742 +KKKJ7 791 +9Q879 118 +TKT33 946 +KK5K2 645 +83T4K 41 +K7Q2J 712 +99Q9Q 451 +58355 491 +6Q7T8 680 +5T3TT 199 +Q577A 188 +KTK3T 551 +Q664Q 359 +49383 22 +QT626 354 +T6TT6 73 +724K9 737 +AAA7A 530 +3KAA3 375 +3KK3K 994 +9A992 133 +QK5K7 971 +QJQ26 88 +82782 989 +TA59Q 967 +33233 553 +KQ246 963 +5J389 1 +333J3 270 +ATQQQ 150 +A77TT 140 +KK525 182 +TA4J8 871 +2T92T 262 +8K6A5 576 +9JJ36 319 +2Q883 970 +79877 134 +6J676 940 +55459 838 +43444 756 +48945 655 +KJ997 295 +9Q65K 623 +34KQT 879 +38282 549 +T892Q 844 +Q8KAK 849 +8TT68 315 +33AAA 338 +3TTT3 944 +TTTQT 718 +44TA9 733 +396Q3 780 +5A427 18 +TQAKJ 668 +99J79 658 +8833Q 513 +TTTAT 304 +T5558 252 +9T999 960 +JQQQQ 331 +888J3 255 +JQQ8J 753 +T5554 282 +A4928 90 +48TT7 303 +K889Q 457 +63A3A 44 +97935 224 +6K5A9 583 +AJ955 531 +78448 251 +QJT99 200 +T344J 708 +TT65J 813 +K999K 758 +4T634 486 +78JQ8 36 +9J86J 859 +94JJ9 189 +Q4JQ4 458 +6438A 180 +3645K 509 +T22J2 7 +9K992 272 +JAAAT 581 +AA262 197 +K996K 127 +99899 254 +55TTT 729 +4T9JA 834 +TAA5A 125 +JQ925 511 +9K895 846 +89899 305 +7J787 59 +77977 651 +J5A49 616 +Q3993 323 +3A3TT 567 +89388 212 +KKKK6 740 +8T79T 779 +A7AA7 702 +QQ2Q2 880 +48396 6 +33373 155 +9K73T 932 +KJTJT 728 +TK424 935 +64666 160 +3K337 499 +76337 890 +AAAA2 420 +KAJ32 987 +3K333 925 +66655 911 +QK54J 437 +7JJKA 40 +Q5Q5Q 489 +QQ84Q 355 +8K66K 330 +QTTTJ 899 +JJQJQ 171 +4688T 54 +AAAAJ 604 +5K6KJ 24 +54554 856 +K2K2K 535 +A5AAA 285 +385JK 213 +64T89 705 +K4K46 841 +288Q9 410 +39AAJ 97 +9Q48A 115 +8448K 861 +Q33QQ 508 +J8A2A 317 +A92AJ 179 +2222Q 532 diff --git a/2023/days/07/src/main.rs b/2023/days/07/src/main.rs new file mode 100644 index 0000000..2be664b --- /dev/null +++ b/2023/days/07/src/main.rs @@ -0,0 +1,14 @@ +mod part1; +mod part2; +mod parse; + +fn main() { + let input = include_str!("./input.txt"); + let mut structured_input = parse::parse(input); + + println!("Part One"); + println!("Result: {}", part1::part1(&mut structured_input)); + + println!("Part Two"); + println!("Result: {}", part2::part2(&mut structured_input)); +} diff --git a/2023/days/07/src/parse.rs b/2023/days/07/src/parse.rs new file mode 100644 index 0000000..70818a1 --- /dev/null +++ b/2023/days/07/src/parse.rs @@ -0,0 +1,648 @@ +use itertools::Itertools; + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] +pub enum Card { + Ace = 14, + King = 13, + Queen = 12, + Jack = 11, + Tim = 10, + Nine = 9, + Eight = 8, + Seven = 7, + Six = 6, + Five = 5, + Four = 4, + Three = 3, + Two = 2, + Joker = 1, +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] +pub enum Formation { + FiveOfKind = 7, + FourOfKind = 6, + FullHouse = 5, + ThreeOfKind = 4, + TwoPair = 3, + OnePair = 2, + HighCard = 1, +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct Hand { + formation: Formation, + cards: [Card; 5], +} + +impl Hand { + pub fn new(cards: [Card; 5]) -> Hand { + Hand { + formation: Self::determine_formation(&cards), + cards, + } + } + fn determine_formation(cards: &[Card; 5]) -> Formation { + let mut counts = cards.iter().counts(); + let jokers = counts.remove(&Card::Joker).unwrap_or(0); + let types = counts.len(); + let max_of_type = counts.into_values().max().unwrap_or(0) + jokers; + match types { + // if 0 types, they are all joker. + 0 => Formation::FiveOfKind, + 1 => Formation::FiveOfKind, + 2 => { + // if there are 4 of 1 kind, doesnt matter what the other card is. If there are + // three of a kind but only 2 card types, the other 2 must be a pair. + match max_of_type { + 4 => Formation::FourOfKind, + 3 => Formation::FullHouse, + _ => panic!("idk what type of hand this is: {:?}", cards), + } + } + 3 => { + // if there are 3 types, it could either be three of a kind, or two pair. + match max_of_type { + 3 => Formation::ThreeOfKind, + 2 => Formation::TwoPair, + _ => panic!("idk what type of hand this is: {:?}", cards), + } + } + 4 => Formation::OnePair, + 5 => Formation::HighCard, + _ => panic!("how are there more than 5 types!"), + } + } + pub fn turn_jacks_to_jokers(&mut self) { + self.cards = self + .cards + .map(|c| if c == Card::Jack { Card::Joker } else { c }); + } +} + +pub fn parse(input: &str) -> Vec<(Hand, u32)> { + input + .lines() + .map(|line| { + let mut splits = line.split(' '); + let hand = splits.next().unwrap(); + let bid: u32 = splits.next().unwrap().parse().unwrap(); + let hand: Vec = hand + .chars() + .map(|c| match c { + 'A' => Card::Ace, + 'K' => Card::King, + 'Q' => Card::Queen, + 'J' => Card::Jack, + 'T' => Card::Tim, + '9' => Card::Nine, + '8' => Card::Eight, + '7' => Card::Seven, + '6' => Card::Six, + '5' => Card::Five, + '4' => Card::Four, + '3' => Card::Three, + '2' => Card::Two, + e => panic!("invalid card {}", e), + }) + .collect(); + (Hand::new(hand.try_into().unwrap()), bid) + }) + .collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_ord_with_joker_conversion() { + let mut input = vec![ + ( + Hand::new([Card::Two, Card::Three, Card::Four, Card::Five, Card::Ace]), + 1, + ), + ( + Hand::new([Card::Queen, Card::Two, Card::King, Card::Joker, Card::Joker]), + 13, + ), + ( + Hand::new([Card::Queen, Card::Two, Card::Queen, Card::Two, Card::Queen]), + 19, + ), + ( + Hand::new([Card::Tim, Card::Three, Card::Tim, Card::Three, Card::Joker]), + 17, + ), + ( + Hand::new([ + Card::Tim, + Card::Three, + Card::Queen, + Card::Three, + Card::Three, + ]), + 11, + ), + ( + Hand::new([Card::Two, Card::Three, Card::Four, Card::Five, Card::Joker]), + 3, + ), + ( + Hand::new([Card::Joker, Card::Three, Card::Four, Card::Five, Card::Ace]), + 2, + ), + ( + Hand::new([Card::Three, Card::Two, Card::Tim, Card::Three, Card::King]), + 5, + ), + ( + Hand::new([Card::Tim, Card::Five, Card::Five, Card::Joker, Card::Five]), + 29, + ), + ( + Hand::new([Card::King, Card::King, Card::Six, Card::Seven, Card::Seven]), + 7, + ), + ( + Hand::new([Card::King, Card::Tim, Card::Joker, Card::Joker, Card::Tim]), + 34, + ), + ( + Hand::new([ + Card::Queen, + Card::Queen, + Card::Queen, + Card::Joker, + Card::Ace, + ]), + 31, + ), + ( + Hand::new([ + Card::Joker, + Card::Joker, + Card::Joker, + Card::Joker, + Card::Joker, + ]), + 37, + ), + ( + Hand::new([Card::Joker, Card::Ace, Card::Ace, Card::Ace, Card::Ace]), + 43, + ), + ( + Hand::new([Card::Ace, Card::Ace, Card::Ace, Card::Ace, Card::Joker]), + 59, + ), + ( + Hand::new([Card::Ace, Card::Ace, Card::Ace, Card::Ace, Card::Ace]), + 61, + ), + ( + Hand::new([Card::Two, Card::Ace, Card::Ace, Card::Ace, Card::Ace]), + 23, + ), + ( + Hand::new([ + Card::Two, + Card::Joker, + Card::Joker, + Card::Joker, + Card::Joker, + ]), + 53, + ), + ( + Hand::new([ + Card::Joker, + Card::Joker, + Card::Joker, + Card::Joker, + Card::Two, + ]), + 41, + ), + ]; + input.iter_mut().for_each(|i| i.0.turn_jacks_to_jokers()); + input.sort_by(|a, b| a.0.cmp(&b.0)); + println!("{:#?}", input); + //check that the bids are sorted (the input is curated to ensure that the bids are sorted + //when the hands are sorted.) + assert!(input.windows(2).all(|w| w[0].1 <= w[1].1)) + } + + #[test] + fn test_determine_formation_after_joker_conversion() { + let mut tests = vec![ + ( + Hand::new([Card::Two, Card::Three, Card::Four, Card::Five, Card::Ace]), + Formation::HighCard, + ), + ( + Hand::new([Card::Queen, Card::Two, Card::King, Card::Joker, Card::Joker]), + Formation::ThreeOfKind, + ), + ( + Hand::new([Card::Queen, Card::Two, Card::Queen, Card::Two, Card::Queen]), + Formation::FullHouse, + ), + ( + Hand::new([Card::Tim, Card::Three, Card::Tim, Card::Three, Card::Joker]), + Formation::FullHouse, + ), + ( + Hand::new([ + Card::Tim, + Card::Three, + Card::Queen, + Card::Three, + Card::Three, + ]), + Formation::ThreeOfKind, + ), + ( + Hand::new([Card::Two, Card::Three, Card::Four, Card::Five, Card::Joker]), + Formation::OnePair, + ), + ( + Hand::new([Card::Joker, Card::Three, Card::Four, Card::Five, Card::Ace]), + Formation::OnePair, + ), + ( + Hand::new([Card::Three, Card::Two, Card::Tim, Card::Three, Card::King]), + Formation::OnePair, + ), + ( + Hand::new([Card::Tim, Card::Five, Card::Five, Card::Joker, Card::Five]), + Formation::FourOfKind, + ), + ( + Hand::new([Card::King, Card::King, Card::Six, Card::Seven, Card::Seven]), + Formation::TwoPair, + ), + ( + Hand::new([Card::King, Card::Tim, Card::Joker, Card::Joker, Card::Tim]), + Formation::FourOfKind, + ), + ( + Hand::new([ + Card::Queen, + Card::Queen, + Card::Queen, + Card::Joker, + Card::Ace, + ]), + Formation::FourOfKind, + ), + ( + Hand::new([ + Card::Joker, + Card::Joker, + Card::Joker, + Card::Joker, + Card::Joker, + ]), + Formation::FiveOfKind, + ), + ( + Hand::new([Card::Joker, Card::Ace, Card::Ace, Card::Ace, Card::Ace]), + Formation::FiveOfKind, + ), + ( + Hand::new([Card::Ace, Card::Ace, Card::Ace, Card::Ace, Card::Joker]), + Formation::FiveOfKind, + ), + ( + Hand::new([Card::Ace, Card::Ace, Card::Ace, Card::Ace, Card::Ace]), + Formation::FiveOfKind, + ), + ( + Hand::new([Card::Two, Card::Ace, Card::Ace, Card::Ace, Card::Ace]), + Formation::FourOfKind, + ), + ( + Hand::new([ + Card::Two, + Card::Joker, + Card::Joker, + Card::Joker, + Card::Joker, + ]), + Formation::FiveOfKind, + ), + ( + Hand::new([ + Card::Joker, + Card::Joker, + Card::Joker, + Card::Joker, + Card::Two, + ]), + Formation::FiveOfKind, + ), + ]; + tests.iter_mut().for_each(|i| i.0.turn_jacks_to_jokers()); + for test in tests { + assert_eq!(test.0.formation, test.1) + } + } + + #[test] + fn test_ord() { + let mut input = vec![ + ( + Hand::new([Card::Two, Card::Three, Card::Four, Card::Five, Card::Ace]), + 1, + ), + ( + Hand::new([Card::Queen, Card::Two, Card::King, Card::Jack, Card::Jack]), + 13, + ), + ( + Hand::new([Card::Queen, Card::Two, Card::Queen, Card::Two, Card::Queen]), + 19, + ), + ( + Hand::new([Card::Tim, Card::Three, Card::Tim, Card::Three, Card::Jack]), + 17, + ), + ( + Hand::new([ + Card::Tim, + Card::Three, + Card::Queen, + Card::Three, + Card::Three, + ]), + 11, + ), + ( + Hand::new([Card::Two, Card::Three, Card::Four, Card::Five, Card::Jack]), + 3, + ), + ( + Hand::new([Card::Jack, Card::Three, Card::Four, Card::Five, Card::Ace]), + 2, + ), + ( + Hand::new([Card::Three, Card::Two, Card::Tim, Card::Three, Card::King]), + 5, + ), + ( + Hand::new([Card::Tim, Card::Five, Card::Five, Card::Jack, Card::Five]), + 29, + ), + ( + Hand::new([Card::King, Card::King, Card::Six, Card::Seven, Card::Seven]), + 7, + ), + ( + Hand::new([Card::King, Card::Tim, Card::Jack, Card::Jack, Card::Tim]), + 34, + ), + ( + Hand::new([Card::Queen, Card::Queen, Card::Queen, Card::Jack, Card::Ace]), + 31, + ), + ( + Hand::new([Card::Jack, Card::Jack, Card::Jack, Card::Jack, Card::Jack]), + 37, + ), + ( + Hand::new([Card::Jack, Card::Ace, Card::Ace, Card::Ace, Card::Ace]), + 43, + ), + ( + Hand::new([Card::Ace, Card::Ace, Card::Ace, Card::Ace, Card::Jack]), + 59, + ), + ( + Hand::new([Card::Ace, Card::Ace, Card::Ace, Card::Ace, Card::Ace]), + 61, + ), + ( + Hand::new([Card::Two, Card::Ace, Card::Ace, Card::Ace, Card::Ace]), + 23, + ), + ( + Hand::new([Card::Two, Card::Jack, Card::Jack, Card::Jack, Card::Jack]), + 53, + ), + ( + Hand::new([Card::Jack, Card::Jack, Card::Jack, Card::Jack, Card::Two]), + 41, + ), + ]; + input.sort_by(|a, b| a.0.cmp(&b.0)); + println!("{:#?}", input); + assert_eq!( + input.iter().map(|h| h.1).collect::>(), + vec![3, 1, 2, 5, 13, 17, 34, 7, 11, 29, 31, 19, 53, 23, 41, 43, 59, 37, 61] + ) + } + + #[test] + fn test_determine_formation() { + let tests = vec![ + ( + Hand::new([Card::Two, Card::Three, Card::Four, Card::Five, Card::Ace]), + Formation::HighCard, + ), + ( + Hand::new([Card::Queen, Card::Two, Card::King, Card::Jack, Card::Jack]), + Formation::OnePair, + ), + ( + Hand::new([Card::Queen, Card::Two, Card::Queen, Card::Two, Card::Queen]), + Formation::FullHouse, + ), + ( + Hand::new([Card::Tim, Card::Three, Card::Tim, Card::Three, Card::Jack]), + Formation::TwoPair, + ), + ( + Hand::new([ + Card::Tim, + Card::Three, + Card::Queen, + Card::Three, + Card::Three, + ]), + Formation::ThreeOfKind, + ), + ( + Hand::new([Card::Two, Card::Three, Card::Four, Card::Five, Card::Jack]), + Formation::HighCard, + ), + ( + Hand::new([Card::Jack, Card::Three, Card::Four, Card::Five, Card::Ace]), + Formation::HighCard, + ), + ( + Hand::new([Card::Three, Card::Two, Card::Tim, Card::Three, Card::King]), + Formation::OnePair, + ), + ( + Hand::new([Card::Tim, Card::Five, Card::Five, Card::Jack, Card::Five]), + Formation::ThreeOfKind, + ), + ( + Hand::new([Card::King, Card::King, Card::Six, Card::Seven, Card::Seven]), + Formation::TwoPair, + ), + ( + Hand::new([Card::King, Card::Tim, Card::Jack, Card::Jack, Card::Tim]), + Formation::TwoPair, + ), + ( + Hand::new([Card::Queen, Card::Queen, Card::Queen, Card::Jack, Card::Ace]), + Formation::ThreeOfKind, + ), + ( + Hand::new([Card::Jack, Card::Jack, Card::Jack, Card::Jack, Card::Jack]), + Formation::FiveOfKind, + ), + ( + Hand::new([Card::Jack, Card::Ace, Card::Ace, Card::Ace, Card::Ace]), + Formation::FourOfKind, + ), + ( + Hand::new([Card::Ace, Card::Ace, Card::Ace, Card::Ace, Card::Jack]), + Formation::FourOfKind, + ), + ( + Hand::new([Card::Ace, Card::Ace, Card::Ace, Card::Ace, Card::Ace]), + Formation::FiveOfKind, + ), + ( + Hand::new([Card::Two, Card::Ace, Card::Ace, Card::Ace, Card::Ace]), + Formation::FourOfKind, + ), + ( + Hand::new([Card::Two, Card::Jack, Card::Jack, Card::Jack, Card::Jack]), + Formation::FourOfKind, + ), + ( + Hand::new([Card::Jack, Card::Jack, Card::Jack, Card::Jack, Card::Two]), + Formation::FourOfKind, + ), + ]; + for test in tests { + assert_eq!(test.0.formation, test.1) + } + } + + #[test] + fn test_parse() { + let input = concat!( + "2345A 1\n", + "Q2KJJ 13\n", + "Q2Q2Q 19\n", + "T3T3J 17\n", + "T3Q33 11\n", + "2345J 3\n", + "J345A 2\n", + "32T3K 5\n", + "T55J5 29\n", + "KK677 7\n", + "KTJJT 34\n", + "QQQJA 31\n", + "JJJJJ 37\n", + "JAAAA 43\n", + "AAAAJ 59\n", + "AAAAA 61\n", + "2AAAA 23\n", + "2JJJJ 53\n", + "JJJJ2 41\n", + ); + assert_eq!( + parse(input), + vec![ + ( + Hand::new([Card::Two, Card::Three, Card::Four, Card::Five, Card::Ace]), + 1 + ), + ( + Hand::new([Card::Queen, Card::Two, Card::King, Card::Jack, Card::Jack]), + 13 + ), + ( + Hand::new([Card::Queen, Card::Two, Card::Queen, Card::Two, Card::Queen]), + 19 + ), + ( + Hand::new([Card::Tim, Card::Three, Card::Tim, Card::Three, Card::Jack]), + 17 + ), + ( + Hand::new([ + Card::Tim, + Card::Three, + Card::Queen, + Card::Three, + Card::Three + ]), + 11 + ), + ( + Hand::new([Card::Two, Card::Three, Card::Four, Card::Five, Card::Jack]), + 3 + ), + ( + Hand::new([Card::Jack, Card::Three, Card::Four, Card::Five, Card::Ace]), + 2 + ), + ( + Hand::new([Card::Three, Card::Two, Card::Tim, Card::Three, Card::King]), + 5 + ), + ( + Hand::new([Card::Tim, Card::Five, Card::Five, Card::Jack, Card::Five]), + 29 + ), + ( + Hand::new([Card::King, Card::King, Card::Six, Card::Seven, Card::Seven]), + 7 + ), + ( + Hand::new([Card::King, Card::Tim, Card::Jack, Card::Jack, Card::Tim]), + 34 + ), + ( + Hand::new([Card::Queen, Card::Queen, Card::Queen, Card::Jack, Card::Ace]), + 31 + ), + ( + Hand::new([Card::Jack, Card::Jack, Card::Jack, Card::Jack, Card::Jack]), + 37 + ), + ( + Hand::new([Card::Jack, Card::Ace, Card::Ace, Card::Ace, Card::Ace]), + 43 + ), + ( + Hand::new([Card::Ace, Card::Ace, Card::Ace, Card::Ace, Card::Jack]), + 59 + ), + ( + Hand::new([Card::Ace, Card::Ace, Card::Ace, Card::Ace, Card::Ace]), + 61 + ), + ( + Hand::new([Card::Two, Card::Ace, Card::Ace, Card::Ace, Card::Ace]), + 23 + ), + ( + Hand::new([Card::Two, Card::Jack, Card::Jack, Card::Jack, Card::Jack]), + 53 + ), + ( + Hand::new([Card::Jack, Card::Jack, Card::Jack, Card::Jack, Card::Two]), + 41 + ) + ] + ); + } +} diff --git a/2023/days/07/src/part1.rs b/2023/days/07/src/part1.rs new file mode 100644 index 0000000..2bc8791 --- /dev/null +++ b/2023/days/07/src/part1.rs @@ -0,0 +1,104 @@ +use crate::parse::*; + +pub fn part1(input: &mut [(Hand, u32)]) -> usize { + input.sort_by(|a, b| a.0.cmp(&b.0) ); + input + .iter() + .enumerate() + .map(|i| (i.0 + 1) * i.1 .1 as usize) + .sum() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part1() { + let mut input = vec![ + ( + Hand::new([Card::Two, Card::Three, Card::Four, Card::Five, Card::Ace]), + 1, + ), + ( + Hand::new([Card::Queen, Card::Two, Card::King, Card::Jack, Card::Jack]), + 13, + ), + ( + Hand::new([Card::Queen, Card::Two, Card::Queen, Card::Two, Card::Queen]), + 19, + ), + ( + Hand::new([Card::Tim, Card::Three, Card::Tim, Card::Three, Card::Jack]), + 17, + ), + ( + Hand::new([ + Card::Tim, + Card::Three, + Card::Queen, + Card::Three, + Card::Three, + ]), + 11, + ), + ( + Hand::new([Card::Two, Card::Three, Card::Four, Card::Five, Card::Jack]), + 3, + ), + ( + Hand::new([Card::Jack, Card::Three, Card::Four, Card::Five, Card::Ace]), + 2, + ), + ( + Hand::new([Card::Three, Card::Two, Card::Tim, Card::Three, Card::King]), + 5, + ), + ( + Hand::new([Card::Tim, Card::Five, Card::Five, Card::Jack, Card::Five]), + 29, + ), + ( + Hand::new([Card::King, Card::King, Card::Six, Card::Seven, Card::Seven]), + 7, + ), + ( + Hand::new([Card::King, Card::Tim, Card::Jack, Card::Jack, Card::Tim]), + 34, + ), + ( + Hand::new([Card::Queen, Card::Queen, Card::Queen, Card::Jack, Card::Ace]), + 31, + ), + ( + Hand::new([Card::Jack, Card::Jack, Card::Jack, Card::Jack, Card::Jack]), + 37, + ), + ( + Hand::new([Card::Jack, Card::Ace, Card::Ace, Card::Ace, Card::Ace]), + 43, + ), + ( + Hand::new([Card::Ace, Card::Ace, Card::Ace, Card::Ace, Card::Jack]), + 59, + ), + ( + Hand::new([Card::Ace, Card::Ace, Card::Ace, Card::Ace, Card::Ace]), + 61, + ), + ( + Hand::new([Card::Two, Card::Ace, Card::Ace, Card::Ace, Card::Ace]), + 23, + ), + ( + Hand::new([Card::Two, Card::Jack, Card::Jack, Card::Jack, Card::Jack]), + 53, + ), + ( + Hand::new([Card::Jack, Card::Jack, Card::Jack, Card::Jack, Card::Two]), + 41, + ), + ]; + assert_eq!(part1(&mut input), 6592); + } +} diff --git a/2023/days/07/src/part2.rs b/2023/days/07/src/part2.rs new file mode 100644 index 0000000..aebc04a --- /dev/null +++ b/2023/days/07/src/part2.rs @@ -0,0 +1,129 @@ +use crate::parse::*; + +pub fn part2(input: &mut [(Hand, u32)]) -> usize { + input.iter_mut().for_each(|i| i.0.turn_jacks_to_jokers()); + input.sort_by(|a, b| a.0.cmp(&b.0) ); + input + .iter() + .enumerate() + .map(|i| (i.0 + 1) * i.1 .1 as usize) + .sum() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part2() { + let mut input = vec![ + ( + Hand::new([Card::Two, Card::Three, Card::Four, Card::Five, Card::Ace]), + 1, + ), + ( + Hand::new([Card::Queen, Card::Two, Card::King, Card::Joker, Card::Joker]), + 13, + ), + ( + Hand::new([Card::Queen, Card::Two, Card::Queen, Card::Two, Card::Queen]), + 19, + ), + ( + Hand::new([Card::Tim, Card::Three, Card::Tim, Card::Three, Card::Joker]), + 17, + ), + ( + Hand::new([ + Card::Tim, + Card::Three, + Card::Queen, + Card::Three, + Card::Three, + ]), + 11, + ), + ( + Hand::new([Card::Two, Card::Three, Card::Four, Card::Five, Card::Joker]), + 3, + ), + ( + Hand::new([Card::Joker, Card::Three, Card::Four, Card::Five, Card::Ace]), + 2, + ), + ( + Hand::new([Card::Three, Card::Two, Card::Tim, Card::Three, Card::King]), + 5, + ), + ( + Hand::new([Card::Tim, Card::Five, Card::Five, Card::Joker, Card::Five]), + 29, + ), + ( + Hand::new([Card::King, Card::King, Card::Six, Card::Seven, Card::Seven]), + 7, + ), + ( + Hand::new([Card::King, Card::Tim, Card::Joker, Card::Joker, Card::Tim]), + 34, + ), + ( + Hand::new([ + Card::Queen, + Card::Queen, + Card::Queen, + Card::Joker, + Card::Ace, + ]), + 31, + ), + ( + Hand::new([ + Card::Joker, + Card::Joker, + Card::Joker, + Card::Joker, + Card::Joker, + ]), + 37, + ), + ( + Hand::new([Card::Joker, Card::Ace, Card::Ace, Card::Ace, Card::Ace]), + 43, + ), + ( + Hand::new([Card::Ace, Card::Ace, Card::Ace, Card::Ace, Card::Joker]), + 59, + ), + ( + Hand::new([Card::Ace, Card::Ace, Card::Ace, Card::Ace, Card::Ace]), + 61, + ), + ( + Hand::new([Card::Two, Card::Ace, Card::Ace, Card::Ace, Card::Ace]), + 23, + ), + ( + Hand::new([ + Card::Two, + Card::Joker, + Card::Joker, + Card::Joker, + Card::Joker, + ]), + 53, + ), + ( + Hand::new([ + Card::Joker, + Card::Joker, + Card::Joker, + Card::Joker, + Card::Two, + ]), + 41, + ), + ]; + assert_eq!(part2(&mut input), 6839); + } +} diff --git a/2023/days/08/Cargo.toml b/2023/days/08/Cargo.toml new file mode 100644 index 0000000..afe04f1 --- /dev/null +++ b/2023/days/08/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "day08" +authors.workspace = true +description.workspace = true +version.workspace = true +edition.workspace = true + +[dependencies] +aoc_libs.workspace = true +regex.workspace = true +once_cell.workspace = true +collection_literals.workspace = true diff --git a/2023/days/08/src/input.txt b/2023/days/08/src/input.txt new file mode 100644 index 0000000..bc44497 --- /dev/null +++ b/2023/days/08/src/input.txt @@ -0,0 +1,752 @@ +LLRRLRRRLLRLRRLLLLRLRRLRRRLRLRRRLLRRLRRRLLRRLRRLRRLLRRRLRRLRRLRRRLRRLRLRLRRLRRLRRRLLRRLLLRRLRRRLRRRLRRRLRRLRRRLRLLRLRRRLRLRRLLRLRRRLRRRLRLRRRLRRRLRLRLRRLRRLRLRRLLRRRLRRRLRRRLLRRRLRLRLRLRLLRRRLRRRLRRLRRRLLRLRRLRRLRRRLRRRLRRLRLRLRRRLRRLRRLRRRLLRRLRLRLRRRLRLRLRRLRRLLRRLRRRLLRLLRLRLRRRR + +FGF = (HTC, DTX) +PTP = (MCL, BDN) +LHL = (LJF, BDX) +XMM = (KCX, JHL) +GLD = (RNN, MXG) +HSR = (JPX, CXF) +CRF = (BMJ, FHT) +QSS = (KPH, FVD) +RHV = (LRD, XDS) +KTT = (XPS, VCX) +LQK = (TLF, VJX) +MMK = (VJV, HQV) +RKX = (RKG, XJB) +HDM = (NFK, JNB) +PFJ = (QDJ, NDH) +JKB = (MDK, MRJ) +BSP = (QBQ, JPM) +FQH = (HJD, VHF) +QQL = (VDB, KGM) +TRB = (KTC, RGN) +VXC = (NDK, MVK) +BCS = (PSX, PLK) +FHK = (MLK, RDP) +TVB = (JXV, SSR) +GXD = (KSF, BRK) +MNJ = (MHG, CRF) +RLC = (TGD, CHV) +LBQ = (NQK, MHP) +JLH = (FGB, KNM) +PCN = (CQF, NDF) +FVP = (NKS, RCB) +GHL = (TTB, KLQ) +MTB = (VDM, FKT) +LLB = (VXL, TRT) +RSS = (GDP, TKD) +SFH = (FCM, GKF) +KSF = (VQB, JXJ) +LJH = (PNS, DGC) +TJC = (KQM, BVL) +PRL = (TCG, GCQ) +NBG = (GNR, SRM) +CST = (FXL, BDF) +XXH = (KVH, KSM) +FJP = (PKX, DSF) +DTS = (FFF, DQM) +CMG = (VBJ, DBF) +NHD = (TCJ, DHF) +KKF = (RVP, FVR) +LDS = (VPJ, MPN) +GHC = (DBK, SCS) +KVK = (NFV, MXJ) +NTN = (TDC, VNC) +FCR = (DCR, FQH) +PLK = (GHT, PBT) +VJF = (VJN, PVB) +TKR = (GHS, TTP) +PQJ = (VGB, SGP) +TGM = (JQM, PPK) +LFQ = (QGB, QXB) +RDP = (HSF, MQV) +SGP = (HVK, XMV) +FTB = (RFV, MLT) +LCX = (RSB, RSB) +VGD = (XJB, RKG) +PFD = (RGK, JGB) +DBK = (RMP, RSH) +TTC = (NDH, QDJ) +PVF = (QRG, QCV) +BGV = (TDS, DRK) +VHF = (XTB, TGM) +DBF = (GGT, BRQ) +TFG = (SVV, FCV) +MDK = (THF, PLQ) +NDF = (BSP, STC) +SMZ = (KHB, TST) +SLC = (BKM, BCS) +NSV = (VVM, VQG) +GCA = (XQT, RCD) +FVD = (NXJ, MBJ) +HCH = (MRF, RQJ) +PLN = (BNK, CLF) +TTP = (BCP, SLC) +BRF = (SHR, CTK) +KCX = (PDR, HHQ) +GMG = (NFV, MXJ) +SNN = (XDS, LRD) +SBB = (JXL, BFK) +NCV = (KVH, KSM) +DQQ = (FFF, DQM) +THT = (MFP, VSD) +GVH = (KHF, TKB) +HPC = (MKX, SVS) +KSS = (QQQ, HSR) +NCP = (FCV, SVV) +FGB = (LGN, LKJ) +TST = (DFV, GND) +PJR = (VMQ, HPB) +BHB = (VMQ, HPB) +LMG = (SHS, XJC) +GGT = (TQQ, XQK) +PKR = (QQR, JGG) +FLR = (LJP, VQT) +NFK = (HKG, BPJ) +MGG = (SST, MCT) +BVD = (SNV, TTH) +GHX = (GMK, JXG) +PDR = (HCD, HNG) +XJN = (NHR, CBN) +XRG = (LBQ, MTV) +VFM = (MMS, VXT) +PPP = (LHR, HJH) +FJG = (NLS, CCF) +NDK = (RHD, BVD) +VSB = (LKB, CCX) +NJG = (PTK, MCD) +MLS = (XCQ, FCR) +QSM = (CBJ, GRG) +PTC = (NJG, FLT) +MRJ = (PLQ, THF) +HJD = (XTB, TGM) +XCQ = (DCR, FQH) +HPN = (CQD, CTP) +BDJ = (JND, JRB) +PXL = (VXT, MMS) +NFV = (SFX, BDQ) +SNQ = (PQJ, TNG) +LSL = (KFN, JFL) +SMK = (FQS, FJJ) +QDV = (BDX, LJF) +GMK = (TSJ, SVF) +GDP = (MML, MML) +GRG = (PVF, CKG) +CXF = (MNJ, TBZ) +LKM = (HJH, LHR) +GHS = (BCP, SLC) +XBH = (BDS, NDQ) +NLL = (NJT, QCJ) +MXJ = (BDQ, SFX) +FCF = (QQQ, QQQ) +SXG = (LFQ, TTZ) +PLP = (MJL, FPL) +FSV = (SBB, JFC) +NLH = (TDS, DRK) +QDM = (GHX, GGM) +JJB = (MSQ, MMK) +TRS = (BXN, RLM) +DMP = (RTP, CHG) +XGG = (PCC, XKH) +MCT = (NLK, DTM) +DLC = (JTQ, BLF) +VBJ = (GGT, BRQ) +XQD = (NTN, XRC) +FKM = (QKK, JBQ) +PNN = (RGN, KTC) +LCM = (DTG, GHC) +LKJ = (LFV, RNG) +HRR = (JND, JRB) +BDN = (SNQ, NVC) +RSH = (PJS, LHG) +CTP = (DJM, NHF) +XMV = (CFJ, MDV) +HXM = (PTP, XVQ) +CKG = (QCV, QRG) +GKK = (CRG, MPJ) +LNS = (VSB, GNQ) +RVP = (JJB, LCN) +DVH = (QLD, QGV) +CPH = (PMN, QSC) +BXQ = (CPH, DSQ) +SDM = (DSB, CNV) +RNN = (SHM, LSL) +VQC = (GKH, DMP) +KXV = (GKN, PTC) +TNK = (NMK, PKR) +TSL = (MTV, LBQ) +VSD = (LGH, HNM) +QRQ = (QXH, GRQ) +NKS = (NSL, HPN) +TQC = (JQK, TXF) +THF = (TVM, KKF) +VSL = (PLN, GDS) +SSN = (FTB, NXF) +NHF = (BFG, XTZ) +HSP = (QRQ, DFC) +JQM = (BNP, PMD) +GDV = (RVK, MQF) +MTK = (TGD, CHV) +FFX = (DSN, XXJ) +HKG = (THT, KNJ) +RCN = (DCB, XFN) +HCD = (TDF, BQM) +TKJ = (JPV, GRR) +RVK = (HXX, PRL) +HDN = (TRT, VXL) +KHQ = (DQQ, DTS) +MPJ = (PLP, KBG) +SFX = (KTT, NTG) +NMJ = (BGV, NLH) +LXK = (CRB, GXD) +KBG = (FPL, MJL) +GNQ = (LKB, CCX) +MRV = (RVK, MQF) +PKH = (NPN, MHQ) +NLK = (LTJ, RXP) +LBH = (VTP, SGG) +NTG = (VCX, XPS) +CCD = (GVF, SSJ) +BBB = (SSR, JXV) +NSL = (CQD, CQD) +BNK = (SGS, JQD) +TTB = (KVK, GMG) +FDR = (RBS, TXD) +PJG = (RTV, JQS) +LGV = (LSB, NPF) +XVQ = (MCL, BDN) +BMJ = (KRT, XXN) +XCM = (LXK, VKJ) +CCF = (SDR, PTQ) +GSS = (PJR, BHB) +CJL = (QKK, JBQ) +FBT = (VJF, SGL) +DSB = (QKQ, RBK) +SGS = (MLQ, PXT) +PKX = (KPF, CNQ) +JND = (SDG, SND) +DJM = (BFG, BFG) +LHK = (SBB, JFC) +QLD = (SGX, KDP) +NPF = (VDC, KHQ) +BRQ = (XQK, TQQ) +NGQ = (JNB, NFK) +NFH = (MPN, VPJ) +KHF = (LKG, GLD) +XKC = (XTX, XTX) +DJG = (XGL, BTF) +LGN = (RNG, LFV) +HQV = (CJL, FKM) +JPV = (SVD, XJN) +TSJ = (NMD, MGG) +QRG = (HBD, CST) +FXL = (PFX, HVV) +TNG = (VGB, SGP) +HXX = (GCQ, TCG) +RTP = (CDD, QJR) +RXN = (LFQ, LFQ) +MVK = (BVD, RHD) +PLR = (FVP, DHP) +GRR = (XJN, SVD) +DHJ = (VRN, DTR) +HSF = (TSS, JSQ) +TXN = (FGF, NMV) +CBJ = (CKG, PVF) +GHT = (RCN, NTR) +SMH = (FJG, LQD) +CVN = (PLR, DDF) +SJK = (TTF, SLQ) +LMN = (XHT, CFF) +KLQ = (GMG, KVK) +KXC = (CHP, NLL) +KNM = (LKJ, LGN) +QHK = (LNV, GKK) +BTH = (KVR, FNQ) +QFV = (PRK, LTV) +DBH = (HND, HFC) +CRG = (KBG, PLP) +TCG = (DVF, BXQ) +SJQ = (KPR, QKP) +JMJ = (TTB, KLQ) +RFV = (XBH, CGX) +AAA = (QDM, GMV) +JTQ = (HRR, BDJ) +MHQ = (HPQ, KXC) +SDG = (HGR, RJN) +PNS = (FMC, JKB) +KHB = (DFV, GND) +NXJ = (MLS, HLT) +HND = (LVF, BBJ) +FCZ = (RCD, XQT) +NFP = (FVD, KPH) +NTH = (FVH, DJG) +GMV = (GHX, GGM) +FKT = (CLC, BTH) +LTV = (BKP, HVT) +VLF = (DLX, FMB) +NNP = (NFH, LDS) +GQV = (RTR, NMJ) +MCD = (PFK, HPC) +XML = (RNR, GJF) +TXD = (LGT, QSM) +DKG = (RTV, JQS) +MQF = (PRL, HXX) +XJB = (HKV, FLR) +SHS = (VVH, CHN) +PMD = (NSV, BMQ) +TLJ = (DMP, GKH) +CMA = (TST, KHB) +CRB = (KSF, BRK) +XQT = (TXN, LNN) +QHF = (XKH, PCC) +FQM = (PKR, NMK) +DHP = (NKS, RCB) +KSM = (DKP, SDM) +LKB = (RQV, BRF) +BVL = (TRB, PNN) +GJF = (NTH, JRX) +HTC = (HRL, HXM) +JGB = (QVX, GMR) +VJV = (CJL, FKM) +RGK = (QVX, GMR) +KPF = (JCK, XDV) +LNV = (CRG, MPJ) +QNP = (LXK, VKJ) +MFT = (NJK, VVL) +PBT = (RCN, NTR) +CKV = (XHT, CFF) +RCD = (TXN, LNN) +MBJ = (HLT, MLS) +QDC = (NMJ, RTR) +SVV = (FJC, MJR) +STN = (LQC, HFR) +QXB = (RPJ, MHL) +VJN = (TVB, BBB) +GKH = (RTP, CHG) +XGL = (PMX, FFX) +KNH = (FGB, KNM) +TVN = (QKP, KPR) +JFC = (BFK, JXL) +LHG = (TFG, NCP) +HFT = (HND, HFC) +DKP = (DSB, CNV) +LGH = (DCG, QPN) +LGC = (VVL, NJK) +HSC = (NTJ, QQL) +CFF = (JMJ, GHL) +PFH = (SGL, VJF) +LGT = (GRG, CBJ) +JSQ = (SFH, RVQ) +VDM = (CLC, BTH) +NTR = (DCB, XFN) +KVH = (DKP, SDM) +BVQ = (LSH, SDX) +NRC = (QCH, TRS) +DCB = (KBT, TSR) +DGC = (FMC, JKB) +VMQ = (LJR, LJR) +MXG = (LSL, SHM) +CPM = (TRS, QCH) +DLX = (LQN, TJC) +GDS = (BNK, CLF) +JRK = (PGJ, NHD) +JXV = (DRH, CVN) +SVD = (CBN, NHR) +LCN = (MSQ, MMK) +MJL = (RQL, RGF) +JLT = (QRQ, DFC) +BGP = (DPV, VXC) +PSQ = (PJR, BHB) +NTJ = (KGM, VDB) +SGX = (VFM, PXL) +QBQ = (MCM, VNV) +CHV = (QJN, CMG) +DRK = (BKT, LBH) +SVS = (NPV, HCH) +BCP = (BKM, BCS) +BXN = (PSQ, GSS) +GQJ = (SMH, XHX) +NPV = (RQJ, MRF) +NMV = (HTC, DTX) +LKR = (SPG, SJK) +HLT = (XCQ, FCR) +SKX = (HSC, CFR) +SDR = (BLQ, FKV) +FCN = (FKT, VDM) +VPB = (CJR, FHK) +MHL = (PFJ, TTC) +XQK = (BBK, PBQ) +MDV = (SCJ, BKF) +VDC = (DQQ, DTS) +RTV = (LDP, PCN) +GRQ = (FDR, DHG) +NDH = (JGX, SSN) +NCG = (GNR, SRM) +LQN = (BVL, KQM) +NHR = (FQM, TNK) +LJR = (GDP, GDP) +JXL = (VKV, MJQ) +QCH = (BXN, RLM) +QGB = (MHL, RPJ) +DDN = (GLT, DHJ) +SHR = (BGP, FCX) +DPV = (MVK, NDK) +XHT = (GHL, JMJ) +QKK = (LCX, LCX) +TRT = (QFV, NHT) +PBQ = (DPX, LNS) +JHL = (HHQ, PDR) +DCG = (JLX, VSL) +SST = (NLK, DTM) +QPN = (JLX, VSL) +GXS = (FJP, DCM) +VJX = (DKB, FCZ) +XXJ = (HDN, LLB) +JPM = (VNV, MCM) +QGV = (SGX, KDP) +QNA = (QGB, QXB) +CQD = (DJM, DJM) +TTF = (TVN, SJQ) +CHP = (QCJ, NJT) +BBJ = (LVT, TKJ) +VKJ = (CRB, GXD) +LJF = (FFL, KXV) +TKD = (MML, ZZZ) +QKP = (CKV, LMN) +CQF = (STC, BSP) +PHM = (FHK, CJR) +BTF = (PMX, FFX) +JRX = (FVH, DJG) +PMN = (NBG, NCG) +LKG = (RNN, MXG) +NXB = (JLH, KNH) +MLQ = (FBT, PFH) +JML = (XKC, GLX) +NHT = (PRK, LTV) +BLQ = (SKX, HGL) +BDX = (FFL, KXV) +DVN = (SCR, JML) +FPL = (RQL, RGF) +MMS = (SVR, KSV) +FLT = (PTK, MCD) +PTQ = (BLQ, FKV) +DHG = (RBS, TXD) +QSC = (NCG, NBG) +LFV = (NXP, GMF) +XDS = (KQP, STN) +PVB = (BBB, TVB) +JGX = (NXF, FTB) +CNB = (PRR, JRK) +TQQ = (PBQ, BBK) +GMF = (MKH, CRH) +SDP = (KCQ, PKV) +MHP = (HMR, LCM) +RRS = (QGV, QLD) +PKV = (XKG, HTH) +JLX = (GDS, PLN) +RJN = (VGD, RKX) +NMK = (QQR, JGG) +PFK = (SVS, MKX) +NXF = (MLT, RFV) +VVM = (HDM, NGQ) +VSJ = (QDG, VKM) +RBS = (QSM, LGT) +KFN = (RRS, DVH) +XXN = (XMM, SKM) +TXF = (LKM, PPP) +DFV = (VLF, GPC) +RMP = (PJS, LHG) +LVP = (QDG, VKM) +DFC = (QXH, GRQ) +GPC = (DLX, FMB) +LJP = (CCD, FSM) +MPN = (PFD, RSN) +SGG = (RHV, SNN) +BDF = (HVV, PFX) +QQR = (GVH, QSB) +RPJ = (TTC, PFJ) +NDQ = (NXV, XQD) +RGF = (BVQ, GMB) +TXM = (DCM, FJP) +VRN = (XFV, MFG) +FCX = (VXC, DPV) +RQJ = (HFT, DBH) +MLT = (CGX, XBH) +TSR = (QSS, NFP) +BCD = (VQC, TLJ) +JQK = (PPP, LKM) +DSF = (CNQ, KPF) +CVS = (LDS, NFH) +VTP = (SNN, RHV) +FTA = (MHG, CRF) +RNR = (NTH, JRX) +DRH = (PLR, DDF) +KSV = (SMK, NHC) +VKM = (HFV, LMG) +DTR = (XFV, MFG) +MML = (QDM, GMV) +HPQ = (CHP, NLL) +GKF = (QHK, TDM) +TDF = (DHX, LPT) +PXT = (FBT, PFH) +BRK = (VQB, JXJ) +VXT = (KSV, SVR) +HNM = (QPN, DCG) +HHQ = (HNG, HCD) +MPG = (JJS, SMZ) +CGS = (QDC, GQV) +GMR = (GQJ, RMH) +BKF = (CNB, NKP) +VDB = (VPB, PHM) +DSQ = (PMN, QSC) +DTX = (HRL, HXM) +QXH = (FDR, DHG) +LPT = (QDV, LHL) +DKB = (XQT, RCD) +QJN = (VBJ, DBF) +FVR = (JJB, LCN) +MFG = (CPM, NRC) +FMC = (MDK, MRJ) +JLL = (RXN, SXG) +NQK = (LCM, HMR) +KBT = (QSS, NFP) +DHX = (QDV, LHL) +SKM = (JHL, KCX) +FSM = (SSJ, GVF) +NVC = (TNG, PQJ) +SRM = (HSP, JLT) +FCM = (TDM, QHK) +NPN = (HPQ, KXC) +JGG = (QSB, GVH) +DCM = (DSF, PKX) +BLF = (BDJ, HRR) +JXJ = (JCC, LGV) +PSX = (PBT, GHT) +CRH = (NXX, BCD) +SCS = (RSH, RMP) +LTJ = (FSV, LHK) +PSV = (PKV, KCQ) +TVM = (FVR, RVP) +LSH = (DDN, HNX) +XTX = (RXN, RXN) +RKG = (FLR, HKV) +JNB = (BPJ, HKG) +GKN = (NJG, FLT) +RLM = (PSQ, GSS) +CNQ = (XDV, JCK) +HFR = (TQC, KLB) +RQV = (SHR, CTK) +DSN = (HDN, LLB) +FFF = (KSR, KSR) +FJJ = (FCF, KSS) +KPH = (NXJ, MBJ) +KCQ = (XKG, HTH) +PPK = (BNP, PMD) +TKB = (LKG, GLD) +JQD = (MLQ, PXT) +BPJ = (THT, KNJ) +RBK = (FCN, MTB) +PDK = (GHS, TTP) +SDX = (DDN, HNX) +BQM = (DHX, LPT) +KNJ = (MFP, VSD) +CLC = (FNQ, KVR) +XPS = (NXB, SXK) +CLF = (JQD, SGS) +DQM = (KSR, LQK) +XKG = (MRV, GDV) +RHD = (TTH, SNV) +RTR = (BGV, NLH) +QSB = (TKB, KHF) +BKP = (PJG, DKG) +RMH = (XHX, SMH) +PGR = (PNS, DGC) +GND = (VLF, GPC) +PCC = (QNP, XCM) +KDP = (PXL, VFM) +SPG = (TTF, SLQ) +SXK = (KNH, JLH) +PFX = (MFT, LGC) +BKM = (PLK, PSX) +TGD = (CMG, QJN) +NXV = (NTN, XRC) +MFP = (HNM, LGH) +MQQ = (RSB, MPG) +TBZ = (CRF, MHG) +XDV = (TKR, PDK) +DVF = (CPH, DSQ) +SNV = (GXS, TXM) +DCR = (HJD, VHF) +QDG = (LMG, HFV) +MHG = (FHT, BMJ) +NKP = (PRR, JRK) +XRC = (VNC, TDC) +JFL = (RRS, DVH) +KRT = (SKM, XMM) +CDD = (DVN, PDM) +NXP = (MKH, CRH) +LVT = (GRR, JPV) +NJT = (RLC, MTK) +HVV = (MFT, LGC) +RNG = (GMF, NXP) +SVR = (SMK, NHC) +QDJ = (SSN, JGX) +RQL = (BVQ, GMB) +HMR = (GHC, DTG) +CGX = (BDS, NDQ) +MJQ = (LVP, VSJ) +XJC = (CHN, VVH) +FFL = (GKN, PTC) +XJS = (SJK, SPG) +JQS = (PCN, LDP) +SHM = (JFL, KFN) +HPB = (LJR, RSS) +JXG = (SVF, TSJ) +STC = (QBQ, JPM) +FHT = (XXN, KRT) +LRD = (KQP, STN) +VCX = (SXK, NXB) +KSR = (TLF, TLF) +KQM = (PNN, TRB) +KTC = (TSL, XRG) +VKV = (VSJ, LVP) +XTB = (PPK, JQM) +BFK = (MJQ, VKV) +GLT = (VRN, DTR) +VPJ = (PFD, RSN) +BKT = (SGG, VTP) +BMQ = (VVM, VQG) +KVR = (QHF, XGG) +LNH = (QDC, GQV) +SLQ = (SJQ, TVN) +CJR = (RDP, MLK) +JCK = (TKR, PDK) +GVF = (XXH, NCV) +LQC = (TQC, KLB) +TSS = (SFH, RVQ) +HRL = (XVQ, PTP) +TDM = (GKK, LNV) +BNP = (BMQ, NSV) +BFG = (RNQ, PKH) +CFJ = (BKF, SCJ) +QQQ = (JPX, JPX) +MQV = (JSQ, TSS) +XHX = (LQD, FJG) +PMX = (XXJ, DSN) +KGM = (VPB, PHM) +GNR = (JLT, HSP) +NLS = (PTQ, SDR) +MSQ = (VJV, HQV) +FMB = (TJC, LQN) +XFV = (NRC, CPM) +RSN = (JGB, RGK) +PRK = (HVT, BKP) +HFV = (XJC, SHS) +SVF = (NMD, MGG) +QVX = (GQJ, RMH) +TCF = (BLF, JTQ) +MLK = (HSF, MQV) +RVQ = (FCM, GKF) +GLX = (XTX, JLL) +PDM = (SCR, JML) +HGR = (RKX, VGD) +JRB = (SND, SDG) +FKV = (SKX, HGL) +TDC = (LNH, CGS) +FVH = (XGL, BTF) +NHC = (FQS, FJJ) +BBK = (LNS, DPX) +VVH = (NNP, CVS) +NJK = (DLC, TCF) +SGL = (VJN, PVB) +MTV = (NQK, MHP) +PJS = (TFG, NCP) +DTG = (SCS, DBK) +TCJ = (SDP, PSV) +VGB = (HVK, XMV) +MCL = (SNQ, NVC) +NXX = (TLJ, VQC) +HVK = (MDV, CFJ) +NMD = (MCT, SST) +TTZ = (QXB, QGB) +VNC = (LNH, CGS) +GMB = (LSH, SDX) +CHN = (NNP, CVS) +FCV = (MJR, FJC) +HNG = (TDF, BQM) +SCR = (XKC, GLX) +DDF = (DHP, FVP) +CTK = (BGP, FCX) +CHG = (QJR, CDD) +VXL = (QFV, NHT) +SSJ = (XXH, NCV) +RNQ = (NPN, MHQ) +FJC = (XJF, XML) +XTZ = (PKH, RNQ) +CBN = (TNK, FQM) +RSB = (JJS, JJS) +TTH = (GXS, TXM) +HJH = (LKR, XJS) +VQB = (JCC, LGV) +HKV = (LJP, VQT) +RGN = (XRG, TSL) +MKX = (NPV, HCH) +JJS = (TST, KHB) +JPX = (MNJ, MNJ) +HTH = (MRV, GDV) +VQT = (CCD, FSM) +PGJ = (DHF, TCJ) +DHF = (SDP, PSV) +XJF = (GJF, RNR) +LQD = (CCF, NLS) +MRF = (DBH, HFT) +FNQ = (XGG, QHF) +GGM = (JXG, GMK) +BDS = (NXV, XQD) +MCM = (PGR, LJH) +LDP = (NDF, CQF) +QCJ = (RLC, MTK) +CCX = (RQV, BRF) +HBD = (BDF, FXL) +CBA = (RNQ, PKH) +MJR = (XJF, XML) +JCC = (LSB, NPF) +VQG = (NGQ, HDM) +RCB = (NSL, HPN) +QCV = (HBD, CST) +TDS = (LBH, BKT) +CNV = (QKQ, RBK) +KLB = (JQK, TXF) +XKH = (QNP, XCM) +SCJ = (CNB, NKP) +HGL = (CFR, HSC) +BDQ = (NTG, KTT) +PRR = (PGJ, NHD) +KPR = (CKV, LMN) +HFC = (LVF, BBJ) +TLF = (DKB, DKB) +SND = (HGR, RJN) +VNV = (PGR, LJH) +PLQ = (KKF, TVM) +LVF = (LVT, TKJ) +QJR = (PDM, DVN) +HVT = (DKG, PJG) +CFR = (QQL, NTJ) +DTM = (LTJ, RXP) +HNX = (GLT, DHJ) +QKQ = (FCN, MTB) +PTK = (HPC, PFK) +FQS = (FCF, KSS) +JBQ = (LCX, MQQ) +RXP = (LHK, FSV) +SSR = (DRH, CVN) +LSB = (VDC, KHQ) +DPX = (GNQ, VSB) +ZZZ = (GMV, QDM) +XFN = (TSR, KBT) +LNN = (NMV, FGF) +KQP = (LQC, HFR) +LHR = (XJS, LKR) +GCQ = (DVF, BXQ) +VVL = (TCF, DLC) +MKH = (NXX, BCD) diff --git a/2023/days/08/src/main.rs b/2023/days/08/src/main.rs new file mode 100644 index 0000000..456385c --- /dev/null +++ b/2023/days/08/src/main.rs @@ -0,0 +1,14 @@ +mod part1; +mod part2; +mod parse; + +fn main() { + let input = include_str!("./input.txt"); + let structured_input = parse::parse(input); + + println!("Part One"); + println!("Result: {}", part1::part1(&structured_input)); + + println!("Part Two"); + println!("Result: {}", part2::part2(&structured_input)); +} diff --git a/2023/days/08/src/parse.rs b/2023/days/08/src/parse.rs new file mode 100644 index 0000000..c8364a4 --- /dev/null +++ b/2023/days/08/src/parse.rs @@ -0,0 +1,79 @@ +use std::collections::HashMap; + +use once_cell::sync::Lazy; +use regex::Regex; + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum Direction { + Left, + Right, +} + +#[derive(Debug, Hash, PartialEq, Eq)] +pub struct Node { + pub left: String, + pub right: String, +} + +static NODE_REGEX: Lazy = Lazy::new(|| { + Regex::new(r"^([[:alnum:]]{3}) = \(([[:alnum:]]{3}), ([[:alnum:]]{3})\)$").unwrap() +}); + +pub fn parse(input: &str) -> (Vec, HashMap) { + let mut lines = input.lines(); + let mut directions = Vec::new(); + //parse the directions + let dirline = lines.next().unwrap(); + for char in dirline.chars() { + directions.push(match char { + 'L' => Direction::Left, + 'R' => Direction::Right, + e => panic!("unexpected direction {}", e), + }) + } + //skip a blank line + lines.next(); + + // process the rest of the lines + let mut graph = HashMap::new(); + for line in lines { + let captures = NODE_REGEX.captures(line).unwrap(); + graph.insert( + captures[1].to_string(), + Node { + left: captures[2].to_string(), + right: captures[3].to_string(), + }, + ); + } + (directions, graph) +} + +#[cfg(test)] +mod tests { + use super::*; + use collection_literals::collection; + + #[test] + fn test_parse() { + let input = concat!( + "LLR\n", + "\n", + "AAA = (BBB, BBB)\n", + "BBB = (AAA, ZZZ)\n", + "ZZZ = (ZZZ, ZZZ)\n", + ); + println!("{:#?}", parse(input)); + assert_eq!( + parse(input), + ( + vec![Direction::Left, Direction::Left, Direction::Right], + collection! { + "AAA".to_string() => Node{ left: "BBB".to_string(), right: "BBB".to_string() }, + "BBB".to_string() => Node{ left: "AAA".to_string(), right: "ZZZ".to_string() }, + "ZZZ".to_string() => Node{ left: "ZZZ".to_string(), right: "ZZZ".to_string() }, + } + ) + ); + } +} diff --git a/2023/days/08/src/part1.rs b/2023/days/08/src/part1.rs new file mode 100644 index 0000000..37ac4f1 --- /dev/null +++ b/2023/days/08/src/part1.rs @@ -0,0 +1,37 @@ +use std::collections::HashMap; + +use crate::parse::*; + +pub fn part1(input: &(Vec, HashMap)) -> usize { + let mut nodes_visited: usize = 0; + let mut current_node: String = "AAA".to_string(); + while current_node != *"ZZZ" { + let direction = input.0[nodes_visited % input.0.len()]; + match direction { + Direction::Left => current_node = input.1.get(¤t_node).unwrap().left.clone(), + Direction::Right => current_node = input.1.get(¤t_node).unwrap().right.clone(), + }; + nodes_visited += 1; + } + nodes_visited +} + +#[cfg(test)] +mod tests { + use collection_literals::collection; + + use super::*; + + #[test] + fn test_part1() { + let input: (Vec, HashMap) = ( + vec![Direction::Left, Direction::Left, Direction::Right], + collection! { + "AAA".to_string() => Node{ left: "BBB".to_string(), right: "BBB".to_string() }, + "BBB".to_string() => Node{ left: "AAA".to_string(), right: "ZZZ".to_string() }, + "ZZZ".to_string() => Node{ left: "ZZZ".to_string(), right: "ZZZ".to_string() }, + }, + ); + assert_eq!(part1(&input), 6); + } +} diff --git a/2023/days/08/src/part2.rs b/2023/days/08/src/part2.rs new file mode 100644 index 0000000..c1092dd --- /dev/null +++ b/2023/days/08/src/part2.rs @@ -0,0 +1,113 @@ +use aoc_libs::misc::arr_lcm; +use std::collections::HashMap; + +use crate::parse::*; + +// note about inputs: each "ends with A" node is the starting point, +// and is not returned to part of the loop. +// eatch 'Z' node is at the 'end' of the loop, +// so the time when you first hit z is equal to your cycle time. + +pub fn part2(input: &(Vec, HashMap)) -> usize { + let (directions, graph) = input; + let starting_points = find_starting_points(graph); + println!("{:?}", starting_points); + let cycle_lengths: Vec<_> = starting_points + .iter() + .inspect(|p| print!("starting point {}: ", p)) + .map(|p| cycle_len_and_offset(p, directions, graph)) + .inspect(|c| println!("cycles: {}", c)) + .collect(); + arr_lcm(&cycle_lengths) +} + +//returns the length of the loop +fn cycle_len_and_offset( + start: &str, + directions: &[Direction], + graph: &HashMap, +) -> usize { + let mut current_node: String = start.to_string(); + let mut dir_index: usize = 0; + let mut cycles: usize = 0; + while !current_node.ends_with('Z') { + match directions[dir_index % directions.len()] { + Direction::Left => current_node = graph.get(¤t_node).unwrap().left.clone(), + Direction::Right => current_node = graph.get(¤t_node).unwrap().right.clone(), + }; + cycles += 1; + dir_index += 1; + // println!("finding index: {}", current_node); + } + cycles +} + +fn find_starting_points(input: &HashMap) -> Vec { + let mut ret = Vec::new(); + for point in input.keys() { + if point.ends_with('A') { + ret.push(point.to_string()) + } + } + ret +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_find_len_of_cycle() { + let input = parse(concat!( + "LR\n", + "\n", + "11A = (11B, XXX)\n", + "11B = (XXX, 11Z)\n", + "11Z = (11B, XXX)\n", + "22A = (22B, XXX)\n", + "22B = (22C, 22C)\n", + "22C = (22Z, 22Z)\n", + "22Z = (22B, 22B)\n", + "XXX = (XXX, XXX)\n", + )); + assert_eq!(cycle_len_and_offset("11A", &input.0, &input.1), 2); + assert_eq!(cycle_len_and_offset("22A", &input.0, &input.1), 3); + } + + #[test] + fn test_find_starting_points() { + let input = parse(concat!( + "LR\n", + "\n", + "11A = (11B, XXX)\n", + "11B = (XXX, 11Z)\n", + "11Z = (11B, XXX)\n", + "22A = (22B, XXX)\n", + "22B = (22C, 22C)\n", + "22C = (22Z, 22Z)\n", + "22Z = (22B, 22B)\n", + "XXX = (XXX, XXX)\n", + )); + let starting_points = find_starting_points(&input.1); + assert_eq!(starting_points.len(), 2); + assert!(starting_points.contains(&"11A".to_string())); + assert!(starting_points.contains(&"22A".to_string())); + } + + #[test] + fn test_part2() { + let input = parse(concat!( + "LR\n", + "\n", + "11A = (11B, XXX)\n", + "11B = (XXX, 11Z)\n", + "11Z = (11B, XXX)\n", + "22A = (22B, XXX)\n", + "22B = (22C, 22C)\n", + "22C = (22Z, 22Z)\n", + "22Z = (22B, 22B)\n", + "XXX = (XXX, XXX)\n", + )); + assert_eq!(part2(&input), 6); + } +} diff --git a/2023/days/09/Cargo.toml b/2023/days/09/Cargo.toml new file mode 100644 index 0000000..ec42136 --- /dev/null +++ b/2023/days/09/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "day09" +authors.workspace = true +description.workspace = true +version.workspace = true +edition.workspace = true + +[dependencies] +aoc_libs.workspace = true diff --git a/2023/days/09/src/input.txt b/2023/days/09/src/input.txt new file mode 100644 index 0000000..9d38ad6 --- /dev/null +++ b/2023/days/09/src/input.txt @@ -0,0 +1,200 @@ +13 14 13 10 5 -2 -11 -22 -35 -50 -67 -86 -107 -130 -155 -182 -211 -242 -275 -310 -347 +9 19 37 66 111 177 266 388 625 1318 3490 9701 25720 63813 149272 333318 718069 1503353 3071375 6134368 11983281 +17 46 98 176 281 429 679 1172 2193 4286 8484 16784 33150 65659 131075 264391 538087 1099560 2241224 4527470 9018149 +7 8 7 15 65 227 628 1477 3095 5950 10697 18223 29697 46625 70910 104917 151543 214292 297355 405695 545137 +16 20 32 75 200 503 1144 2368 4528 8110 13760 22313 34824 52601 77240 110662 155152 213400 288544 384215 504584 +12 19 22 16 -5 -46 -106 -162 -130 213 1366 4324 10909 24244 49406 94298 170784 296135 494838 800824 1260175 +2 6 26 72 158 308 570 1038 1882 3389 6024 10529 18090 30617 51200 84825 139458 227632 368702 591966 940886 +22 46 83 136 215 355 655 1362 3045 6934 15547 33816 71102 144866 287545 559746 1075870 2053792 3909961 7437838 14134735 +11 28 56 110 211 392 719 1340 2589 5207 10809 22836 48395 101619 209484 421412 824479 1566646 2891150 5186042 9053851 +18 41 80 155 308 608 1164 2162 3949 7210 13337 25194 48675 95789 190569 380005 753596 1477199 2849870 5396645 10016062 +27 45 78 149 302 624 1293 2676 5512 11226 22431 43686 82589 151295 268560 462423 773649 1260067 2001948 3108579 4726200 +-4 -8 -13 0 71 277 765 1806 3871 7731 14593 26319 45879 78460 134275 235391 431268 831772 1672945 3440668 7091533 +3 16 32 55 106 241 575 1307 2748 5384 10073 18593 34941 68045 136906 279649 568545 1133784 2199646 4137747 7543244 +12 37 77 132 202 287 387 502 632 777 937 1112 1302 1507 1727 1962 2212 2477 2757 3052 3362 +21 25 24 23 40 123 392 1125 2909 6873 15012 30615 58861 107802 190292 328053 560129 959637 1665192 2936927 5251986 +-3 4 31 85 169 285 443 684 1131 2086 4193 8687 17747 34967 65953 119046 206161 343720 553643 864345 1311669 +12 39 94 190 340 557 854 1244 1740 2355 3102 3994 5044 6265 7670 9272 11084 13119 15390 17910 20692 +8 3 6 32 108 279 614 1212 2208 3779 6150 9600 14468 21159 30150 41996 57336 76899 101510 132096 169692 +19 34 45 58 97 211 481 1027 2015 3664 6253 10128 15709 23497 34081 48145 66475 89966 119629 156598 202137 +19 32 43 45 36 32 85 301 856 2020 4216 8156 15115 27474 49920 92445 178177 363369 786019 1778286 4114938 +21 23 28 49 115 297 747 1743 3732 7381 13707 24503 43577 79880 154567 315616 666091 1415815 2971538 6088153 12113739 +12 25 38 55 85 142 245 418 690 1095 1672 2465 3523 4900 6655 8852 11560 14853 18810 23515 29057 +2 1 -3 -10 -20 -33 -49 -68 -90 -115 -143 -174 -208 -245 -285 -328 -374 -423 -475 -530 -588 +15 31 53 83 130 228 479 1144 2816 6725 15248 32734 66829 130665 246726 454311 825117 1497239 2749951 5165469 9968628 +13 22 41 94 227 530 1182 2527 5189 10234 19387 35312 61963 105014 172376 274809 426637 646574 958669 1393378 1988771 +10 27 61 128 265 541 1078 2086 3929 7275 13453 25271 48812 97287 199231 415823 876990 1854968 3909809 8167901 16837713 +20 41 69 115 210 426 919 2014 4376 9357 19685 40775 83102 166290 325847 623822 1165084 2121433 3766357 6523955 11036362 +20 41 79 145 260 469 859 1576 2833 4898 8048 12472 18103 24356 29746 31357 24130 -65 -53611 -154621 -328754 +12 15 14 14 20 31 44 93 361 1429 4792 13917 36403 88335 202900 447124 953909 1982790 4034693 8068571 15910501 +7 1 -10 -26 -47 -73 -104 -140 -181 -227 -278 -334 -395 -461 -532 -608 -689 -775 -866 -962 -1063 +8 17 28 41 56 73 92 113 136 161 188 217 248 281 316 353 392 433 476 521 568 +-7 -7 -3 20 91 253 563 1092 1925 3161 4913 7308 10487 14605 19831 26348 34353 44057 55685 69476 85683 +19 41 75 131 239 467 955 1978 4070 8281 16709 33558 67130 133373 261887 505645 956125 1766081 3182815 5595557 9601425 +19 38 76 145 252 412 679 1198 2286 4562 9162 18098 34869 65554 120910 220664 402655 742670 1397682 2699767 5358228 +-8 -12 -16 -20 -24 -28 -32 -36 -40 -44 -48 -52 -56 -60 -64 -68 -72 -76 -80 -84 -88 +14 19 25 47 123 330 805 1770 3568 6733 12138 21281 36762 62959 106853 179040 295716 485185 810417 1439321 2840823 +-5 -10 -5 27 113 307 712 1508 3008 5813 11227 22245 45678 96398 205401 434621 903560 1836489 3645526 7077172 13474410 +6 12 37 100 225 454 877 1695 3352 6804 14053 29199 60520 124585 254292 514213 1028998 2034192 3964089 7598714 14302319 +9 -1 -3 16 71 191 448 1014 2276 5083 11286 24888 54380 117243 248195 513614 1035739 2031815 3875387 7189552 12985245 +13 9 3 11 67 227 573 1217 2305 4021 6591 10287 15431 22399 31625 43605 58901 78145 102043 131379 167019 +3 13 41 93 185 367 766 1656 3563 7413 14731 27899 50481 87623 146536 237070 372387 569741 851373 1245529 1787609 +26 35 37 26 -2 -45 -94 -139 -186 -289 -601 -1448 -3430 -7553 -15396 -29317 -52702 -90261 -148375 -235498 -362618 +24 35 46 57 68 79 90 101 112 123 134 145 156 167 178 189 200 211 222 233 244 +-1 -3 7 45 137 336 752 1595 3231 6251 11553 20437 34713 56822 89970 138275 206927 302361 432443 606669 836377 +5 14 43 100 196 351 596 980 1613 2813 5492 12035 28135 66420 153386 342383 737601 1537808 3114941 6152870 11887554 +-4 6 31 79 177 390 850 1806 3720 7456 14647 28396 54601 104440 198986 377657 713404 1339426 2495079 4602917 8394985 +8 14 26 47 83 143 236 375 620 1224 2998 8105 21675 54992 131693 299673 653536 1375886 2810998 5591955 10852643 +-6 -6 -6 -13 -32 -48 15 366 1463 4197 10185 22236 45083 86509 159036 282393 487032 819020 1346700 2169585 3430026 +16 35 67 113 174 251 345 457 588 739 911 1105 1322 1563 1829 2121 2440 2787 3163 3569 4006 +18 25 35 61 126 269 567 1182 2449 5043 10322 21086 43303 89970 189428 402531 856796 1812337 3786333 7783995 15721100 +1 0 -3 -8 -15 -24 -35 -48 -63 -80 -99 -120 -143 -168 -195 -224 -255 -288 -323 -360 -399 +22 29 36 43 50 57 64 71 78 85 92 99 106 113 120 127 134 141 148 155 162 +12 25 47 93 190 380 730 1359 2492 4551 8293 15005 26766 46786 79832 132751 215100 339893 524475 791533 1170254 +3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60 63 +8 22 44 75 116 168 232 309 400 506 628 767 924 1100 1296 1513 1752 2014 2300 2611 2948 +7 18 45 93 171 292 473 735 1103 1606 2277 3153 4275 5688 7441 9587 12183 15290 18973 23301 28347 +16 25 41 71 122 201 315 471 676 937 1261 1655 2126 2681 3327 4071 4920 5881 6961 8167 9506 +11 8 7 14 34 73 153 358 946 2603 6990 17860 43245 99637 219904 468209 967955 1953669 3866490 7528970 14465012 +5 7 7 9 24 70 172 362 679 1169 1885 2887 4242 6024 8314 11200 14777 19147 24419 30709 38140 +20 41 88 184 360 655 1116 1798 2764 4085 5840 8116 11008 14619 19060 24450 30916 38593 47624 58160 70360 +5 1 -3 -7 -11 -15 -19 -23 -27 -31 -35 -39 -43 -47 -51 -55 -59 -63 -67 -71 -75 +14 28 49 84 144 244 403 644 994 1484 2149 3028 4164 5604 7399 9604 12278 15484 19289 23764 28984 +22 39 76 159 327 632 1139 1926 3084 4717 6942 9889 13701 18534 24557 31952 40914 51651 64384 79347 96787 +-2 2 14 48 128 302 671 1448 3080 6489 13516 27685 55442 108067 204505 375415 668794 1157596 1949834 3201726 5134524 +8 26 74 174 355 653 1111 1779 2714 3980 5648 7796 10509 13879 18005 22993 28956 36014 44294 53930 65063 +23 33 50 91 180 356 702 1409 2889 5944 11981 23232 42888 74981 123741 192008 278083 370147 437052 413881 180172 +3 21 50 101 197 368 646 1058 1610 2250 2793 2786 1286 -3481 -14617 -37247 -79459 -153541 -277572 -477429 -789277 +11 24 52 113 232 438 776 1348 2397 4448 8520 16423 31154 57406 102204 175682 292015 470520 736940 1124925 1677724 +-10 -6 14 71 204 480 1012 2001 3833 7274 13814 26222 49416 91898 168406 305363 552580 1008090 1868702 3527701 6753848 +20 34 64 128 254 493 939 1767 3313 6233 11791 22339 42065 78098 142072 252264 436434 735508 1208258 1937146 3035512 +2 10 22 45 90 169 301 550 1131 2634 6438 15432 35251 76403 157947 313829 603648 1130570 2070406 3717599 6556112 +3 14 47 113 223 383 590 829 1076 1332 1752 2991 6966 18339 47197 113725 256297 545618 1109757 2178733 4163617 +9 24 49 94 186 381 792 1643 3363 6738 13143 24880 45652 81207 140190 235245 384413 612876 955101 1457442 2181262 +14 23 35 58 105 197 366 658 1136 1883 3005 4634 6931 10089 14336 19938 27202 36479 48167 62714 80621 +27 44 59 64 57 56 117 356 975 2292 4775 9080 16093 26976 43217 66684 99683 145020 206067 286832 392033 +17 25 33 41 49 57 65 73 81 89 97 105 113 121 129 137 145 153 161 169 177 +17 32 70 139 249 433 788 1552 3245 6924 14644 30289 61045 119922 229851 429893 783891 1391526 2401936 4033413 6616003 +16 27 55 113 230 463 916 1774 3367 6293 11651 21464 39397 71870 129603 229529 397057 669452 1104102 1803952 2993211 +11 34 80 162 301 533 917 1545 2563 4231 7097 12477 23695 49066 108610 248366 569762 1288551 2852013 6171819 13087348 +19 26 30 31 29 24 16 5 -9 -26 -46 -69 -95 -124 -156 -191 -229 -270 -314 -361 -411 +1 20 64 146 293 561 1063 2033 3966 7896 15901 31956 63292 122461 230354 420471 744799 1281716 2146406 3504342 5588471 +-4 0 10 41 129 333 731 1413 2475 4021 6200 9375 14701 25775 52754 121612 293282 700634 1615986 3568633 7541309 +14 29 57 101 164 254 391 628 1118 2290 5238 12478 29293 65976 141417 288696 563690 1058247 1920315 3384655 5819558 +12 22 42 72 112 162 222 292 372 462 562 672 792 922 1062 1212 1372 1542 1722 1912 2112 +18 38 82 159 280 460 722 1114 1749 2874 4983 9051 17156 34208 72464 162434 377514 886708 2062686 4695469 10402310 +3 5 19 57 145 338 735 1494 2847 5115 8723 14215 22269 33712 49535 70908 99195 135969 183027 242405 316393 +20 29 38 60 132 334 816 1836 3813 7404 13640 24238 42403 74835 136386 260038 516810 1053119 2157346 4373288 8686278 +16 42 90 173 313 554 995 1863 3648 7320 14640 28559 53665 96580 166117 272869 427704 638366 903014 1199049 1464961 +15 24 33 42 51 60 69 78 87 96 105 114 123 132 141 150 159 168 177 186 195 +8 31 73 153 298 550 988 1770 3200 5825 10567 18895 33042 56272 93202 150184 235752 361139 540869 793429 1142026 +9 30 70 140 259 471 876 1691 3385 6979 14670 31027 65128 134201 269698 527469 1005174 1872859 3427543 6190589 11077866 +-6 0 11 33 89 233 568 1274 2661 5271 10062 18716 34122 61094 107393 185131 312644 516930 836757 1326555 2061215 +6 22 41 56 57 40 22 53 226 709 1860 4547 10912 26080 61944 145656 338842 780748 1782863 4029602 8988143 +-9 -10 -4 15 67 204 545 1347 3146 7020 15048 31086 62104 120613 229283 429883 800389 1486794 2760144 5114905 9431989 +7 26 59 115 203 330 507 765 1178 1885 3098 5078 8056 12071 16692 20586 20889 12332 -13931 -71851 -182431 +25 50 84 133 218 381 694 1277 2328 4164 7285 12537 21617 38505 73019 148687 318659 695614 1504754 3173253 6475212 +4 0 -13 -29 -17 103 501 1516 3817 8718 18751 38637 76837 147924 276125 500603 883477 1522303 2569754 4264250 6975394 +27 47 81 153 311 639 1273 2437 4536 8382 15705 30247 60020 121869 250601 517175 1064855 2180784 4436721 8962954 17974199 +14 13 9 18 75 240 621 1432 3106 6494 13211 26249 51075 97579 183443 339777 620222 1115163 1973237 3432972 5868163 +23 50 93 161 277 492 914 1774 3579 7453 15857 34031 72745 153319 316418 636898 1248031 2379836 4418061 7992677 14107645 +11 10 21 56 127 246 425 676 1011 1442 1981 2640 3431 4366 5457 6716 8155 9786 11621 13672 15951 +26 45 69 98 132 171 215 264 318 377 441 510 584 663 747 836 930 1029 1133 1242 1356 +15 41 78 131 225 419 830 1676 3361 6664 13177 26300 53407 110349 230417 481486 997646 2035714 4073411 7975968 15273628 +-8 -8 -6 -4 2 30 119 334 774 1597 3082 5745 10513 18946 33506 57948 98120 163906 273862 465454 815928 +8 17 26 35 44 53 62 71 80 89 98 107 116 125 134 143 152 161 170 179 188 +-1 5 16 35 77 177 397 823 1538 2555 3704 4510 4223 2477 1816 15090 84677 329015 1049600 2966735 7719325 +4 15 32 59 108 199 360 627 1044 1663 2544 3755 5372 7479 10168 13539 17700 22767 28864 36123 44684 +-5 0 16 60 178 464 1087 2343 4767 9362 18027 34292 64492 119530 217386 386519 670275 1132348 1863234 2987460 4671150 +8 13 29 70 160 330 615 1051 1672 2507 3577 4892 6448 8224 10179 12249 14344 16345 18101 19426 20096 +2 7 12 14 26 92 302 807 1834 3701 6832 11772 19202 29954 45026 65597 93042 128947 175124 233626 306762 +13 22 55 135 310 683 1460 3025 6057 11710 21883 39613 69630 119119 198740 323963 516781 807870 1239271 1867675 2768398 +-9 -4 16 59 142 297 585 1133 2218 4431 8962 18062 35782 69203 130622 241651 441077 799858 1449144 2631225 4789554 +17 30 53 86 129 182 245 318 401 494 597 710 833 966 1109 1262 1425 1598 1781 1974 2177 +16 31 57 92 134 181 231 282 332 379 421 456 482 497 499 486 456 407 337 244 126 +15 23 45 95 192 361 640 1097 1863 3193 5577 9934 17943 32647 59747 110768 211035 418963 869777 1868209 4073414 +15 41 89 166 277 425 611 834 1091 1377 1685 2006 2329 2641 2927 3170 3351 3449 3441 3302 3005 +13 21 40 89 207 459 933 1736 3024 5143 9015 16975 34352 72189 151614 310506 613247 1164513 2128234 3753045 6405757 +16 23 38 68 130 264 551 1136 2256 4273 7712 13304 22034 35194 54441 81860 120032 172107 241882 333884 453458 +12 18 24 22 14 35 199 777 2326 5912 13508 28700 57900 112345 211255 386631 690296 1203918 2052904 3425218 5596354 +-8 -13 -18 -23 -28 -33 -38 -43 -48 -53 -58 -63 -68 -73 -78 -83 -88 -93 -98 -103 -108 +5 2 -3 -1 29 127 377 956 2206 4728 9528 18351 34588 65629 128400 261301 548362 1166341 2475406 5194738 10747314 +-9 -17 -13 18 105 315 784 1765 3731 7612 15304 30678 61474 122778 243443 478215 931187 1801827 3475476 6699809 12924125 +16 30 44 58 72 86 100 114 128 142 156 170 184 198 212 226 240 254 268 282 296 +-4 8 33 73 136 237 395 634 1019 1796 3769 9158 23371 58431 139277 314867 677022 1391344 2746409 5229879 9643306 +11 19 22 16 -7 -59 -159 -336 -612 -921 -880 748 7202 26037 73573 183088 419305 903051 1851778 3644040 6919135 +3 7 23 51 87 122 139 108 -21 -327 -929 -1999 -3777 -6588 -10861 -17150 -26157 -38757 -56025 -79265 -110041 +26 47 76 110 141 168 237 537 1594 4619 12080 28582 62153 126048 241197 439437 767682 1293199 2110172 3347750 5179789 +1 -3 5 43 135 311 607 1065 1733 2665 3921 5567 7675 10323 13595 17581 22377 28085 34813 42675 51791 +26 36 51 78 121 181 256 341 428 506 561 576 531 403 166 -209 -754 -1504 -2497 -3774 -5379 +24 49 83 120 161 228 376 695 1305 2378 4283 8064 16660 37614 88602 208180 476214 1052579 2250883 4679724 9513235 +6 11 34 83 159 267 436 749 1395 2780 5782 12315 26488 56816 120170 248451 499348 973001 1836946 3362379 5975549 +7 1 0 21 91 242 504 899 1439 2131 2992 4077 5523 7612 10856 16107 24695 38597 60640 94741 146187 +15 28 45 60 63 40 -27 -160 -385 -732 -1235 -1932 -2865 -4080 -5627 -7560 -9937 -12820 -16275 -20372 -25185 +12 19 30 45 64 87 114 145 180 219 262 309 360 415 474 537 604 675 750 829 912 +13 37 73 123 189 273 377 503 653 829 1033 1267 1533 1833 2169 2543 2957 3413 3913 4459 5053 +8 24 59 123 226 378 589 869 1228 1676 2223 2879 3654 4558 5601 6793 8144 9664 11363 13251 15338 +6 0 1 22 90 259 623 1329 2590 4698 8037 13096 20482 30933 45331 64715 90294 123460 165801 219114 285418 +1 0 4 15 33 59 104 204 441 970 2052 4093 7689 13677 23192 37730 59217 90084 133348 192699 272593 +18 22 33 57 109 231 522 1202 2761 6298 14256 31955 70704 153980 329421 691523 1423433 2871746 5676622 10992031 20849292 +21 23 32 62 131 275 575 1194 2432 4832 9409 18127 34816 66802 127618 241273 448679 816973 1452622 2519364 4262217 +3 10 22 41 68 108 186 383 907 2220 5248 11707 24584 48818 92232 166773 290123 487750 795474 1262629 1955908 +17 29 59 129 284 597 1180 2217 4044 7313 13292 24371 44865 82229 148827 264427 459627 780453 1294409 2098301 3328202 +-4 -7 -4 11 44 101 188 311 476 689 956 1283 1676 2141 2684 3311 4028 4841 5756 6779 7916 +13 31 65 132 273 571 1184 2408 4801 9423 18284 35154 66995 126451 236111 435682 793821 1427231 2530787 4423992 7621045 +-2 -5 -7 -5 16 92 291 737 1664 3518 7130 14019 27008 51653 99674 196927 400914 837061 1769967 3736899 7787848 +-7 -8 9 65 194 460 988 2015 3970 7595 14122 25524 44861 76745 127951 208204 331175 515722 787415 1180387 1739556 +21 44 94 181 311 498 791 1326 2429 4835 10159 21876 47279 101271 213575 442351 900001 1802661 3566842 7001844 13698911 +9 17 23 27 29 29 27 23 17 9 -1 -13 -27 -43 -61 -81 -103 -127 -153 -181 -211 +9 15 15 4 -11 3 122 493 1382 3245 6810 13147 23740 40756 68207 115815 209575 416951 901321 2031090 4585703 +15 26 51 114 247 502 981 1886 3601 6851 13046 25016 48484 94825 185957 362689 698703 1323992 2464873 4514282 8158873 +28 48 72 93 98 67 -31 -251 -694 -1518 -2883 -4725 -6176 -4292 8596 50348 160256 421832 1007774 2265645 4875030 +10 31 77 158 281 450 664 923 1271 1929 3607 8160 19938 48615 115226 265034 594392 1305015 2809553 5929150 12249559 +11 31 66 133 257 470 820 1399 2399 4205 7534 13629 24517 43340 74768 125503 204883 325595 504506 763621 1131177 +14 19 31 62 120 212 356 616 1182 2519 5613 12362 26228 53462 105720 206075 402990 801955 1634195 3399266 7148256 +5 -3 -6 14 89 276 686 1539 3264 6689 13407 26460 51554 99104 187509 348173 632919 1124589 1951784 3308874 5482599 +-4 3 34 112 283 625 1266 2420 4446 7930 13784 23349 38481 61590 95592 143723 209152 294317 399894 523294 656567 +-4 5 33 88 192 399 815 1624 3145 5985 11417 22210 44287 89811 182627 367450 724810 1394557 2611681 4759268 8444498 +15 30 58 110 197 330 520 778 1115 1542 2070 2710 3473 4370 5412 6610 7975 9518 11250 13182 15325 +14 11 2 -2 32 169 513 1214 2486 4655 8264 14270 24376 41549 70783 120174 202382 336563 550862 885566 1397024 +18 43 79 125 182 263 410 716 1359 2669 5267 10352 20327 40295 81829 172433 378440 857986 1978345 4565832 10419624 +4 10 17 26 42 88 231 636 1675 4136 9608 21163 44514 89909 175172 330649 607626 1093546 1940883 3423120 6042846 +3 22 53 98 162 263 459 900 1927 4263 9384 20245 42704 88286 179422 359061 707675 1372260 2614095 4884884 8944614 +4 15 38 73 120 179 250 333 428 535 654 785 928 1083 1250 1429 1620 1823 2038 2265 2504 +23 42 81 152 262 406 554 631 489 -130 -1641 -4674 -10144 -19334 -33992 -56443 -89717 -137694 -205267 -298524 -424950 +12 19 49 116 230 404 678 1165 2136 4196 8684 18602 40728 90256 200608 443427 967876 2075253 4356031 8933736 17886258 +-2 -8 -16 -16 7 73 207 438 805 1393 2443 4607 9452 20356 43984 92583 187392 363526 676762 1212730 2099093 +15 20 22 21 17 10 0 -13 -29 -48 -70 -95 -123 -154 -188 -225 -265 -308 -354 -403 -455 +2 5 14 30 53 82 115 149 180 203 212 200 159 80 -47 -233 -490 -831 -1270 -1822 -2503 +8 15 38 93 209 435 852 1596 2894 5121 8921 15540 27768 52407 106190 228941 511121 1148880 2550469 5537596 11722540 +-7 4 30 71 127 198 284 385 501 632 778 939 1115 1306 1512 1733 1969 2220 2486 2767 3063 +4 21 54 101 157 212 245 214 42 -401 -1320 -3021 -5941 -10682 -18049 -29092 -45152 -67911 -99446 -142287 -199479 +24 44 72 121 229 467 952 1889 3693 7283 14711 30431 63812 134129 280578 582555 1200874 2461318 5022490 10208249 20654203 +16 44 87 158 277 466 759 1245 2165 4087 8186 16659 33308 64327 119332 212676 365094 605726 974569 1525412 2329311 +23 51 104 192 325 513 766 1094 1507 2015 2628 3356 4209 5197 6330 7618 9071 10699 12512 14520 16733 +10 25 51 92 164 314 665 1513 3530 8178 18521 40743 86848 179241 358175 693406 1301834 2373431 4208375 7269030 12251244 +12 27 60 111 175 257 398 722 1523 3415 7570 16073 32432 62295 114440 202106 344702 569835 915392 1431035 2177845 +26 49 81 132 228 419 803 1580 3151 6278 12322 23577 43719 78390 135938 228335 372296 590623 913799 1381858 2046558 +13 13 25 74 204 497 1103 2287 4510 8579 15939 29260 53625 98891 184223 346449 654819 1236049 2315277 4280846 7783762 +10 31 75 145 249 406 653 1054 1721 2875 4998 9151 17554 34538 67982 131336 246300 446175 779821 1316045 2148095 +13 15 17 16 19 55 189 554 1427 3390 7660 16783 36127 77064 163516 344803 719657 1479081 2979707 5864762 11257059 +9 21 37 66 129 268 555 1100 2060 3670 6359 11077 20036 38154 75584 151800 301771 584784 1096751 1988587 3500239 +9 23 37 51 65 79 93 107 121 135 149 163 177 191 205 219 233 247 261 275 289 +3 6 27 74 157 302 581 1180 2541 5628 12381 26436 54203 106408 200219 362090 631471 1065546 1745175 2782230 4328529 +3 21 49 96 195 422 916 1896 3668 6604 11047 17037 23644 27511 19924 -18697 -128591 -387257 -936475 -2024770 -4072135 +2 19 49 85 125 186 324 662 1428 3005 5995 11299 20215 34556 56790 90204 139094 208983 306869 441505 623713 +3 -2 -12 -31 -56 -63 9 271 889 2076 4066 7065 11174 16279 21903 27015 29791 27322 15264 -12575 -64716 +-7 -12 -9 28 138 383 875 1840 3763 7691 15813 32487 65944 130968 252929 473633 859549 1513078 2587643 4307502 6993318 +2 1 -3 -13 -27 -17 104 527 1604 3917 8359 16227 29327 50091 81706 128255 194870 287897 415073 585715 810921 +-3 -1 2 6 11 17 24 32 41 51 62 74 87 101 116 132 149 167 186 206 227 +13 26 44 64 92 165 385 976 2383 5443 11681 23833 46794 89362 167440 309821 568385 1035568 1873426 3360638 5966520 +14 43 88 154 261 457 833 1552 2918 5524 10539 20244 39039 75362 145344 279640 535806 1019929 1923066 3580526 6565265 +9 6 5 6 9 14 21 30 41 54 69 86 105 126 149 174 201 230 261 294 329 +-3 12 39 84 173 364 759 1516 2861 5100 8631 13956 21693 32588 47527 67548 93853 127820 171015 225204 292365 +12 20 52 124 251 454 780 1348 2447 4728 9552 19581 39730 78636 150846 279981 503198 877348 1487316 2457130 3964541 +10 4 -3 -11 -20 -30 -41 -53 -66 -80 -95 -111 -128 -146 -165 -185 -206 -228 -251 -275 -300 +23 45 69 102 160 276 530 1122 2528 5807 13164 28920 61095 123874 241299 452612 819765 1437713 2448215 4057986 6562170 +22 47 91 160 273 481 903 1800 3731 7881 16734 35407 74202 153333 311438 620531 1211684 2318227 4346981 7993474 14424847 +3 18 59 136 255 417 617 843 1075 1284 1431 1466 1327 939 213 -955 -2685 -5114 -8397 -12708 -18241 +23 49 87 137 199 273 359 457 567 689 823 969 1127 1297 1479 1673 1879 2097 2327 2569 2823 +24 35 47 71 128 250 480 878 1551 2737 4986 9495 18669 36996 72341 137782 254130 453295 782681 1310815 2134438 diff --git a/2023/days/09/src/main.rs b/2023/days/09/src/main.rs new file mode 100644 index 0000000..086d872 --- /dev/null +++ b/2023/days/09/src/main.rs @@ -0,0 +1,14 @@ +mod part1; +mod part2; +mod parse; + +fn main() { + let input = include_str!("./input.txt"); + let mut structured_input = parse::parse(input); + + println!("Part One"); + println!("Result: {}", part1::part1(&structured_input)); + + println!("Part Two"); + println!("Result: {}", part2::part2(&mut structured_input)); +} diff --git a/2023/days/09/src/parse.rs b/2023/days/09/src/parse.rs new file mode 100644 index 0000000..4d80e69 --- /dev/null +++ b/2023/days/09/src/parse.rs @@ -0,0 +1,48 @@ +pub fn parse(input: &str) -> Vec> { + input + .lines() + .map(|l| l.split(' ').map(|n| n.parse().unwrap()).collect()) + .collect() +} + +pub fn get_differences(input: &[i32]) -> Vec { + input.windows(2).map(|p| p[1] - p[0]).collect() +} + +pub fn extrapolate_sequence(input: &[i32]) -> i32 { + if input.iter().all(|i| *i == 0) { + return 0; + }; + let diffs = get_differences(input); + input.last().unwrap() + extrapolate_sequence(&diffs) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_get_differences() { + assert_eq!(get_differences(&[0, 3, 6, 9, 12, 15]), vec![3, 3, 3, 3, 3]); + assert_eq!(get_differences(&[1, 3, 6, 10, 15, 21]), vec![2, 3, 4, 5, 6]); + } + + #[test] + fn test_extrapolate_sequence() { + assert_eq!(extrapolate_sequence(&[0, 3, 6, 9, 12, 15]), 18); + assert_eq!(extrapolate_sequence(&[1, 3, 6, 10, 15, 21]), 28); + } + + #[test] + fn test_parse() { + let input = concat!("0 3 6 9 12 15\n", "1 3 6 10 15 21\n", "10 13 16 21 30 45\n",); + assert_eq!( + parse(input), + vec![ + vec![0, 3, 6, 9, 12, 15], + vec![1, 3, 6, 10, 15, 21], + vec![10, 13, 16, 21, 30, 45], + ] + ); + } +} diff --git a/2023/days/09/src/part1.rs b/2023/days/09/src/part1.rs new file mode 100644 index 0000000..315964f --- /dev/null +++ b/2023/days/09/src/part1.rs @@ -0,0 +1,20 @@ +use crate::parse::*; + +pub fn part1(input: &[Vec]) -> i32 { + input.iter().map(|l| extrapolate_sequence(l)).sum() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part1() { + let input = vec![ + vec![0, 3, 6, 9, 12, 15], + vec![1, 3, 6, 10, 15, 21], + vec![10, 13, 16, 21, 30, 45], + ]; + assert_eq!(part1(&input), 114); + } +} diff --git a/2023/days/09/src/part2.rs b/2023/days/09/src/part2.rs new file mode 100644 index 0000000..c6b4189 --- /dev/null +++ b/2023/days/09/src/part2.rs @@ -0,0 +1,26 @@ +use crate::parse::*; + +pub fn part2(input: &mut [Vec]) -> i32 { + input + .iter_mut() + .map(|l| { + l.reverse(); + extrapolate_sequence(l) + }) + .sum() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part2() { + let mut input = vec![ + vec![0, 3, 6, 9, 12, 15], + vec![1, 3, 6, 10, 15, 21], + vec![10, 13, 16, 21, 30, 45], + ]; + assert_eq!(part2(&mut input), 2); + } +} diff --git a/2023/days/11/Cargo.toml b/2023/days/11/Cargo.toml new file mode 100644 index 0000000..73faadb --- /dev/null +++ b/2023/days/11/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "day11" +authors.workspace = true +description.workspace = true +version.workspace = true +edition.workspace = true + +[dependencies] +aoc_libs.workspace = true +collection_literals.workspace = true +itertools.workspace = true diff --git a/2023/days/11/src/input.txt b/2023/days/11/src/input.txt new file mode 100644 index 0000000..7e78179 --- /dev/null +++ b/2023/days/11/src/input.txt @@ -0,0 +1,140 @@ +.#..........#.....................#........................................................#....................................#........... +...................#........................................#......................#........................................................ +...........................................#......#..................#...................................................#.................. +....#......................#...............................................#.........................#.....#......#................#........ +.................................................................#.......................#.................................................. +..............................................................................................................................#............. +.......#........#.............#...................................................#...................................#..................... +.........................#...................................#............................................................................#. +....................#.............#.........#..........................................#...............#.................................... +.....................................................#...............#.............................................................#........ +...........................................................................................................................#................ +..........................................................#.........................................#...............#....................... +..............................................................................................#............................................. +.#........#........................#......#..............................................#..............................#...............#... +...............#......#...............................#.......#.........#......#.............................#.................#............ +...............................#..............#............................................................................................. +............................................................................................................................................ +.........................#.......................................#.......................................................................... +..................#........................#......................................#........................................#................ +..................................................#.......#..............................................#........................#.......#. +...#........#........................#....................................#...............#................................................. +............................................................................................................................................ +.......#........................#....................................................................................#...................... +...............#...........#........................................................................#....................................... +.............................................#................#.........#.............................................................#..... +...........#...........................#................#...........................#....................................................... +..................................................#.......................................#.............#................................... +.....#..................#..........#..............................#.............................#........................................#.. +..............................#...............................................................................................#............. +...................................................................................................................#........................ +..............#..........................................#.............#...........................#..............................#......... +...#...................................#.........................................#.......................................................... +..................#...................................................................#................................................#.... +..........................#...................................#.........................................#................................... +............................................................................................................................................ +.........#...........#..........#..........................................#....................#..............#........#.....#...........#. +....................................................#....................................................................................... +.............................................#.............................................................................................. +......................................#..................#..............................#...........#.......#............................... +............................#..................................#..............#............................................................. +...............#............................................................................................................................ +...........................................#............................#.......................#........................................... +.....#..............#.................................................................................#...........................#......... +............................................................................................................................................ +........................................#..........#.................#..........................................#........................... +.............................................#.................................#...........#................................................ +...............................#.......................#...........................................#.......#....................#........... +#........#.............#...............................................................................................#...................# +.....................................#........................#..........#.........#........................................................ +.................#............................................................................#............................................. +..........................#.......................................#.................................................#....................... +.....................................................#...................................#....................................#............. +..#......................................................................................................................................... +.............#.....#.......................#.............#....................................................#........................#.... +......#........................................................................................#............................................ +.................................#.................................#........................................................................ +.................................................................................#.......................#................................#. +#.....................................................#...................................................................#.....#........... +.........#..................................................#......................................#........................................ +..............................#.............#.................................................................#.......#..................... +........................#............................................................#......#................................#.............. +.............#.............................................................................................................................. +.....#........................................................#............#..........................#...........................#......... +...........................#......#.................................................................................#...................#... +.........#.....................................#...............................#............................................................ +..................#.......................................#.......#................................#........................................ +...............................#.....................#...................................#................................#................. +..............#..........................#.............................#............#.....................#.....................#.........#. +.................................................................................................................#.......................... +......#..................................................................................................................................... +...........#.............#.........#........................................................................................................ +...................................................................#..............#..................#...................................... +..................#...........................................................................................#............................. +........#.................................#..............#.................................................................#..........#..... +...#.....................................................................#..............#.......#........................................... +............................................................................................................................................ +............................................................................................................................................ +.................................#................#..........................................................#...............#.............# +..............#............................................................#................................................................ +......#.....................#..........................#........#.....#............#..............#......................................... +....................#..................................................................................#..................#................. +....................................#.........#........................................................................................#.... +..........................................................#..............#.................................................................. +................#...............................................................................................#.............#............. +............................................................................................................................................ +............................#...................#......#.............#..............................................#....................... +.............#...................................................................................#........................................#. +......................#..........................................................#.......#.................................................. +#...........................................................#............................................................................... +.........#.........................#.................#....................................................#.................#............... +............................................................................................................................................ +...................#.............................................#.....#.................................................................... +........................#.........................#.....................................................................................#... +.....#........................................................................................................................#............. +.......................................#...............................................................#.........#.......................... +............................#...........................#...........#......................#..............................#.......#......... +..#................................#...........#............................................................................................ +.................#..................................#...................#................................................................... +..........#.................................................#................................................#.............................. +.....................#...............................................................................#...................................... +..............#..................#..............................#.............#....................................#.........#........#..... +...#.............................................................................................#.......................................... +............................................#..........................................#.................................................... +.........#...............................................#..............................................................#................... +................#.........#................................................................................................................. +.....#..................................#............................#..............................#........#..................#..........# +...............................#............................................................................................................ +....................................................#........#.............................................................................. +........#..........................#.........#...............................................................................#.............. +....................................................................................................................#....................... +....................#........#......................................#.........#.....#.....#................................................. +................................................................................................................................#.....#..... +...............#..........................................#...............#...............................#................................. +...#..............................#......................................................................................................... +........................................................................................#............#....................................#. +............................................................................................................................#............... +...................................................................................#............................#........................... +#........#........#........#..........#.........#........................................................................................... +.............................................................#..............................#............................#.................. +................................#.......................#................................................................................... +.......................#................................................#...............#.........#..................#................#..... +............#..................................................................#........................#................................... +............................................................................................................................................ +......#.....................#.......#......#..............#......#.......................................................................... +.....................#...................................................................................................................... +................................#................................................#.............#...........................#.............#.. +..............................................................................................................#............................. +............#............#..........................................................................#.............................#......... +.....#...........#.....................#.............................#.....#........................................#....................... +................................................#...........#..........................#.................................................... +............................................................................................................................................ +#..........................#.....#................................................................#......................................#.. +..........................................#.................................................................#.............#................. +................#.........................................................#................................................................. +.......#..............................#..............................................#..........................................#........... +........................#...................................#............................................................................... +............................................................................................................................#............... +..............................#.....................#.............................#...........#.................#........................... +...............................................#................#.....#................................................#.................... +...................#...................#.................#.................#.........................#...................................... diff --git a/2023/days/11/src/main.rs b/2023/days/11/src/main.rs new file mode 100644 index 0000000..456385c --- /dev/null +++ b/2023/days/11/src/main.rs @@ -0,0 +1,14 @@ +mod part1; +mod part2; +mod parse; + +fn main() { + let input = include_str!("./input.txt"); + let structured_input = parse::parse(input); + + println!("Part One"); + println!("Result: {}", part1::part1(&structured_input)); + + println!("Part Two"); + println!("Result: {}", part2::part2(&structured_input)); +} diff --git a/2023/days/11/src/parse.rs b/2023/days/11/src/parse.rs new file mode 100644 index 0000000..01d4a4d --- /dev/null +++ b/2023/days/11/src/parse.rs @@ -0,0 +1,388 @@ +use std::collections::HashSet; + +use aoc_libs::distances::Distances; +use aoc_libs::points::UPoint; +use itertools::Itertools; + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum Space { + Galaxy, + Space, +} + +#[derive(Debug, PartialEq, Eq)] +pub struct SparseSpace { + galaxies: HashSet, + empty_rows: HashSet, + empty_columns: HashSet, +} + +impl SparseSpace { + pub fn get_distance_between_galaxies( + &self, + galaxy1: &UPoint, + galaxy2: &UPoint, + expantion: &usize, + ) -> usize { + // println!("distance between {:?} and {:?}", galaxy1, galaxy2); + + //get unexpanded distance. + let mut distance = galaxy1.taxicab_distance(galaxy2); + // println!("unexpanded distance is {}", distance); + + //expand rows + for y in galaxy1.y.min(galaxy2.y)+1..galaxy1.y.max(galaxy2.y) { + if self.empty_rows.contains(&y) { + // println!("expanding row {}", y); + distance += expantion + } + } + + //expand columns. + for x in galaxy1.x.min(galaxy2.x)+1..galaxy1.x.max(galaxy2.x) { + if self.empty_columns.contains(&x) { + // println!("expanding col {}", x); + distance += expantion + } + } + distance + } + + pub fn get_sum_of_distances(&self, expantion: usize) -> usize { + self.galaxies + .iter() + .combinations(2) + // .inspect(|pair| println!("{:?}", pair)) + .map(|pair| self.get_distance_between_galaxies(pair[0], pair[1], &expantion)) + // .inspect(|distance| println!("{:?}", distance)) + .sum() + } +} + +impl From>> for SparseSpace { + fn from(value: Vec>) -> Self { + let mut galaxies: HashSet = HashSet::new(); + let mut empty_rows: HashSet = HashSet::new(); + let mut empty_columns: HashSet = HashSet::new(); + //find all galaxies and empty rows. + for (y, row) in value.iter().enumerate() { + let mut has_galaxy = false; + for (x, space) in row.iter().enumerate() { + if *space == Space::Galaxy { + has_galaxy = true; + galaxies.insert(UPoint { x, y }); + }; + } + if !has_galaxy { + empty_rows.insert(y); + }; + } + + //find all empty columns + for x in 0..value[0].len() { + let mut has_galaxy = false; + for y in 0..value.len() { + if value[y][x] == Space::Galaxy { + has_galaxy = true; + } + } + if !has_galaxy { + empty_columns.insert(x); + }; + } + + SparseSpace { + galaxies, + empty_rows, + empty_columns, + } + } +} + +pub fn parse(input: &str) -> SparseSpace { + parse_to_space(input).into() +} + +pub fn parse_to_space(input: &str) -> Vec> { + input + .lines() + .map(|l| { + l.chars() + .map(|c| match c { + '#' => Space::Galaxy, + '.' => Space::Space, + _ => panic!("unexpected char {}", c), + }) + .collect() + }) + .collect() +} + +#[cfg(test)] +mod tests { + use collection_literals::collection; + + use super::*; + + #[test] + fn test_get_sum_of_distances() { + let tested = SparseSpace { + galaxies: collection! { + UPoint { x: 0, y: 2 }, + UPoint { x: 0, y: 9 }, + UPoint { x: 1, y: 5 }, + UPoint { x: 3, y: 0 }, + UPoint { x: 4, y: 9 }, + UPoint { x: 6, y: 4 }, + UPoint { x: 7, y: 1 }, + UPoint { x: 7, y: 8 }, + UPoint { x: 9, y: 6 } + }, + empty_rows: collection! {3, 7}, + empty_columns: collection! {2, 5, 8}, + }; + assert_eq!(tested.get_sum_of_distances(1), 374) + } + + #[test] + fn test_get_distance_between_galaxies() { + let tested = SparseSpace { + galaxies: collection! { + UPoint { x: 0, y: 2 }, + UPoint { x: 0, y: 9 }, + UPoint { x: 1, y: 5 }, + UPoint { x: 3, y: 0 }, + UPoint { x: 4, y: 9 }, + UPoint { x: 6, y: 4 }, + UPoint { x: 7, y: 1 }, + UPoint { x: 7, y: 8 }, + UPoint { x: 9, y: 6 } + }, + empty_rows: collection! {3, 7}, + empty_columns: collection! {2, 5, 8}, + }; + assert_eq!( + tested.get_distance_between_galaxies( + &UPoint { x: 4, y: 9 }, + &UPoint { x: 1, y: 5 }, + &1 + ), + 9 + ); + assert_eq!( + tested.get_distance_between_galaxies( + &UPoint { x: 7, y: 8 }, + &UPoint { x: 0, y: 3 }, + &1 + ), + 15 + ); + assert_eq!( + tested.get_distance_between_galaxies( + &UPoint { x: 0, y: 2 }, + &UPoint { x: 9, y: 6 }, + &1 + ), + 17 + ); + assert_eq!( + tested.get_distance_between_galaxies( + &UPoint { x: 0, y: 9 }, + &UPoint { x: 4, y: 9 }, + &1 + ), + 5 + ); + assert_eq!( + tested.get_distance_between_galaxies( + &UPoint { x: 3, y: 0 }, + &UPoint { x: 6, y: 4 }, + &1 + ), + 9 + ); + assert_eq!( + tested.get_distance_between_galaxies( + &UPoint { x: 7, y: 8 }, + &UPoint { x: 7, y: 8 }, + &1 + ), + 0 + ); + } + + #[test] + fn test_parse() { + let input = concat!( + "...#......\n", + ".......#..\n", + "#.........\n", + "..........\n", + "......#...\n", + ".#........\n", + ".........#\n", + "..........\n", + ".......#..\n", + "#...#.....\n", + ); + assert_eq!( + parse(input), + SparseSpace { + galaxies: collection! { + UPoint { x: 0, y: 2 }, + UPoint { x: 0, y: 9 }, + UPoint { x: 1, y: 5 }, + UPoint { x: 3, y: 0 }, + UPoint { x: 4, y: 9 }, + UPoint { x: 6, y: 4 }, + UPoint { x: 7, y: 1 }, + UPoint { x: 7, y: 8 }, + UPoint { x: 9, y: 6 } + }, + empty_rows: collection! {3, 7}, + empty_columns: collection! {2, 5, 8} + } + ) + } + + #[test] + fn test_parse_to_space() { + let input = concat!( + "...#......\n", + ".......#..\n", + "#.........\n", + "..........\n", + "......#...\n", + ".#........\n", + ".........#\n", + "..........\n", + ".......#..\n", + "#...#.....\n", + ); + assert_eq!( + parse_to_space(input), + vec![ + vec![ + Space::Space, + Space::Space, + Space::Space, + Space::Galaxy, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space + ], + vec![ + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Galaxy, + Space::Space, + Space::Space + ], + vec![ + Space::Galaxy, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space + ], + vec![ + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space + ], + vec![ + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Galaxy, + Space::Space, + Space::Space, + Space::Space + ], + vec![ + Space::Space, + Space::Galaxy, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space + ], + vec![ + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Galaxy + ], + vec![ + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space + ], + vec![ + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Galaxy, + Space::Space, + Space::Space + ], + vec![ + Space::Galaxy, + Space::Space, + Space::Space, + Space::Space, + Space::Galaxy, + Space::Space, + Space::Space, + Space::Space, + Space::Space, + Space::Space + ] + ] + ); + } +} diff --git a/2023/days/11/src/part1.rs b/2023/days/11/src/part1.rs new file mode 100644 index 0000000..1e36057 --- /dev/null +++ b/2023/days/11/src/part1.rs @@ -0,0 +1,27 @@ +use crate::parse::*; + +pub fn part1(input: &SparseSpace) -> usize { + input.get_sum_of_distances(1) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part1() { + let input = concat!( + "...#......\n", + ".......#..\n", + "#.........\n", + "..........\n", + "......#...\n", + ".#........\n", + ".........#\n", + "..........\n", + ".......#..\n", + "#...#.....\n", + ); + assert_eq!(part1(&parse(input)), 374) + } +} diff --git a/2023/days/11/src/part2.rs b/2023/days/11/src/part2.rs new file mode 100644 index 0000000..97e5a45 --- /dev/null +++ b/2023/days/11/src/part2.rs @@ -0,0 +1,28 @@ +use crate::parse::*; + +pub fn part2(input: &SparseSpace) -> usize { + input.get_sum_of_distances(999_999) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part2() { + let input = concat!( + "...#......\n", + ".......#..\n", + "#.........\n", + "..........\n", + "......#...\n", + ".#........\n", + ".........#\n", + "..........\n", + ".......#..\n", + "#...#.....\n", + ); + assert_eq!(parse(input).get_sum_of_distances(9), 1030); + assert_eq!(parse(input).get_sum_of_distances(99), 8410); + } +} diff --git a/2023/template/Cargo.toml b/2023/template/Cargo.toml new file mode 100644 index 0000000..801326a --- /dev/null +++ b/2023/template/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "template" +authors.workspace = true +description.workspace = true +version.workspace = true +edition.workspace = true + +[dependencies] +aoc_libs.workspace = true diff --git a/2023/template/src/input.txt b/2023/template/src/input.txt new file mode 100644 index 0000000..e69de29 diff --git a/2023/template/src/main.rs b/2023/template/src/main.rs new file mode 100644 index 0000000..456385c --- /dev/null +++ b/2023/template/src/main.rs @@ -0,0 +1,14 @@ +mod part1; +mod part2; +mod parse; + +fn main() { + let input = include_str!("./input.txt"); + let structured_input = parse::parse(input); + + println!("Part One"); + println!("Result: {}", part1::part1(&structured_input)); + + println!("Part Two"); + println!("Result: {}", part2::part2(&structured_input)); +} diff --git a/2023/template/src/parse.rs b/2023/template/src/parse.rs new file mode 100644 index 0000000..ed7984c --- /dev/null +++ b/2023/template/src/parse.rs @@ -0,0 +1,16 @@ +pub type StructuredInput = usize; + +pub fn parse(input: &str) -> StructuredInput { + unimplemented!() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse() { + let input = concat!(); + assert_eq!(0, 0); + } +} diff --git a/2023/template/src/part1.rs b/2023/template/src/part1.rs new file mode 100644 index 0000000..bcd1611 --- /dev/null +++ b/2023/template/src/part1.rs @@ -0,0 +1,15 @@ +use crate::parse::*; + +pub fn part1(input: &StructuredInput) -> usize { + unimplemented!() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part1() { + assert_eq!(0, 0); + } +} diff --git a/2023/template/src/part2.rs b/2023/template/src/part2.rs new file mode 100644 index 0000000..687e0cf --- /dev/null +++ b/2023/template/src/part2.rs @@ -0,0 +1,15 @@ +use crate::parse::*; + +pub fn part2(input: &StructuredInput) -> usize { + unimplemented!() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part2() { + assert_eq!(0, 0); + } +} diff --git a/2024/.gitignore b/2024/.gitignore new file mode 100644 index 0000000..3639c96 --- /dev/null +++ b/2024/.gitignore @@ -0,0 +1,6 @@ +# ---> Zig +.zig-cache/ +zig-out/ +build/ +build-*/ +docgen_tmp/ diff --git a/2024/README.md b/2024/README.md new file mode 100644 index 0000000..416012d --- /dev/null +++ b/2024/README.md @@ -0,0 +1,2 @@ +# advent_of_code_2024 + diff --git a/2024/build.zig b/2024/build.zig new file mode 100644 index 0000000..8bf641a --- /dev/null +++ b/2024/build.zig @@ -0,0 +1,75 @@ +const std = @import("std"); + +pub fn build(b: *std.Build) !void { + const allocator = b.allocator; + + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + + const run_all = b.step("run", "Run all days"); + const test_all = b.step("test", "Test all days"); + const check = b.step("check", "run checks"); + + const utils_mod = b.createModule(.{ .root_source_file = b.path("src/utils/mod.zig") }); + + var dirIt = (try std.fs.cwd().openDir( + "./src/days", + .{ .iterate = true }, + )).iterate(); + + while (try dirIt.next()) |entry| { + if (entry.kind == .directory) {} + // each day entry will have a main.zig + const source_file = try std.fs.path.join(allocator, &.{ "src", "days", entry.name, "main.zig" }); + defer allocator.free(source_file); + //make sure the main.zig exists + _ = std.fs.cwd().openFile(source_file, .{}) catch continue; + + const exe = b.addExecutable(.{ + .name = entry.name, + .root_source_file = b.path(source_file), + .target = target, + .optimize = optimize, + }); + exe.root_module.addImport("utils", utils_mod); + + b.installArtifact(exe); + const install_cmd = b.addInstallArtifact(exe, .{}); + const install_step = b.step( + b.fmt("install_{s}", .{entry.name}), + b.fmt("install {s}", .{entry.name}), + ); + install_step.dependOn(&install_cmd.step); + b.installArtifact(exe); + + const run_cmd = b.addRunArtifact(exe); + const run_step = b.step( + b.fmt("run_{s}", .{entry.name}), + b.fmt("run {s}", .{entry.name}), + ); + run_step.dependOn(&run_cmd.step); + run_all.dependOn(&run_cmd.step); + + const exe_test = b.addTest(.{ + .root_source_file = b.path(source_file), + .target = target, + .optimize = optimize, + }); + const test_cmd = b.addRunArtifact(exe_test); + const test_step = b.step( + b.fmt("test_{s}", .{entry.name}), + b.fmt("test {s}", .{entry.name}), + ); + test_step.dependOn(&test_cmd.step); + test_all.dependOn(&test_cmd.step); + + const exe_check = b.addExecutable(.{ + .name = entry.name, + .root_source_file = b.path(source_file), + .target = target, + .optimize = optimize, + }); + exe_check.root_module.addImport("utils", utils_mod); + check.dependOn(&exe_check.step); + } +} diff --git a/2024/build.zig.zon b/2024/build.zig.zon new file mode 100644 index 0000000..7f01cca --- /dev/null +++ b/2024/build.zig.zon @@ -0,0 +1,46 @@ +.{ + // This is the default name used by packages depending on this one. For + // example, when a user runs `zig fetch --save `, this field is used + // as the key in the `dependencies` table. Although the user can choose a + // different name, most users will stick with this provided value. + // + // It is redundant to include "zig" in this name because it is already + // within the Zig package namespace. + .name = .aoc2024, + + // This is a [Semantic Version](https://semver.org/). + // In a future version of Zig it will be used for package deduplication. + .version = "0.0.1", + + // Together with name, this represents a globally unique package + // identifier. This field is generated by the Zig toolchain when the + // package is first created, and then *never changes*. This allows + // unambiguous detection of one package being an updated version of + // another. + // + // When forking a Zig project, this id should be regenerated (delete the + // field and run `zig build`) if the upstream project is still maintained. + // Otherwise, the fork is *hostile*, attempting to take control over the + // original project's identity. Thus it is recommended to leave the comment + // on the following line intact, so that it shows up in code reviews that + // modify the field. + .fingerprint = 0x25105d4386327470, // Changing this has security and trust implications. + + // Tracks the earliest Zig version that the package considers to be a + // supported use case. + .minimum_zig_version = "0.14.0", + + // Specifies the set of files and directories that are included in this package. + // Only files and directories listed here are included in the `hash` that + // is computed for this package. Only files listed here will remain on disk + // when using the zig package manager. As a rule of thumb, one should list + // files required for compilation plus any license(s). + // Paths are relative to the build root. Use the empty string (`""`) to refer to + // the build root itself. + // A directory listed here means that all files within, recursively, are included. + .paths = .{ + "build.zig", + "build.zig.zon", + "src", + }, +} diff --git a/2024/src/days/template/input.txt b/2024/src/days/template/input.txt new file mode 100644 index 0000000..e69de29 diff --git a/2024/src/days/template/lib.zig b/2024/src/days/template/lib.zig new file mode 100644 index 0000000..95a0b68 --- /dev/null +++ b/2024/src/days/template/lib.zig @@ -0,0 +1 @@ +const std = @import("std"); diff --git a/2024/src/days/template/main.zig b/2024/src/days/template/main.zig new file mode 100644 index 0000000..8c0f96f --- /dev/null +++ b/2024/src/days/template/main.zig @@ -0,0 +1,10 @@ +const std = @import("std"); +const part1 = @import("part1.zig"); +const part2 = @import("part2.zig"); +const input = @embedFile("input.txt"); + +pub fn main() !void { + const stdout = std.io.getStdErr().writer(); + try stdout.print("Part1: {d}\n", .{part1.solve(input)}); + try stdout.print("Part2: {d}\n", .{part2.solve(input)}); +} diff --git a/2024/src/days/template/part1.zig b/2024/src/days/template/part1.zig new file mode 100644 index 0000000..2ded691 --- /dev/null +++ b/2024/src/days/template/part1.zig @@ -0,0 +1,14 @@ +const lib = @import("lib.zig"); +const std = @import("std"); +const utils = @import("utils"); + +pub fn solve(comptime input: []const u8) i32 { + return input.len; +} + +test "part1 sample" { + const input = + \\0 + ; + try std.testing.expectEqual(solve(input), 1); +} diff --git a/2024/src/days/template/part2.zig b/2024/src/days/template/part2.zig new file mode 100644 index 0000000..30680d9 --- /dev/null +++ b/2024/src/days/template/part2.zig @@ -0,0 +1,14 @@ +const lib = @import("lib.zig"); +const std = @import("std"); +const utils = @import("utils"); + +pub fn solve(comptime input: []const u8) i32 { + return input.len; +} + +test "part2 sample" { + const input = + \\0 + ; + try std.testing.expectEqual(solve(input), 1); +} diff --git a/2024/src/utils/mod.zig b/2024/src/utils/mod.zig new file mode 100644 index 0000000..95a0b68 --- /dev/null +++ b/2024/src/utils/mod.zig @@ -0,0 +1 @@ +const std = @import("std"); diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..4153cd3 --- /dev/null +++ b/LICENSE @@ -0,0 +1,287 @@ + EUROPEAN UNION PUBLIC LICENCE v. 1.2 + EUPL © the European Union 2007, 2016 + +This European Union Public Licence (the ‘EUPL’) applies to the Work (as defined +below) which is provided under the terms of this Licence. Any use of the Work, +other than as authorised under this Licence is prohibited (to the extent such +use is covered by a right of the copyright holder of the Work). + +The Work is provided under the terms of this Licence when the Licensor (as +defined below) has placed the following notice immediately following the +copyright notice for the Work: + + Licensed under the EUPL + +or has expressed by any other means his willingness to license under the EUPL. + +1. Definitions + +In this Licence, the following terms have the following meaning: + +- ‘The Licence’: this Licence. + +- ‘The Original Work’: the work or software distributed or communicated by the + Licensor under this Licence, available as Source Code and also as Executable + Code as the case may be. + +- ‘Derivative Works’: the works or software that could be created by the + Licensee, based upon the Original Work or modifications thereof. This Licence + does not define the extent of modification or dependence on the Original Work + required in order to classify a work as a Derivative Work; this extent is + determined by copyright law applicable in the country mentioned in Article 15. + +- ‘The Work’: the Original Work or its Derivative Works. + +- ‘The Source Code’: the human-readable form of the Work which is the most + convenient for people to study and modify. + +- ‘The Executable Code’: any code which has generally been compiled and which is + meant to be interpreted by a computer as a program. + +- ‘The Licensor’: the natural or legal person that distributes or communicates + the Work under the Licence. + +- ‘Contributor(s)’: any natural or legal person who modifies the Work under the + Licence, or otherwise contributes to the creation of a Derivative Work. + +- ‘The Licensee’ or ‘You’: any natural or legal person who makes any usage of + the Work under the terms of the Licence. + +- ‘Distribution’ or ‘Communication’: any act of selling, giving, lending, + renting, distributing, communicating, transmitting, or otherwise making + available, online or offline, copies of the Work or providing access to its + essential functionalities at the disposal of any other natural or legal + person. + +2. Scope of the rights granted by the Licence + +The Licensor hereby grants You a worldwide, royalty-free, non-exclusive, +sublicensable licence to do the following, for the duration of copyright vested +in the Original Work: + +- use the Work in any circumstance and for all usage, +- reproduce the Work, +- modify the Work, and make Derivative Works based upon the Work, +- communicate to the public, including the right to make available or display + the Work or copies thereof to the public and perform publicly, as the case may + be, the Work, +- distribute the Work or copies thereof, +- lend and rent the Work or copies thereof, +- sublicense rights in the Work or copies thereof. + +Those rights can be exercised on any media, supports and formats, whether now +known or later invented, as far as the applicable law permits so. + +In the countries where moral rights apply, the Licensor waives his right to +exercise his moral right to the extent allowed by law in order to make effective +the licence of the economic rights here above listed. + +The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to +any patents held by the Licensor, to the extent necessary to make use of the +rights granted on the Work under this Licence. + +3. Communication of the Source Code + +The Licensor may provide the Work either in its Source Code form, or as +Executable Code. If the Work is provided as Executable Code, the Licensor +provides in addition a machine-readable copy of the Source Code of the Work +along with each copy of the Work that the Licensor distributes or indicates, in +a notice following the copyright notice attached to the Work, a repository where +the Source Code is easily and freely accessible for as long as the Licensor +continues to distribute or communicate the Work. + +4. Limitations on copyright + +Nothing in this Licence is intended to deprive the Licensee of the benefits from +any exception or limitation to the exclusive rights of the rights owners in the +Work, of the exhaustion of those rights or of other applicable limitations +thereto. + +5. Obligations of the Licensee + +The grant of the rights mentioned above is subject to some restrictions and +obligations imposed on the Licensee. Those obligations are the following: + +Attribution right: The Licensee shall keep intact all copyright, patent or +trademarks notices and all notices that refer to the Licence and to the +disclaimer of warranties. The Licensee must include a copy of such notices and a +copy of the Licence with every copy of the Work he/she distributes or +communicates. The Licensee must cause any Derivative Work to carry prominent +notices stating that the Work has been modified and the date of modification. + +Copyleft clause: If the Licensee distributes or communicates copies of the +Original Works or Derivative Works, this Distribution or Communication will be +done under the terms of this Licence or of a later version of this Licence +unless the Original Work is expressly distributed only under this version of the +Licence — for example by communicating ‘EUPL v. 1.2 only’. The Licensee +(becoming Licensor) cannot offer or impose any additional terms or conditions on +the Work or Derivative Work that alter or restrict the terms of the Licence. + +Compatibility clause: If the Licensee Distributes or Communicates Derivative +Works or copies thereof based upon both the Work and another work licensed under +a Compatible Licence, this Distribution or Communication can be done under the +terms of this Compatible Licence. For the sake of this clause, ‘Compatible +Licence’ refers to the licences listed in the appendix attached to this Licence. +Should the Licensee's obligations under the Compatible Licence conflict with +his/her obligations under this Licence, the obligations of the Compatible +Licence shall prevail. + +Provision of Source Code: When distributing or communicating copies of the Work, +the Licensee will provide a machine-readable copy of the Source Code or indicate +a repository where this Source will be easily and freely available for as long +as the Licensee continues to distribute or communicate the Work. + +Legal Protection: This Licence does not grant permission to use the trade names, +trademarks, service marks, or names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the copyright notice. + +6. Chain of Authorship + +The original Licensor warrants that the copyright in the Original Work granted +hereunder is owned by him/her or licensed to him/her and that he/she has the +power and authority to grant the Licence. + +Each Contributor warrants that the copyright in the modifications he/she brings +to the Work are owned by him/her or licensed to him/her and that he/she has the +power and authority to grant the Licence. + +Each time You accept the Licence, the original Licensor and subsequent +Contributors grant You a licence to their contributions to the Work, under the +terms of this Licence. + +7. Disclaimer of Warranty + +The Work is a work in progress, which is continuously improved by numerous +Contributors. It is not a finished work and may therefore contain defects or +‘bugs’ inherent to this type of development. + +For the above reason, the Work is provided under the Licence on an ‘as is’ basis +and without warranties of any kind concerning the Work, including without +limitation merchantability, fitness for a particular purpose, absence of defects +or errors, accuracy, non-infringement of intellectual property rights other than +copyright as stated in Article 6 of this Licence. + +This disclaimer of warranty is an essential part of the Licence and a condition +for the grant of any rights to the Work. + +8. Disclaimer of Liability + +Except in the cases of wilful misconduct or damages directly caused to natural +persons, the Licensor will in no event be liable for any direct or indirect, +material or moral, damages of any kind, arising out of the Licence or of the use +of the Work, including without limitation, damages for loss of goodwill, work +stoppage, computer failure or malfunction, loss of data or any commercial +damage, even if the Licensor has been advised of the possibility of such damage. +However, the Licensor will be liable under statutory product liability laws as +far such laws apply to the Work. + +9. Additional agreements + +While distributing the Work, You may choose to conclude an additional agreement, +defining obligations or services consistent with this Licence. However, if +accepting obligations, You may act only on your own behalf and on your sole +responsibility, not on behalf of the original Licensor or any other Contributor, +and only if You agree to indemnify, defend, and hold each Contributor harmless +for any liability incurred by, or claims asserted against such Contributor by +the fact You have accepted any warranty or additional liability. + +10. Acceptance of the Licence + +The provisions of this Licence can be accepted by clicking on an icon ‘I agree’ +placed under the bottom of a window displaying the text of this Licence or by +affirming consent in any other similar way, in accordance with the rules of +applicable law. Clicking on that icon indicates your clear and irrevocable +acceptance of this Licence and all of its terms and conditions. + +Similarly, you irrevocably accept this Licence and all of its terms and +conditions by exercising any rights granted to You by Article 2 of this Licence, +such as the use of the Work, the creation by You of a Derivative Work or the +Distribution or Communication by You of the Work or copies thereof. + +11. Information to the public + +In case of any Distribution or Communication of the Work by means of electronic +communication by You (for example, by offering to download the Work from a +remote location) the distribution channel or media (for example, a website) must +at least provide to the public the information requested by the applicable law +regarding the Licensor, the Licence and the way it may be accessible, concluded, +stored and reproduced by the Licensee. + +12. Termination of the Licence + +The Licence and the rights granted hereunder will terminate automatically upon +any breach by the Licensee of the terms of the Licence. + +Such a termination will not terminate the licences of any person who has +received the Work from the Licensee under the Licence, provided such persons +remain in full compliance with the Licence. + +13. Miscellaneous + +Without prejudice of Article 9 above, the Licence represents the complete +agreement between the Parties as to the Work. + +If any provision of the Licence is invalid or unenforceable under applicable +law, this will not affect the validity or enforceability of the Licence as a +whole. Such provision will be construed or reformed so as necessary to make it +valid and enforceable. + +The European Commission may publish other linguistic versions or new versions of +this Licence or updated versions of the Appendix, so far this is required and +reasonable, without reducing the scope of the rights granted by the Licence. New +versions of the Licence will be published with a unique version number. + +All linguistic versions of this Licence, approved by the European Commission, +have identical value. Parties can take advantage of the linguistic version of +their choice. + +14. Jurisdiction + +Without prejudice to specific agreement between parties, + +- any litigation resulting from the interpretation of this License, arising + between the European Union institutions, bodies, offices or agencies, as a + Licensor, and any Licensee, will be subject to the jurisdiction of the Court + of Justice of the European Union, as laid down in article 272 of the Treaty on + the Functioning of the European Union, + +- any litigation arising between other parties and resulting from the + interpretation of this License, will be subject to the exclusive jurisdiction + of the competent court where the Licensor resides or conducts its primary + business. + +15. Applicable Law + +Without prejudice to specific agreement between parties, + +- this Licence shall be governed by the law of the European Union Member State + where the Licensor has his seat, resides or has his registered office, + +- this licence shall be governed by Belgian law if the Licensor has no seat, + residence or registered office inside a European Union Member State. + +Appendix + +‘Compatible Licences’ according to Article 5 EUPL are: + +- GNU General Public License (GPL) v. 2, v. 3 +- GNU Affero General Public License (AGPL) v. 3 +- Open Software License (OSL) v. 2.1, v. 3.0 +- Eclipse Public License (EPL) v. 1.0 +- CeCILL v. 2.0, v. 2.1 +- Mozilla Public Licence (MPL) v. 2 +- GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3 +- Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for + works other than software +- European Union Public Licence (EUPL) v. 1.1, v. 1.2 +- Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong + Reciprocity (LiLiQ-R+). + +The European Commission may update this Appendix to later versions of the above +licences without producing a new version of the EUPL, as long as they provide +the rights granted in Article 2 of this Licence and protect the covered Source +Code from exclusive appropriation. + +All other changes or additions to this Appendix require the production of a new +EUPL version.