예제 #1
0
        cache_key = f"{current} {repr(keys)}"
        if cache_key in cache:
            return cache[cache_key]

        result = float('inf')
        for key, dist in reachable(current, keys):
            new_dist = dist + distance_to_collect(all_keys[key], keys - {key})
            result = min(result, new_dist)

        cache[cache_key] = result
        return result

    return distance_to_collect(start, set(all_keys.keys()))


# def part2(lines):
#     """
#     >>> part2()
#
#     """

if __name__ == "__main__":
    import doctest
    doctest.testmod()

    puzzle = Puzzle(year=2019, day=18)
    lines = puzzle.input_data.split('\n')
    puzzle.answer_a = inspect(part1(lines), prefix='Part 1: ')
    # puzzle.answer_b = inspect(part2(lines), prefix='Part 2: ')
예제 #2
0
    return len(paint(program, start=0))


def part2(program):
    hull = paint(program, start=1)
    minx_coord = min(c.x for c in hull.keys())
    miny_coord = min(c.y for c in hull.keys())
    maxx_coord = max(c.x for c in hull.keys())
    maxy_coord = max(c.y for c in hull.keys())

    visualisation = []
    for y in range(maxy_coord, miny_coord - 1, -1):
        row = []
        for x in range(minx_coord, maxx_coord + 1):
            if hull[Coord(x, y)] == 1:
                row.append('█')
            else:
                row.append(' ')
        visualisation.append(''.join(row))
    return input('Hull:\n' + '\n'.join(visualisation))


if __name__ == "__main__":
    import doctest
    doctest.testmod()

    puzzle = Puzzle(year=2019, day=11)
    program = [int(val) for val in puzzle.input_data.split(',')]
    puzzle.answer_a = inspect(part1(program), prefix='Part 1: ')
    puzzle.answer_b = inspect(part2(program), prefix='Part 2: ')
예제 #3
0
    >>> part1(example_2)
    58
    """
    portals = {}
    unmatched = {}
    for y, row in enumerate(donut):
        process_line(row, lambda x: Coord(x, y), portals, unmatched)
    for x in range(len(donut[0])):
        column = ''.join([row[x] for row in donut])
        process_line(column, lambda y: Coord(x, y), portals, unmatched)
    begin = unmatched['AA']
    end = unmatched['ZZ']

    return pathfind(donut, portals, begin, end)


# def part2(donut):
#     """
#     >>> part2()
#
#     """

if __name__ == "__main__":
    import doctest
    doctest.testmod()

    puzzle = Puzzle(year=2019, day=20)
    donut = puzzle.input_data.split('\n')
    puzzle.answer_a = inspect(part1(donut), prefix='Part 1: ')
    # puzzle.answer_b = inspect(part2(donut), prefix='Part 2: ')
예제 #4
0
        ]
    return ''.join(map(str, digits[:8]))


def part2(number, phases=100):
    """
    >>> part2('03036732577212944063491565474664')
    '84462026'
    >>> part2('02935109699940807407585447034323')
    '78725270'
    >>> part2('03081770884921959731165446850517')
    '53553731'
    """
    offset = int(number[:7])
    digits = [int(digit) for digit in number] * 10000
    digits = reversed(digits[offset:])
    for _ in range(phases):
        digits = [value % 10 for value in accumulate(digits, func=add)]
    return ''.join(map(str, reversed(digits[-8:])))


if __name__ == "__main__":
    import doctest
    doctest.testmod()
    print("Tests complete!")

    puzzle = Puzzle(year=2019, day=16)
    number = puzzle.input_data
    puzzle.answer_a = inspect(part1(number), prefix='Part 1: ')
    puzzle.answer_b = inspect(part2(number), prefix='Part 2: ')
예제 #5
0
            stack.append(child)
    return routes


def part1(orbits):
    """
    >>> part1(["COM)B", "B)C", "C)D", "D)E", "E)F", "B)G", "G)H", "D)I", "E)J", "J)K", "K)L"])
    42
    """
    routes = build_routes(orbits)
    return sum([len(route) for route in routes.values()])


def part2(orbits):
    """
    >>> part2(["COM)B", "B)C", "C)D", "D)E", "E)F", "B)G", "G)H", "D)I", "E)J", "J)K", "K)L", "K)YOU", "I)SAN"])
    4
    """
    routes = build_routes(orbits)
    return len(set(routes['YOU']) ^ set(routes['SAN']))


if __name__ == "__main__":
    import doctest
    doctest.testmod()

    puzzle = Puzzle(year=2019, day=6)
    orbits = puzzle.input_data.split('\n')
    puzzle.answer_a = inspect(part1(orbits), prefix='Part 1: ')
    puzzle.answer_b = inspect(part2(orbits), prefix='Part 2: ')
예제 #6
0
    for start in range(0, len(pixels), LAYER_LENGTH):
        layers.append(pixels[start:start + LAYER_LENGTH])
    counts = sorted((Counter(layer) for layer in layers),
                    key=lambda count: count[0])
    fewest_zeroes = counts[0]
    return fewest_zeroes[1] * fewest_zeroes[2]


def part2(pixels):
    layers = []
    for start in range(0, len(pixels), LAYER_LENGTH):
        layers.append(pixels[start:start + LAYER_LENGTH])
    rows = []
    for y in range(HEIGHT):
        row = []
        for x in range(WIDTH):
            pixels = [layer[WIDTH * y + x] for layer in layers]
            pixel = [pixel for pixel in pixels if pixel != 2][0]
            row.append(' ' if pixel == 0 else '█')
        rows.append(''.join(row))
    return input('\n'.join(rows))


