1
0
Fork 0

add 2024/day1-day5 python

This commit is contained in:
Sebastian Mark 2024-12-06 13:06:10 +01:00
parent 6c64d1b62e
commit 7c4e98ebcf
5 changed files with 360 additions and 0 deletions

51
2024/01/main.py Executable file
View file

@ -0,0 +1,51 @@
#!/usr/bin/env python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
# Author: Sebastian Mark
# CC-BY-SA (https://creativecommons.org/licenses/by-sa/4.0/deed.de)
# pylint: disable=missing-module-docstring,missing-function-docstring,consider-using-f-string
def readinput() -> (list[int], list[int]):
a = []
b = []
with open("input", "r", encoding="utf-8") as file:
for line in file:
num1, num2 = map(int, line.split())
a.append(num1)
b.append(num2)
return a, b
def distance(list_a: list[int], list_b: list[int]) -> int:
list_a.sort()
list_b.sort()
dist = 0
for a_val, b_val in zip(list_a, list_b):
dist += abs(a_val - b_val)
return dist
def similarity(list_a: list[int], list_b: list[int]) -> int:
sim = 0
for a_val in list_a:
sim += a_val * list_b.count(a_val)
return sim
def main():
list_a, list_b = readinput()
# part1
print("Distance: %d" % distance(list_a, list_b))
# part 2
print("Similarity: %d" % similarity(list_a, list_b))
if __name__ == "__main__":
main()

76
2024/02/main.py Executable file
View file

@ -0,0 +1,76 @@
#!/usr/bin/env python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
# Author: Sebastian Mark
# CC-BY-SA (https://creativecommons.org/licenses/by-sa/4.0/deed.de)
# pylint: disable=missing-module-docstring,missing-function-docstring,consider-using-f-string
def readinput() -> list[int]:
reports = []
with open("input", "r", encoding="utf-8") as file:
for line in file:
levels = list(map(int, line.split(" ")))
reports.append(levels)
return reports
def is_valid_level_difference(i: int, j: int) -> bool:
if i == j:
return False
if abs(i - j) > 3:
return False
return True
def is_sorted(levels: list) -> bool:
asc_sorted = levels == sorted(levels)
desc_sorted = levels == sorted(levels, reverse=True)
return asc_sorted or desc_sorted
def is_save(levels: list) -> bool:
if not is_sorted(levels):
return False
for i in range(len(levels) - 1):
if not is_valid_level_difference(levels[i], levels[i + 1]):
return False
return True
def remove_level_by_index(levels: list, index: int) -> list:
copy = levels.copy()
copy.pop(index)
return copy
def is_save_with_damper(levels: list) -> bool:
if is_save(levels):
return True
for i in range(len(levels)):
if is_save(remove_level_by_index(levels, i)):
return True
return False
def main():
reports = readinput()
# part 1
save_count = sum(is_save(report) for report in reports)
print("Save reports: %d" % save_count)
# part 2
save_count = sum(is_save_with_damper(report) for report in reports)
print("Save reports (with damper): %d" % save_count)
if __name__ == "__main__":
main()

52
2024/03/main.py Normal file
View file

@ -0,0 +1,52 @@
#!/usr/bin/env python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
# Author: Sebastian Mark
# CC-BY-SA (https://creativecommons.org/licenses/by-sa/4.0/deed.de)
# pylint: disable=missing-module-docstring,missing-function-docstring,consider-using-f-string
import re
def readinput() -> str:
with open("input", "r", encoding="utf-8") as file:
lines = file.read()
return lines
def find_and_execute_instructions(m: str) -> int:
regex = r"mul\((\d{1,3}),(\d{1,3})\)"
res = sum(int(inst[0]) * int(inst[1]) for inst in re.findall(regex, m))
return res
def find_and_execute_enabled_instructions(m: str) -> int:
regex = r"mul\(\d{1,3},\d{1,3}\)|do\(\)|don't\(\)"
res = 0
allowed = True
for inst in re.findall(regex, m):
if inst.startswith("mul"):
if allowed:
res += find_and_execute_instructions(inst)
else:
allowed = inst.startswith("do()")
return res
def main():
currupted_memory = readinput()
# part 1
instructions_result = find_and_execute_instructions(currupted_memory)
print("Result: %d" % instructions_result)
# part 2
instructions_result = find_and_execute_enabled_instructions(currupted_memory)
print("Result (only enabled): %d" % instructions_result)
if __name__ == "__main__":
main()

89
2024/04/main.py Normal file
View file

