コード例 #1
0
def read_moons():
    lines = util.read_input("day12")
    moons = []
    for line in lines:
        pos = re.sub(r"[<>=xyz\s]", "", line).split(",")
        moons.append(Planet(tuple(map(int, pos))))
    return moons
コード例 #2
0
ファイル: day9.py プロジェクト: emopavlov/advent-of-code-2019
# Your Intcode computer will also need a few other capabilities:
#
#     The computer's available memory should be much larger than the initial program. Memory beyond the initial program starts with the value 0 and can be read or written like any other memory. (It is invalid to try to access memory at a negative address, though.)
#     The computer should have support for large numbers. Some instructions near the beginning of the BOOST program will verify this capability.
#
# Here are some example programs that use these features:
#
#     109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99 takes no input and produces a copy of itself as output.
#     1102,34915192,34915192,7,4,7,99,0 should output a 16-digit number.
#     104,1125899906842624,99 should output the large number in the middle.
#
# The BOOST program will ask for a single input; run it in test mode by providing it the value 1. It will perform a series of checks on each opcode, output any opcodes (and the associated parameter modes) that seem to be functioning incorrectly, and finally output a BOOST keycode.
#
# Once your Intcode computer is fully functional, the BOOST program should report no malfunctioning opcodes when run in test mode; it should only output a single value, the BOOST keycode. What BOOST keycode does it produce?

input_1 = list(map(int, util.read_input("day9", ",")))

comp = incode_computer.IntcodeComputer(input_1)
comp.run([1])
print("Part One:", comp.output_list)

# --- Part Two ---
#
# You now have a complete Intcode computer.
#
# Finally, you can lock on to the Ceres distress signal! You just need to boost your sensors using the BOOST program.
#
# The program runs in sensor boost mode by providing the input instruction the value 2. Once run, it will boost the sensors automatically, but it might take a few seconds to complete the operation on slower hardware. In sensor boost mode, the program will output a single value: the coordinates of the distress signal.
#
# Run the BOOST program in sensor boost mode. What are the coordinates of the distress signal?
コード例 #3
0
ファイル: day7.py プロジェクト: emopavlov/advent-of-code-2019
#
#     Max thruster signal 65210 (from phase setting sequence 1,0,4,3,2):
#
#     3,31,3,32,1002,32,10,32,1001,31,-2,31,1007,31,0,33,
#     1002,33,7,33,1,33,31,31,1,32,31,31,4,31,99,0,0,0
#
# Try every combination of phase settings on the amplifiers. What is the highest signal that can be sent to the thrusters?

amps_count = 5
phase_setting_min = 0
phase_setting_max = 4

settings_list = itertools.permutations(
    range(phase_setting_min, phase_setting_max + 1), amps_count)

the_input = list(map(int, util.read_input("day7", ",")))

max_output = 0
for setting in settings_list:
    apm_input = 0
    for phase in setting:
        computer = incode_computer.IntcodeComputer(the_input)
        computer.run([phase, apm_input])
        apm_input = computer.output_list[-1]

    max_output = max(apm_input, max_output)

print("Part One:", max_output)

# --- Part Two ---
#
コード例 #4
0
        previous_tiers = [c for tier in tiers for c in tier]
        for k, d in defs_to_add.items():
            if set(map(lambda x: x.chemical,
                       d.inputs)).issubset(previous_tiers):
                next_tier.append(d.output.chemical)

        defs_to_add = {
            k: v
            for k, v in defs_to_add.items() if k not in next_tier
        }
        tiers.append(next_tier)

    return tiers


the_input = read_input("day14")
definitions = read_definitions(the_input)
tiers = definition_tiers(definitions)
e = Expression(definitions, tiers, [Compound("FUEL", 1)])
e.to_ore()
print("Part One:", e.compounds[0].quantity)

