Пример #1
0
                                         x), max(xmax,
                                                 x), min(ymin,
                                                         y), max(ymax, y)

        to_flip = set()

        for x in range(xmin - 1, xmax + 2):
            for y in range(ymin - 1, ymax + 2):

                nbr_count = 0
                for dx, dy in DIRECTION_VECTORS.values():
                    if (x + dx, y + dy) in flipped_tiles:
                        nbr_count += 1

                if (x, y) in flipped_tiles:
                    if nbr_count == 0 or nbr_count > 2:
                        to_flip.add((x, y))
                elif nbr_count == 2:
                    to_flip.add((x, y))

        for tile in to_flip:
            flip_tile(flipped_tiles, tile)

    return flipped_tiles


initial_flipped_tiles = initialise_floor(load_input_list("day24.txt"))
print(f"Part 1 => {len(initial_flipped_tiles)}")
final_flipped_tiles = evolve_floor(initial_flipped_tiles, 100)
print(f"Part 2 => {len(final_flipped_tiles)}")
Пример #2
0

def count_trees(tree_map, slope):

    trees = 0
    rows = len(tree_map)
    cols = len(tree_map[0])
    x, y = 0, 0
    dx, dy = slope

    while y < rows:
        if tree_map[y][x] == '#':
            trees += 1
        x = (x + dx) % cols
        y += dy

    return trees


input_data = load_input_list("day3.txt")


def prod_slopes(tree_map, slopes_list):
    return reduce(mul, (count_trees(tree_map, slope) for slope in slopes_list))


slopes = [[(3, 1)], [(1, 1), (3, 1), (5, 1), (7, 1), (1, 2)]]

for i, s in enumerate(slopes):
    print(f"Part {i + 1} => {prod_slopes(input_data, s)}")
Пример #3
0
        raise ValueError(f"{operand} and {modulus} are not coprime")

    return inv % modulus


# Chinese Remainder Theorem
#   Any sequence of pairs (c, m) where 0 <= c < m and all m are pairwise coprime defines a set of
#   simultaneous linear congruences with exactly one solution x satisfying 0 <= x < product(m).
def chinese_remainder(congruence_list):

    prod_m = reduce(mul, (m for c, m in congruence_list))
    solution = 0

    for c, m in congruence_list:
        p = prod_m // m
        solution = (solution + (m - c) * p * mod_inverse(p, m)) % prod_m

    return solution


earliest_dep, bus_schedule = load_input_list("day13.txt")
bus_array = {
    i: int(bus)
    for i, bus in enumerate(bus_schedule.split(',')) if bus != 'x'
}

print(
    f"Part 1 => {reduce(mul, find_first_bus(int(earliest_dep), bus_array.values()))}"
)
print(f"Part 2 => {chinese_remainder(bus_array.items())}")
Пример #4
0
    return False


def iterate_grid(initial_grid, dimensions, iterations):

    active_points = set()

    for y, row in enumerate(initial_grid):
        for x, cube in enumerate(row):
            if cube == '#':
                active_points.add(tuple([x, y] + [0] * (dimensions - 2)))

    for _ in range(iterations):

        new_active_points = set()

        for point in product(*get_new_active_range(active_points, dimensions)):
            if new_state_is_active(active_points, point):
                new_active_points.add(point)

        active_points = new_active_points

    return len(active_points)


starting_grid = [list(row) for row in load_input_list("day17.txt")]

print(f"Part 1 => {iterate_grid(starting_grid, 3, 6)}")
print(f"Part 1 => {iterate_grid(starting_grid, 4, 6)}")
Пример #5
0
    writemem_pattern = re.compile(r"^mem\[([0-9]+)\] = ([0-9]+)$")

    bitmask = None
    mem_map = {}

    for line in program:

        match = bitmask_pattern.match(line)
        if match:
            bitmask = (BitmaskV2 if chip_ver2 else BitmaskV1)(match.group(1))
            continue

        match = writemem_pattern.match(line)
        if not match:
            raise ValueError(f"Invalid instruction: {line}")

        if chip_ver2:
            value = int(match.group(2))
            for addr in bitmask.apply(int(match.group(1))):
                mem_map[addr] = value
        else:
            mem_map[int(match.group(1))] = bitmask.apply(int(match.group(2)))

    return sum(mem_map.values())


docking_program = load_input_list("day14.txt")

