Esempio n. 1
0
def test_build_bridges():
    spans = line_parser(test, parse=parse)
    for i, bridge in enumerate(build_bridges(spans), 1):
        assert 0 in bridge[0]
    assert i == 11
Esempio n. 2
0
def part2(directions):
    position = (0, 0)
    heading = (0, 1)
    visited = set()
    turn = {
        'R': lambda m: (-m[1], m[0]),
        'L': lambda m: (m[1], -m[0]),
    }
    for t, d in directions:
        heading = turn[t](heading)
        for _ in range(d):
            if position in visited:
                break
            visited.add(position)
            position = tuple(p + h for p, h in zip(position, heading))
    return sum(abs(p) for p in position)


def parse(line):
    turn = line[0]
    steps = int(line[1:])
    return (turn, steps)


if __name__ == '__main__':
    directions = line_parser(get_input(day=1, year=2016),
                             parse=parse,
                             seperator=", ")
    print("Part 1: {}".format(part1(directions)))
    print("Part 2: {}".format(part2(directions)))
Esempio n. 3
0
            queue.append((i + 1, used + [buckets[i]]))
            queue.append((i + 1, used))


def test_storage_gen():
    buckets = [15, 10, 5, 5, 20]
    assert len(list(storage_gen(buckets, 25))) == 4


def part1(buckets, volume=150):
    count = 0
    for b in storage_gen(buckets, volume):
        count += 1
    return count


def part2(buckets, volume=150):
    shortest = []
    for b in storage_gen(buckets, volume):
        if shortest == [] or len(b) < len(shortest[0]):
            shortest = [b]
        elif len(b) == len(shortest[0]):
            shortest.append(b)
    return len(shortest)


if __name__ == '__main__':
    buckets = line_parser(get_input(day=17, year=2015))
    print("Part 1: {}".format(part1(buckets)))
    print("Part 2: {}".format(part2(buckets)))
Esempio n. 4
0
def test_part1():
    ingredients = line_parser(test_text, parse=parse)
    assert 62842880 == part1(ingredients)
Esempio n. 5
0

def make_set(table, seed):
    seen = set()
    queue = [seed]
    while queue:
        p = queue.pop()
        if p not in seen:
            seen.add(p)
            queue.extend(table[p])
    return seen


def part1(table):
    return len(make_set(table, 0))


def part2(table):
    return len(set(frozenset(make_set(table, v)) for v in table.keys()))


def parse(line):
    ppid, pids = line.split(' <-> ')
    return (int(ppid), tuple(int(p) for p in pids.split(', ')))


if __name__ == '__main__':
    table = dict(line_parser(get_input(day=12, year=2017), parse=parse))
    print("Part 1: {}".format(part1(table)))
    print("Part 2: {}".format(part2(table)))
Esempio n. 6
0
#!/usr/bin/env python3

from get_input import get_input, line_parser


def part1(lines, update=None):
    i, count = 0, 0
    lines = lines[:]
    if update is None:
        update = lambda x: x + 1
    while 0 <= i < len(lines):
        jump = lines[i]
        lines[i] = update(lines[i])
        count += 1
        i += jump
    return count


def part2(lines):
    return part1(lines, update=lambda x: x + 1 if x < 3 else x - 1)


if __name__ == '__main__':
    lines = line_parser(get_input(day=5, year=2017))
    print("Solution Part 1 {}".format(part1(lines)))
    print("Solution Part 2 {}".format(part2(lines)))
Esempio n. 7
0
def test_part2():
    reindeer = line_parser(test_text, parse=parse)
    assert part2(reindeer, time=1000) == 689
Esempio n. 8
0
from get_input import get_input, line_parser


def part1(addresses):
    lowest = 0
    for start, end in sorted(addresses):
        if start <= lowest <= end:
            lowest = end + 1
    return lowest


def part2(addresses):
    allowed_addresses = 0
    head = 0
    for start, end in sorted(addresses):
        if head < start:
            allowed_addresses += start - head
        head = max(end + 1, head)
    return 2**32 - head + allowed_addresses


def parse(line):
    return tuple(int(n) for n in line.split('-'))


