class Y2017D5(object): def __init__(self, file_name): self.input = Input(file_name).ints() def part1(self): result = 0 cpu_instructions = self.input.copy() input_length = len(self.input) pointer = 0 while 0 <= pointer < input_length: value = cpu_instructions[pointer] cpu_instructions[pointer] += 1 pointer += value result += 1 print("Part 1:", result) def part2(self): result = 0 cpu_instructions = self.input.copy() input_length = len(self.input) pointer = 0 while 0 <= pointer < input_length: value = cpu_instructions[pointer] if value >= 3: cpu_instructions[pointer] -= 1 else: cpu_instructions[pointer] += 1 pointer += value result += 1 print("Part 2:", result)
class Y2021D25(object): def __init__(self, file_name): self._grid = Input(file_name).grid() def part1(self): result = 0 grid = self._grid.copy() while True: result += 1 changed_east, grid = self._mutate(grid, Moving.EAST) changed_south, grid = self._mutate(grid, Moving.SOUTH) # grid.print() # print() if not changed_east and not changed_south: break print("Part 1:", result) @staticmethod def _mutate(grid: Grid[str], moving: Moving) -> (bool, Grid[str]): result = grid.copy() max_x = grid.max_x max_y = grid.max_y locations = grid.find('>') if moving == Moving.EAST else grid.find('v') something_changed = False for location in locations: test = location.right( ) if moving == Moving.EAST else location.down() if test.x > max_x: test = Coordinate(0, test.y, system=test.system) if test.y > max_y: test = Coordinate(test.x, 0, system=test.system) if grid[test] == '.': result[test] = '>' if moving == Moving.EAST else 'v' result[location] = '.' something_changed = True return something_changed, result
class Y2021D11(object): def __init__(self, file_name): self._grid = Input(file_name).grid().map(lambda x: int(x)) def part1(self): result = 0 grid = self._grid.copy() for _ in range(100): result += self._step(grid) print("Part 1:", result) def part2(self): grid = self._grid.copy() step = 0 while True: step += 1 flash_count = self._step(grid) if flash_count == 100: result = step break print("Part 2:", result) @staticmethod def _step(grid: InfiniteGrid[int]) -> int: result = 0 for row in range(10): for col in range(10): grid[col, row] = grid[col, row] + 1 should_flash = grid.find(lambda value: value > 9) already_flashed = set() queue: Queue = Queue() while should_flash: queue.put(should_flash.pop()) while not queue.empty(): coordinate: Coordinate = queue.get() if coordinate in already_flashed: continue already_flashed.add(coordinate) grid[coordinate] = 0 result += 1 neighbors = coordinate.neighbors8() for neighbor in neighbors: if neighbor not in grid: continue if neighbor in already_flashed: continue grid[neighbor] += 1 if grid[neighbor] > 9: queue.put(neighbor) return result
class Y2018D18(object): def __init__(self, file_name): self.initial_grid = Input(file_name).grid() def part1(self): grid = self.initial_grid.copy() for i in range(10): grid = self._mutate(grid) wooded = len(grid.find('|')) lumberyards = len(grid.find('#')) result = wooded * lumberyards print("Part 1:", result) def part2(self): grid = self.initial_grid.copy() grid_lookup = {} minute_lookup = {} my_hash = self._hash(grid) minute = 0 while my_hash not in grid_lookup: grid_lookup[my_hash] = grid minute_lookup[my_hash] = minute grid = self._mutate(grid) my_hash = self._hash(grid) minute += 1 wanted = 1000000000 remaining = (wanted - minute) % (minute - minute_lookup[my_hash]) for _ in range(remaining): grid = self._mutate(grid) wooded = len(grid.find('|')) lumberyards = len(grid.find('#')) result = wooded * lumberyards print("Part 2:", result) @staticmethod def _hash(grid: Grid[str]): coordinates = sorted(list(grid)) md5_func = hashlib.md5() for coordinate in coordinates: md5_func.update(str(coordinate).encode()) md5_func.update(grid[coordinate].encode()) return md5_func.hexdigest() @staticmethod def _mutate(grid: Grid[str]) -> Grid[str]: result = Grid[str](grid.width, grid.height) for coordinate, acre in grid.items(): tree_count = 0 lumberyard_count = 0 for neighbor in coordinate.neighbors8(): if grid[neighbor] == '|': tree_count += 1 elif grid[neighbor] == '#': lumberyard_count += 1 if acre == '.' and tree_count >= 3: result[coordinate] = '|' elif acre == '|' and lumberyard_count >= 3: result[coordinate] = '#' elif acre == '#' and (lumberyard_count < 1 or tree_count < 1): result[coordinate] = '.' else: result[coordinate] = acre return result