print(f"part 1 => {run_docking_program(docking_program)}")
print(f"part 2 => {run_docking_program(docking_program, 2)}")
Пример #6
0
    for instr in instructions:

        match = pattern.match(instr)
        if not match:
            raise ValueError(f"Invalid instruction \"{instr}\"")

        move = match.group(1)
        size = int(match.group(2))

        if move in (LEFT, RIGHT):
            heading = rotate_point(heading, move, size)
        elif move == FORWARD:
            position = move_point(position, heading, size)
        elif use_waypoint:
            heading = move_point(heading, DIRECTION_VECTOR[move], size)
        else:
            position = move_point(position, DIRECTION_VECTOR[move], size)

    return position


def manhattan_dist(point):
    x, y = point
    return abs(x) + abs(y)


navigation_instr = load_input_list("day12.txt")
print(f"Part 1 => {manhattan_dist(navigate(navigation_instr))}")
print(f"Part 2 => {manhattan_dist(navigate(navigation_instr, True))}")
Пример #7
0
    upper = 2 ** len(bsp_code) - 1

    for c in bsp_code:
        mid = (lower + upper) // 2
        if c == high_char:
            lower = mid + 1
        elif c == low_char:
            upper = mid
        else:
            raise ValueError(f"Invalid character '{c}'")

    return lower

def seat_id(bp_code):

    row = resolve_bsp(bp_code[:7], 'F', 'B')
    col = resolve_bsp(bp_code[7:], 'L', 'R')

    return (8 * row) + col

taken_seats = sorted(seat_id(s) for s in load_input_list("day5.txt").split('\n'))

print(f"Part 1 => {taken_seats[-1]}")

prev = taken_seats[0]
for s in taken_seats[1:]:
    if s - prev == 2:
        print(f"Part 2 => {s - 1}")
        break
    prev = s
Пример #8
0
def safe_ingredients(allergen_map, ingredient_counts):
    return set(ingredient_counts.keys()).difference(
        set.union(*allergen_map.values()))


def resolve_allergens(allergen_map):

    resolved = {}

    while len(allergen_map) > 0:
        for allerg, ingreds in sorted(allergen_map.items(),
                                      key=lambda x: len(x[1])):
            possibilities = list(ingreds.difference(set(resolved.values())))
            if len(possibilities) == 1:
                resolved[allerg] = possibilities[0]
                allergen_map.pop(allerg)

    return resolved


allergens, ingredients = parse_ingredients(load_input_list("day21.txt"))
print(
    f"Part 1 => {sum(ingredients[i] for i in safe_ingredients(allergens, ingredients))}"
)

allergen_ingredient_map = resolve_allergens(allergens)
canonical = ','.join(
    [allergen_ingredient_map[i] for i in sorted(allergen_ingredient_map)])
print(f"Part 2 => {canonical}")
Пример #9
0
        arg = int(instr_match.group(3))

        if sgn == '-':
            arg *= -1

        if swap_instr == current_instr:
            opr = {"acc": "acc", "jmp": "nop", "nop": "jmp"}[opr]

        action = {
            "acc": lambda pos, acc, arg: (pos + 1, acc + arg),
            "jmp": lambda pos, acc, arg: (pos + arg, acc),
            "nop": lambda pos, acc, arg: (pos + 1, acc)
        }[opr]

        current_instr, accumulator = action(current_instr, accumulator, arg)

        if current_instr == end_instr:
            terminated = True

    return (terminated, accumulator)


code = load_input_list("day8.txt")

print(f"Part 1 => {run_program(code)[1]}")

for swap_line in range(len(code)):
    terms, accum = run_program(code, swap_line)
    if terms:
        print(f"Part 2 => {accum}")
Пример #10
0
            if (char == '*') and add_result:
                operand = add_result
                add_result = 0
        else:
            if add_has_precedence:
                add_result += int(char)
            else:
                operand = int(char)

        if operand:
            if result is None:
                result = operand
            else:
                result = result + operand if operation == '+' else result * operand

    if add_result:
        if result is None:
            result = add_result
        else:
            result *= add_result

    return result


input_expressions = load_input_list("day18.txt")

print(f"Part 1 => {sum(eval_expression(expr) for expr in input_expressions)}")
print(
    f"Part 2 => {sum(eval_expression(expr, True) for expr in input_expressions)}"
)