if __name__ == '__main__':
    addresses = line_parser(get_input(day=20, year=2016), parse=parse)
    print('Part 1: {}'.format(part1(addresses)))
    print('Part 2: {}'.format(part2(addresses)))
Esempio n. 9
0
def part1(weights):
    quantum, items = None, None
    for group_a in split_gen(weights, 3):
        if items and len(group_a) > items:
            return quantum
        items = len(group_a)
        quantum = min(quantum or product(group_a), product(group_a))


def product(items):
    total = 1
    for n in items:
        total *= n
    return total


def part2(weights):
    quantum, items = None, None
    for group_a in split_gen(weights, 4):
        if items and len(group_a) > items:
            return quantum
        items = len(group_a)
        quantum = min(quantum or product(group_a), product(group_a))


if __name__ == '__main__':
    weights = line_parser(get_input(day=24, year=2015))
    print("Part 1: {}".format(part1(weights)))
    print("Part 2: {}".format(part2(weights)))
Esempio n. 10
0
        else:
            continue
        result = Program(prog).run()
        if not (0 <= result.index < len(result)):
            return result.accumulator


def parse(line):
    command, value = line.split(' ')
    return (command, int(value))


TEST_TEST_PART1 = """
nop +0
acc +1
jmp +4
acc +3
jmp -3
acc -99
acc +1
jmp -4
acc +6
"""

if __name__ == "__main__":
    assert part1(line_parser(TEST_TEST_PART1, parse=parse)) == 5
    assert part2(line_parser(TEST_TEST_PART1, parse=parse)) == 8
    LINES = line_parser(get_input(day=8, year=2020), parse=parse)
    print(f"Part 1: {part1(LINES)}")
    print(f"Part 2: {part2(LINES)}")
Esempio n. 11
0
        assert a == a_gen

def part1(start_a, start_b, sample=40000000):
    total = 0
    gen_a = generator(start_a, 16807, bits=16)
    gen_b = generator(start_b, 48271, bits=16)
    for i, (a,b) in enumerate(zip(gen_a, gen_b)):
        if i > sample:
            return total
        if a == b:
            total += 1

def test_part1():
    assert part1(65, 8921, sample=5) == 1
    assert part1(65, 8921) == 588

def part2(start_a, start_b, sample=5000000):
    total = 0
    gen_a = generator(start_a,16807,critera=4,bits=16)
    gen_b = generator(start_b,48271,critera=8,bits=16)
    for i, (a,b) in enumerate(zip(gen_a, gen_b)):
        if i > sample:
            return total
        if a == b:
            total += 1

if __name__ == '__main__':
    a, b = line_parser(get_input(day=15, year=2017), parse=lambda line:int(line.split(' ')[-1]))
    print("Part 1: {}".format(part1(a, b)))
    print("Part 2: {}".format(part2(a, b)))
Esempio n. 12
0
    return abas

def test_find_aba():
    assert [] == find_abas('abcde')
    assert ['bab'] == find_abas('aba')
    assert [] == find_abas('aaae')
    assert ['bab'] == find_abas('eabae')
    assert ['bab', 'aba', 'bab', 'aba'] == find_abas('ababab')


def part2(lines):
    count = 0
    for nets, hypers in lines:
        babs = [i for net in nets for i in find_abas(net)]
        for bab in babs:
            if any(bab in hyper for hyper in hypers):
                count += 1
                break
    return count
        
def parse(line):
    matches = re.findall(r'\w+', line)
    return ([matches[n] for n in range(0, len(matches), 2)],
        [matches[n] for n in range(1, len(matches), 2)])

if __name__ == '__main__':
    lines = line_parser(get_input(day=7, year=2016), parse=parse)
    print("Part 1: {}".format(part1(lines)))
    print("Part 2: {}".format(part2(lines)))

Esempio n. 13
0

@command
def dec(x):
    x.set(x.get() - 1)


@command
def jnz(x, y):
    return y.get() if x.get() != 0 else 1


