Пример #1
0
def run(data):
    data += '\n'
    data = data.replace('\n', ' else 0\nΣ = max(Σ, *wtf().values())\n')
    data = data.replace('inc', '+=').replace('dec', '-=')
    d = crazydict()
    exec(data, {}, d)
    b = d.pop('Σ')
    return max(d.values()), b
Пример #2
0
def exe(data):
    data += "\n"
    data = data.replace("\n", " else 0\nΣ = max(Σ, *wtf().values())\n")
    data = data.replace("inc", "+=").replace("dec", "-=")
    d = crazydict()
    exec(data, {}, d)
    b = d.pop("Σ")
    return max(d.values()), b
Пример #3
0
def part_b(data):
    registers = {}.fromkeys("abcd", 12)
    patch_target = dedent("""\
        cpy b c
        inc a
        dec c
        jnz c -2
        dec d
        jnz d -5""")
    patch = dedent("""\
        mul b d a
        cpy 0 c
        cpy 0 d
        pass
        pass
        pass""")
    patch_length = len(patch.splitlines())
    assert patch_length == len(patch_target.splitlines())
    patch_start = len(data[:data.find(patch_target)].splitlines())
    patched_area = range(patch_start + 1, patch_start + 1 + patch_length)
    patched_data = data.replace(patch_target, patch, 1)
    lines = patched_data.splitlines()
    registers = compute(reg=registers,
                        lines=lines,
                        original_data=data,
                        patched_area=patched_area)
    return registers["a"]
Пример #4
0
def run(data):
    d = {}
    for line in data.replace(' <->', ',').splitlines():
        xs = [int(x) for x in line.split(', ')]
        d[tuple(xs)] = set(xs)

    while True:
        for tuple_, set1 in d.items():
            try:
                match = next(k for k, set2 in d.items()
                             if k != tuple_ and set1 & set2)
            except StopIteration:
                # no match for this key - keep looking
                continue
            else:
                # merging match and set1
                d[tuple_] = set1 | d.pop(match)
                break
        else:
            # no match for any key - we are done!
            break

    [set0] = [v for v in d.values() if 0 in v]
    a = len(set0)
    b = len(d)
    return a, b
Пример #5
0
def reduce(data):
    length = len(data)
    while True:
        for char in reacts:
            data = data.replace(char, '')
        if len(data) != length:
            length = len(data)
        else:
            break
    return len(data)
Пример #6
0
def react(data, remove=None):
    if remove is not None:
        data = data.replace(remove, "").replace(remove.swapcase(), "")
    result = []
    for char in data:
        if result and char == result[-1].swapcase():
            result.pop()
        else:
            result.append(char)
    return "".join(result)
Пример #7
0
def parsed(data):
    # decompose "flip" operations into cut + stride
    data = data.replace("deal into new stack",
                        "cut -1\ndeal with increment -1")
    ops = []
    for line in data.splitlines():
        op, *crap, n = line.split()
        n = int(n)
        assert op in {"cut", "deal"}
        ops.append((op, n))
    return ops
Пример #8
0
def get_distance_matrix(data):
    n_rows = 1 + data.count('\n')
    maze = np.fromstring(data.replace('\n', ''),
                         dtype='S1').reshape(n_rows, -1).astype('U1')
    targets = sorted([x for x in data if x.isdigit()])
    n = len(targets)

    states = []
    for target in targets:
        [row], [col] = np.where(maze == target)
        states.append(complex(col, -row))

    d = np.zeros((n, n), dtype=int)
    for a, b in combinations(range(n), 2):
        d[a, b] = d[b, a] = bfs(states[a], states[b], maze)

    return d
Пример #9
0
def tubemaze(data):
    A = np.fromiter(data.replace('\n', ''),
                    dtype='U1').reshape(len(data.splitlines()), -1)
    x = np.array([-1, A[0].argmax()], dtype=int)
    v = np.array([1, 0], dtype=int)
    letters = ''
    for i in count():
        x += v
        a = A[tuple(x)]
        if a == '+':
            v = v[::-1]
            if A[tuple(x + v)] == ' ':
                v *= -1
        elif a not in '-| ':
            letters += a
        elif a == ' ':
            return letters, i
Пример #10
0
def tubemaze(data):
    A = np.fromiter(data.replace("\n", ""), dtype="U1")
    A = A.reshape(len(data.splitlines()), -1)
    x = np.array([-1, A[0].argmax()], dtype=int)
    v = np.array([1, 0], dtype=int)
    letters = ""
    for i in count():
        x += v
        a = A[tuple(x)]
        if a == "+":
            v = v[::-1]
            if A[tuple(x + v)] == " ":
                v *= -1
        elif a not in "-| ":
            letters += a
        elif a == " ":
            return letters, i
