diff options
-rw-r--r-- | 1.py | 2 | ||||
-rw-r--r-- | 2.py | 18 | ||||
-rw-r--r-- | 3.py | 23 | ||||
-rw-r--r-- | 4.py | 9 | ||||
-rw-r--r-- | 5.py | 29 | ||||
-rw-r--r-- | 6.py | 8 | ||||
-rw-r--r-- | 7.py | 93 |
7 files changed, 182 insertions, 0 deletions
@@ -0,0 +1,2 @@ +print(max(sum(int(n) for n in group.split('\n')) for group in open('1.in').read().rstrip().split('\n\n'))) +print(sum(sorted(sum(int(n) for n in group.split('\n')) for group in open('1.in').read().rstrip().split('\n\n'))[-3:])) @@ -0,0 +1,18 @@ +with open('2.in') as f: + inp = [] + for line in f: + a, b = line.rstrip().split() + inp.append((ord(a) - ord('A'), ord(b) - ord('X'))) +def shape_score(me): + return me + 1 +def outcome_score(opp, me): + return (3 - opp + me + 1) % 3 * 3 +def p1(opp, me): + return shape_score(me) + outcome_score(opp, me) +print(sum(p1(a, b) for a, b in inp)) +def shape_for_outcome(opp, outcome): + return (3 + opp + outcome + 2) % 3 +def p2(opp, outcome): + me = shape_for_outcome(opp, outcome) + return p1(opp, me) +print(sum(p2(a, b) for a, b in inp)) @@ -0,0 +1,23 @@ +with open('3.in') as f: + rucksacks = [line.rstrip() for line in f] + +def priority(itm): + if itm.islower(): + return ord(common) - ord('a') + 1 + else: + return ord(common) - ord('A') + 27 + +total = 0 +for rucksack in rucksacks: + half = len(rucksack) // 2 + a, b = set(rucksack[:half]), set(rucksack[half:]) + common = set.intersection(a, b).pop() + total += priority(common) +print(total) + +total = 0 +for i in range(0, len(rucksacks), 3): + a, b, c = map(set, rucksacks[i:i+3]) + common = set.intersection(a, set.intersection(b, c)).pop() + total += priority(common) +print(total) @@ -0,0 +1,9 @@ +with open('4.in') as f: + inp = [tuple(tuple(map(int, elf.split('-'))) for elf in line.rstrip().split(',')) for line in f] +def fully_contains(a, b): + return b[0] >= a[0] and b[1] <= a[1] or a[0] >= b[0] and a[1] <= b[1] +def overlaps(a, b): + return b[0] <= a[0] <= b[1] or b[0] <= a[1] <= b[1] or \ + a[0] <= b[0] <= a[1] # or a[0] <= b[1] <= a[1] +print(sum(fully_contains(a, b) for a, b in inp)) +print(sum(overlaps(a, b) for a, b in inp)) @@ -0,0 +1,29 @@ +from copy import deepcopy +with open('5.in.test') as f: + stacks, instructions = f.read().rstrip().split('\n\n') +layers = stacks.split('\n') +stacks = [list() for _ in range((len(layers[-1]) + 1) // 4)] +for layer in reversed(layers[:-1]): + for i in range(len(stacks)): + c = layer[i * 4 + 1] + if c != ' ': + stacks[i].append(c) +instructions = [i.split(' ') for i in instructions.split('\n')] +instructions = [tuple(int(i) for i in (i[1], i[3], i[5])) for i in instructions] +def part1(stacks, instructions): + stacks = deepcopy(stacks) + for count, src, dst in instructions: + for _ in range(count): + stacks[dst-1].append(stacks[src-1].pop()) + return ''.join(s[-1] for s in stacks) +def part2(stacks, instructions): + stacks = deepcopy(stacks) + for count, src, dst in instructions: + tmp = list() + for _ in range(count): + tmp.append(stacks[src-1].pop()) + for _ in range(count): + stacks[dst-1].append(tmp.pop()) + return ''.join(s[-1] for s in stacks) +print(part1(stacks, instructions)) +print(part2(stacks, instructions)) @@ -0,0 +1,8 @@ +with open('6.in') as f: + inp = f.read().rstrip() +def solve(inp, n): + for i in range(n, len(inp)): + if len(set(inp[i-n:i])) == n: + return i +print(solve(inp, 4)) +print(solve(inp, 14)) @@ -0,0 +1,93 @@ +from __future__ import annotations + +from dataclasses import dataclass + +@dataclass +class File: + size: int + +@dataclass +class Directory: + up: Directory + entries: dict[str, File|Directory] + def __init__(self, up=None): + self.up = up if up else self + self.entries = dict() + def __getitem__(self, key): + match key: + case '..': + return self.up + case '.': + return self + case d: + return self.entries[d] + def __setitem__(self, key, value): + self.entries[key] = value + def get(self, key, default=None): + try: + return self[key] + except KeyError: + return default + +with open('7.in.test') as f: + inp = [tuple(line.rstrip().split()) for line in f] +root = Directory() +pwd = root +for line in inp: + match line: + case ['$', 'cd', d]: + match d: + case '/': pwd = root + case d: + pwd = pwd[d] + assert(isinstance(pwd, Directory)) + case ['$', 'ls']: + continue + case ['dir', name]: + pwd[name] = Directory(pwd) + case [size, name]: + pwd[name] = File(int(size)) + +dirsizes = dict() +def getsize(d: Directory, path=tuple()) -> int: + if path in dirsizes: + return dirsizes[path] + size = 0 + for k, e in d.entries.items(): + match e: + case File(s): + size += s + case Directory(_, _) as d: + size += getsize(d, path + (k,)) + dirsizes[size] = size + return size + +def part1(root): + answer = 0 + def solve(d, path=tuple()): + nonlocal answer + for k, e in d.entries.items(): + if isinstance(e, Directory): + solve(e, path + (k,)) + size = getsize(d, path) + if size <= 100000: + answer += size + solve(root) + return answer +def part2(root): + used = getsize(root) + unused = 70000000 - used + need = 30000000 - unused + smallest = used + def solve(d, path=tuple()): + nonlocal smallest + for k, e in d.entries.items(): + if isinstance(e, Directory): + solve(e, path + (k,)) + size = getsize(d, path) + if size >= need and size < smallest: + smallest = size + solve(root) + return smallest +print(part1(root)) +print(part2(root)) |