feat: Redo of the AoC repo starting over with 2015 and keeping up with

2025 (completed day 2 so far)
This commit is contained in:
2025-12-02 07:55:08 -06:00
commit c936d7d573
29 changed files with 668 additions and 0 deletions

Binary file not shown.

59
15/1/main.py Normal file
View File

@@ -0,0 +1,59 @@
'''Day 1 of 2015 AOC'''
def process_input_string(input_string: str) -> int:
'''Take in an input string and give back the floor number based on the instructions.
Keyword Args:
input_string (str) - String of encoded instructions
Return:
int - Floor number
'''
curr_floor = 0
for char in input_string:
if char == '(':
curr_floor += 1
elif char == ')':
curr_floor -= 1
return curr_floor
def find_the_basement(input_string: str) -> int:
'''Take in an input string of instructions and give back the position of the instruction entering the basement, or hitting floor "-1".
Keyword Args:
input_string (str) - String of encoded instructions
Return:
int - Position of instruction in the string
'''
curr_floor = 0
for index, char in enumerate(input_string):
if char == '(':
curr_floor += 1
elif char == ')':
curr_floor -= 1
if curr_floor == -1:
# Add one to give the 1s based position instead of the 0s based index
return index + 1
def main():
'''Entrypoint'''
with open('input.txt', encoding='utf-8') as fh:
input_string = fh.readline()
output = process_input_string(input_string)
print(f'Part 1: {output}')
output = find_the_basement(input_string)
print(f'Part 2: {output}')
if __name__ == "__main__":
main()

28
15/1/test_day1.py Normal file
View File

@@ -0,0 +1,28 @@
import pytest
from main import find_the_basement, process_input_string
@pytest.mark.parametrize('test_input, expected',
[
('(())', 0),
('()()', 0),
('(((', 3),
('(()(()(', 3),
('))(((((', 3),
('())', -1),
('))(', -1),
(')))', -3),
(')())())', -3)
])
def test_instruction_examples(test_input, expected):
assert process_input_string(test_input) == expected
@pytest.mark.parametrize('test_input, expected',
[
(')', 1),
('()())', 5)
])
def test_basement_instructions(test_input, expected):
assert find_the_basement(test_input) == expected

Binary file not shown.

38
15/2/main.py Normal file
View File

@@ -0,0 +1,38 @@
'''AoC day 2'''
def get_surface_area(l: int, w: int, h: int) -> int:
'''Take the dimensions of the box and return its surface area
Keyword args:
l (int) - Length
w (int) - Width
h (int) - Height
'''
return 2*l*w + 2*w*h + 2*h*l
def get_slack_amount(l: int, w: int, h: int) -> int:
'''Take dimensions and return the value of the smallest'''
return min([l*w, w*h, h*l])
def get_ribbon_amount(l: int, w: int, h: int) -> int:
return min([2*h + 2*w, 2*l + 2*w, 2*h + 2*l]) + (l*w*h)
def main():
'''Entrypoint'''
# Surface area for wrapping paper
with open('input.txt', encoding='utf-8') as fh:
sum = 0
r_sum = 0
for line in fh:
l, w, h = [int(x) for x in line.split('x')]
# print(f'{l} {w} {h}')
sum += get_surface_area(l, w, h)
sum += get_slack_amount(l, w, h)
r_sum += get_ribbon_amount(l, w, h)
print(f'Part 1, sum of wrapping paper: {sum}')
print(f'Part 2, sum of ribbon: {r_sum}')
if __name__ == "__main__":
main()

27
15/2/test_day2.py Normal file
View File

@@ -0,0 +1,27 @@
import pytest
from main import get_slack_amount, get_surface_area, get_ribbon_amount
@pytest.mark.parametrize('l, w, h, expected',
[
(2, 3, 4, 52),
(1, 1, 10, 42)
])
def test_surface_area(l, w, h, expected):
assert get_surface_area(l, w, h) == expected
@pytest.mark.parametrize('l, w, h, expected',
[
(2, 3, 4, 6),
(1, 1, 10, 1)
])
def test_slack_amount(l, w, h, expected):
assert get_slack_amount(l, w, h) == expected
@pytest.mark.parametrize('l, w, h, expected',
[
(2, 3, 4, 34),
(1, 1, 10, 14)
])
def test_ribbon_amount(l, w, h, expected):
assert get_ribbon_amount(l, w, h) == expected

Binary file not shown.

66
15/3/main.py Normal file
View File

@@ -0,0 +1,66 @@
'''AoC day 2'''
def get_new_pos(curr_pos, instruction):
if instruction == '<':
new_pos = (curr_pos[0] - 1, curr_pos[1])
elif instruction == '>':
new_pos = (curr_pos[0] + 1, curr_pos[1])
elif instruction == '^':
new_pos = (curr_pos[0], curr_pos[1] + 1)
elif instruction == 'v':
new_pos = (curr_pos[0], curr_pos[1] - 1)
else:
new_pos = (0, 0)
return new_pos
def process_instructions(instruction_set: str) -> int:
'''Run through a set of instructions to return the number of unique houses visited
Keyword args:
instruction_set (str) - Directional arrow instruction string giving moves to new locations
Returns:
int - Number of unique houses visited
'''
visited_house_coordinates = {(0,0)}
curr_pos = (0, 0)
for instruction in instruction_set:
curr_pos = get_new_pos(curr_pos, instruction)
visited_house_coordinates.add(curr_pos)
return len(visited_house_coordinates)
def process_robo_instructions(instruction_set: str) -> int:
visited_house_coordinates = {(0,0)}
santa_pos = (0,0)
robot_pos = (0,0)
for index, instruction in enumerate(instruction_set):
if index % 2 == 0:
santa_pos = get_new_pos(santa_pos, instruction)
visited_house_coordinates.add(santa_pos)
else:
robot_pos = get_new_pos(robot_pos, instruction)
visited_house_coordinates.add(robot_pos)
return len(visited_house_coordinates)
def main():
'''Entrypoint'''
with open('input.txt', encoding='utf-8') as fh:
instruction_set = fh.readline()
unique_houses = process_instructions(instruction_set)
print(f'Part1: {unique_houses}')
robo_houses = process_robo_instructions(instruction_set)
print(f'Part2: {robo_houses}')
if __name__ == "__main__":
main()

