Compare commits

...

19 Commits

Author SHA1 Message Date
cb69657218 black formatter 2022-12-08 14:18:03 +01:00
aaron
701c168ad1 my brain hurts 2022-12-08 00:32:11 +01:00
aaron
1ea592b42e kind of solve part a 2022-12-08 00:15:32 +01:00
7ce7f045af add skeletton 2022-12-07 15:26:06 +01:00
3a65fdf38e type annotations++ 2022-12-07 15:13:28 +01:00
aaron
fdb7fe64e6 fix comments 2022-12-06 16:47:14 +01:00
aaron
7ba19b3579 solve day 6 part 2 2022-12-06 16:42:28 +01:00
aaron
b46117b788 solve part b 2022-12-05 23:34:34 +01:00
aaron
89a16489cb solve day 5 part a 2022-12-05 23:12:52 +01:00
aaron
f9ab5ccc76 add pipenv 2022-12-04 17:05:09 +01:00
aaron
35dc133357 update comments 2022-12-04 14:56:57 +01:00
aaron
d8464c07fc fix prints 2022-12-04 14:49:35 +01:00
aaron
22413c844b add function comment 2022-12-04 14:34:47 +01:00
aaron
5a5f94d557 solve day 4 2022-12-04 14:25:37 +01:00
aaron
eb62bfaf03 fix naming 2022-12-03 15:06:22 +01:00
aaron
0c9ac4346d move priority list 2022-12-03 14:51:28 +01:00
aaron
5cd5b10ec1 fix comment 2022-12-03 14:44:09 +01:00
aaron
27147cd9bd black formatter 2022-12-03 14:42:25 +01:00
aaron
36deee750f add solution to part b 2022-12-03 14:36:15 +01:00
9 changed files with 431 additions and 24 deletions

View File

