Ejemplo n.º 1
0
Archivo: day10.py Proyecto: oabm/aoc
        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)
Ejemplo n.º 2
0
Archivo: day12.py Proyecto: oabm/aoc
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)
Ejemplo n.º 3
0
Archivo: day11.py Proyecto: oabm/aoc
            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)
Ejemplo n.º 4
0
Archivo: day05.py Proyecto: oabm/aoc
        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)
Ejemplo n.º 5
0
Archivo: day04.py Proyecto: oabm/aoc
#!/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)
Ejemplo n.º 6
0
Archivo: day16.py Proyecto: oabm/aoc
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)
Ejemplo n.º 7
0
Archivo: day20.py Proyecto: oabm/aoc
        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)
Ejemplo n.º 8
0
Archivo: day17.py Proyecto: oabm/aoc
        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)
Ejemplo n.º 9
0
Archivo: day05.py Proyecto: oabm/aoc
#!/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)
Ejemplo n.º 10
0
Archivo: day08.py Proyecto: oabm/aoc
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'
Ejemplo n.º 11
0
#!/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)
Ejemplo n.º 12
0
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)
Ejemplo n.º 13
0
# == !(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))
Ejemplo n.º 14
0
Archivo: day03.py Proyecto: oabm/aoc
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)
Ejemplo n.º 15
0
        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)
Ejemplo n.º 16
0
Archivo: day08.py Proyecto: oabm/aoc
    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)
Ejemplo n.º 17
0
        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)
Ejemplo n.º 18
0
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)
Ejemplo n.º 19
0
Archivo: day03.py Proyecto: oabm/aoc
            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)
Ejemplo n.º 20
0
Archivo: day22.py Proyecto: oabm/aoc
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)
Ejemplo n.º 21
0
Archivo: day15.py Proyecto: oabm/aoc
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)
Ejemplo n.º 22
0
#!/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)
Ejemplo n.º 23
0
Archivo: day10.py Proyecto: oabm/aoc
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)
Ejemplo n.º 24
0
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)
Ejemplo n.º 25
0
            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)
Ejemplo n.º 26
0
Archivo: day07.py Proyecto: oabm/aoc
@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)
Ejemplo n.º 27
0
        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)
Ejemplo n.º 28
0
	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)
Ejemplo n.º 29
0
Archivo: day21.py Proyecto: oabm/aoc
                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)
Ejemplo n.º 30
0
Archivo: day07.py Proyecto: oabm/aoc
                    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)