def parse(line):
    assembunny = {
        re.compile(r'cpy (\S+) (\S+)'): cpy,
        re.compile(r'inc (\S+)'): inc,
        re.compile(r'dec (\S+)'): dec,
        re.compile(r'jnz (\S+) (\S+)'): jnz
    }
    for code, func in assembunny.items():
        m = code.match(line)
        if m:
            return (line, func(*m.groups()))
    raise ValueError("Not a valid line {}".format(line))


if __name__ == '__main__':
    commands = line_parser(get_input(day=12, year=2016), parse=parse)
    print('Part 1: {}'.format(part1(commands)))
    print('Part 2: {}'.format(part2(commands)))
Esempio n. 14
0
        update(registers, oper)
        max_val = max(v for v in registers.values())
        if biggest is None or max_val > biggest:
            biggest = max_val
    return biggest


def update(env, oper):
    if oper.test_func(env[oper.test_reg], oper.test_val):
        env[oper.mod_reg] = oper.mod_func(env[oper.mod_reg], oper.mod_val)


def parser(line):
    try:
        match = re.match(REGEX, line).groupdict()
    except AttributeError:
        raise ValueError("Not a match {}".format(line))
    return Update(mod_reg=match['mod_reg'],
                  mod_func=UPDATE[match['mod_func']],
                  mod_val=int(match['mod_val']),
                  test_reg=match['test_reg'],
                  test_func=OPERATORS[match['test_func']],
                  test_val=int(match['test_val']),
                  line=line)


if __name__ == '__main__':
    lines = line_parser(get_input(day=8, year=2017), parse=parser)
    print("Part 1: {}".format(part1(lines)))
    print("Part 2: {}".format(part2(lines)))
Esempio n. 15
0
def test_part2():
    nodes = line_parser(TEST_TEXT, parse=parse, numbered=True)
    assert part2(nodes, upper=25) == 7
Esempio n. 16
0
def distribute(memory):
    while True:
        i, biggest = max(enumerate(memory), key=lambda n: (n[1], -n[0]))
        memory[i] = 0
        for j in range(i+1, i+1+biggest):
            memory[j % len(memory)] += 1
        yield tuple(memory)

def part1(nums):
    sequences_seen = set()
    for count, sequence in enumerate(distribute(nums), 1):
        if sequence in sequences_seen:
            return count
        sequences_seen.add(sequence)

def part2(nums):
    first = None
    sequences_seen = set()
    for count, sequence in enumerate(distribute(nums), 1):
        if sequence in sequences_seen:
            if first is not None:
                return count - first
            first = count
            sequences_seen.clear()
        sequences_seen.add(sequence)

if __name__ == '__main__':
    nums = line_parser(get_input(day=6, year=2017), seperator='\t')
    print("Solution part 1: {}".format(part1(nums)))
    print("Solution part 2: {}".format(part2(nums)))
Esempio n. 17
0

def new_add(loc_a, loc_b, limit=3):
    loc_c = []
    for a, b in zip(loc_a, loc_b):
        loc_c.append(a + b)
    assert sum(abs(c) for c in loc_c) < limit
    return tuple(loc_c)


def part2(instructions):
    grid = (("1"), ("234"), ("56789"), ("ABC"), ("D"))

    position = (-2, 0)
    moves = {"U": (-1, 0), "D": (1, 0), "L": (0, -1), "R": (0, 1)}
    code = ""
    for instruction in instructions:
        for move in instruction:
            try:
                position = new_add(moves[move], position)
            except AssertionError:
                continue
        code += grid[2 + position[0]][2 - abs(position[0]) + position[1]]
    return code


if __name__ == '__main__':
    instructions = line_parser(get_input(day=2, year=2016), parse=tuple)
    print("Part 1: {}".format(part1(instructions)))
    print("Part 2: {}".format(part2(instructions)))
Esempio n. 18
0
    # No general purpose algo for figuring this one out
    reg = {v: 0 if v != 'a' else 1 for v in "abcdefgh"}
    state = ProgRunner(program, reg=reg)
    for s in state:
        if s.i == 10:
            if s.reg['b'] % s.reg['d'] == 0:
                s.i = 25
                # print("{:4} % {:4} == 0, {} skip to {}".format(
                # s.reg['b'], s.reg['d'], s.reg['h'], s))
            else:
                s.i = 20
    return s.reg['h']


