1
0
Fork 0

porting over AOC from previous years to a monorepo.

This commit is contained in:
Gabe Venberg 2026-04-16 14:45:29 +02:00
commit 84c4cf9991
194 changed files with 30104 additions and 0 deletions

140
2020/.gitignore vendored Normal file
View file

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

1
2020/.python-version Normal file
View file

@ -0,0 +1 @@
3.13

3
2020/README.md Normal file
View file

@ -0,0 +1,3 @@
# advent_of_code_2020
Python [advent of code](https://adventofcode.com/2020) 2020

54
2020/days/01/day1.py Executable file
View file

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

6
2020/days/01/example1 Normal file
View file

@ -0,0 +1,6 @@
1721
979
366
299
675
1456

200
2020/days/01/input Normal file
View file

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

33
2020/days/01/test_day1.py Normal file
View file

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

51
2020/days/02/day2.py Executable file
View file

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

3
2020/days/02/example1 Normal file
View file

@ -0,0 +1,3 @@
1-3 a: abcde
1-3 b: cdefg
2-9 c: ccccccccc

1000
2020/days/02/input Normal file

File diff suppressed because it is too large Load diff

37
2020/days/02/test_day2.py Normal file
View file

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

38
2020/days/03/day3.py Executable file
View file

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

11
2020/days/03/example1 Normal file
View file

@ -0,0 +1,11 @@
..##.......
#...#...#..
.#....#..#.
..#.#...#.#
.#...##..#.
..#.##.....
.#.#.#....#
.#........#
#.##...#...
#...##....#
.#..#...#.#

323
2020/days/03/input Normal file
View file

@ -0,0 +1,323 @@
........#.............#........
...#....#...#....#.............
.#..#...#............#.....#..#
..#......#..##............###..
..........#......#..#..#.......
.#..#.......#.........#.#......
.........#..#....##..#.##....#.
..#....##...#..................
##..........#.##...#....##..#..
...#....#...#..............#...
...........................#..#
..##.##.#..................#...
...#.##..#............#........
........#.......#...#.....##.#.
.##..........#......#.......#..
...#..........#...#..#.......#.
......#...#...#.##.......#.#...
........#...#...#...##.........
#..............#.#....#.......#
..#..#..#.#....#...............
.....#........#...#..........#.
##......#...#..#.##.......#....
..#.#.....#.#.............#.#.#
#..#..##......##...#...........
..#......#........#.....#......
.....#.......#....#.#...#......
...#........#...........#...#..
.......#.#...........###....#..
...#...........##....##........
#....#..####....#.....#..#....#
..........#...........#........
...#.......#....#.#.........#..
....#...#.......#..###.........
......#......#..#......#..#....
...#.....#............#..#.....
...#.#.#.#..#.......#.....#....
#....##...#.........#...##.....
#..#.......#..#..#..#...##.....
#.......#............#.....#...
.#........##....##...#........#
.....#...#.....................
.......#........#..............
.....#............#.#.#...#.#..
.....##..#.............#.......
..#.##..#........#..#...#......
.........#.#....#...........#..
.#.....#..#....#.....#...#.....
....#.#................#.......
...............##......#...#...
.##...#...#.......##.#....#....
............#........#.......#.
......##.#.#...................
.#.#..............#.......#....
#.....#...#.......#..#...#.....
.............#....#..#......#..
........#...##................#
.......#...#..#..##............
..#..#...##...#..#.#.....#...#.
.#.#...#.........#.#...........
...###....#.......#...#........
........#......##.#...#..##..#.
.....................#.#.......
.............#...........#...#.
#..#..#.....#.#...#............
...#....#.....#...........#....
..##.....##...#......#..##.....
#.....#.....###.#.....#....##..
.#...........###...............
..................#..##.#...#..
................#....##.#......
.#.#.#...#....#.........#..#.#.
#.......#........##............
.......##.#....#.#............#
..........#..##.#....#.........
........##..#....#.............
.........#....#...........##...
#.........#.#..#..#..........#.
.....#........#......#.........
....#.#.#...............#......
.#..#..##...#.##..........#....
..#....................#.#.....
.........#....#...........#.#.#
........#....##.##.............
..#.....#.......#..#......#....
#..........#.#.....#.#....#....
........##.#.....#..#.....#.#..
...................#...#....#.#
............#..#....#...#...#..
..............#.#.........#....
...#..#..#.#..##..##...........
.#...........................#.
.#.......#...........#....#.#.#
......#..#...#........#...##...
.........#......#.#.......#...#
...#..##................#......
.............#.#..##....#.#....
...............#..#......#.....
.#......#.#.#....#........#....
........#..#.##..#..#.........#
...#....#.#...#..#.......#..#..
..#...##.........#..#...#......
...#...........#.............#.
....#.....................#....
.....#..#...............#.#...#
....#..........#........#......
..#....#........##..##.........
...#....#..#.#.......#...#.....
..#........#....#...##....#.#..
.#...#........##.....#....###..
#....#....##......#........#...
.........#..#.#..........#....#
....#...#.....#.......##.......
..............#..........#.##..
#...#..#..............#......#.
.................#......##....#
..#..##..#.......#..#.#......#.
.............#........#.....#.#
.#.##............#..#..........
..#...#...........#..##........
.#....#...#....#.......#.......
...#.#..#..#..#....#.....#..#..
....#..##..............#...#...
#..........###......###........
.##.##......#..#............#..
.#...........#.#.....#...#.....
#.#..#...#............#........
.........#...#...#..........##.
.......###..#..........#.......
...........###.....#........#..
.#.............#.....#......#..
...#.....#....#.#.........##...
....##..##...#.......##........
......#....##.........#......#.
..........#.....##..#.....#..#.
..........####...#..#.........#
.##....#..#.#...#.......#......
...#.#.##.#.#...#....#.#.#.....
.........#...##........##.....#
..#........#..........##...##.#
##...##..........#.#...........
..............#......#.........
........#.....#.#.......#......
.#...#.....#....#.#..#.........
.....#....................##...
....#..................#.#...##
.....#............#..##........
#..........#....#.#.......##.#.
....#..#.....................#.
#..#....##.....#...............
..#...#..#..##....#.#..........
.......#......#.#.......#.....#
...#.#.......#...#.##..........
....#..........#....#.#.#......
.......#..#..........#..##.....
#......#......#...#......#...#.
###..#....##......##........#..
.#..........#.....#.......#.#..
.......#.....#.....#.#.........
..#...#....#...................
..............#.##.............
.#...#.......#.##...#.#.......#
.......#......................#
....#.#...#.#........#.........
.#......#....#...#.............
#.......#...###.....#.#.#..#...
#....##.#...............##.....
..#.......#..................#.
.....####...............#......
.##......#......#.#.......##.#.
#......##..###....#....#......#
.##.......##.##...#.##.........
......##............#.......#..
......#..#.....##.#............
.#..........#.....##...........
#.........#......#......##.#...
.........#.......#..#......#.#.
.........#.......#...........#.
.#..##.#..................##...
.............#.............#...
.....##........#......##...##..
..#..#.#.....#..#....#.........
.....#....#.....#.....#........
#......##.....#....#....#......
#.................#..#.#......#
.......#..#......#....#.#...#.#
....#.........#..#..........#.#
##......#............#...#...#.
....##......#...#.....#....##..
.#...##.........#..............
......#.....................#..
..#..........###....#..........
#....#...#..#.............#....
#........#.#......#....#.......
.#...#.......#..#...#.#...#..#.
................##.#.....#.....
###.......#...#................
...#.......#...#.#.....#.......
..#.........#.....#.#.......#..
......#.......................#
#.....#.#..#....#.......#......
...#....#..#....####...........
.............#.....#...##......
.......#.........#...#..#......
.##..#.........#....#.#........
....##...#.#...........#....#..
.........................##....
..###.......##....#.#.........#
.#....#.#.#...........##....#..
......#...#..#..#..#..#.......#
..#....#.#.......#..#..#..#...#
.....##...#.##....#.#...#......
.........#..#....#..#..........
.##..##.........#.#.....#......
..........#...##...#.#...#.....
#.##..#..#.............#.......
...#...........#.......#......#
.......#....#....#...##.......#
..#.##........###..#......#....
...#...........###......#..#..#
.#.........#.#.........#.#.....
##.......##.##.##......##......
............#...#..........#...
....................#..........
...#..#...........#...#...#....
.................#...#......###
...#................#.#.##.....
...............#........#......
#.............##......#.#..#...
..#.#.....#..#.##.....##...#...
......#.........#......#.......
#.......#......#....#........#.
.#..##.....#.........#.........
....##.##.#...#.........##.#...
...............#..#..#..##.....
.#..#...............###........
.##............##..............
...............#...##...#...#.#
..#.#......#.#..#.............#
#.#..#..##.........#.#.#...#...
....##.#....................##.
.........#..#.....#.....#..#..#
....#......#......#.##....#....
........###..#.............#..#
##................#.........#..
#.....#.......#....#...........
..#.......#..#........#....#...
..#.#.##..#.#...##........#.##.
..#..........#............#....
..........#...............##...
..........###........#.#.......
.....###..#.............#......
##.............#...#.....#.....
.....#......#....#........#.#..
............#..#..............#
.................#...........##
#........#.........###.....#...
..#.#..............##......#.#.
.#...........#.........#..##..#
...............................
.#.....#..#....#....#......#...
.#...#......#.#..#....#.......#
......#.##.......#......#......
......#..###..#................
#..#.....#........##...#.......
......##.........##....#...##..
.#..........#.................#
#..#.......#...............#...
.........#..###....#.#.##.#....
..#...#.##..##...............##
.........#.....................
.#....##...#......#....#.......
............#..........#..#....
...#......##....#....#........#
.#...................#.........
#.#........###....#..........#.
.........#....#....#........##.
.#....#..#.........#..#........
...............#..#...#..#...##
.........#....##....#......#...
.#.............................
...#........#...#.#...#.#..#...
.....#..##...#.#...............
#.....#....#.........#.........
#...#...........##.........#...
..##........#.#...#...#......#.
...........#.....#...#.#.......
......###....#.....#...........
......##...#..........#....#.#.
.......##..##..........#.......
....#............#..#....##....
..##...................#.#.....
...#.#..#.#....................
.#..##..#............##.###..#.
#.#...#....#.#..........#.#....
........#....#.....#...........
..##....#...#.......#..........
...........##.##....#..........
.....#............#............
.......#.............#....#....
.................#......#......
......##.......#....#..##...#..
.#..#....#.....................
...#.#.#...#......##...........
##........##.#....#....#.......
.......#.....#..#..#...#.##....
#..........#....#.#..#..#..#...
...##..............#...........
.........#.....#.#....#.......#
.........#....##..#..##..#.....
.....#......................#..
...###...#..#......#...........
....#.....................#....
...............................
..#.....###.......#..#....#....
#..........#.................#.
......#.......###.......#..##..
.............#.##..............
......#..#.#..#...........#....
...#....##.#...#..#.#...#....#.
..................#...#....#.##
......#.#....#.................
......#.#.....#.....#..##......
#..##...........#..#.....#.##..

43
2020/days/03/test_day3.py Normal file
View file

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

132
2020/days/04/day4.py Executable file
View file

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

13
2020/days/04/example1 Normal file
View file

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

1146
2020/days/04/input Normal file

File diff suppressed because it is too large Load diff

65
2020/days/04/test_day4.py Normal file
View file

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

46
2020/days/05/day5.py Executable file
View file

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

4
2020/days/05/example1 Normal file
View file

@ -0,0 +1,4 @@
FBFBBFFRLR
BFFFBBFRRR
FFFBBBFRRR
BBFFBBFRLL

859
2020/days/05/input Normal file
View file

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

33
2020/days/05/test_day5.py Normal file
View file

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

47
2020/days/06/day6.py Executable file
View file

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

15
2020/days/06/example1 Normal file
View file

@ -0,0 +1,15 @@
abc
a
b
c
ab
ac
a
a
a
a
b

2199
2020/days/06/input Normal file

File diff suppressed because it is too large Load diff

55
2020/days/06/test_day6.py Normal file
View file

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

6
2020/main.py Normal file
View file

@ -0,0 +1,6 @@
def main():
print("Hello from 2020!")
if __name__ == "__main__":
main()

9
2020/pyproject.toml Normal file
View file

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

31
2020/template/template.py Executable file
View file

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

View file

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

75
2020/uv.lock generated Normal file
View file

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

1
2022/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target

197
2022/Cargo.lock generated Normal file
View file

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

21
2022/Cargo.toml Normal file
View file

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

6
2022/aoc_libs/Cargo.toml Normal file
View file

@ -0,0 +1,6 @@
[package]
name = "aoc_libs"
version.workspace = true
authors.workspace = true
edition.workspace = true
description.workspace = true

1
2022/aoc_libs/src/lib.rs Normal file
View file

@ -0,0 +1 @@
pub mod points;

211
2022/aoc_libs/src/points.rs Normal file
View file

@ -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<UPoint> {
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<const X: usize, const Y: usize, T> {
matrix: [[T; X]; Y],
max_point: Point,
min_point: Point,
zero_coord: UPoint,
}
impl<const X: usize, const Y: usize, T> 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<T, const X: usize, const Y: usize> std::ops::IndexMut<Point> 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<T, const X: usize, const Y: usize> std::ops::Index<Point> 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<T, const X: usize, const Y: usize> From<FourQuadrantMatrix<{ X }, { Y }, T>> for [[T; X]; Y] {
fn from(value: FourQuadrantMatrix<{ X }, { Y }, T>) -> Self {
value.matrix
}
}

6
2022/days/01/Cargo.toml Normal file
View file

@ -0,0 +1,6 @@
[package]
name = "day01"
authors.workspace = true
description.workspace = true
version.workspace = true
edition.workspace = true

2255
2022/days/01/src/input.txt Normal file

File diff suppressed because it is too large Load diff

14
2022/days/01/src/main.rs Normal file
View file

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

48
2022/days/01/src/parse.rs Normal file
View file

@ -0,0 +1,48 @@
#[derive(Debug, PartialEq, Eq)]
pub struct Elf(pub Vec<usize>);
pub fn parse(input: &str) -> Vec<Elf> {
input
.trim()
.split("\n\n")
.map(|group| {
Elf(group
.split('\n')
.map(|line| line.parse().unwrap())
.collect())
})
.collect::<Vec<Elf>>()
}
#[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])
]
);
}
}