@@ -3,42 +3,58 @@ import string
from aocd.models import Puzzle from aocd.models import Puzzle
from aocd import submit from aocd import submit
def eval_priority(rucksack: str) -> int:
'''
evaluates the priority of a duplicate item
'''
# create a map of priority values # create a map of priority values
priorities = dict(zip(string.ascii_letters, range(1, 53))) priorities = dict(zip(string.ascii_letters, range(1, 53)))
def eval_item_priority(rucksack: str) -> int:
"""
evaluates the priority of a common item
"""
# slize rucksack into compartments # slize rucksack into compartments
size = len(rucksack) size = len(rucksack)
a, b = rucksack[: size // 2], rucksack[size // 2 :] a, b = rucksack[: size // 2], rucksack[size // 2 :]
# find the duplicate item # find the common item
duplicate = ''.join( common = "".join(set(a).intersection(b))
set(a).intersection(b)
)
# return the priority # return the priority
return priorities[duplicate] return priorities[common]
def eval_badge_priority(rucksacks: list) -> int:
"""
evaluate the priority of duplicate items over groups of three rucksacks
"""
# find common item amongst three sets
common = "".join(set(rucksacks[0]) & set(rucksacks[1]) & set(rucksacks[2]))
# convert to priority list
return priorities[common]
def parse_input(data: list) -> list: def parse_input(data: list) -> list:
''' """
parses the input data and generates a list parses the input data and generates a list
''' """
# split move set into a list of rounds # split rucksack set into a list
return [ move for move in data.split('\n')] return [rucksack for rucksack in data.split("\n")]
if __name__ == "__main__": if __name__ == "__main__":
# get puzzle and parse data # get puzzle and parse data
puzzle = Puzzle(year=2022, day=3) puzzle = Puzzle(year=2022, day=3)
supplies = parse_input(puzzle.input_data) supplies = parse_input(puzzle.input_data)
# part a: determine the priority of all duplicate items # part a: determine the priority of dupplicate items in compartments
answer = sum([eval_priority(rucksack) for rucksack in supplies]) answer_a = sum([eval_item_priority(rucksack) for rucksack in supplies])
print(f'sum of priorities of all duplicate items: {answer}') print(f"sum of priorities of all common items amongst compartments: {answer_a}")
submit(answer, part='a', day=3, year=2022) submit(answer_a, part="a", day=3, year=2022)
# part b: # part b: determine the priority of common items in groups of three and create a priority summary
#submit(total, part='b', day=3, year=2022) groups = [supplies[i : i + 3] for i in range(0, len(supplies), 3)]
answer_b = sum([eval_badge_priority(group) for group in groups])
print(f"sum of priorities of all common items amongst groups of three: {answer_b}")
submit(answer_b, part="b", day=3, year=2022)

56
4/cleanup.py Normal file
View File

@@ -0,0 +1,56 @@
from aocd.models import Puzzle
from aocd import submit
def find_overlaps(sets: list) -> int:
"""
count the number of sets that overlap
"""
# generate a list where ones correlate to intersecting pairs
overlaps = [1 if set.intersection(*pair) else 0 for pair in sets]
return sum(overlaps)
def find_subsets(sets: list) -> int:
"""
count the number of sets that fully contain each other
"""
# generate a list where ones correlate to subsets of a and b
subsets = [
1 if pair[0].issubset(pair[1]) or pair[1].issubset(pair[0]) else 0
for pair in sets
]
return sum(subsets)
def parse_input(data: list) -> list:
"""
parses the input data and generates a list of set tuples
"""
# get a list of section pairs
sections = [sections.split(",") for sections in data.split("\n")]
# generate a list of section pairs with sets of discrete ranges
sets = list()
for pair in sections:
a, b = pair[0].split("-")
c, d = pair[1].split("-")
a, b, c, d = int(a), int(b), int(c), int(d)
sets.append([set(range(a, b + 1)), set(range(c, d + 1))])
return sets
if __name__ == "__main__":
# get puzzle and parse data
puzzle = Puzzle(year=2022, day=4)
sections = parse_input(puzzle.input_data)
# part a: find the number of sections that fully contain each other
answer_a = find_subsets(sections)
print(f"sum of all cleanup sections that fully contain each other: {answer_a}")
submit(answer_a, part="a", day=4, year=2022)
# part b: determine the priority of common items in groups of three and create a priority summary
answer_b = find_overlaps(sections)
print(f"sum of all cleanup section that intersect: {answer_b}")
submit(answer_b, part="b", day=4, year=2022)

76
5/supplystacks.py Normal file
View File

@@ -0,0 +1,76 @@
from copy import deepcopy
from aocd.models import Puzzle
from aocd import submit
def crate_mover_9000(stacks: dict, moves: list) -> str:
"""
execute moves on the stacks and return the top of each stack
the crate mover 9000 only moves single crates.
"""
# take a deep copy so embedded list do not get messed up
stacks = deepcopy(stacks)
# for each move, execute on stacks
for amount, index, dest in moves:
for i in range(amount):
stacks[dest].append(stacks[index].pop())
# take the last element fom each stack and append to output
return "".join([stack[-1] for stack in stacks.values()])
def crate_mover_9001(stacks: dict, moves: list) -> str:
"""
execute moves on the stacks and return the top of each stack
the crate mover 9001 moves stacks of crates.
"""
# take a deep copy so embedded list do not get messed up
stacks = deepcopy(stacks)
# for each move, move amount of crates from index to dest
for amount, index, dest in moves:
stacks[dest].extend(stacks[index][-amount:])
stacks[index] = stacks[index][:-amount]
# take the last element fom each stack and append to output
return "".join([stack[-1] for stack in stacks.values()])
def parse_input(data: list) -> list:
"""
turn input data into usable data types:
stacks_str -> dict of moves {'index':['A','B','C']}
moves_str -> list of opeations [amount, index, dest]
"""
# get input data
stacks_str, moves_str = data.split("\n\n")
# transpose field for easier parsing (thx linalg course)
transposed_stacks = list(map(list, zip(*stacks_str.splitlines())))
# parse stacks
stacks = {}
for line in transposed_stacks[1::4]:
stack = [c for c in line if c != " "]
key = stack.pop()
stack.reverse()
stacks[key] = stack
# parse moves
moves = []
for move in moves_str.splitlines():
_, amount, _, index, _, dest = move.split(" ")
# print(f'move {amount} from {index} to {dest}')
moves.append((int(amount), index, dest))
# return parsed data
return stacks, moves
if __name__ == "__main__":
# get puzzle and parse data
puzzle = Puzzle(year=2022, day=5)
stacks, moves = parse_input(puzzle.input_data)
# part a:
answer_a = crate_mover_9000(stacks, moves)
print(f"{answer_a}")
submit(answer_a, part="a", day=5, year=2022)
# part b:
answer_b = crate_mover_9001(stacks, moves)
print(f"{answer_b}")
submit(answer_b, part="b", day=5, year=2022)

29
6/tuningtrouble.py Normal file
View File

@@ -0,0 +1,29 @@
from aocd.models import Puzzle
from aocd import submit
def get_marker_pos(signal: str, N: int) -> int:
"""
iterate over input signal and find the first occurence
where the set from i to i+N equals N. This means there
are no duplicates within this particular range.
"""
for i in range(0, len(signal)):
if len(set(signal[i : i + N])) == N:
return i + N
if __name__ == "__main__":
# get puzzle and parse data
puzzle = Puzzle(year=2022, day=6)
signal = puzzle.input_data
# part a: find marker with 4 different chars
answer_a = get_marker_pos(signal, 4)
print(f"{answer_a}")
submit(answer_a, part="a", day=6, year=2022)
# part b: find marker with 14 different chars
answer_b = get_marker_pos(signal, 14)
print(f"{answer_b}")
submit(answer_b, part="b", day=6, year=2022)

71
7/nospaceleft.py Normal file
View File

@@ -0,0 +1,71 @@
from aocd.models import Puzzle
from aocd import submit
def get_sizes_a(dirs: dict, max_size: int) -> int:
"""
return the size of all dirs which are at most max_size big
"""
filtered_dirs = [value for value in dirs.values() if value < max_size]
return sum(filtered_dirs)
def get_sizes_b(dirs: dict, needed_size: int) -> int:
"""
return the smallest size of a dir which when deleted amounts
to the needed size of 30M.
"""
total_size = 70000000
used_size = dirs[("/",)]
max_free = needed_size - (total_size - used_size)
filtered_dirs = [value for value in dirs.values() if value > max_free]
return min(filtered_dirs)
def parse_input(input_str: str) -> list:
"""
the input string consists of the following four message types
- $ cd .. -> pop dir name from stack
- $ cd [dir] -> push dir name to stack
- $ ls -> ignore
- dir [dir] -> ignore
- [size] [file] -> sum up the sizes of all files in this dir
parsing is done by implementing a state machine which gathers all
available information in the following dictionary.
- {list['/','dir','path']:int(size_sum)}
"""
path = list()
dirs = dict()
for line in input_str.splitlines():
match line.split():
case ("$", "cd", ".."):
path.pop()
case ("$", "cd", name):
path.append(name)
case ("$", "ls"):
continue
case ("dir", _):
continue
case (size, file):
size = int(size)
for i in range(len(path)):
key = tuple(path[: i + 1]) # list not hashable
dirs.setdefault(key, 0) # initialize key for += to work
dirs[key] += size # dirs needs to be initialized
return dirs
if __name__ == "__main__":
# get puzzle and parse data
puzzle = Puzzle(year=2022, day=7)
dirs = parse_input(puzzle.input_data)
# part a: get the sum of all dirs where the size is at most 100k
answer_a = get_sizes_a(dirs, 100000)
print(f"{answer_a}")
submit(answer_a, part="a", day=7, year=2022)
# part b: find the smallest D (huehue) that will free up at least 30M
answer_b = get_sizes_b(dirs, 30000000)
print(f"{answer_b}")
submit(answer_b, part="b", day=7, year=2022)

11
Pipfile Normal file
View File

@@ -0,0 +1,11 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
advent-of-code-data = "*"
black = "*"
[requires]
python_version = ">=3.10"

141
Pipfile.lock generated Normal file
View File

@@ -0,0 +1,141 @@
{
"_meta": {
"hash": {
"sha256": "75e5e305a53ca8155d7ed18e6d764f46789d737487f9bea8f0891f6a56726e8d"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.11"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"advent-of-code-data": {
"hashes": [
"sha256:552e7886c193c52cac71f14ef55c5d7cc1c7ebd0e9e2271be37b01df739f92cc",
"sha256:823be87d393b4cd9eef7dc123fdf1078c979b6ad898d8c54bc7b95ff10582209"
],
"index": "pypi",
"version": "==1.3.1"
},
"beautifulsoup4": {
"hashes": [
"sha256:58d5c3d29f5a36ffeb94f02f0d786cd53014cf9b3b3951d42e0080d8a9498d30",
"sha256:ad9aa55b65ef2808eb405f46cf74df7fcb7044d5cbc26487f96eb2ef2e436693"
],
"markers": "python_full_version >= '3.6.0'",
"version": "==4.11.1"
},
"certifi": {
"hashes": [
"sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14",
"sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382"
],
"markers": "python_version >= '3.6'",
"version": "==2022.9.24"
},
"charset-normalizer": {
"hashes": [
"sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845",
"sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"
],
"markers": "python_full_version >= '3.6.0'",
"version": "==2.1.1"
},
"idna": {
"hashes": [
"sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4",
"sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"
],
"markers": "python_version >= '3.5'",
"version": "==3.4"
},
"pebble": {
"hashes": [
"sha256:8274aa0959f387b368ede47666129cbe5d123f276a1bd9cafe77e020194b2141",
"sha256:bdcfd9ea7e0aedb895b204177c19e6d6543d9962f4e3402ebab2175004863da8"
],
"markers": "python_version >= '3.6'",
"version": "==5.0.3"
},
"python-dateutil": {
"hashes": [
"sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86",
"sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'",
"version": "==2.8.2"
},
"pytz-deprecation-shim": {
"hashes": [
"sha256:8314c9692a636c8eb3bda879b9f119e350e93223ae83e70e80c31675a0fdc1a6",
"sha256:af097bae1b616dde5c5744441e2ddc69e74dfdcb0c263129610d85b87445a59d"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
"version": "==0.1.0.post0"
},
"requests": {
"hashes": [
"sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983",
"sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"
],
"markers": "python_version >= '3.7' and python_version < '4'",
"version": "==2.28.1"
},
"six": {
"hashes": [
"sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
"sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'",
"version": "==1.16.0"
},
"soupsieve": {
"hashes": [
"sha256:3b2503d3c7084a42b1ebd08116e5f81aadfaea95863628c80a3b774a11b7c759",
"sha256:fc53893b3da2c33de295667a0e19f078c14bf86544af307354de5fcf12a3f30d"
],
"markers": "python_version >= '3.6'",
"version": "==2.3.2.post1"
},
"termcolor": {
"hashes": [
"sha256:67cee2009adc6449c650f6bcf3bdeed00c8ba53a8cda5362733c53e0a39fb70b",
"sha256:fa852e957f97252205e105dd55bbc23b419a70fec0085708fc0515e399f304fd"
],
"markers": "python_version >= '3.7'",
"version": "==2.1.1"
},
"tzdata": {
"hashes": [
"sha256:2b88858b0e3120792a3c0635c23daf36a7d7eeeca657c323da299d2094402a0d",
"sha256:fe5f866eddd8b96e9fcba978f8e503c909b19ea7efda11e52e39494bad3a7bfa"
],
"markers": "python_version >= '3.6'",
"version": "==2022.7"
},
"tzlocal": {
"hashes": [
"sha256:89885494684c929d9191c57aa27502afc87a579be5cdd3225c77c463ea043745",
"sha256:ee5842fa3a795f023514ac2d801c4a81d1743bbe642e3940143326b3a00addd7"
],
"markers": "python_version >= '3.6'",
"version": "==4.2"
},
"urllib3": {
"hashes": [
"sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc",
"sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
"version": "==1.26.13"
}
},
"develop": {}
}

View File

@@ -13,8 +13,16 @@ Solutions for the advent of code 2022
- After a successful login extract your session token from your browser - After a successful login extract your session token from your browser
- Create a `.env` file and make sure to export the environment variable below - Create a `.env` file and make sure to export the environment variable below
- The lib will outomatically work if the environment variable is present - The lib will outomatically work if the environment variable is present
- `Pipenv` automatically loads `.env` files
```bash ```bash
$ cat .env $ cat .env
export AOC_SESSION="53616c..." export AOC_SESSION="53616c..."
``` ```
## how to get a pipenv shell
```bash
$ pipenv install
$ pipenv shell
```

View File

@@ -1 +0,0 @@
advent-of-code-data