if __name__ == "__main__":
    import doctest
    doctest.testmod()

    puzzle = Puzzle(year=2019, day=8)
    pixels = [int(pixel) for pixel in puzzle.input_data]
    puzzle.answer_a = inspect(part1(pixels), prefix='Part 1: ')
    puzzle.answer_b = inspect(part2(pixels), prefix='Part 2: ')
예제 #7
0
def part2(asteroids, target=200, station=Coord(11, 13)):
    """
    >>> part2([".#....#####...#..", "##...##.#####..##", "##...#...#.#####.", "..#.....X...###..", "..#.#.....#....##"], 2, station=Coord(8, 3))
    900
    """
    asteroids = parse_asteroids(asteroids)
    destroyed = asteroids = [
        other - station for other in asteroids if other != station
    ]
    destroyed = sorted(destroyed,
                       key=lambda asteroid:
                       (test_asteroid(asteroid, asteroids),
                        (360 - asteroid.angle_to(Coord(0, -1))) % 360))
    print([(
        c + station,
        360 - c.angle_to(Coord(0, -1)),
    ) for c in destroyed])
    result = destroyed[target - 1] + station
    return result.x * 100 + result.y


if __name__ == "__main__":
    import doctest
    doctest.testmod()

    puzzle = Puzzle(year=2019, day=10)
    asteroids = puzzle.input_data.split('\n')
    print(asteroids)
    # puzzle.answer_a = inspect(part1(asteroids), prefix='Part 1: ')
    puzzle.answer_b = inspect(part2(asteroids, target=200), prefix='Part 2: ')
예제 #8
0
from aocd.models import Puzzle

from computer import Computer
from util import inspect


def part1(state):
    comp = Computer(state, mem_override={1: 12, 2: 2})
    comp.run()
    return comp.mem0


def part2(state):
    TARGET = 19690720
    for noun, verb in itertools.product(range(100), repeat=2):
        comp = Computer(state, mem_override={1: noun, 2: verb})
        comp.run()
        if comp.mem0 == TARGET:
            return 100 * noun + verb


if __name__ == "__main__":
    import doctest
    doctest.testmod()

    puzzle = Puzzle(year=2019, day=2)
    state = [int(val) for val in puzzle.input_data.split(',')]
    puzzle.answer_a = inspect(part1(state), prefix='Part 1: ')
    puzzle.answer_b = inspect(part2(state), prefix='Part 2: ')
예제 #9
0
        steps += 1
    return steps


def lcm(denominators):
    return reduce(lambda a, b: a * b // gcd(a, b), denominators)


def part2(moons):
    """
    >>> part2(['<x=-1, y=0, z=2>', '<x=2, y=-10, z=-7>', '<x=4, y=-8, z=8>', '<x=3, y=5, z=-1>'])
    2772
    >>> part2(['<x=-8, y=-10, z=0>', '<x=5, y=5, z=10>', '<x=2, y=-7, z=3>', '<x=9, y=-8, z=-3>'])
    4686774924
    """
    moons = [parse(moon) for moon in moons]
    x_repeat = sim_1d([Moon1(moon.pos.x) for moon in moons])
    y_repeat = sim_1d([Moon1(moon.pos.y) for moon in moons])
    z_repeat = sim_1d([Moon1(moon.pos.z) for moon in moons])
    return lcm([x_repeat, y_repeat, z_repeat])


if __name__ == "__main__":
    import doctest
    doctest.testmod()

    puzzle = Puzzle(year=2019, day=12)
    moons = puzzle.input_data.split('\n')
    puzzle.answer_a = inspect(part1(moons, 1000), prefix='Part 1: ')
    puzzle.answer_b = inspect(part2(moons), prefix='Part 2: ')
예제 #10
0
    135
    """
    points = set(follow_line(line1))
    return min(pos.manhatten_dist() for pos in follow_line(line2)
               if pos in points)


def part2(line1, line2):
    """
    >>> part2('R8,U5,L5,D3', 'U7,R6,D4,L4')
    30
    >>> part2('R75,D30,R83,U83,L12,D49,R71,U7,L72', 'U62,R66,U55,R34,D71,R55,D58,R83')
    610
    >>> part2('R98,U47,R26,D63,R33,U87,L62,D20,R33,U53,R51', 'U98,R91,D20,R16,D67,R40,U7,R15,U6,R7')
    410
    """
    points = {pos: steps + 1 for steps, pos in enumerate(follow_line(line1))}
    return min(steps + 1 + points[pos]
               for steps, pos in enumerate(follow_line(line2))
               if pos in points)


if __name__ == "__main__":
    import doctest
    doctest.testmod()

    puzzle = Puzzle(year=2019, day=3)
    lines = puzzle.input_data.split('\n')
    puzzle.answer_a = inspect(part1(*lines), prefix='Part 1: ')
    puzzle.answer_b = inspect(part2(*lines), prefix='Part 2: ')
예제 #11
0
def part1(modules):
    return sum(fuel_required(module) for module in modules)


def fuel_gen(mass):
    """
    >>> sum(list(fuel_gen(14)))
    2
    >>> sum(list(fuel_gen(1969)))
    966
    >>> sum(list(fuel_gen(100756)))
    50346
    """
    while (mass := fuel_required(mass)) > 0:
        yield mass


def part2(modules):
    return sum(sum(fuel_gen(module)) for module in modules)


if __name__ == "__main__":
    import doctest
    doctest.testmod()

    puzzle = Puzzle(year=2019, day=1)
    modules = [int(module) for module in puzzle.input_data.split('\n')]
    puzzle.answer_a = inspect(part1(modules), prefix='Part 1: ')
    puzzle.answer_b = inspect(part2(modules), prefix='Part 2: ')