Пример #11
0
def part_ab(data):
    d = {}
    for line in data.replace(" <->", ",").splitlines():
        xs = [int(x) for x in line.split(", ")]
        d[tuple(xs)] = set(xs)

    while True:
        for tuple_, set1 in d.items():
            try:
                match = next(k for k, set2 in d.items()
                             if k != tuple_ and set1 & set2)
            except StopIteration:
                continue  # no match for this key - keep looking
            else:
                d[tuple_] = set1 | d.pop(match)
                break  # merged match and set1
        else:
            break  # no match for any key - we are done!

    [set0] = [v for v in d.values() if 0 in v]
    a = len(set0)
    b = len(d)
    return a, b
Пример #12
0
def parsed(data):
    h = len(data.splitlines())
    A = np.fromiter(data.replace("\n", ""), dtype="<U1").reshape(h, -1)
    A = (A == "|").astype(complex) + (A == "#").astype(complex) * 1j
    return A
Пример #13
0
class Machine:
    def __init__(self, a=0, b=0):
        self.regs = {'a': a, 'b': b}
        self.i = 0

    def run(self, program):
        while 0 <= self.i < len(program):
            op, *args = program[self.i].split(' ')
            if op in ('jmp', 'jie', 'jio'):
                if (op == 'jie' and self.regs[args[0]] % 2 == 0
                        or op == 'jio' and self.regs[args[0]] == 1):
                    self.i += int(args[1])
                    continue
                elif op == 'jmp':
                    self.i += int(args[0])
                    continue
            if op == 'hlf':
                self.regs[args[0]] = int(self.regs[args[0]] / 2)
            elif op == 'tpl':
                self.regs[args[0]] *= 3
            elif op == 'inc':
                self.regs[args[0]] += 1
            self.i += 1
        return self.regs['b']


program = data.replace(',', '').split('\n')
print('part 1:', Machine().run(program))
print('part 2:', Machine(a=1).run(program))
Пример #14
0
def part_2(data):
    return min([reduce(data.replace(chr(i), '').replace(chr(i + 32), '')) for i in range(65, 65 + 26)])
Пример #15
0
from aocd import data, lines, submit
import sys
from collections import Counter, defaultdict, deque
import functools
from sortedcontainers import SortedList, SortedDict, SortedSet
import itertools
import u
import math
import time
import operator