# --- Part Two ---
#
# After collecting ORE for a while, you check your cargo hold: 1 trillion (1000000000000) units of ORE.
#
# With that much ore, given the examples above:
#
#     The 13312 ORE-per-FUEL example could produce 82892753 FUEL.
#     The 180697 ORE-per-FUEL example could produce 5586022 FUEL.
#     The 2210736 ORE-per-FUEL example could produce 460664 FUEL.
コード例 #5
0
ファイル: day8.py プロジェクト: emopavlov/advent-of-code-2019
# For example, given an images 3 pixels wide and 2 pixels tall, the images data 123456789012 corresponds to the following images layers:
#
# Layer 1: 123
#          456
#
# Layer 2: 789
#          012
#
# The images you received is 25 pixels wide and 6 pixels tall.
#
# To make sure the images wasn't corrupted during transmission, the Elves would like you to find the layer that contains the fewest 0 digits. On that layer, what is the number of 1 digits multiplied by the number of 2 digits?

l_height = 6
l_width = 25

the_input = util.read_input("day8")[0]


def layers():
    n = l_width * l_height
    for i in range(0, len(the_input), n):
        yield the_input[i:i + n]


def count(seek, layer):
    return layer.count(seek)


code = 0
zero_count = 99999999  # something big
for l in layers():
コード例 #6
0
        return expand(m, set(map(lambda t: t.position(), ps)), x, y)

    graph = bfs_to_graph(ps, maze_expand)

    # add teleportation
    for name in list(map(lambda n: n.name, ps)):
        alt_name = name + "X"
        if graph.has_node(alt_name):
            graph.add_node(name, alt_name, 1)
            graph.add_node(alt_name, name, 1)

    return graph


if __name__ == "__main__":
    maze = util.read_input("day20", should_strip=False)
    m = Matrix()
    m.init_from_string('\n'.join(maze))
    ps = portals(m)

    g = construct_graph(ps, m)
    min_distance = dijkstra(g, "AA", "ZZ")

    print("Part Onw: ", min_distance)

# --- Part Two ---
#
# Strangely, the exit isn't open when you reach it. Then, you remember: the ancient Plutonians were famous for building recursive spaces.
#
# The marked connections in the maze aren't portals: they physically connect to a larger or smaller copy of the maze. Specifically, the labeled tiles around the inside edge actually connect to a smaller copy of the same maze, and the smaller copy's inner labeled tiles connect to yet a smaller copy, and so on.
#
コード例 #7
0
ファイル: day1.py プロジェクト: emopavlov/advent-of-code-2019
#     For a mass of 12, divide by 3 and round down to get 4, then subtract 2 to get 2.
#     For a mass of 14, dividing by 3 and rounding down still yields 4, so the fuel required is also 2.
#     For a mass of 1969, the fuel required is 654.
#     For a mass of 100756, the fuel required is 33583.
#
# The Fuel Counter-Upper needs to know the total fuel requirement. To find it, individually calculate the fuel needed
# for the mass of each module (your puzzle input), then add together all the fuel values.
#
# What is the sum of the fuel requirements for all of the modules on your spacecraft?


def fuel_for_mass(mass):
    return mass // 3 - 2


input1 = map(int, util.read_input("day1"))
required_fuel_1 = sum(map(fuel_for_mass, input1))
print("Part One:", required_fuel_1)

# --- Part Two ---
#
# During the second Go / No Go poll, the Elf in charge of the Rocket Equation Double-Checker stops the launch sequence.
# Apparently, you forgot to include additional fuel for the fuel you just added.
#
# Fuel itself requires fuel just like a module - take its mass, divide by three, round down, and subtract 2.
# However, that fuel also requires fuel, and that fuel requires fuel, and so on. Any mass that would require negative
# fuel should instead be treated as if it requires zero fuel; the remaining mass,
# if any, is instead handled by wishing really hard, which has no mass and is outside the scope of this calculation.
#
# So, for each module mass, calculate its fuel and add it to the total. Then, treat the fuel amount you just calculated
# as the input mass and repeat the process, continuing until a fuel requirement is zero or negative. For example:
コード例 #8
0
def next_phase(input):
    result = ""
    for i in range(len(input)):
        result += str(calculate_element(input, i + 1))
    return result


def phase_n(input, n):
    result = input
    for i in range(n):
        result = next_phase(result)
    return result