def is_prime(n):
    if n % 2 == 0:
        return False
    for m in range(3, int((n + 1)**0.5), 2):
        if n % m == 0:
            return False
    return True


if __name__ == '__main__':
    lines = line_parser(get_input(day=23, year=2017),
                        parse=lambda line: line.split(' '))
    # Part 1: 3025
    # Part 2: 915
    print("Part 1: {}".format(part1(lines)))
    print("Part 2: {}".format(part2(lines)))
Esempio n. 19
0
class Reindeer(object):
    def __init__(self, name, speed, time, rest):
        self.name = name
        self.speed = int(speed)
        self.time = int(time)
        self.rest = int(rest)

    def distance(self, time):
        location = 0
        while True:
            if time <= self.time:
                return location + time * self.speed
            location += self.speed * self.time
            time -= self.time
            if time <= self.rest:
                return location
            time -= self.rest


def parse(line):
    form = re.compile(r'(?P<name>\w+) can fly (?P<speed>\d+) km/s for ' + \
        '(?P<time>\d+) seconds, but then must rest for (?P<rest>\d+) seconds.')
    m = form.match(line)
    return Reindeer(**m.groupdict())


if __name__ == "__main__":
    reindeer = line_parser(get_input(day=14, year=2015), parse=parse)
    print("Part 1: {}".format(part1(reindeer)))
    print("Part 2: {}".format(part2(reindeer)))
Esempio n. 20
0
def dense_hash(values, block_size=16):
    hash_str = ''
    for block_start in range(0, len(values), block_size):
        h = 0
        for char in values[block_start:block_start+block_size]:
            h ^= char
        hash_str += format(h, '02x')
    return hash_str

def part1(lengths, n_items=256):
    chars = ''.join( chr(l) for l in lengths )
    items = knot_hash(chars, hash_size=n_items, iterations=1)
    return items[0] * items[1]

def test_part1():
    test_input = [227,169,3,166,246,201,0,47,1,255,2,254,96,3,97,144]
    assert part1(test_input) == 13760

def part2(chars, hash_size=256, iterations=64, block_size=16):
    hash_vals = knot_hash(chars)
    return dense_hash(hash_vals)

def test_part2():
    assert 'a2582a3a0e66e6e86e3812dcb672a272' == part2('')
    assert '33efeb34ea91902bb2f59c9920caa6cd' == part2('AoC 2017')

if __name__ == '__main__':
    line = get_input(day=10, year=2017).strip()
    print("Part 1: {}".format(part1(line_parser(line, seperator=','))))
    print("Part 2: {}".format(part2(line)))
Esempio n. 21
0
    dist = [0] * buckets
    dist[0] = volume
    while True:
        yield dist
        dist[0] -= 1
        dist[1] += 1
        if dist[0] < 0:
            i = 1
            while dist[0] < 0:
                if i + 1 >= len(dist):
                    raise StopIteration
                dist[i + 1] += 1
                dist[0] += dist[i] - 1
                dist[i] = 0
                i += 1


def parse(line):
    ingredient = re.compile(
        r'(?P<name>\w+): capacity (?P<capacity>-?\d+), ' +
        'durability (?P<durability>-?\d+), flavor (?P<flavor>-?\d+), ' +
        'texture (?P<texture>-?\d+), calories (?P<calories>-?\d+)')
    m = ingredient.match(line)
    return {k: int(v) if k != 'name' else v for k, v in m.groupdict().items()}


if __name__ == '__main__':
    ingredients = line_parser(get_input(day=15, year=2015), parse=parse)
    print("Part 1: {}".format(part1(ingredients)))
    print("Part 2: {}".format(part2(ingredients)))
Esempio n. 22
0
        counts = Counter(c for c in name if c != '-')
        key = sorted(counts.items(), key=lambda v: (-v[1], v[0]))
        check = ''.join(k[0] for k in key[:5])
        if check == checksum:
            total += id_num
    return total


def part2(sectors):
    for name, shift, _ in sectors:
        word = ''
        for c in name:
            if c == '-':
                word += ' '
            else:
                word += chr(((ord(c) - 97 + shift) % 26) + 97)
        if 'northpole' in word:
            return shift


