Beispiel #1
0
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)
Beispiel #2
0
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
Beispiel #3
0
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
Beispiel #4
0
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