#!/usr/bin/env python3 from utils import advent from collections import namedtuple, defaultdict advent.setup(2018, 6) fin = advent.get_input() ################################################## def dist(p1, x, y): return abs(p1.x - x) + abs(p1.y - y) def compute_counts(bigbound): counts = defaultdict(int) for i in range(-bigbound, bigbound): if i % 100 == 0: print(str(i) + '...') for j in range(-bigbound, bigbound): min_dist = 999999999 nearest = None ignore = False for p in pts: d = dist(p, i, j) if d < min_dist:
#!/usr/bin/env python3 from utils import advent from collections import defaultdict, namedtuple from string import * advent.setup(2018, 7) fin = advent.get_input() ################################################## def wtf(graph, node, q, visited): global lol visited.add(node) # print('visited', node) lol += node for n in graph[node].next: q.add(n) while len(q): for n in sorted(q): # print('tryng', n) if all(x in visited for x in graph[n].need): # print(' need satisfied, can visit', n) if n not in q: # print(' not in queue!') break
for c, cell in enumerate(row): if cell == FLOOR: continue occ = occ_counter(previous, r, c) if cell == EMPTY and occ == 0: grid[r][c] = OCCUPIED elif cell == OCCUPIED and occ >= occ_threshold: grid[r][c] = EMPTY if grid == previous: return sum(row.count(OCCUPIED) for row in grid) previous = grid from utils.timer import * advent.setup(2020, 11) fin = advent.get_input() original = list(map(list, map(str.rstrip, fin.readlines()))) MAXROW, MAXCOL = len(original) - 1, len(original[0]) - 1 OCCUPIED, EMPTY, FLOOR = '#L.' total_occupied = evolve(deepcopy(original), occupied_neighbors, 4) advent.print_answer(1, total_occupied) total_occupied = evolve(deepcopy(original), occupied_in_sight, 5) advent.print_answer(2, total_occupied)
#!/usr/bin/env python3 from utils import advent advent.setup(2018, 3) fin = advent.get_input() ans = 0 ans2 = 0 ################################################## canvas = [] for i in range(1000): canvas.append([]) for j in range(1000): canvas[i].append({'ids': set(), 'tot': 0}) claims = {} for line in fin: cid, claim = line.strip().replace(' ', '').split('@') cid = int(cid[1:]) start, size = claim.split(':') x, y = map(int, start.split(',')) w, h = map(int, size.split('x')) claims[cid] = (x, y, w, h) for cid, c in claims.items(): for i in range(c[0], c[0] + c[2]): for j in range(c[1], c[1] + c[3]): canvas[i][j]['tot'] += 1
#!/usr/bin/env python3 from utils import advent import sys import copy import networkx as nx from sortedcontainers import SortedKeyList advent.setup(2018, 15, True) fin = advent.get_input() # print(*fin) ################################################## class Ripperoni(Exception): pass def log(s, *a): if LOG: sys.stderr.write(s.format(*a)) sys.stderr.flush() def dump(): log(' ' + ' '*10 + '1'*10 + '2'*10 + '3'*10 + '\n') log(' ' + '0123456789'*4 + '\n') for i, row in enumerate(cavern): log('{:>2d} ', i) for j, cell in enumerate(row): if (i, j) in elves:
dx, dy = bx - ax, by - ay div = abs(gcd(dx, dy)) return dx // div, dy // div def manhattan(ax, ay, bx, by): return abs(bx - ax) + abs(by - ay) def angle(ax, ay, bx, by): rad = atan2(by - ay, bx - ax) + PI rad = rad % (2 * PI) - PI / 2 return rad if rad >= 0 else 2 * PI + rad advent.setup(2019, 10) fin = advent.get_input() grid = [l.rstrip() for l in fin] asteroids = set() for y, row in enumerate(grid): for x, cell in enumerate(row): if cell == '#': asteroids.add((x, y)) station = None max_in_sight = 0 for src in asteroids: lines_of_sight = set()
@lru_cache() def real_fn(i): if i == len(nums) - 1: return 1 tot = 0 for j in range(i + 1, min(i + 4, len(nums))): if nums[j] - nums[i] <= 3: tot += real_fn(j) return tot return real_fn(i) advent.setup(2020, 10) fin = advent.get_input() nums = map(int, fin.readlines()) nums = sorted(nums) dist1, dist3 = 1, 1 for cur, nxt in zip(nums, nums[1:]): delta = nxt - cur if delta == 1: dist1 += 1 elif delta == 3: dist3 += 1 ans = dist1 * dist3
#!/usr/bin/env python3 from utils import advent advent.setup(2018, 4) fin = advent.get_input() ans = 0 ans2 = 0 arr = [] for l in fin: gid = -1 if 'wakes up' in l: action = 'w' elif 'falls asleep' in l: action = 's' elif 'begins shift' in l: action = 'b' gid = l[l.find('#') + 1:] gid = int(gid[:gid.find(' ')]) date, time = l[1:17].split(' ') y, m, d = map(int, date.split('-')) h, mm = map(int, time.split(':')) arr.append({ 'date': (y, m, d), 'time': (h, mm), 'action': action,
#!/usr/bin/env python3 from utils import advent advent.setup(2018, 16) fin = advent.get_input() # print(*fin) ################################################## def simulate(r1, o, r2): op, a, b, c = o count = 0 # addr if r2[c] == r1[a] + r1[b]: count += 1 elif 'addr' in ops[op]: ops[op].remove('addr') # addi if r2[c] == r1[a] + b: count += 1 elif 'addi' in ops[op]: ops[op].remove('addi') # mulr if r2[c] == r1[a] * r1[b]: count += 1 elif 'mulr' in ops[op]: ops[op].remove('mulr') # muli if r2[c] == r1[a] * b: count += 1 elif 'muli' in ops[op]: ops[op].remove('muli')
c1, c2 = deck1.popleft(), deck2.popleft() if len(deck1) >= c1 and len(deck2) >= c2: sub1, sub2 = tuple(deck1)[:c1], tuple(deck2)[:c2] p1win, _ = recursive_play(deque(sub1), deque(sub2)) else: p1win = c1 > c2 if p1win: deck1.extend((c1, c2)) else: deck2.extend((c2, c1)) return (True, deck1) if deck1 else (False, deck2) advent.setup(2020, 22) fin = advent.get_input() deck1, deck2 = map(str.splitlines, fin.read().split('\n\n')) deck1 = deque(map(int, deck1[1:])) deck2 = deque(map(int, deck2[1:])) winner_deck = play(deck1.copy(), deck2.copy()) winner_score = score(winner_deck) advent.print_answer(1, winner_score) _, winner_deck = recursive_play(deck1, deck2) winner_score = score(winner_deck) advent.print_answer(2, winner_score)
return set((x + dx, y + dy) for x, y in grid for dx, dy in deltas) def evolve(grid): new = set() for p in all_neighbors(grid): n = black_adjacent(grid, *p) if n == 2 or (n == 1 and p in grid): new.add(p) return new advent.setup(2020, 24) fin = advent.get_input() grid = set() # coords of tiles with black side up rexp = re.compile(r'e|w|se|sw|ne|nw') for line in fin: moves = rexp.findall(line) p = walk(moves) if p in grid: grid.remove(p) else: grid.add(p) n_black = len(grid)
#!/usr/bin/env python3 from utils import advent import re advent.setup(2018, 17) fin = advent.get_input() # print(*fin) ################################################## rexp = re.compile(r'-?\d+') minx, miny = 9999, 9999 maxx, maxy = -9999, -9999 horizontal = [] vertical = [] for l in fin: a, b, c = map(int, rexp.findall(l)) if l.startswith('x'): minx = min(minx, a) maxx = max(maxx, a) miny = min(miny, b) maxy = max(maxy, c) vertical.append([a, b, c]) else: miny = min(miny, a) maxy = max(maxy, a)
visited.add(color) count_can_contain(G, color, visited) return len(visited) @lru_cache() def count_contained(src): tot = 0 for qty, color in contains[src]: tot += qty * (1 + count_contained(color)) return tot advent.setup(2020, 7) fin = advent.get_input() contained_by = defaultdict(list) contains = defaultdict(list) inner_exp = re.compile(r'(\d+) ([\w ]+) bags?[.,]') for line in fin: outer, inners = line.split(' bags contain ') inners = inner_exp.findall(inners) for qty, inner in inners: contained_by[inner].append(outer) contains[outer].append((int(qty), inner)) can_contain_gold = count_can_contain(contained_by, 'shiny gold')
#!/usr/bin/env python3 from utils import advent from itertools import count advent.setup(2020, 3) fin = advent.get_input() grid = [l.rstrip() for l in fin] height, width = len(grid), len(grid[0]) trees = 0 for row, col in zip(range(height), count(0, 3)): if grid[row][col % width] == '#': trees += 1 advent.print_answer(1, trees) total = trees for dr, dc in ((1, 1), (1, 5), (1, 7), (2, 1)): trees = 0 for row, col in zip(range(0, height, dr), count(0, dc)): if grid[row][col % width] == '#': trees += 1 total *= trees advent.print_answer(2, total)
#!/usr/bin/env python3 from utils import advent import sys from blist import blist advent.setup(2018, 9) fin = advent.get_input() ################################################## s = fin.read().split() nplayers, last_marble = int(s[0]), int(s[6]) marbles = blist([0]) cur_marble = 0 cur_idx = 0 cur_player = 1 scores = {} # nplayers = 10 # last_marble = 1618 for i in range(1, nplayers + 1): scores[i] = 0 while cur_marble < last_marble: cur_marble += 1
for _ in range(n): p = (p[0] + MOVE_DX[d], p[1] + MOVE_DY[d]) visited.add(p) cur_steps += 1 if p not in steps: steps[p] = cur_steps return visited, steps def manhattan(p): return abs(p[0]) + abs(p[1]) advent.setup(2019, 3) lines = advent.get_input().readlines() all_visited = [] all_steps = [] for l in lines: visited, steps = get_visited_and_steps(map(make_move, l.split(','))) all_visited.append(visited) all_steps.append(steps) intersections = set.intersection(*all_visited) min_distance = min(map(manhattan, intersections)) advent.print_answer(1, min_distance) shortest_path = min(sum(l[p] for l in all_steps) for p in intersections)
while len(r): c = r.popleft() if c in ignore: continue if len(l) and c ^ l[-1] == 0x20: l.pop() else: l.append(c) return l advent.setup(2018, 5) fin = advent.get_input(mode='rb') polymer = fin.read().rstrip() trimmed = react_fast(polymer) reacted_len = len(trimmed) advent.print_answer(1, reacted_len) best_reacted_len = reacted_len for l, L in zip(ascii_lowercase.encode(), ascii_uppercase.encode()): reacted_len = len(react_fast(trimmed, {l, L})) if reacted_len < best_reacted_len: best_reacted_len = reacted_len
#!/usr/bin/env python3 from utils import advent import sys import copy advent.setup(2018, 13) fin = advent.get_input() # print(*fin) ################################################## def kill(crashxy): for i, cart in enumerate(carts): if tuple(cart[:2]) == crashxy: carts.pop(i) break def dump(crashxy=(-1, -1)): cartdict = dict((tuple(c[:2]), c[2]) for c in carts) for i, l in enumerate(matrix): for j, c in enumerate(l): if (i, j) == crashxy: sys.stdout.write('X') elif (i, j) in cartdict: sys.stdout.write(cartdict[i, j]) else:
#!/usr/bin/env python3 from utils import advent from itertools import islice advent.setup(2019, 4) fin = advent.get_input() lo, hi = map(int, fin.read().split('-')) n_valid1 = 0 n_valid2 = 0 for pwd in range(lo, hi + 1): digits = str(pwd) pairs = tuple(zip(digits, digits[1:])) if all(a <= b for a, b in pairs) and any(a == b for a, b in pairs): n_valid1 += 1 digits = 'x' + digits + 'x' quadruplets = zip(digits, digits[1:], digits[2:], digits[3:]) if any(a != b and b == c and c != d for a, b, c, d in quadruplets): n_valid2 += 1 advent.print_answer(1, n_valid1) advent.print_answer(2, n_valid2)
#!/usr/bin/env python3 from utils import advent advent.setup(2018, 8) fin = advent.get_input() ################################################## def scan(n, cur_id): nchilds = n[0] nmeta = n[1] if nchilds == 0: tree[cur_id] = ([], n[2:2+nmeta]) return sum(tree[cur_id][1]), 2 + nmeta cur_len = 2 meta_sum = 0 childs = [] for _ in range(nchilds): child_id = cur_id + cur_len childs.append(child_id) child_meta_sum, child_len = scan(n[cur_len:], child_id) meta_sum += child_meta_sum cur_len += child_len tree[cur_id] = (childs, n[cur_len:cur_len+nmeta])
#!/usr/bin/env python3 from utils import advent advent.setup(2019, 1) fin = advent.get_input() nums = map(int, fin.readlines()) nums = tuple(map(lambda n: n // 3 - 2, nums)) total = sum(nums) advent.print_answer(1, total) for n in nums: while n > 0: n = max(n // 3 - 2, 0) total += n advent.print_answer(2, total)
assigned = [None] * len(possible) while any(possible): for i, poss in enumerate(possible): if len(poss) == 1: assigned[i] = match = poss.pop() break for other in possible: if match in other: other.remove(match) return assigned advent.setup(2020, 16) fin = advent.get_input() ranges, my_ticket, tickets = parse_input(fin) total = sum(map(sum, map(invalid_fields, tickets))) advent.print_answer(1, total) tickets.append(my_ticket) n_fields = len(my_ticket) possible = [set(range(n_fields)) for _ in range(len(ranges))] for ticket in filter(is_valid, tickets): for rng, poss in zip(ranges, possible): for i, value in enumerate(ticket): if value not in rng and i in poss:
SOUTH: lambda x, y, n: (x, y - n), EAST: lambda x, y, n: (x + n, y), WEST: lambda x, y, n: (x - n, y) } # Function to apply to rotate around the origin. ROTMAP = { (LEFT, 90): lambda x, y: (-y, x), (LEFT, 180): lambda x, y: (-x, -y), (LEFT, 270): lambda x, y: (y, -x), (RIGHT, 90): lambda x, y: (y, -x), (RIGHT, 180): lambda x, y: (-x, -y), (RIGHT, 270): lambda x, y: (-y, x), } advent.setup(2020, 12) fin = advent.get_input() commands = tuple(map(lambda l: (l[0], int(l[1:])), fin)) x, y = 0, 0 dx, dy = 1, 0 # start facing EAST for cmd, n in commands: if cmd == 'F': x += dx * n y += dy * n elif cmd in 'LR': dx, dy = ROTMAP[cmd, n](dx, dy) else: x, y = MOVEMAP[cmd](x, y, n)
for img in arrangements(image): n = 0 for r in range(image_sz - pattern_h): for c in range(image_sz - pattern_w): if all(img[r + dr][c + dc] == '#' for dr, dc in deltas): n += 1 if n != 0: return n MONSTER_PATTERN = (' # ', '# ## ## ###', ' # # # # # # ') advent.setup(2020, 20) fin = advent.get_input() tiles = parse_input(fin) corners = match_tiles(tiles) ans = prod(corners) advent.print_answer(1, ans) top_left_id, matching_sides = corners.popitem() top_left = tiles[top_left_id] if matching_sides in ('ne', 'en'): top_left = rotate90(top_left) elif matching_sides in ('nw', 'wn'): top_left = rotate90(rotate90(top_left))
while hi - lo > 1: x = (lo + hi) // 2 width, y = get_width(x, target) if width > target: hi = x best = (x, y) elif width < target: lo = x return best advent.setup(2019, 19) fin = advent.get_input() program = list(map(int, fin.read().split(','))) total = sum(map(run, product(range(50), range(50)))) advent.print_answer(1, total) TARGET = 100 bestx, besty = bin_search(10, 9999, TARGET) for x in range(bestx, bestx - 10, -1): width, y = get_width(x, TARGET) if width >= TARGET: bestx, besty = x, y
if tok.isdigit(): val = int(tok) * multiplier accumulator = op(accumulator, val) elif tok == '+': op = add elif tok == '*': if plus_precedence: multiplier = accumulator accumulator = 0 else: op = mul elif tok == '(': val = evaluate(tokens, plus_precedence) * multiplier accumulator = op(accumulator, val) else: # ')' break return accumulator advent.setup(2020, 18) fin = advent.get_input() exprs = tuple(map(tokenize, fin)) total = sum(map(evaluate, map(deque, exprs))) advent.print_answer(1, total) total = sum(map(partial(evaluate, plus_precedence=True), map(deque, exprs))) advent.print_answer(2, total)
#!/usr/bin/env python3 from utils import advent advent.setup(2018, 11) fin = advent.get_input() ################################################## def fuel(x, y): rid = x + 10 powlevel = ((((rid * y + serial_no) * rid) // 100) % 10) - 5 return powlevel def get_power(xy, m=3): s = 0 x, y = xy for j in range(y, y + m): for i in range(x, x + m): s += grid[j][i] return s serial_no = int(fin.read()) grid = [] for j in range(300 + 1): grid.append([]) for i in range(300 + 1):
def bfs_farthest(maze, src): visited = set() queue = deque([(0, src)]) while queue: dist, node = queue.popleft() if node not in visited: visited.add(node) for n in filter(lambda n: n not in visited, neighbors4(maze, *node)): queue.append((dist + 1, n)) return dist advent.setup(2019, 15) fin = advent.get_input() program = list(map(int, fin.read().split(','))) vm = IntcodeVM(program) startpos = (0, 0) maze, oxygen = wall_follower(vm, startpos) min_dist = bfs_shortest(maze, startpos, oxygen) advent.print_answer(1, min_dist) time = bfs_farthest(maze, oxygen) advent.print_answer(2, time)
for ingr, possible in possible_allers.items(): if len(possible) == 1: break aller = possible.pop() assigned[aller] = ingr del possible_allers[ingr] for ingr, possible in possible_allers.items(): if aller in possible: possible.remove(aller) return assigned advent.setup(2020, 21) fin = advent.get_input() recipes, possible_allers, recipes_with = parse_input(fin) safe = safe_ingredients(recipes, possible_allers, recipes_with) tot = sum(ingr in r for r in recipes for ingr in safe) advent.print_answer(1, tot) for ingr in safe: del possible_allers[ingr] assigned = simplify(possible_allers) lst = ','.join(map(assigned.get, sorted(assigned)))
#!/usr/bin/env python3 from utils import advent from functools import reduce, partial advent.setup(2020, 6) fin = advent.get_input() into_sets = partial(map, set) unionize = partial(reduce, set.union) intersect = partial(reduce, set.intersection) raw_groups = fin.read().split('\n\n') groups = tuple(map(tuple, map(into_sets, map(str.splitlines, raw_groups)))) n_any_yes = sum(map(len, map(unionize, groups))) n_all_yes = sum(map(len, map(intersect, groups))) advent.print_answer(1, n_any_yes) advent.print_answer(2, n_all_yes)