27
2022/days/01/src/part1.rs Normal file
View file

@ -0,0 +1,27 @@
use crate::parse;
pub fn part1(input: &[parse::Elf]) -> usize {
input
.iter()
.map(|elf| elf.0.iter().sum::<usize>())
.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);
}
}

27
2022/days/01/src/part2.rs Normal file
View file

@ -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::<usize>())
.collect::<Vec<usize>>();
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);
}
}

6
2022/days/02/Cargo.toml Normal file
View file

@ -0,0 +1,6 @@
[package]
name = "day02"
authors.workspace = true
description.workspace = true
version.workspace = true
edition.workspace = true

2500
2022/days/02/src/input.txt Normal file

File diff suppressed because it is too large Load diff

13
2022/days/02/src/main.rs Normal file
View file

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

62
2022/days/02/src/part1.rs Normal file
View file

@ -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<Strategy> {
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
}
]
);
}
}

87
2022/days/02/src/part2.rs Normal file
View file

@ -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<ResultStrategy> {
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);
}
}

View file

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

6
2022/days/03/Cargo.toml Normal file
View file

@ -0,0 +1,6 @@
[package]
name = "day03"
authors.workspace = true
description.workspace = true
version.workspace = true
edition.workspace = true

300
2022/days/03/src/input.txt Normal file
View file

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

