Ejemplo n.º 1
0
    def __init__(self, file_name):
        self.grid = Input(file_name).grid()

        self.starting_coordinate = min(self.grid.find('|'))

        turtle = Turtle(direction=TurtleDirection.DOWN, coordinate=self.starting_coordinate)

        self.secret_message = ""
        self.step_count = 0

        while True:
            next_turtle = turtle.forward()
            self.step_count += 1  # We probably moved forward, but we might have to turn instead

            current_character = self.grid[next_turtle.coordinate]
            if current_character in [None, ' ']:
                found_next_path = False

                for direction_turtle in [turtle.turn_left(), turtle.turn_right()]:
                    neighbor_turtle = direction_turtle.forward()
                    if neighbor_turtle.coordinate == turtle.coordinate:
                        continue  # Don't go backwards

                    if self.grid[neighbor_turtle.coordinate] not in [None, ' ']:
                        found_next_path = True
                        next_turtle = direction_turtle
                        self.step_count -= 1  # Turns out, we didn't move forward, we turned
                        break

                if not found_next_path:
                    break
            elif current_character.isalpha():
                self.secret_message += current_character

            turtle = next_turtle
Ejemplo n.º 2
0
    def __init__(self, file_name):
        banks = [int(x) for x in Input(file_name).line().split('\t')]

        self.redistribution_cycles = 0
        seen: Dict[str, int] = {}
        num_banks = len(banks)
        while True:
            bank_str = ",".join(str(x) for x in banks)

            if bank_str in seen:
                break
            seen[bank_str] = self.redistribution_cycles

            index, value = max(enumerate(banks), key=lambda x: (x[1], -x[0]))
            banks[index] = 0
            value_to_fill = ((value - 1) // num_banks) + 1
            num_to_fill = value // value_to_fill
            for i in range(num_to_fill):
                banks[(index + i + 1) % num_banks] += value_to_fill

            banks[(index + num_to_fill + 1) %
                  num_banks] += value - (value_to_fill * num_to_fill)

            self.redistribution_cycles += 1

        self.cycle_size = self.redistribution_cycles - seen[bank_str]
Ejemplo n.º 3
0
    def __init__(self, file_name):
        lines = Input(file_name).lines()
        self._graph: Graph[str] = Graph()

        for line in lines:
            start, end = line.split('-')
            self._graph.add(start, end)
Ejemplo n.º 4
0
    def __init__(self, file_name):
        self.instructions = Input(file_name).lines()
        self.grid: InfiniteGrid[bool] = InfiniteGrid[bool]()

        reference_coordinate = Coordinate(0, 0)

        for instruction in self.instructions:
            coordinate = reference_coordinate
            index = 0
            while index < len(instruction):
                if instruction[index] == 'n':
                    if instruction[index + 1] == 'w':
                        coordinate = coordinate.left().up()
                    elif instruction[index + 1] == 'e':
                        coordinate = coordinate.up()
                    index += 2
                elif instruction[index] == 's':
                    if instruction[index + 1] == 'w':
                        coordinate = coordinate.down()
                    elif instruction[index + 1] == 'e':
                        coordinate = coordinate.right().down()
                    index += 2
                elif instruction[index] == 'w':
                    coordinate = coordinate.left()
                    index += 1
                elif instruction[index] == 'e':
                    coordinate = coordinate.right()
                    index += 1

            if coordinate in self.grid:
                self.grid[coordinate] = not self.grid[coordinate]
            else:
                self.grid[coordinate] = True
Ejemplo n.º 5
0
    def __init__(self, file_name):
        lines = Input(file_name).lines()
        self.grid = InfiniteGrid[str]()

        for line in lines:
            x_matched = re.match(r'x=(\d+), y=(\d+)..(\d+)', line)
            y_matched = re.match(r'y=(\d+), x=(\d+)..(\d+)', line)

            if x_matched is not None:
                x = int(x_matched.group(1))
                start_y = int(x_matched.group(2))
                end_y = int(x_matched.group(3))

                for y in range(start_y, end_y + 1):
                    self.grid[x, y] = '#'
            elif y_matched is not None:
                y = int(y_matched.group(1))
                start_x = int(y_matched.group(2))
                end_x = int(y_matched.group(3))

                for x in range(start_x, end_x + 1):
                    self.grid[x, y] = '#'
            else:
                raise ValueError(f"Couldn't match the line!")

        self._fill_grid_with_water()
Ejemplo n.º 6
0
    def __init__(self, file_name):
        lines = Input(file_name).lines()

        hit_points = 0
        damage = 0
        armor = 0

        for line in lines:
            if line.startswith("Hit Points"):
                hit_points = int(line[12:])
            elif line.startswith("Damage"):
                damage = int(line[8:])
            elif line.startswith("Armor"):
                armor = int(line[7:])

        boss_fight = BossFight(hit_points, damage, armor)

        self.best_gold = 1000
        self.worst_gold = 0

        for weapon_item in self.shop_weapons.values():
            for armor_item in self.shop_armor.values():
                for left_ring, right_ring in itertools.combinations(self.shop_rings.values(), r=2):
                    cost = weapon_item.cost + armor_item.cost + left_ring.cost + right_ring.cost
                    my_hp = 100
                    my_damage = weapon_item.damage + armor_item.damage + left_ring.damage + right_ring.damage
                    my_armor = weapon_item.armor + armor_item.armor + left_ring.armor + right_ring.armor

                    fight_result = boss_fight.fight(my_hp, my_damage, my_armor)

                    if fight_result > 0:
                        self.best_gold = min(self.best_gold, cost)
                    else:
                        self.worst_gold = max(self.worst_gold, cost)
Ejemplo n.º 7
0
    def __init__(self, file_name):
        lines = Input(file_name).lines()

        self.ingredients = set()

        for line in lines:
            matched = self.regex.match(line)
            self.ingredients.add(Ingredient(
                name=matched.group(1),
                capacity=int(matched.group(2)),
                durability=int(matched.group(3)),
                flavor=int(matched.group(4)),
                texture=int(matched.group(5)),
                calories=int(matched.group(6))
            ))

        self.best_recipe = 0
        self.bast_with_calorie_limitation = 0

        for multipliers in itertools.product(range(101), repeat=len(self.ingredients)):
            if sum(multipliers) != 100:
                continue

            capacity = max(0, sum(i.capacity * m for i, m in zip(self.ingredients, multipliers)))
            durability = max(0, sum(i.durability * m for i, m in zip(self.ingredients, multipliers)))
            flavor = max(0, sum(i.flavor * m for i, m in zip(self.ingredients, multipliers)))
            texture = max(0, sum(i.texture * m for i, m in zip(self.ingredients, multipliers)))
            calories = max(0, sum(i.calories * m for i, m in zip(self.ingredients, multipliers)))

            score = capacity * durability * flavor * texture
            self.best_recipe = max(self.best_recipe, score)

            if calories == 500:
                self.bast_with_calorie_limitation = max(self.bast_with_calorie_limitation, score)
Ejemplo n.º 8
0
    def __init__(self, file_name):
        groups = Input(file_name).grouped()

        self.choices: List[int] = [int(x) for x in groups[0][0].split(',')]
        self.boards: List[BingoBoard] = [
            BingoBoard(group) for group in groups[1:]
        ]
Ejemplo n.º 9
0
    def __init__(self, file_name):
        lines = Input(file_name).lines()
        self.foods = []
        self.all_allergens = set()
        self.all_ingredients = set()

        for line in lines:
            matched = re.match(r'([ \w]+) \(contains ([ ,\w]+)\)', line)
            allergens = set(matched.group(2).split(', '))
            ingredients = set(matched.group(1).split(' '))
            self.foods.append(
                Food(ingredients=ingredients, allergens=allergens))
            self.all_ingredients = self.all_ingredients.union(ingredients)
            self.all_allergens = self.all_allergens.union(allergens)

        allergen_to_ingredients: Dict[str, Set[str]] = {}

        for allergen in self.all_allergens:
            names = None
            for food in self.foods:
                if allergen in food.allergens:
                    if names is None:
                        names = set(food.ingredients)
                    else:
                        names = names.intersection(set(food.ingredients))
            allergen_to_ingredients[allergen] = names

        self.known_allergens: Dict[str, str] = reduce_possibilities(
            allergen_to_ingredients)
Ejemplo n.º 10
0
    def __init__(self, file_name):
        lines = Input(file_name).lines()
        self.machine = None
        self.diagnostic_checksum_steps = 0

        begin_state_re = re.compile(r'Begin in state (\w+)')
        diagnostic_checksum_re = re.compile(
            r'Perform a diagnostic checksum after (\d+) steps.')
        in_state_re = re.compile(r'In state (\w+):')
        current_value_re = re.compile(r'\s+If the current value is (\d+):')
        write_value_re = re.compile(r'\s+- Write the value (\d+).')
        move_slot_re = re.compile(r'\s+- Move one slot to the (\w+).')
        continue_state_re = re.compile(r'\s+- Continue with state (\w+).')

        current_state = None
        current_value = None
        new_value = None
        cursor_change = None
        new_state = None
        actions = {}
        for line in lines:
            if (matched := begin_state_re.match(line)) is not None:
                self.machine = TuringMachine(matched.group(1))
            elif (matched := diagnostic_checksum_re.match(line)) is not None:
                self.diagnostic_checksum_steps = int(matched.group(1))
Ejemplo n.º 11
0
    def __init__(self, file_name):
        self.vm = WatchVM(Input(file_name).lines())

        # Some modifications to make this vm finish this century for part 1
        self.vm.instructions[8] = Idvup(2, 3, 5)  # Yes, custom instruction
        gtrr = self.vm.instructions[9]
        self.vm.instructions[9] = Igtrr(5, gtrr.b, gtrr.c)
Ejemplo n.º 12
0
    def __init__(self, file_name):
        lines = Input(file_name).lines()
        self.coordinates: Set[Coordinate] = set()
        self.grid = InfiniteGrid[Coordinate]()

        for line in lines:
            x, y = line.split(', ')
            coordinate = Coordinate(int(x),
                                    int(y),
                                    system=CoordinateSystem.X_RIGHT_Y_DOWN)
            self.coordinates.add(coordinate)
            self.grid[coordinate] = coordinate

        self.bounding_box: BoundingBox = self.grid.bounding_box

        for x, y in self.bounding_box:
            test_coordinate = Coordinate(
                x, y, system=CoordinateSystem.X_RIGHT_Y_DOWN)

            distances = dict(
                (coordinate, test_coordinate.manhattan(coordinate))
                for coordinate in self.coordinates)
            _, min_distance = min(distances.items(), key=lambda i: i[1])
            min_coordinates = [
                coordinate for coordinate, distance in distances.items()
                if distance == min_distance
            ]

            if len(min_coordinates) != 1:
                continue

            self.grid[test_coordinate] = min_coordinates[0]
Ejemplo n.º 13
0
    def __init__(self, file_name):
        lines = Input(file_name).lines()
        self.orbits = {}

        for line in lines:
            split = line.split(')')
            self.orbits[split[1].strip()] = split[0].strip()
Ejemplo n.º 14
0
class Y2017D10(object):
    def __init__(self, file_name):
        self.input = Input(file_name).line()

    def part1(self):
        circle: List[int] = list(range(256))
        circle_size = len(circle)

        current_position = 0
        skip_size = 0

        for length in self.input.split(','):
            length = int(length)
            for i in range(length // 2):
                from_index: int = (current_position + i) % circle_size
                to_index: int = (current_position + length - i - 1) % circle_size
                temp: int = circle[from_index]
                circle[from_index] = circle[to_index]
                circle[to_index] = temp

            current_position = (current_position + length + skip_size) % circle_size
            skip_size += 1

        result = circle[0] * circle[1]
        print("Part 1:", result)

    def part2(self):
        result = KnotHash(self.input).hex

        print("Part 2:", result)
Ejemplo n.º 15
0
    def __init__(self, file_name):
        self.lines = Input(file_name).lines()
        self.moons = []
        self.velocities = []
        self.reset()

        self._origin_vector = Vector(0, 0, 0)
Ejemplo n.º 16
0
    def __init__(self, file_name):
        lines = Input(file_name).lines()

        value_re = re.compile(r'value (\d+) goes to bot (\d+)')
        give_re = re.compile(
            r'bot (\d+) gives low to (bot|output) (\d+) and high to (bot|output) (\d+)'
        )

        self.bots = {}
        self.outputs = {}

        for line in lines:
            if (matched := give_re.match(line)) is not None:
                bot_id = int(matched.group(1))
                bot = self.bots.setdefault(bot_id, Bot())
                bot.low_out_type = OutType.Bot if matched.group(
                    2) == "bot" else OutType.Output
                bot.low_out_num = int(matched.group(3))
                bot.high_out_type = OutType.Bot if matched.group(
                    4) == "bot" else OutType.Output
                bot.high_out_num = int(matched.group(5))
            elif (matched := value_re.match(line)) is not None:
                bot_id = int(matched.group(2))
                bot = self.bots.setdefault(bot_id, Bot())
                bot.values.append(int(matched.group(1)))
Ejemplo n.º 17
0
    def __init__(self, file_name):
        lines = Input(file_name).lines()

        self.firewall: Dict[int, int] = {}

        for line in lines:
            key, value = line.split(': ')
            self.firewall[int(key)] = int(value)
Ejemplo n.º 18
0
    def __init__(self, file_name):
        rule_lines, self.messages = Input(file_name).grouped()

        self.rules = {}

        for line in rule_lines:
            key, value = line.split(': ')
            self.rules[int(key)] = value
Ejemplo n.º 19
0
    def __init__(self, file_name):
        line = Input(file_name).line()

        start = Coordinate(0, 0)
        grid = self._build_map(start, line)

        walkable = ['X', '.', '|', '-']
        self.flood_map = grid.flood_map(start, *walkable)
Ejemplo n.º 20
0
 def __init__(self, file_name):
     lines = Input(file_name).lines()
     self.expressions: List[Expression] = [
         Expression([
             int(x) if x.isnumeric() else str(x)
             for x in list(line.replace(' ', ''))
         ]) for line in lines
     ]
Ejemplo n.º 21
0
    def __init__(self, file_name):
        line = Input(file_name).line()

        self.layers = []
        layer_size = self._width * self._height
        for i in range(0, len(line), layer_size):
            self.layers.append(
                Layer(self._width, self._height, line[i:i + layer_size]))
Ejemplo n.º 22
0
    def __init__(self, file_name):
        lines = Input(file_name).lines()

        self.instructions = []
        for line in lines:
            if matched := re.match(r"nop ([+-]\d+)", line):
                self.instructions.append(Instruction(InstructionType.NOP, int(matched.group(1))))
            elif matched := re.match(r"acc ([+-]\d+)", line):
                self.instructions.append(Instruction(InstructionType.ACC, int(matched.group(1))))
Ejemplo n.º 23
0
    def __init__(self, file_name):
        line = Input(file_name).line()
        codes = line.split(',')

        self._flash = {}
        for index in range(len(codes)):
            self._flash[index] = int(codes[index])

        self.ram = {}
        self.instruction_pointer = 0
        self.halted = False
        self.waiting_for_input = False
        self._input_address = 0
        self.has_output = False
        self._output_value = 0
        self._relative_base = 0

        self.reset()
Ejemplo n.º 24
0
    def __init__(self, file_name):
        lines = Input(file_name).lines()
        self._starting_positions = {}

        player_position_regex = re.compile(
            r'Player (\d+) starting position: (\d+)')
        for line in lines:
            match = player_position_regex.match(line)
            self._starting_positions[int(match.group(1))] = int(match.group(2))
Ejemplo n.º 25
0
    def __init__(self, file_name):
        initial_grid = Input(file_name).grid()
        self.grid = InfiniteGrid[NodeType]()

        center_x = center_y = initial_grid.width // 2
        for x, y in product(range(initial_grid.width), repeat=2):
            self.grid[x - center_x,
                      y - center_y] = NodeType.Infected if initial_grid[
                          x, y] == '#' else NodeType.Clean
Ejemplo n.º 26
0
 def __init__(self, file_name):
     self.base_grid = Grid.from_str(Input(file_name).lines())
     biodiversity = 0
     for col in range(5):
         for row in range(5):
             if self.base_grid[col, row] == '#':
                 index = 5 * row + col
                 biodiversity |= 2**index
     self.with_biodiversity = GridWithBiodiversity(self.base_grid, biodiversity)
Ejemplo n.º 27
0
    def __init__(self, file_name):
        floors = Input(file_name).line()

        self.floor = 0
        self.first_basement_index = None
        for index, character in enumerate(floors):
            self.floor += 1 if character == '(' else -1
            if self.floor == -1 and self.first_basement_index is None:
                self.first_basement_index = index + 1
Ejemplo n.º 28
0
    def __init__(self, file_name):
        lines = Input(file_name).lines()

        self.seats_ids = []

        for line in lines:
            row, col = self._get_seat(line)
            self.seats_ids.append(row * 8 + col)

        self.seats_ids = sorted(self.seats_ids)
Ejemplo n.º 29
0
    def __init__(self, file_name):
        lines = Input(file_name).lines()

        self.tasking: Tasking[str] = Tasking[str]()

        for line in lines:
            matched = re.match(
                r"Step (\w) must be finished before step (\w) can begin.",
                line)
            self.tasking.requires(matched.group(2), matched.group(1))
Ejemplo n.º 30
0
    def __init__(self, file_name):
        start, pairs = Input(file_name).grouped()

        pairs_map: Dict[str, str] = {}
        pair: str
        for pair in pairs:
            _from, _to = pair.split(' -> ')
            pairs_map[_from] = _to

        self._poly = Polymerization(start[0], pairs_map)