def parse(line):
    m = re.match(r'([a-z-]+)-(\d+)\[([a-z]{5})\]$', line)
    name, id_num, checksum = m.groups()
    return (name, int(id_num), checksum)


if __name__ == '__main__':
    sectors = line_parser(get_input(day=4, year=2016), parse=parse)
    print("Part 1: {}".format(part1(sectors)))
    print("Part 2: {}".format(part2(sectors)))
Esempio n. 23
0
        'samoyeds': lambda v: v == 2,
        'pomeranians': lambda v: v < 3,
        'akitas': lambda v: v == 0,
        'vizslas': lambda v: v == 0,
        'goldfish': lambda v: v < 5,
        'trees': lambda v: v > 3,
        'cars': lambda v: v == 2,
        'perfumes': lambda v: v == 1,
    }
    aunts = filter_aunts(aunts, props)
    assert len(aunts) == 1
    return list(aunts.keys())[0]


def parse(line):
    aunt_n = line.index(':')
    aunt = int(line[4:aunt_n])
    props = {}
    for prop in line[aunt_n + 2:].split(', '):
        k, v = prop.split(': ')
        props[k] = int(v)
    return (aunt, props)


if __name__ == '__main__':
    aunts = dict(line_parser(get_input(day=16, year=2015), parse=parse))
    # Part 1: 103
    # Part 2: 405
    print("Part 1: {}".format(part1(aunts)))
    print("Part 2: {}".format(part2(aunts)))
Esempio n. 24
0
                new[key] = value.difference(set(mapping.values()))
        if new == allergens:
            raise NotImplementedError()
        allergens = new
    return mapping


def part1(lines):
    mapping = set(get_mapping(lines).values())
    return sum(1 for (ingred, _) in lines for i in ingred
               if i not in mapping)


def part2(lines):
    mapping = get_mapping(lines)
    return ','.join(kv[1] for kv in
                    sorted(mapping.items(), key=lambda kv: kv[0]))


def parse(line):
    m = re.match(r"([^()]+)(?: \(contains (.+)\))", line)
    ingredients = tuple(m.group(1).strip().split(' '))
    contains = tuple(m.group(2).split(', '))
    return (ingredients, contains)


if __name__ == "__main__":
    LINES = line_parser(get_input(day=21, year=2020), parse=parse)
    print(f"Part 1: {part1(LINES)}")
    print(f"Part 2: {part2(LINES)}")
Esempio n. 25
0
    return start


def part1(boardingpasses):
    max_id = 0
    for boardingpass in boardingpasses:
        row = binary_search([char == "F" for char in boardingpass[:7]], 0, 127)
        col = binary_search([char == "L" for char in boardingpass[7:]], 0, 7)
        max_id = max(row * 8 + col, max_id)
    return max_id


def part2(boardingpasses):
    seats = {(row, col) for row in range(128) for col in range(8)}
    for boardingpass in boardingpasses:
        row = binary_search([char == "F" for char in boardingpass[:7]], 0, 127)
        col = binary_search([char == "L" for char in boardingpass[7:]], 0, 7)
        seats.remove((row, col))
    seat = [s for s in seats if 10 < s[0] and s[0] < 100]
    assert len(seat) == 1
    seat = seat.pop()
    return seat[0] * 8 + seat[1]


if __name__ == "__main__":
    LINES = line_parser(get_input(day=5, year=2020), parse=list)
    assert binary_search([c == "F" for c in "FBFBBFF"], 0, 127) == 44
    assert binary_search([c == 'L' for c in "RLR"], 0, 7) == 5
    print(f"Part 1: {part1(LINES)}")
    print(f"Part 2: {part2(LINES)}")
Esempio n. 26
0
import re


def part1(disks):
    for time in count(0):
        for disk, holes, start in disks:
            if (time + disk + start) % holes != 0:
                break
        else:
            return time


def test_part1():
    disks = ((1, 5, 4), (2, 2, 1))
    assert 5 == part1(disks)


def part2(disks):
    return part1(disks + [(len(disks) + 1, 11, 0)])