14
2022/days/03/src/main.rs Normal file
View file

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

54
2022/days/03/src/part1.rs Normal file
View file

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

78
2022/days/03/src/part2.rs Normal file
View file

@ -0,0 +1,78 @@
use crate::utilities::*;
use std::collections::HashSet;
struct Group(HashSet<char>, HashSet<char>, HashSet<char>);
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<Group> {
let mut output: Vec<Group> = 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);
}
}

View file

@ -0,0 +1,93 @@
use std::collections::HashSet;
#[derive(Debug, PartialEq, Eq)]
pub struct Rucksack(pub HashSet<char>, pub HashSet<char>);
pub fn parse(input: &str) -> Vec<Rucksack> {
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',])
),
]
);
}
}

10
2022/days/04/Cargo.toml Normal file
View file

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

1000
2022/days/04/src/input.txt Normal file

File diff suppressed because it is too large Load diff

14
2022/days/04/src/main.rs Normal file
View file

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

27
2022/days/04/src/part1.rs Normal file
View file

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

27
2022/days/04/src/part2.rs Normal file
View file

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

View file

@ -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<Regex> = 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)),
]
);
}
}

10
2022/days/05/Cargo.toml Normal file
View file

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

514
2022/days/05/src/input.txt Normal file
View file

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

14
2022/days/05/src/main.rs Normal file
View file

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