20
15/3/test_day3.py Normal file
View File

@@ -0,0 +1,20 @@
import pytest
from main import process_instructions, process_robo_instructions
@pytest.mark.parametrize('given, expected',
[
('>', 2),
('^>v<', 4),
('^v^v^v^v^v', 2)
])
def test_instructions(given, expected):
assert process_instructions(given) == expected
@pytest.mark.parametrize('given, expected',
[
('^v', 3)
])
def test_part2_instructions(given, expected):
assert process_robo_instructions(given) == expected

Binary file not shown.

26
15/4/main.py Normal file
View File

@@ -0,0 +1,26 @@
import hashlib
def search_hashes(secret: str, match_str: str) -> int:
num = 1
while True:
search_string_bytes = (secret + str(num)).encode()
hash_string = hashlib.md5(search_string_bytes).hexdigest()
if hash_string.startswith(match_str):
return num
num += 1
def main():
num = search_hashes('ckczppom', '00000')
print(f'Part1: {num}')
num = search_hashes('ckczppom', '000000')
print(f'Part2: {num}')
if __name__ == "__main__":
main()

11
15/4/test_main.py Normal file
View File

@@ -0,0 +1,11 @@
import pytest
from main import search_hashes
@pytest.mark.parametrize('given, match, expected',
[
('abcdef', '00000', 609043),
('pqrstuv', '00000', 1048970)
])
def test_searching(given, match, expected):
assert search_hashes(given, match) == expected

Binary file not shown.

81
15/5/main.py Normal file
View File

@@ -0,0 +1,81 @@
def check_contains_no_bad_chars(test: str) -> bool:
bad_chars = ['ab', 'cd', 'pq', 'xy']
if any(el in test for el in bad_chars):
return False
return True
def check_doubled_char(input: str) -> bool:
for index, letter in enumerate(input):
if index - 1 > 0 and input[index - 1] == letter:
return True
if index + 1 < len(input) and input[index + 1] == letter:
return True
return False
def check_vowel_count(input: str) -> bool:
'''Give a count of vowels in a string
Keyword args:
input (str) - String to search to vowels
Return:
int - The number of found vowels
'''
sum = 0
for letter in input:
if letter in 'aeiou':
sum += 1
if sum > 2:
return True
return False
def check_if_nice(test: str) -> bool:
if check_contains_no_bad_chars(test) and check_doubled_char(test) and check_vowel_count(test):
return True
return False
def check_nonoverlapping_repeats(test: str) -> bool:
splitup = [test[i:i+2] for i in range(0, len(test), 2)]
for el in splitup:
check = splitup.pop()
if check in splitup:
return True
return False
def check_repeat_everyother(test: str) -> bool:
for index, letter in enumerate(test):
if index + 2 < len(test) and test[index+2] == letter:
return True
return False
def check_if_nice_part2(test: str) -> bool:
return check_nonoverlapping_repeats(test) and check_repeat_everyother(test)
def main():
with open('input.txt', encoding='utf-8') as fh:
total = 0
for line in fh:
# print(line.strip())
if check_if_nice(line.strip()):
total += 1
print(f'Part1: {total}')
if __name__ == "__main__":
main()

77
15/5/test_main.py Normal file
View File

@@ -0,0 +1,77 @@
import pytest
from main import check_contains_no_bad_chars, check_doubled_char, check_vowel_count, check_if_nice, check_nonoverlapping_repeats, check_repeat_everyother, check_if_nice_part2
@pytest.mark.parametrize('given, expected',
[
('aei', True),
('xazegov', True),
('aeiouaeiouaeiou', True),
('mnqpcbt', False)
])
def test_vowel_counting(given, expected):
assert check_vowel_count(given) == expected
@pytest.mark.parametrize('given, expected',
[
('aabbccdd', True),
('whythisword', False),
('hegwjzuvuyypxyu', True)
])
def test_double_counting(given, expected):
assert check_doubled_char(given) == expected
@pytest.mark.parametrize('given, expected',
[
('aabbccdd', False),
('whythisword', True)
])
def test_bad_chars(given, expected):
assert check_contains_no_bad_chars(given) == expected
@pytest.mark.parametrize('given, expected',
[
('ugknbfddgicrmopn', True),
('aaa', True),
('jchzalrnumimnmhp', False),
('haegwjzuvuyypxyu', False),
('dvszwmarrgswjxmb', False)
])
def test_examples(given, expected):
assert check_if_nice(given) == expected
@pytest.mark.parametrize('given, expected',
[
('xyxy', True),
('xxyxx', True),
('aaa', False)
])
def test_nonopverlapping(given, expected):
assert check_nonoverlapping_repeats(given) == expected
@pytest.mark.parametrize('given, expected',
[
('xyx', True),
('xxyxx', True),
('abcdefeghi', True),
('aaa', True),
('blargh', False)
])
def test_repeat_everyother(given, expected):
assert check_repeat_everyother(given) == expected
@pytest.mark.parametrize('given, expected',
[
('qjhvhtzxzqqjkmpb', True),
('xxyxx', True),
('uurcxstgmygtbstg', False),
('ieodomkazucvgmuy', False)
])
def test_part2_examples(given, expected):
assert check_if_nice_part2(given) == expected