def parse(line):
    frmt = r'Disc #(\d+) has (\d+) positions; at time=0, it is at position (\d+).'
    return tuple(int(g) for g in re.match(frmt, line).groups())


if __name__ == '__main__':
    disks = line_parser(get_input(day=15, year=2016), parse=parse)
    print("Part 1: {}".format(part1(disks)))
    print("Part 2: {}".format(part2(disks)))
Esempio n. 27
0
#!/usr/bin/env python3

from get_input import get_input, line_parser
from collections import Counter

def part1(lines):
    phrase_counter = [Counter() for _ in range(len(lines[0]))]
    for line in lines:
        for i, c in enumerate(line):
            phrase_counter[i][c] += 1 
    return ''.join(max(p.items(), key=lambda q: q[1])[0] for p in phrase_counter)

def part2(lines):
    phrase_counter = [Counter() for _ in range(len(lines[0]))]
    for line in lines:
        for i, c in enumerate(line):
            phrase_counter[i][c] += 1 
    return ''.join(min(p.items(), key=lambda q: q[1])[0] for p in phrase_counter)
    

if __name__ == '__main__':
    lines = line_parser(get_input(day=6, year=2016), parse=lambda l: tuple(l), seperator='\n')
    print("Part 1: {}".format(part1(lines)))
    print("Part 2: {}".format(part2(lines)))
Esempio n. 28
0
/dev/grid/node-x2-y1    9T    8T     1T   88%
/dev/grid/node-x2-y2    9T    6T     3T   66%"""

def test_part2():
    nodes = line_parser(TEST_TEXT, parse=parse, numbered=True)
    assert part2(nodes, upper=25) == 7

def build(nodes, full_limit):
    max_x, max_y = 0, 0
    full_nodes = set()
    for n in nodes:
        max_x, max_y = max(max_x, n.x), max(max_y, n.y)
        if n.used == 0:
            zero = Point(n.x, n.y)
        elif n.used > full_limit:
            full_nodes.add(Point(n.x, n.y))
    return (max_x, max_y), zero, full_nodes

def parse(line, i):
    if i < 2:
        return
    regex = r'/dev/grid/node-x(\d+)-y(\d+)\s+(\d+)T\s+(\d+)T\s+(\d+)T\s+(\d+)%'
    args = (int(g) for g in re.match(regex, line).groups())
    return Node(*args)

if __name__ == '__main__':
    nodes = line_parser(get_input(day=22, year=2016), parse=parse, numbered=True)
    print("Part 1: {}".format(part1(nodes)))
    print("Part 2: {}".format(part2(nodes)))

Esempio n. 29
0
def part1(lines):
    door_public, card_public = lines
    door_loop = None
    card_loop = None
    loop_number = 1
    public = 7
    while door_loop is None or card_loop is None:
        print(f"{loop_number}: {public}")
        loop_number += 1
        public = (7 * public) % 20201227

        if card_loop is None and public == card_public:
            card_loop = loop_number
        if door_loop is None and public == door_public:
            door_loop = loop_number
    private = transform(door_public, card_loop)
    assert private == transform(card_public, door_loop)
    return private


def part2(lines):
    return "Merry Christmas!"


if __name__ == "__main__":
    assert part1([17807724, 5764801]) == 14897079
    LINES = line_parser(get_input(day=25, year=2020))
    print(f"Part 1: {part1(LINES)}")
    print(f"Part 2: {part2(LINES)}")
Esempio n. 30
0
from get_input import get_input, line_parser


def paper(l, w, h):
    sides = (l * w, w * h, h * l)
    return 2 * sum(sides) + min(sides)


def part1(lines):
    return sum(paper(*line) for line in lines)


def ribbon(l, w, h):
    s, m, l = sorted((l, w, h))
    return 2 * (s + m) + s * m * l


def part2(lines):
    return sum(ribbon(*line) for line in lines)


def parse(line):
    return tuple(int(n) for n in line.split('x'))


if __name__ == '__main__':
    lines = line_parser(get_input(day=2, year=2015), parse=parse)
    print("Part 1: {}".format(part1(lines)))
    print("Part 2: {}".format(part2(lines)))