the_input = read_input("day16")[0]
print("Part One:", phase_n(the_input, 100))

# --- Part Two ---
#
# Now that your FFT is working, you can decode the real signal.
#
# The real signal is your puzzle input repeated 10000 times. Treat this new signal as a single input list. Patterns are still calculated as before, and 100 phases of FFT are still applied.
#
# The first seven digits of your initial input signal also represent the message offset. The message offset is the location of the eight-digit message in the final output list. Specifically, the message offset indicates the number of digits to skip before reading the eight-digit message. For example, if the first seven digits of your initial input signal were 1234567, the eight-digit message would be the eight digits after skipping 1,234,567 digits of the final output list. Or, if the message offset were 7 and your final output list were 98765432109876543210, the eight-digit message would be 21098765. (Of course, your real message offset will be a seven-digit number, not a one-digit number like 7.)
#
# Here is the eight-digit message in the final output list after 100 phases. The message offset given in each input has been highlighted. (Note that the inputs given below are repeated 10000 times to find the actual starting input lists.)
#
#     03036732577212944063491565474664 becomes 84462026.
#     02935109699940807407585447034323 becomes 78725270.
#     03081770884921959731165446850517 becomes 53553731.
コード例 #9
0
ファイル: day3.py プロジェクト: emopavlov/advent-of-code-2019
            return Location(start.x, start.y + distance)
        elif direction == "D":
            return Location(start.x, start.y - distance)
        elif direction == "R":
            return Location(start.x + distance, start.y)
        elif direction == "L":
            return Location(start.x - distance, start.y)
        else:
            print("EXCEPTION! WTF")


def manhattan_distance(l1, l2):
    return abs(l1.x - l2.x) + abs(l1.y - l2.y)


day_3_input = util.read_input("day3")
path1 = day_3_input[0].split(",")
path2 = day_3_input[1].split(",")

# Part One ####################################################################
min_distance = 10000000  # Something big

wire1 = Wire(path1)
wire2 = Wire(path2)
for s1 in wire1.sections:
    for s2 in wire2.sections:
        the_x = s1.intersection(s2)
        if isinstance(the_x, Location) and the_x != Location(0, 0):
            min_distance = min(min_distance, manhattan_distance(Location(0, 0), the_x))
        elif isinstance(the_x, Section):
            min_x = min(map(abs, range(the_x.start.x, the_x.end.x)))
コード例 #10
0
#     #
#
#
# Then, perhaps west (3) gets a reply of 0, south (2) gets a reply of 1, south again (2) gets a reply of 0, and then west (3) gets a reply of 2:
#
#
#    ##
#   #..#
#   D.#
#    #
#
# Now, because of the reply of 2, you know you've found the oxygen system! In this example, it was only 2 moves away from the repair droid's starting position.
#
# What is the fewest number of movement commands required to move the repair droid from its starting position to the location of the oxygen system?

program = list(map(int, read_input("day15", ",")))
droid_computer = IntcodeComputer(program)
area_map = Map()
droid_location = Location(0, 0)
area_map.set(0, 0, empty)

droid_on_target = bfs(Droid(droid_computer, droid_location))

# --- Part Two ---
#
# You quickly repair the oxygen system; oxygen gradually fills the area.
#
# Oxygen starts in the location containing the repaired oxygen system. It takes one minute for oxygen to spread to all open locations that are adjacent to a location that already contains oxygen. Diagonal locations are not adjacent.
#
# In the example above, suppose you've used the droid to explore the area fully and have the following map (where locations that currently contain oxygen are marked O):
#
コード例 #11
0
ファイル: day6.py プロジェクト: emopavlov/advent-of-code-2019
#                \
#                 I
#
# In this visual representation, when two objects are connected by a line, the one on the right directly orbits the one on the left.
#
# Here, we can count the total number of orbits as follows:
#
#     D directly orbits C and indirectly orbits B and COM, a total of 3 orbits.
#     L directly orbits K and indirectly orbits J, E, D, C, B, and COM, a total of 7 orbits.
#     COM orbits nothing.
#
# The total number of direct and indirect orbits in this example is 42.
#
# What is the total number of direct and indirect orbits in your map data?