48
2022/days/05/src/part1.rs Normal file
View file

@ -0,0 +1,48 @@
use crate::utilities::*;
pub fn part1(input: &(WorkArea, Vec<Move>)) -> Vec<char> {
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']);
}
}

48
2022/days/05/src/part2.rs Normal file
View file

@ -0,0 +1,48 @@
use crate::utilities::*;
pub fn part2(input: &(WorkArea, Vec<Move>)) -> Vec<char> {
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']);
}
}

View file

@ -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<Vec<char>>,
}
impl WorkArea {
pub fn new(stacks: Vec<Vec<char>>) -> 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<char> = 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<Vec<char>> {
&self.stacks
}
}
pub fn parse(input: &str) -> (WorkArea, Vec<Move>) {
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<char>> = 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<Move> {
static PARSE_MOVES_REGEX: Lazy<Regex> =
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
},
]
)
);
}
}

6
2022/days/06/Cargo.toml Normal file
View file

@ -0,0 +1,6 @@
[package]
name = "day06"
authors.workspace = true
description.workspace = true
version.workspace = true
edition.workspace = true

View file

@ -0,0 +1 @@
bhzhtzzsczszsjjjzddfzdfzfjfzfbbnntnzznwzzvfvrrqmrmmdzzfqfhqhsqqpwpgwpppbtbnnstthmhrrsmmvsmmhjmjfmfsfjfnfnjjvcjjszjszjsszbznzbnzndzzmlldsdgdcddmqmfqqlcllbvllztzctzczdzttlmtlthtmhtmhmmszsllvzvdzzzsqzqbqccvfvcffzsfslfsllcglclwlvwvzzdsslggtzzgzdzmzddjljvvztttsgscsstztjztjztzvzwwthtftppnmpmmcpmmjlmjjjsfjsjppgcgwcggzffzwzbbmbrbprpqqpccfncfnffvcffsqqtzqzqwzwvzwwwbjbfbcbfblltnlnhhcthtvvzzfcfgfddlggbbshsggplglqqbrbggsvvzdvvlfvlvpvhhmggbrrnppjfjhffttfpffbdfbfvfqvvtcvvbvnnhbhhglgjgzzghhwrrtntrtwwfdfdmmcmtctftpptllzqllzflfrrgqgvgdvdfdbddprrrgccqvqnnmtmvmffpzzqggfbfnfwwqdqldqqlnqnttnbttrffnmmzwzjjtrjtrtmmqsmqmffqmfqfhhbthbhdhvdhvdvmvdmdhdshsqslldzztvvmzzdcccmbbhfhshrrrpsrrqqmdmmgdmmwdmdjdqqmcmttpgtgwgpwpprbrprhrsrllhsllprlplhppfzpffbhbccwdwbbrpbpvpqqmsspjssmbbmfmrmnrnwwgbwwbpwpjwwhqqgcqcvqccgffzpfftcffqlqjjznnlflhhlcczhzvhzhmzhmhfhnnqznntstwtggqjgjhggsvslltjlttfjjgffjzjwzzqzrrhlhzhbhphmhlmlzmzsmzmccvllgrrpbrbfbjfjttqjttdrdhhggqgddppqgpqgpgtptjptpllwccmwcmcpmcppdrrtstqqczqzvvlsltlddnvdvggcqqblqqsjqjttzhtzzszllqsqfqddqdbqddwqddfzzlczcscfsfpfdpdrpddsggcqchcfcpcssstwstwtggghvhqhzzqssjddwjwbjjsnjnfnwwglwwfnfhnnscsggzgjzzhzmmqfqsqwqrwqqqdtdcttzvvnbngbbcdbdggddnmddgzghhzgghwwbjbttlwlcctlccwwdhhrqrvrjjlglssgttpllwclwwtptwptwtvthtbhbzhbzhhrsrwwwnrwrfwfnwnhhnqqdjqjpqqwdwttzhttcdttvztzltzlzmzddrsdsfdsfftdfffmwffrjrffqrfqfsfqqqgqjggwzzrnnqfnqffdbfbtbbrpbrpbptpwttjmjjzrrhhqppdzdtdjttqwwtddjdzzmgzzhwwwdsdgssprsrgsgbbphhdpdwppnfppdqqwzzpbzzqwqpqsqhqdhqqtwwjnnmvmwvmmwwgjgzjjvcjcvcjcnjcncmmphmmvmwmwpwbbtbffhnhshgssgvgvrrbwbtbddqmqfqvvfqvqdvvdbvdbdcdfdlflmffrwwgmmttrztrrfrqrpqrrzjrjpjdpjprrnhhbhcbbcwwqlwwcssbddfrfjrfjfrjfjvvdmdtdzzlvzlzhzmhmhphchnnfqnffvccfpfbfpfqpprrmttzrzzjzmjmzjmmfvmmrzrqqdllgjlglcchssgllsbllrbrlrjlrrhhfwwsqwsstpssznzcznzqzssvtvtrrqwqvvtssgfsfhssljjnwjnjddjdggclcrrfsfhsstgtdtctfttvvsbvvbtbttcgcssjlslhlpljpppwzwnwdnngmgjjbzznwwdllrrfppshhvdhhldhdbbdbjbdjjrnjjzhzfhhsqqbqgmsbvnjsptlrsszlqfmgprvscphmqztbgtlrqvcgdzcptcqjncrdtfqnghnbmwwmcjgtjlbvqqzslgbbntrdfnvfjvfgcgngndjcspgwmpnsrqzzvzljbzlzzrwflrqqqmhsvqwbmdftnhwwzgqrlhddbbtwvbphljmstcjzvpjqwcnhlvpqvqdgvntgqzqwrlwbwvngwtqgrhznlzcvbwqmwncccjctrdzrmzjsvrmcfpjjcczhbvdfwhqvczggfmrspvprvvthvtqnsphpcsdmbrtbdqljvssdrhwjsrrlzprstpgqcbpmnpdgzgjttwcfrgjnsghmszlclgvmlsjrqfvflbnhwwphtvrnrbhdvdglcvgpzfsjpwwhtlvvdzthsrldfzhnlrblzsjjnwclqsqzgdbflhvpwcrtfbfbjcjttbjpvfgvfcswnqqwshbmqlscdzzwshfqwsvwnwzltbnrmzzhzvtwpzqcgwshpvzgtcmwrtrwctnpzbznnwqphnrgwljtrcwlqmvlndwrdrctztnmswslqmbjcmtlrmcpjvzccqszrnflqnqzttbhqlrhbmqdpscqvfgtdbnwjdcljwcbgbgjfzgrgpwqzqgbnrtpntfthhdbqmswvhnmwmszpghgjjzrbnbbfjblpstdfslmmmqfdcrhblqjqfphnldrvvfpnfrcvprjnqbzbspfpjtgqhnjbhnrwzcjvdbshhqpgrmzqpmjfmqwqvvdbddbsldwzzsrhnhsjjnvljrbwcnjrnjpmrrvfthftgptgtlpbgqffthflgftwcrqcqwqwrmrcmfrcqgmrnqjbscdcgrqlhjzthvzdgjbvpswflqcgsnlmgmvcsttsgmnqdtvwdvrndvfdcvrcwmqlmlhtrvthsndsrmnsfmdmfnpfmfhzjqmtcjzcrnsjdztztvgdtlrmbdmmstbfgpmmzthcslpvgrpgfljfgqlqhldfwvvvdvbzjtdtppbtrnqwsqztjrsjhtfrgmvsdngvsdzjgpwrldqpzdpvhljzpjvttwltdwcrhcbrgrvdrmpwvdwjchqsjfprbgtjtzggvgrgmlvvwqrjfprbbgjjqrtdfnrdffwbswbvqtqtfsrhsgrjhftqldhmcnmsnfflmdrzqdjmbqqgqsttdmtrrvfsjnccnhcpcvqtrzdjzrpwswmjvvgsgwvnmdgqwlctrlhqnsmczbwsjhmtgvdcgsndzlstcwchcztqqbtdwfvlljdvdlzljslgnzpmqvzfcvqhdzvgchffqgfwrnmwqzwgbzblpmvddlvnhglrhdnwzqwztzgjczjpwcjwmpnrnrhncfjfggrbphrjztwtfqmfjlwfhnqfftfghbnvtwgtmdzzrdrtmfrwhrrbhzmcllsgqzwzzqtgdggvzptvtdcpzmtmsfcfbjtzlbdrwhdbtdhhrgggmddnzsvjwgcdcqfppqwphfvlhmgqsznlhmgpnjvcvrwwppnphchgsrhjwjcpjggsrcwrvnllfgrmjltfzwhmbqwpwwzmrtlqcprrqztcgnghcbvzrbfptjmhtdcfhhffdbrswqpnpppnpqwtflrrmqgjzctmmvvvwzllbsfdvpqjtmvpjcpmjztscsgbdznfgcmtjzdqzwqrsvstnnvddcstzqjtnbsnlptpmbmfqmhppgnjrffqrtchgptbmwlwbwbcqqfngpbwtwdmlmdstmqwcwjtbwbbbhghgptmvhfmvqfvpwqzwnbjdhpwlgjgvprdjbnlzhnllssbpvzfzspwsscfpqtpdvtzvqncfrfrgddsdglqvpblmpcczlqfdmwzmgvrljhqtcglcvfhbdwhbttqqrjbqwhsrhrbjwmtqwqddvdggdwfsmnpbpvvgsqnvvrqntwmbzdnqpmmqtbnlsbmslpfmqjtgvbddhwvlvjtlrhqdpfnjwtbhwjwdrpgctbbrdqvbbnvgqwngrhqfvwzmlqtmhfqphnmczlbdpnbmpvwrsjbcnjnvcfgnsvlhpzdgdzgvfbgwdcrswznrggnghzssdwqvvlwftqhbnwdvghhvjlqqmcnqmvbwhrrnsswlwmwbsmpcpdzzgmcmqnzpvjpzqbwcsgdhqtqhcpbtqftvscmntsbdcbrndvlfhprpblzbjcpqhfljtvnvtgvrcgqbsgl

