From f9abb90915755c571c380452190f625a1868abfe Mon Sep 17 00:00:00 2001 From: Thibaud Date: Tue, 29 Jul 2025 20:29:15 +0200 Subject: [PATCH] some more days --- 2015/day1/day1.py | 19 ++++++++++ 2018/day7/day7.py | 88 +++++++++++++++++++++++++++++++++++++++++++++++ 2022/day2/day2.py | 40 +++++++++++++++++++++ 2022/day3/day3.py | 36 +++++++++++++++++++ 2022/day4/day4.py | 45 ++++++++++++++++++++++++ 5 files changed, 228 insertions(+) create mode 100644 2015/day1/day1.py create mode 100644 2018/day7/day7.py create mode 100644 2022/day2/day2.py create mode 100644 2022/day3/day3.py create mode 100644 2022/day4/day4.py diff --git a/2015/day1/day1.py b/2015/day1/day1.py new file mode 100644 index 0000000..81da963 --- /dev/null +++ b/2015/day1/day1.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +def main(inp): + floor = 0 + basement = -1 + for i, c in enumerate(inp): + if c == "(": floor += 1 + elif c == ")": floor -= 1 + if basement == -1 and floor == -1: + basement = i + 1 + print("Part 1: ", floor) + print("Part 2: ", basement) + + +if __name__ == '__main__': + import sys + infile = sys.argv[1] if len(sys.argv) > 1 else "example.txt" + with open(infile) as inp: + main(inp.read().rstrip()) + diff --git a/2018/day7/day7.py b/2018/day7/day7.py new file mode 100644 index 0000000..add624e --- /dev/null +++ b/2018/day7/day7.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python3 +import re +from bisect import insort +from collections import defaultdict + + +def topological_sort(graph, reverse_deps): + # find starting nodes: with no incoming edges (aka indegree 0) + queue = sorted([task for task in graph.keys() if reverse_deps[task] == set()]) + order = [] + seen = set() + while queue != []: + current = queue.pop(0) + if current not in seen: + seen.add(current) + order.append(current) + # add dependencies if all prerequisites are already visited, + # insert them in alphabetical order + for d in graph[current]: + if all(x in order for x in reverse_deps[d]): + insort(queue, d) + return order + + +def main(inp): + dependencies = defaultdict(set) + reverse_deps = defaultdict(set) + for l in inp: + first, second = re.findall(r"[sS]tep (\w)", l) + dependencies[first].add(second) + reverse_deps[second].add(first) + + order = topological_sort(dependencies, reverse_deps) + print("Part 1: ", "".join(order)) + + + done = [] + doing = dict() + + workers = 5 + step = 0 + number_of_tasks = len(order) + while len(done) != number_of_tasks: + assert len(doing) <= workers + for i in range(workers): + # check if the worker has a pending task + if i in doing: + task = doing[i] + if is_task_done(task, step): + #print(f"{step}: worker #{i}, task {task} done") + del doing[i] + done.append(task[0]) + else: + continue + next_task = get_task(dependencies, reverse_deps, done, doing) + if next_task is not None: + #print(f"{step}: worker #{i}, starting task {next_task}") + doing[i] = (next_task, step) + #print(f"{step}: {doing} {done}") + if len(done) == number_of_tasks: + break + step += 1 + print(f"{step}\t{'\t'.join(x[0] for x in doing.values())}") + print(step) + +def get_task(graph, reverse_deps, done, doing): + queue = sorted([task for task in graph.keys() if all(x in done for x in reverse_deps[task])]) + doingg = [x[0] for x in doing.values()] + for t in queue: + if t not in done and t not in doingg: + return t + return None + + +def is_task_done(task, step): + letter, start_t = task + duration = ord(letter) - ord("A") + 61 + if step - start_t >= duration: + return True + return False + + +if __name__ == '__main__': + import sys + infile = sys.argv[1] if len(sys.argv) > 1 else "example.txt" + with open(infile) as inp: + main([l.rstrip() for l in inp.readlines()]) + diff --git a/2022/day2/day2.py b/2022/day2/day2.py new file mode 100644 index 0000000..368a086 --- /dev/null +++ b/2022/day2/day2.py @@ -0,0 +1,40 @@ +def main(content): + table = str.maketrans("XYZ", "ABC") + score = 0 + for c in content: + c = c.translate(table) + w = ord(c[-1]) - ord("A") + 1 + match c: + case "A A" | "B B" | "C C": score += 3 + w + case "A B" | "B C" | "C A": score += 6 + w + case "A C" | "B A" | "C B": score += w + case _: assert False, c + print("Part 1: ", score) + + # x = lose, y = draw, z = win + score = 0 + for c in content: + outcome = c[-1] + if outcome == "Y": + w = ord(c[0]) - ord("A") + 1 + score += 3 + w + elif outcome == "Z": + index = ord(c[0]) - ord("A") + play = "ABC"[(index + 1) % 3] + w = ord(play) - ord("A") + 1 + score += 6 + w + elif outcome == "X": + index = ord(c[0]) - ord("A") + w = ord("ABC"[index - 1]) - ord("A") + 1 + score += w + else: + assert False, outcome + print(score) + + + +if __name__ == "__main__": + import fileinput + #main(['A Y', 'B X', 'C Z']) + main(list(l.rstrip() for l in fileinput.input())) + diff --git a/2022/day3/day3.py b/2022/day3/day3.py new file mode 100644 index 0000000..72802c1 --- /dev/null +++ b/2022/day3/day3.py @@ -0,0 +1,36 @@ +from itertools import zip_longest +from functools import reduce +from operator import and_ + + +def grouper(n, iterable): + "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx" + args = [iter(iterable)] * n + return zip_longest(*args) + + +def split(x): + return set(x[:len(x)//2]), set(x[len(x)//2:]) + + +def get_priority(x): + x = x.pop() + prio = ord(x) + if "a" <= x <= "z": + prio -= ord("a") - 1 + else: + prio -= ord("A") - 27 + return prio + + +def main(content): + total = sum(get_priority(reduce(and_, split(l))) for l in content) + print("Part 1: ", total) + total = sum(get_priority(reduce(and_, map(set, x))) for x in grouper(3, content)) + print("Part 2: ", total) + + +if __name__ == "__main__": + import fileinput + main(list(l.rstrip() for l in fileinput.input())) + diff --git a/2022/day4/day4.py b/2022/day4/day4.py new file mode 100644 index 0000000..e3b832d --- /dev/null +++ b/2022/day4/day4.py @@ -0,0 +1,45 @@ + +def contains(first, second): + "True if first ⊂ second or second ⊂ first" + start_a, end_a = first + start_b, end_b = second + if start_b >= start_a and end_b <= end_a: + return True + start_a, end_a = second + start_b, end_b = first + if start_b >= start_a and end_b <= end_a: + return True + return False + + +def overlaps(first, second): + start_a, end_a = first + start_b, end_b = second + if start_a <= start_b <= end_a: + return True + if start_b <= start_a <= end_b: + return True + return False + + +def main(content): + total = 0 + for l in content: + first, second = [tuple(map(int, x.split("-"))) for x in l.split(",")] + if contains(first, second): + total += 1 + print("Part 1: ", total) + + total = 0 + for l in content: + first, second = [tuple(map(int, x.split("-"))) for x in l.split(",")] + if overlaps(first, second): + total += 1 + print("Part 2: ", total) + + + +if __name__ == "__main__": + import fileinput + main([l.rstrip() for l in fileinput.input()]) +