Source code for kyu_3.line_safari_is_that_a_line.walker_class

"""
Walker class: make moves, check directions, etc...
"""

#  Created by Egor Kostan.
#  GitHub: https://github.com/ikostan
#  LinkedIn: https://www.linkedin.com/in/egor-kostan/


[docs]class Walker: """ Walker class: make moves, check directions, etc... """ def __init__(self, grid: list): # print('__init__') self.__grid: list = grid self.__is_start: bool = True self.__position: dict = self.__get_start_point() self.__direction = self.__set_initial_direction() def __set_initial_direction(self) -> dict: # print('__set_initial_direction') DIRECTION = { 'left': False, 'right': False, 'up': False, 'down': False, } # coordinates row: int = self.__position['row'] col: int = self.__position['col'] # up if row - 1 >= 0: if self.__grid[row - 1][col] in 'X|+': DIRECTION['up'] = True # down if row + 1 < len(self.__grid): if self.__grid[row + 1][col] in 'X|+': DIRECTION['down'] = True # left if col - 1 >= 0: if self.__grid[row][col - 1] in 'X+-': DIRECTION['left'] = True # right if col + 1 < len(self.__grid[row]): if self.__grid[row][col + 1] in 'X+-': DIRECTION['right'] = True print("\nINITIAL DIRECTION: {}".format(DIRECTION)) return DIRECTION @property def position(self) -> str: """ Return char from grid based on current position :return: current char """ # print('position') row: int = self.__position['row'] col: int = self.__position['col'] return self.__grid[row][col]
[docs] def move(self) -> None: """ Make one step if possible :return: None """ print('move') if not self.is_done: # 1. update coordinates if self.__direction['left']: self.__position['prev_col'] = self.__position['col'] self.__position['prev_row'] = self.__position['row'] self.__position['col'] -= 1 elif self.__direction['right']: self.__position['prev_col'] = self.__position['col'] self.__position['prev_row'] = self.__position['row'] self.__position['col'] += 1 elif self.__direction['up']: self.__position['prev_col'] = self.__position['col'] self.__position['prev_row'] = self.__position['row'] self.__position['row'] -= 1 elif self.__direction['down']: self.__position['prev_col'] = self.__position['col'] self.__position['prev_row'] = self.__position['row'] self.__position['row'] += 1 # 2. update flag if self.__is_start: self.__is_start = False # 3. set direction # DEBUG ONLY row: int = self.__position['row'] col: int = self.__position['col'] print('\nchar: {}, ' 'direction: {}, ' 'row: {}, ' 'col: {}, ' 'is_done: {}\n'.format(self.__grid[row][col], [key for key in self.__direction if self.__direction[key]], row, col, self.is_done)) self.__set_direction()
@property def is_done(self) -> bool: """ Check if get to the 'X' point or can make one move only :return: true/false """ # print('is_done') if self.__is_start: if len([val for val in self.__direction.values() if val]) != 1: print('\nRule #1') return True else: if self.position == 'X' and not self.__is_start: print('\nRule #2') return True # if self.__count_possible_directions() != 2: if len([val for val in self.__direction.values() if val]) != 1: print('\nRule #3') # print('possible directions: {}'.format(self.__count_possible_directions())) print(self.__direction) return True return False def __get_start_point(self): """ Locate starting point :return: starting point X """ # print('__get_start_point') for row_i, row in enumerate(self.__grid): for col_i, col in enumerate(row): if col == 'X': return {'prev_row': row_i, 'prev_col': col_i, 'row': row_i, 'col': col_i} def __reset_direction(self) -> None: # print('__reset_direction') for key in self.__direction: self.__direction[key] = False def __set_direction(self) -> None: """ Update directions based on current position and previous direction :return: None """ # print('__set_direction') prev_row = self.__position['prev_row'] prev_col = self.__position['prev_col'] previous_position = self.__grid[prev_row][prev_col] # reset all directions self.__reset_direction() print('prev: {}, pos: {}'.format(previous_position, self.position)) if self.position == '+' and (previous_position == '-' or previous_position == 'X'): self.__direction['up'] = self.__test_up() self.__direction['down'] = self.__test_down() elif self.position == '+' and previous_position == '|': self.__direction['left'] = self.__test_left() self.__direction['right'] = self.__test_right() elif self.position == '+' and previous_position == '+': if self.__position['col'] == self.__position['prev_col']: self.__direction['left'] = self.__test_left() self.__direction['right'] = self.__test_right() elif self.__position['row'] == self.__position['prev_row']: self.__direction['up'] = self.__test_up() self.__direction['down'] = self.__test_down() elif self.position == '-' and (previous_position == '-' or previous_position == 'X'): if self.__position['col'] < self.__position['prev_col']: self.__direction['left'] = self.__test_left() elif self.__position['col'] > self.__position['prev_col']: self.__direction['right'] = self.__test_right() elif self.position == '-' and previous_position == '+': if self.__position['col'] < self.__position['prev_col']: self.__direction['left'] = self.__test_left() elif self.__position['col'] > self.__position['prev_col']: self.__direction['right'] = self.__test_right() elif self.position == '|' and (previous_position == '|' or previous_position == 'X'): if self.__position['row'] < self.__position['prev_row']: self.__direction['up'] = self.__test_up() elif self.__position['row'] > self.__position['prev_row']: self.__direction['down'] = self.__test_down() elif self.position == '|' and previous_position == '+': if self.__position['row'] < self.__position['prev_row']: self.__direction['up'] = self.__test_up() elif self.__position['row'] > self.__position['prev_row']: self.__direction['down'] = self.__test_down() # print('set_direction: {}'.format(self.__direction)) def __test_up(self) -> bool: # print('__test_up') row: int = self.__position['row'] col: int = self.__position['col'] if row - 1 >= 0 and self.__grid[row - 1][col] in 'X|+': return True return False def __test_down(self) -> bool: # print('__test_down') row: int = self.__position['row'] col: int = self.__position['col'] if row + 1 < len(self.__grid) and self.__grid[row + 1][col] in 'X|+': return True return False def __test_left(self) -> bool: # print('__test_left') row: int = self.__position['row'] col: int = self.__position['col'] if col - 1 >= 0 and self.__grid[row][col - 1] in 'X+-': return True return False def __test_right(self) -> bool: # print('__test_right') row: int = self.__position['row'] col: int = self.__position['col'] if col + 1 < len(self.__grid[row]) and self.__grid[row][col + 1] in 'X+-': return True return False def __count_possible_directions(self) -> int: # print('__count_possible_directions') return len([val for val in [self.__test_left(), self.__test_right(), self.__test_up(), self.__test_down()] if val])