add 2024/day1-day5 python
This commit is contained in:
parent
6c64d1b62e
commit
7c4e98ebcf
5 changed files with 360 additions and 0 deletions
51
2024/01/main.py
Executable file
51
2024/01/main.py
Executable 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
76
2024/02/main.py
Executable 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
52
2024/03/main.py
Normal 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
89
2024/04/main.py
Normal 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
92
2024/05/main.py
Normal 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()
|
Loading…
Reference in a new issue