Compare commits
19 Commits
b3258a61ad
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| cb69657218 | |||
|
|
701c168ad1 | ||
|
|
1ea592b42e | ||
| 7ce7f045af | |||
| 3a65fdf38e | |||
|
|
fdb7fe64e6 | ||
|
|
7ba19b3579 | ||
|
|
b46117b788 | ||
|
|
89a16489cb | ||
|
|
f9ab5ccc76 | ||
|
|
35dc133357 | ||
|
|
d8464c07fc | ||
|
|
22413c844b | ||
|
|
5a5f94d557 | ||
|
|
eb62bfaf03 | ||
|
|
0c9ac4346d | ||
|
|
5cd5b10ec1 | ||
|
|
27147cd9bd | ||
|
|
36deee750f |
@@ -3,42 +3,58 @@ import string
|
||||
from aocd.models import Puzzle
|
||||
from aocd import submit
|
||||
|
||||
def eval_priority(rucksack: str) -> int:
|
||||
'''
|
||||
evaluates the priority of a duplicate item
|
||||
'''
|
||||
# create a map of priority values
|
||||
priorities = dict(zip(string.ascii_letters, range(1, 53)))
|
||||
|
||||
# create a map of priority values
|
||||
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
|
||||
size = len(rucksack)
|
||||
a,b = rucksack[:size//2], rucksack[size//2:]
|
||||
a, b = rucksack[: size // 2], rucksack[size // 2 :]
|
||||
|
||||
# find the duplicate item
|
||||
duplicate = ''.join(
|
||||
set(a).intersection(b)
|
||||
)
|
||||
# find the common item
|
||||
common = "".join(set(a).intersection(b))
|
||||
|
||||
# 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:
|
||||
'''
|
||||
parses the input data and generates a list
|
||||
'''
|
||||
# split move set into a list of rounds
|
||||
return [ move for move in data.split('\n')]
|
||||
"""
|
||||
parses the input data and generates a list
|
||||
"""
|
||||
# split rucksack set into a list
|
||||
return [rucksack for rucksack in data.split("\n")]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# get puzzle and parse data
|
||||
puzzle = Puzzle(year=2022, day=3)
|
||||
supplies = parse_input(puzzle.input_data)
|
||||
|
||||
# part a: determine the priority of all duplicate items
|
||||
answer = sum([eval_priority(rucksack) for rucksack in supplies])
|
||||
print(f'sum of priorities of all duplicate items: {answer}')
|
||||
submit(answer, part='a', day=3, year=2022)
|
||||
# part a: determine the priority of dupplicate items in compartments
|
||||
answer_a = sum([eval_item_priority(rucksack) for rucksack in supplies])
|
||||
print(f"sum of priorities of all common items amongst compartments: {answer_a}")
|
||||
submit(answer_a, part="a", day=3, year=2022)
|
||||
|
||||
# part b:
|
||||
#submit(total, part='b', day=3, year=2022)
|
||||
# part b: determine the priority of common items in groups of three and create a priority summary
|
||||
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
56
4/cleanup.py
Normal 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
76
5/supplystacks.py
Normal 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
29
6/tuningtrouble.py
Normal 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
71
7/nospaceleft.py
Normal 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
11
Pipfile
Normal 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
141
Pipfile.lock
generated
Normal 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": {}
|
||||
}
|
||||
@@ -13,8 +13,16 @@ Solutions for the advent of code 2022
|
||||
- After a successful login extract your session token from your browser
|
||||
- Create a `.env` file and make sure to export the environment variable below
|
||||
- The lib will outomatically work if the environment variable is present
|
||||
- `Pipenv` automatically loads `.env` files
|
||||
|
||||
```bash
|
||||
$ cat .env
|
||||
export AOC_SESSION="53616c..."
|
||||
```
|
||||
|
||||
## how to get a pipenv shell
|
||||
|
||||
```bash
|
||||
$ pipenv install
|
||||
$ pipenv shell
|
||||
```
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
advent-of-code-data
|
||||
Reference in New Issue
Block a user