the_input = util.read_input("day6_test")

orbit_map = {}
for line in the_input:
    (center, satellite) = line.split(")")
    if center in orbit_map:
        orbit_map[center].append(satellite)
    else:
        orbit_map[center] = [satellite]

print(orbit_map)


def walk(node, depth=0, path=[]):
    """ iterate tree in pre-order depth-first search order """
    yield node, depth, path + [node]
コード例 #12
0
        asteroids = visible_asteroids(cannon_base, m)
        if len(asteroids) == 0:
            raise Exception("Not found")

        if destroyed + len(asteroids) < n:
            destroyed += len(asteroids)
            for (x, y) in asteroids:
                m.set(x, y, "x")
        else:
            # move to coordinate system with center cannon_base
            sorted_asteroids = sort_points(list(map(lambda a: (a[0] - cannon_base[0], a[1] - cannon_base[1]), asteroids)))
            x, y = sorted_asteroids[n - 1 - destroyed]
            return x + cannon_base[0], y + cannon_base[1]


m = to_matrix(read_input("day10"))
winner = asteroid_with_best_visibility(m)
print("Part One:", winner)


# --- Part Two ---
#
# Once you give them the coordinates, the Elves quickly deploy an Instant Monitoring Station to the location and discover the worst: there are simply too many asteroids.
#
# The only solution is complete vaporization by giant laser.
#
# Fortunately, in addition to an asteroid scanner, the new monitoring station also comes equipped with a giant rotating laser perfect for vaporizing asteroids. The laser starts by pointing up and always rotates clockwise, vaporizing any asteroid it hits.
#
# If multiple asteroids are exactly in line with the station, the laser only has enough power to vaporize one of them before continuing its rotation. In other words, the same asteroids that can be detected can be vaporized, but if vaporizing one asteroid makes another one detectable, the newly-detected asteroid won't be vaporized until the laser has returned to the same position by rotating a full 360 degrees.
#
# For example, consider the following map, where the asteroid with the new monitoring station (and laser) is marked X:
コード例 #13
0
# Parameters that an instruction writes to will never be in immediate mode.
#
# Finally, some notes:
#
#     It is important to remember that the instruction pointer should increase by the number of values in the instruction after the instruction finishes. Because of the new instructions, this amount is no longer always 4.
#     Integers can be negative: 1101,100,-1,4,0 is a valid program (find 100 + -1, store the result in position 4).
#
# The TEST diagnostic program will start by requesting from the user the ID of the system to test by running an input instruction - provide it 1, the ID for the ship's air conditioner unit.
#
# It will then perform a series of diagnostic tests confirming that various parts of the Intcode computer, like parameter modes, function correctly. For each test, it will run an output instruction indicating how far the result of the test was from the expected value, where 0 means the test was successful. Non-zero outputs mean that a function is not working correctly; check the instructions that were run before the output instruction to see which one failed.
#
# Finally, the program will output a diagnostic code and immediately halt. This final output isn't an error; an output followed immediately by a halt means the program finished. If all outputs were zero except the diagnostic code, the diagnostic program ran successfully.
#
# After providing 1 to the only input instruction and passing all the tests, what diagnostic code does the program produce?

the_input = list(map(int, util.read_input("day5", ",")))
the_output = []

# Input should be 1
the_output = incode_computer.IntcodeComputer(the_input).run([1])
print("Part One Finished")

# --- Part Two ---
#
# The air conditioner comes online! Its cold air feels good for a while, but then the TEST alarms start to go off. Since the air conditioner can't vent its heat anywhere but back into the spacecraft, it's actually making the air inside the ship warmer.
#
# Instead, you'll need to use the TEST to extend the thermal radiators. Fortunately, the diagnostic program (your puzzle input) is already equipped for this. Unfortunately, your Intcode computer is not.
#
# Your computer is only missing a few opcodes:
#
#     Opcode 5 is jump-if-true: if the first parameter is non-zero, it sets the instruction pointer to the value from the second parameter. Otherwise, it does nothing.
コード例 #14
0
                    # Found it!
                    return steps

            expanded_front = {m for pos in search_front for m in legal_moves(pos) if m not in visited}
            # increment and repeat
            search_front = expanded_front
            visited = visited.union(search_front)
            steps += 1

        return -1  # not found


