Esempio n. 1
0
def follow(field: CoordinateField, pos):
    '''Finds and yields all positions and their values,
    following 'pos' downwards.
    '''
    last_pos = add(pos, (0, -1))  # Inital direction is: down

    while True:  # Will be left manually
        char = field[pos]  # Char at curren position
        yield pos[0], pos[1], char

        if is_road(char):  # Move forward the same direction
            next_pos = add(pos, direction(last_pos, pos))

            # Finish if out of coordinate field or nothing (space) found:
            if not field.in_field(next_pos) or \
               (not is_road(field[next_pos]) and field[next_pos] != '+'):
                return  # Finished
        else:
            if char != '+':
                raise Exception('Unexpected character: %s' % char)

            # Encountered a '+'. Need to choose new direction:
            for possible in field.adjectents(pos, diagonals=False):
                nchar = field[possible]
                if possible != last_pos and is_road(nchar):
                    next_pos = possible
                    break
            else:
                raise Exception('No direction found in which to turn.')

        last_pos, pos = pos, next_pos
Esempio n. 2
0
def flipped_horizontal(grid: CoordinateField):
    '''Returns a copy of given 'grid' that is flipped horizontally.'''
    copy = grid.empty_copy()

    for x, y, value in grid.items():
        copy[grid.max_x - x, y] = value  # x-axis iterated backwards

    return copy
    def test_adjecents_without_diagonals(self):
        field = CoordinateField()

        expected = [
            (-1, 0),
            (0, -1),
            (0, 1),  # Own position is not yielded
            (1, 0)
        ]

        for pos_res, pos_expected in zip(field.adjectents((0, 0), False),
                                         expected):
            self.assertEqual(pos_res, pos_expected)
Esempio n. 4
0
def load_route(puzzle_input) -> CoordinateField:
    '''Puts the content of 'puzzle_input' into a CordinateField
    and returns it.
    '''
    field = CoordinateField()
    highest_x, highest_y = 0, 0

    for y, line in enumerate(puzzle_input.split('\n')):
        highest_y = y
        for x, char in enumerate(line):
            highest_x = max(highest_x, x)
            field[x, y] = char

    field.set_size(0, highest_x, 0, highest_y)
    return field
Esempio n. 5
0
def find_entry_position(field: CoordinateField) -> tuple:
    '''Determines and returns entry point of the coordinate field.'''
    for x, y, value in field.items():
        if is_road(value) and y == 0:
            return x, y
    else:
        raise Exception('No entry position found!')
Esempio n. 6
0
def solve_part_2(puzzle_input):
    field = CoordinateField(0, 127, 0, 127)  # 128x128

    # Filling coordinate field with 1s and 0s:
    for y, bits in enumerate(disk_bits(puzzle_input)):
        for x, bit in enumerate(map(int, bits)):
            field[x, y] = bit

    return groups(field)
Esempio n. 7
0
def count_group(field: CoordinateField, pos: tuple) -> int:
    '''Finds a group recursivly and returns the amount of found
    coordinates.'''
    if field[pos] != 1:  # Skip grouped (= 'None') and 0s
        return 0

    del field[pos]  # Remove found/grouped numbers
    found = 1

    # Search for adjecent coordinates recursivly:
    for adjecent in field.adjectents(pos, diagonals=False):
        found += count_group(field, adjecent)
    return found
    def test_invalid_value_access(self):
        field = CoordinateField(0, 100, 0, 100)  # (Includes borders, too)

        # Try to get coordinates outside the border:
        self.assertRaises(KeyError, field.__getitem__, [50, 101])
        self.assertRaises(KeyError, field.__getitem__, [-1, 50])

        # Requesting wrong types for coordinates
        for wrong in ('abc', True, b'abc', list(), set(), dict(), 0.1):
            try:
                self.assertRaises(TypeError, field.__getitem__, [wrong, 1])
                self.assertRaises(TypeError, field.__getitem__, [1, wrong])
                self.assertRaises(TypeError, field.__getitem__, [wrong, wrong])
                self.assertRaises(TypeError, field.__getitem__, wrong)
            except AssertionError as error:
                print('Failed with type: %s' % type(wrong).__name__)
                raise error
Esempio n. 9
0
def load_cluster(puzzle_input: str) -> tuple:
    '''Returns a tuple with the coordinatefield and the
    start position (as list).
    '''
    cluster = CoordinateField()
    start_width, start_height = 0, 0

    puzzle_input = puzzle_input.replace(' ', '')  # To work with the test input

    for y, line in enumerate(puzzle_input.split('\n')):
        start_height += 1
        if start_width == 0:
            start_width = len(line)

        for x, _ in filter((lambda x_v: x_v[1] == '#'), enumerate(line)):
            cluster[x, y] = True

    return cluster, [start_width // 2, start_height // 2]
    def test_valid_value_access(self):
        # Setting and getting different values, working of reset() and
        # default None type
        field = CoordinateField()

        # Set and check different values values:
        for test_value in self.NO_INT_EXAMPLES:
            field.clear()  # Delete all existing values

            field[0][0] = test_value
            field[1, 1] = test_value
            field[[-1, -1]] = test_value

            self.assertEqual(field[0, 0], test_value)
            self.assertEqual(field[[1, 1]], test_value)
            self.assertEqual(field[-1][-1], test_value)

        field.clear()
        # Should return None if no value was set:
        self.assertEqual(field[0, 0], None)

        # Should return a SecondDimension when requesting only one axis
        self.assertIsInstance(field[0], SecondDimension)