14
2022/days/06/src/main.rs Normal file
View file

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

23
2022/days/06/src/part1.rs Normal file
View file

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

23
2022/days/06/src/part2.rs Normal file
View file

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

View file

@ -0,0 +1,19 @@
pub fn find_dupes_stupid<T: PartialEq>(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);
}
} */

11
2022/days/07/Cargo.toml Normal file
View file

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

View file

@ -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<RefCell<Node>>;
#[derive(Debug)]
pub struct NodeRef(pub Rc<RefCell<Node>>);
impl Deref for NodeRef {
type Target = Rc<RefCell<Node>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<Rc<RefCell<Node>>> for NodeRef {
fn from(value: Rc<RefCell<Node>>) -> Self {
NodeRef(value)
}
}
impl From<NodeRef> for Rc<RefCell<Node>> {
fn from(value: NodeRef) -> Self {
value.0
}
}
impl NodeRef {
pub fn add_node(&mut self, mut node: Node) -> Result<NodeRef, FileTreeError> {
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<NodeRef, FileTreeError> {
self.add_node(Node::new_file(name, size))
}
pub fn add_dir(&mut self, name: String) -> Result<NodeRef, FileTreeError> {
self.add_node(Node::new_dir(name))
}
pub fn get_all_dirs(&self) -> Vec<NodeRef> {
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<WeakNodeRef>,
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<NodeRef, FileTreeError> {
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<NodeRef> {
match &self.parent {
Some(w) => Some(NodeRef(w.clone().upgrade()?)),
None => None,
}
}
pub fn get_size(&self) -> Result<usize, FileTreeError> {
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<impl Iterator<Item = NodeRef> + '_, 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<NodeRef, FileTreeError> {
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<NodeRef>),
}
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<NodeRef> = 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<usize> = 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
);
}
}

1030
2022/days/07/src/input.txt Normal file

File diff suppressed because it is too large Load diff

19
2022/days/07/src/main.rs Normal file
View file

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

262
2022/days/07/src/parser.rs Normal file
View file

@ -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<Regex> = Lazy::new(|| Regex::new(r"^\$").unwrap());
static PARSE_CD_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"^\$ cd (\S*)$").unwrap());
static PARSE_LS_ENTRY_REGEX: Lazy<Regex> =
Lazy::new(|| Regex::new(r"^([[:alnum:]]*) (\S*)$").unwrap());
#[derive(Debug, PartialEq, Eq)]
pub enum Command {
CdRoot,
CdUp,
Cd(String),
Ls(Vec<LsEntry>),
}
#[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<Command> {
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<std::str::Lines<'_>>) -> Vec<LsEntry> {
let mut ret: Vec<LsEntry> = 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<Command>) -> 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)
}
}