@ -0,0 +1,89 @@
#!/usr/bin/env python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
# Author: Sebastian Mark
# CC-BY-SA (https://creativecommons.org/licenses/by-sa/4.0/deed.de)
# pylint: disable=missing-module-docstring,missing-function-docstring,consider-using-f-string
def readinput() -> list:
with open("input", "r", encoding="utf-8") as file:
lines = file.readlines()
return lines
def find_xmas(grid: list[list], x: int, y: int) -> int:
height = len(grid) - 1
width = len(grid[0]) - 1
count = 0
for searchstring in ["XMAS", "SAMX"]:
# horizontal right
if x + 3 <= width:
found = sum(grid[y][x + i] == searchstring[i] for i in range(4))
if found == 4:
count += 1
# vertical down
if y + 3 <= height:
found = sum(grid[y + i][x] == searchstring[i] for i in range(4))
if found == 4:
count += 1
# diagonal down right
if y + 3 <= height and x + 3 <= width:
found = sum(grid[y + i][x + i] == searchstring[i] for i in range(4))
if found == 4:
count += 1
# diagonal down left
if y + 3 <= height and x - 3 >= 0:
found = sum(grid[y + i][x - i] == searchstring[i] for i in range(4))
if found == 4:
count += 1
return count
def find_cross_mass(grid: list[list], x: int, y: int) -> int:
# check clockwise for
# M.M
# .A.
# S.S
# then rotate the outer ring clockwise and check again
for searchstring in ["MMSS", "SMMS", "SSMM", "MSSM"]:
found = (
grid[y - 1][x - 1] == searchstring[0]
and grid[y - 1][x + 1] == searchstring[1]
and grid[y + 1][x + 1] == searchstring[2]
and grid[y + 1][x - 1] == searchstring[3]
)
if found:
return 1
return 0
def main():
grid = readinput()
count = 0
for y, _ in enumerate(grid):
for x, _ in enumerate(grid[0]):
pos = grid[y][x]
if pos in ["X", "S"]:
count += find_xmas(grid, x, y)
print("XMAS count: %d" % count)
count = 0
for y in range(1, len(grid) - 1):
for x in range(1, len(grid[0]) - 1):
pos = grid[y][x]
if pos == "A":
count += find_cross_mass(grid, x, y)
print("X-MAS count: %d" % count)
if __name__ == "__main__":
main()

92
2024/05/main.py Normal file
View file

@ -0,0 +1,92 @@
#!/usr/bin/env python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
# Author: Sebastian Mark
# CC-BY-SA (https://creativecommons.org/licenses/by-sa/4.0/deed.de)
# pylint: disable=missing-module-docstring,missing-function-docstring,consider-using-f-string
from collections import defaultdict
def readinput() -> list:
with open("input", "r", encoding="utf-8") as file:
lines = file.readlines()
return lines
def get_orders_and_updates() -> tuple[list, list]:
lines = readinput()
sep = lines.index("\n") # newline in input
rules = defaultdict(set)
for line in lines[:sep]:
a, b = map(int, line.split("|"))
rules[a].add(b)
updates = []
for line in lines[sep + 1 :]:
updates.append(list(map(int, line.split(","))))
return (rules, updates)
def validate_rules(update: list, rules: list) -> bool:
for i in range(len(update) - 1):
next_page = update[i + 1]
page = update[i]
if next_page not in rules[page]:
return False
return True
def get_middle_number(update: list) -> int:
return update[int(len(update) / 2)]
def fix_with_rules(update: list, rules: list) -> list:
# this block is inspired by:
# https://github.com/nitekat1124/advent-of-code-2024/blob/main/solutions/day05.py
# filter only the rules for the pages in the current update
filtered_rules = defaultdict(set)
for i in update:
new_rules = []
for x in rules[i]:
if x in update:
new_rules.append(x)
filtered_rules[i] = new_rules
# the more filtered rules for the value exist,
# the further to the end is has to be placed,
# then reverse this
ordered_keys = sorted(
filtered_rules, key=lambda val: len(filtered_rules[val]), reverse=True
)
return ordered_keys
def main():
rules, updates = get_orders_and_updates()
# part 1
count = 0
for update in updates:
if validate_rules(update, rules):
count += get_middle_number(update)
print("Summed updates: %d" % count)
# part 2
count = 0
for update in updates:
if not validate_rules(update, rules):
new_update = fix_with_rules(update, rules)
count += get_middle_number(new_update)
print("Summ fixed updates: %d" % count)
if __name__ == "__main__":
main()