## Second solution: Build graph instead

if __name__ == "__main__":
    m = map_to_matrix(read_input("day18"))
    n = number_of_moves_to_collect_all_keys(m)
    print("Day 18:", n)

# --- Part Two ---
#
# You arrive at the vault only to discover that there is not one vault, but four - each with its own entrance.
#
# On your map, find the area in the middle that looks like this:
#
# ...
# .@.
# ...
#
# Update your map to instead use the correct data:
#
コード例 #15
0
#
# It's a new game for the ship's arcade cabinet! Unfortunately, the arcade is all the way on the other end of the ship. Surely, it won't be hard to build your own - the care package even comes with schematics.
#
# The arcade cabinet runs Intcode software like the game the Elves sent (your puzzle input). It has a primitive screen capable of drawing square tiles on a grid. The software draws tiles to the screen with output instructions: every three output instructions specify the x position (distance from the left), y position (distance from the top), and tile id. The tile id is interpreted as follows:
#
#     0 is an empty tile. No game object appears in this tile.
#     1 is a wall tile. Walls are indestructible barriers.
#     2 is a block tile. Blocks can be broken by the ball.
#     3 is a horizontal paddle tile. The paddle is indestructible.
#     4 is a ball tile. The ball moves diagonally and bounces off objects.
#
# For example, a sequence of output values like 1,2,3,6,5,4 would draw a horizontal paddle tile (1 tile from the left and 2 tiles from the top) and a ball tile (6 tiles from the left and 5 tiles from the top).
#
# Start the game. How many block tiles are on the screen when the game exits?

the_input = list(map(int, read_input("day13", ",")))

comp = IntcodeComputer(the_input)
comp.run()
block_count = comp.output_list[2::3].count(2)
print("Part one:", block_count)

# --- Part Two ---
#
# The game didn't run because you didn't put in any quarters. Unfortunately, you did not bring any quarters. Memory address 0 represents the number of quarters that have been inserted; set it to 2 to play for free.
#
# The arcade cabinet has a joystick that can move left and right. The software reads the position of the joystick with input instructions:
#
#     If the joystick is in the neutral position, provide 0.
#     If the joystick is tilted to the left, provide -1.
#     If the joystick is tilted to the right, provide 1.
コード例 #16
0
# .................
# .................
# .....@...........
# #####.###########
#
# .................
# .................
# .................
# #####@###########
#
# However, if the springdroid successfully makes it across, it will use an output instruction to indicate the amount of damage to the hull as a single giant integer outside the normal ASCII range.
#
# Program the springdroid with logic that allows it to survey the hull without falling into space. What amount of hull damage does it report?

if __name__ == '__main__':
    mem = list(map(int, util.read_input("day21", ",")))
    comp = IntcodeComputer(mem)

    program = """NOT A J
                 NOT C T
                 AND D T
                 OR T J
                 WALK
              """

    compiled = list(map(lambda c: ord(c), program))

    comp.run(compiled)
    result = "".join(
        list(map(lambda o: chr(o) if o < 127 else str(o), comp.output_list)))
    print(result)
コード例 #17
0
            continue
        else:
            visited.add(walker)

        # expand and push in queue
        for d, w in expand_walker(walker_with_doors, graph):
            search_front.put((distance + d, w))

    return -1


if __name__ == "__main__":
    import time
    s_time = time.time()

    m = map_to_matrix(read_input("day18"))
    g = map_to_graph(m)
    n = walk_graph(g, "@")
    print("Part One: ", n)

    print("time: ", time.time() - s_time)

# --- Part Two ---
#
# You arrive at the vault only to discover that there is not one vault, but four - each with its own entrance.
#
# On your map, find the area in the middle that looks like this:
#
# ...
# .@.
# ...