37
2022/days/07/src/part1.rs Normal file
View file

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

44
2022/days/07/src/part2.rs Normal file
View file

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

6
2022/days/08/Cargo.toml Normal file
View file

@ -0,0 +1,6 @@
[package]
name = "day08"
authors.workspace = true
description.workspace = true
version.workspace = true
edition.workspace = true

View file

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

16
2022/days/08/src/main.rs Normal file
View file

@ -0,0 +1,16 @@
mod part1;
mod part2;
mod utilities;
type StructuredInput = Vec<Vec<u8>>;
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));
}

85
2022/days/08/src/part1.rs Normal file
View file

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

109
2022/days/08/src/part2.rs Normal file
View file

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

View file

@ -0,0 +1,26 @@
pub fn parse(input: &str) -> Vec<Vec<u8>> {
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]
]
);
}
}

11
2022/days/09/Cargo.toml Normal file
View file

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

2000
2022/days/09/src/input.txt Normal file

File diff suppressed because it is too large Load diff

15
2022/days/09/src/main.rs Normal file
View file

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

75
2022/days/09/src/parse.rs Normal file
View file

@ -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<Regex> = Lazy::new(|| Regex::new(r"^([URDL]) (\d+)$").unwrap());
pub fn parse(input: &str) -> Vec<Direction> {
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,
]
);
}
}

