if r > m: t2 = t else: t1 = t + 1 return t1 advent.setup(2018, 10) fin = advent.get_input() points = [] for line in fin: points.append(tuple(map(int, re.findall(r'-?\d+', line)))) t = search(points) final_points = set(simulate(points, t)) x, y, w, h = box(final_points) word = '' for j in range(y, y + h + 1): for i in range(x, x + w + 1): word += '#' if (i, j) in final_points else ' ' word += '\n' # Can't really print this nicely, but whatever advent.print_answer(1, '\n' + word) advent.print_answer(2, t)
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) dist = abs(x) + abs(y) advent.print_answer(1, dist) x, y = 0, 0 dx, dy = 10, 1 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: dx, dy = MOVEMAP[cmd](dx, dy, n) # only change from the above code dist = abs(x) + abs(y) advent.print_answer(2, dist)
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)
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 advent.print_answer(2, best_reacted_len)
#!/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)
samples = [l.split('\n') for l in data[0].split('\n\n')] program = [tuple(map(int, l.split())) for l in data[1].split('\n')] ans = 0 for sample in samples: before = tuple(map(int, rexp.findall(sample[0]))) instr = tuple(map(int, rexp.findall(sample[1]))) after = tuple(map(int, rexp.findall(sample[2]))) count = 0 for op_id, op in enumerate(opcodes): if op(before, instr[1], instr[2]) == after[instr[3]]: count += 1 elif op_id in opmap[instr[0]]: opmap[instr[0]].remove(op_id) if count >= 3: ans += 1 advent.print_answer(1, ans) opmap = solve(opmap) regs = [0] * 4 for instr in program: regs[instr[3]] = opcodes[opmap[instr[0]]](regs, instr[1], instr[2]) ans2 = regs[0] advent.print_answer(2, ans2)
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)) elif matching_sides in ('sw', 'ws'): top_left = rotate90(rotate90(rotate90(top_left))) image_dimension = int(len(tiles)**0.5) tiles.pop(top_left_id) image = build_image(top_left, tiles, image_dimension)
grid[y][x] = CLAY for x, y1, y2 in vertical: for y in range(y1, y2 + 1): grid[y][x] = CLAY padw = 2 gridh += 1 gridw += padw * 2 for i in range(len(grid)): grid[i] = [SAND] * padw + grid[i] + [SAND] * padw grid = [[SAND] * gridw] + grid filled = fill(500 - minx + padw, 0) - 1 advent.print_answer(1, filled) retained = filled for y in range(1, gridh): for x in range(1, gridw - 1): if grid[y][x] == WATER and grid[y][x - 1] in (SAND, MOVING_WATER): grid[y][x] = MOVING_WATER retained -= 1 for x in range(gridw - 2, 0, -1): if grid[y][x] == WATER and grid[y][x + 1] in (SAND, MOVING_WATER): grid[y][x] = MOVING_WATER retained -= 1 advent.print_answer(2, retained)
#!/usr/bin/env python3 from utils import advent from itertools import product advent.setup(2020, 5) fin = advent.get_input() table = str.maketrans('BFRL', '1010') seats = fin.read().translate(table).splitlines() ids = tuple(map(lambda s: int(s, 2), seats)) max_id = max(ids) advent.print_answer(1, max_id) min_id = min(ids) expected = max_id * (max_id + 1) // 2 - min_id * (min_id - 1) // 2 my_id = expected - sum(ids) advent.print_answer(2, my_id)
from utils import advent WIDTH, HEIGHT = 25, 6 SIZE = WIDTH * HEIGHT advent.setup(2019, 8) fin = advent.get_input() chars = fin.readline().strip() layers = [chars[i:i + SIZE] for i in range(0, len(chars), SIZE)] best = min(layers, key=lambda l: l.count('0')) checksum = best.count('1') * best.count('2') advent.print_answer(1, checksum) image = ['2'] * SIZE for i in range(SIZE): for l in layers: if l[i] != '2': image[i] = l[i] break conv = {'0': ' ', '1': '#'} decoded = '' for i in range(0, SIZE, WIDTH): decoded += ''.join(map(conv.get, image[i:i + WIDTH])) + '\n'
#!/usr/bin/env python3 from utils import advent from lib.intcode import IntcodeVM advent.setup(2019, 5) fin = advent.get_input() program = list(map(int, fin.read().split(','))) vm = IntcodeVM(program) out = vm.run([1])[-1] advent.print_answer(1, out) out = vm.run([5])[-1] advent.print_answer(2, out)
out = vm.run() grid = ''.join(map(chr, out)).strip().splitlines() rows, columns = len(grid), len(grid[0]) answer = 0 for r in range(1, rows - 1): for c in range(1, columns - 1): if grid[r][c] == SCAFFOLD: n = sum((grid[rr][cc] == SCAFFOLD for rr, cc in ((r + 1, c), (r - 1, c), (r, c + 1), (r, c - 1)))) if n == 4: answer += r * c elif grid[r][c] in '^v<>': startpos = (r, c) startdir = '^v<>'.index(grid[r][c]) advent.print_answer(1, answer) moves = get_moves(grid, startpos, startdir) A, B, C = find_functions(moves) main = ','.join(moves).replace(A, 'A').replace(B, 'B').replace(C, 'C') robot_prog = list(map(ord, '{}\n{}\n{}\n{}\nn\n'.format(main, A, B, C))) vm.reset() vm.code[0] = 2 answer = vm.run(robot_prog)[-1] advent.print_answer(2, answer)
# == !(A & B & C) & D springscript = """\ NOT A J NOT J J AND B J AND C J NOT J J AND D J WALK """ inp = list(map(ord, springscript)) for value in intcode_oneshot(program, inp): continue advent.print_answer(2, value) # (!A & D) | (!B & D) | (!C & D & H) # == (!A | !B | (!C & H)) & D springscript = """\ NOT C J AND H J NOT B T OR T J NOT A T OR T J AND D J RUN """ inp = list(map(ord, springscript))
advent.setup(2018, 3) fin = advent.get_input() canvas = defaultdict(set) claim_ids = set() for line in fin: cid, claim = line.split('@') cid = int(cid[1:]) start, size = claim.split(':') x, y = map(int, start.split(',')) w, h = map(int, size.split('x')) for i in range(x, x + w): for j in range(y, y + h): canvas[i, j].add(cid) claim_ids.add(cid) overlapping = sum(map(lambda x: len(x) > 1, canvas.values())) advent.print_answer(1, overlapping) for c in filter(lambda x: len(x) > 1, canvas.values()): claim_ids -= c assert len(claim_ids) == 1 good = claim_ids.pop() advent.print_answer(2, good)
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 Node(length + nmeta, children, flat[length:length + nmeta]) def sum_meta(node): return sum(node.metadata) + sum(sum_meta(c) for c in node.children) def node_value(node): if not node.children: return sum(node.metadata) value = 0 for i in node.metadata: if 1 <= i <= len(node.children): value += node_value(node.children[i - 1]) return value advent.setup(2018, 8) fin = advent.get_input() nums = list(map(int, fin.read().split())) root = build_tree(nums) meta_sum = sum_meta(root) advent.print_answer(1, meta_sum) value = node_value(root) advent.print_answer(2, value)
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) advent.print_answer(1, n_black) for _ in range(100): grid = evolve(grid) n_black = len(grid) advent.print_answer(2, n_black)
Portal = namedtuple('Portal', ['label', 'side', 'depth']) advent.setup(2019, 20) fin = advent.get_input() grid = tuple(l.strip('\n') for l in fin) MAXROW = len(grid) - 1 MAXCOLUMN = len(grid[0]) - 1 G = build_graph(grid) for p in G: if p.label.startswith('AA'): ENTRANCE = p if p.label.startswith('ZZ'): EXIT = p for p1, p2 in combinations(G, 2): if p1.label == p2.label: G[p1].append((p2, 1)) G[p2].append((p1, 1)) min_steps = dijkstra(G, ENTRANCE, EXIT) advent.print_answer(1, min_steps) G = build_graph(grid) min_steps = dijkstra(G, ENTRANCE, EXIT, get_neighbors=recursive_neighbors) advent.print_answer(2, min_steps)
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) advent.print_answer(2, shortest_path)
def repeat(start, step, size, repetitions): final_step = pow(step, repetitions, size) S = (1 - final_step) * pow(1 - step, size - 2, size) final_start = (start * S) % size return final_start, final_step advent.setup(2019, 22, 1) fin = advent.get_input() moves = build_moves(fin) start, step, size = 0, 1, 10007 target_card = 2019 start, step = transform(start, step, size, moves) position = ((target_card - start) * pow(step, size - 2, size)) % size advent.print_answer(1, position) start, step, size = 0, 1, 119315717514047 target_position = 2020 repetitions = 101741582076661 start, step = transform(start, step, size, moves) start, step = repeat(start, step, size, repetitions) card = (start + step * target_position) % size advent.print_answer(2, card)
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)
#!/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)
for src in asteroids: lines_of_sight = set() for a in asteroids: if a == src: continue lines_of_sight.add(ray(*src, *a)) in_sight = len(lines_of_sight) if in_sight > max_in_sight: max_in_sight = in_sight station = src advent.print_answer(1, max_in_sight) closest = {} target = 200 # This part 2 solution assumes that max_in_sight is always >= target (200). # I.E. the 200th asteroid is destroyed in the first rotation. assert max_in_sight >= target for a in asteroids: if a == station: continue r = ray(*station, *a) m = manhattan(*station, *a)
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)
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 advent.print_answer(1, ans) nums = [0] + nums + [max(nums) + 3] total = arrangements(nums, 0) advent.print_answer(2, total)
@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') advent.print_answer(1, can_contain_gold) total_bags = count_contained('shiny gold') advent.print_answer(2, total_bags)
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 answer = bestx * 10000 + besty advent.print_answer(2, answer)
miny = min(y for _, y in grid) maxy = max(y for _, y in grid) height = maxx - minx + 1 width = maxy - miny + 1 matrix = [([' '] * width) for _ in range(height)] for x in range(height): for y in range(width): if grid[minx + x, miny + y] == WHITE: matrix[x][y] = '#' return matrix advent.setup(2019, 11) fin = advent.get_input() program = list(map(int, fin.read().split(','))) robot = IntcodeVM(program) grid = run_robot(robot, BLACK) n_painted = len(grid) advent.print_answer(1, n_painted) grid = run_robot(robot, WHITE) pic = sparse_to_matrix(grid) pic = ''.join(''.join(x) + '\n' for x in pic) # Can't really print this nicely, but whatever advent.print_answer(2, '\n' + pic)
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))) advent.print_answer(2, lst)
heapq.heappush(queue, n) return total_time advent.setup(2018, 7) fin = advent.get_input() graph = defaultdict(lambda: [0, set()]) for line in fin: s = line.split() graph[s[1]][1].add(s[7]) graph[s[7]][1].add(s[1]) graph[s[7]][0] += 1 roots = [] for letter, node in graph.items(): if node[0] == 0: heapq.heappush(roots, letter) order = lex_toposort(copy.deepcopy(graph), roots[:]) advent.print_answer(1, order) durations = {} for c in graph: durations[c] = ord(c) - ord('A') + 61 total = work(graph, roots, durations, 5) advent.print_answer(2, total)