low, high = u.ints(data.replace("-", " "))
pws = [[(p // 10 ** (5 - e)) % 10 for e in range(6)] for p in range(low, high + 1)]


def asc(pw):
    return all(pw[i] <= pw[i + 1] for i in range(len(pw) - 1))


def group(p):
    return (len(list(g)) for _, g in itertools.groupby(p))


def nosubmit(answer, part):
    print(f"Part {part}:\n{answer}")


# submit = nosubmit

print(f"File line count: {len(lines)}")
Пример #16
0
    while d:
        tok = d.popleft()
        if tok == "(":
            val = evaluate(d, part=part)
        elif tok.isdigit():
            val = int(tok)
        elif tok in "+*":
            op = tok
        elif tok == ")":
            return prev
        if val is not None:
            if op == "+":
                prev += val
            elif op == "*":
                if part == "b":
                    while d and d[0] == "+":
                        d.popleft()
                        r = d.popleft()
                        if r.isdigit():
                            val += int(r)
                        elif r == "(":
                            val += evaluate(d, part=part)
                prev *= val
            val = None
    return prev


lines = data.replace(" ", "").splitlines()
print("part a:", sum([evaluate(deque(line), part="a") for line in lines]))
print("part b:", sum([evaluate(deque(line), part="b") for line in lines]))
Пример #17
0
def read_data(data):
    lines = data.split('\n')
    rows = len(lines)
    cols = len(lines[0])
    return np.array(list(data.replace('\n', ''))).reshape(rows, cols)
Пример #18
0
"""
--- Day 12: Digital Plumber ---
https://adventofcode.com/2017/day/12
"""
import networkx as nx
from aocd import data


graph = nx.Graph()
for line in data.replace(" <->", ",").splitlines():
    n0, *nodes = [int(n) for n in line.split(", ")]
    graph.add_node(n0)
    for node in nodes:
        graph.add_edge(n0, node)

[a] = [len(g) for g in nx.connected_components(graph) if 0 in g]
b = nx.number_connected_components(graph)

print("part a:", a)
print("part b:", b)
Пример #19
0
"""
--- Day 13: Transparent Origami ---
https://adventofcode.com/2021/day/13
"""
from aocd import data
from aoc_wim.ocr import AOCR
from ast import literal_eval

zs, folds = data.replace(",", "+").split("\n\n")
d = {literal_eval(z + "j"): "#" for z in zs.split()}

for i, fold in enumerate(folds.splitlines()):
    axis, n = fold.split("=")
    n = int(n)
    for z in [*d]:
        if axis[-1] == "y" and z.imag > n:
            z_ = complex(z.real, 2 * n - z.imag)
        elif axis[-1] == "x" and z.real > n:
            z_ = complex(2 * n - z.real, z.imag)
        else:
            continue
        d[z_] = "#"
        del d[z]
    if i == 0:
        a = len(d)

print("part a:", a)
print("part b:", AOCR[d])
Пример #20
0
"""
--- Day 9: Stream Processing ---
https://adventofcode.com/2017/day/9
"""
import re

from aocd import data

n_removed = 0
while "!!" in data:
    data = data.replace("!!", "")
data = re.sub("!.", "", data)
n_removed += len(data) - len(re.sub("<.*?>", "", data))
n_removed -= 2 * len(re.findall("<.*?>", data))
data = re.sub("<.*?>", "", data)
score = 0
nesting = 0
for c in data:
    if c == "{":
        nesting += 1
    elif c == "}":
        score += nesting
        nesting -= 1

print("part a:", score)
print("part b:", n_removed)
Пример #21
0
def part_b(data):
    result = len(data)
    for x in set(data.lower()):
        m = part_a(data.replace(x, "").replace(x.upper(), ""))
        result = min(m, result)
    return result
Пример #22
0
from itertools import product, chain
from operator import itemgetter
from collections import defaultdict

import networkx as nx

def neighbours(p):
    yield (p[0] - 1, p[1])
    yield (p[0] + 1, p[1])
    yield (p[0], p[1] - 1)
    yield (p[0], p[1] + 1)

from aocd import data as grid
grid = grid.replace(" ", "#").split("\n")
n, m = len(grid), len(grid[0])
g = defaultdict(lambda: '#', {(i, j): grid[i][j] for i, j in product(range(n), range(m))})

apos = defaultdict(list)
for p in filter(lambda p: g[p] == '.', product(range(n), range(m))):
    for x in filter(lambda k: g[k].isalpha(), neighbours(p)):
        for y in filter(lambda k: g[k].isalpha(), neighbours(x)):
            s = ''.join(map(g.get, sorted([x, y])))
            apos[s].append(p)

lvls = len(apos) * 2

def solve_1():
    graph = nx.Graph()
    for i, j in filter(lambda p: g[p] == '.', product(range(n), range(m))):
        for ni, nj in filter(lambda p: g[p] == '.', neighbours((i, j))):
            graph.add_edge((i, j), (ni, nj))
Пример #23
0
from aocd import data

data = data.replace('ne', 'a').replace('se',
                                       'b').replace('sw',
                                                    'c').replace('nw', 'd')

DIRS = dict(a=1 - 1j, b=1j, c=-1 + 1j, d=-1j, e=1, w=-1)

tiles = [sum(DIRS[c] for c in tile) for tile in data.splitlines()]
floor = {}
for tile in tiles:
    floor[tile] = not floor.get(tile, False)

black = {p for p, v in floor.items() if v}
# 244
print(f'part1 {len(black)}')


def step(pos, black):
    n = sum(1 for d in DIRS.values() if (pos + d) in black)
    return ((pos in black) and not (n == 0 or n > 2)) or n == 2


for day in range(100):
    neighbors = {p + d for p in black for d in DIRS.values()}
    black = {p for p in black | neighbors if step(p, black)}

# 3665
print(f'part2 {len(black)}')
Пример #24
0
--- Day 19: Monster Messages ---
https://adventofcode.com/2020/day/19
"""
from aocd import data


def match(message, remaining):
    if not message or not remaining:
        return not message and not remaining
    first, *rest = remaining
    rule = rules[first]
    if rule in ("a", "b"):
        if message.startswith(rule):
            return match(message[1:], rest)
        return False
    return any(match(message, t + rest) for t in rule)


rules_raw, messages = data.replace('"', "").split("\n\n")
messages = messages.splitlines()
rules = dict(r.split(": ") for r in rules_raw.splitlines())
for k, v in rules.items():
    if v not in "ab":
        rules[k] = [t.split() for t in v.split("|")]

print("part a:", sum(match(m, ["0"]) for m in messages))

rules["8"].append(["42", "8"])
rules["11"].append(["42", "11", "31"])
print("part b:", sum(match(m, ["0"]) for m in messages))