53
2022/days/09/src/part1.rs Normal file
View file

@ -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<Direction>) -> usize {
let mut visited: HashSet<Point> = 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);
}
}

31
2022/days/09/src/part2.rs Normal file
View file

@ -0,0 +1,31 @@
use std::collections::HashSet;
use aoc_libs::points::Point;
use crate::{parse::Direction, rope::Rope};
pub fn part2(input: &Vec<Direction>) -> usize {
let mut visited: HashSet<Point> = 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);
}
}

160
2022/days/09/src/rope.rs Normal file
View file

@ -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<const L: usize> {
segments: [Point; L],
}
impl<const L: usize> Rope<L> {
pub fn new() -> Rope<L> {
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::<L>::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<const L: usize> 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<char>> = 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<Point> = 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)
}
}

10
2022/days/10/Cargo.toml Normal file
View file

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

118
2022/days/10/src/crt.rs Normal file
View file

@ -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<usize> 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<usize> 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
]
]
}
)
}
}

139
2022/days/10/src/input.txt Normal file
View file

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

455
2022/days/10/src/machine.rs Normal file
View file

@ -0,0 +1,455 @@
use std::{collections::VecDeque, fmt};
use crate::crt::Crt;
use crate::parse::*;
pub struct Machine {
instructions: VecDeque<Instruction>,
current_instruction: Option<(Instruction, usize)>,
cycle: usize,
x: i32,
pub crt: Crt,
}
impl Machine {
pub fn load_program(instructions: VecDeque<Instruction>) -> 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);
}
}

16
2022/days/10/src/main.rs Normal file
View file

@ -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()));
}

344
2022/days/10/src/parse.rs Normal file
View file

@ -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<Instruction> {
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
]
);
}
}

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