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
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]
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)
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
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()
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)
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)
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:] ]
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)
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))
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)
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]
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()
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)
def __init__(self, file_name): self.lines = Input(file_name).lines() self.moons = [] self.velocities = [] self.reset() self._origin_vector = Vector(0, 0, 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)))
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)
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
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)
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 ]
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]))
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))))
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()
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))
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
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)
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
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)
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))
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)