import settings import math from collections import defaultdict class Instance: def __init__(self): self.graph = defaultdict(list) self.directions_dict = defaultdict(list) def config(self, fields): adjacency_list = self.__generate_graph() nodes_to_visit = self.generate_target_fields(fields) shortest_path_bfs = self.generate_shortest_path_for_all_targets_bfs(nodes_to_visit) print("Adjacency list: " + str(dict(adjacency_list))) print("List of targets: " + str(nodes_to_visit)) print("The shortest path found by bfs algorithm: " + str(shortest_path_bfs)) def generate_shortest_path_for_all_targets_bfs(self, nodes_to_visit): shortest_bfs_path = [] start_node = 0 for target_node in nodes_to_visit: shortest_bfs_path.extend(self.__shortest_path_bfs(start_node, target_node)[1:]) start_node = target_node return shortest_bfs_path # private def __add_edge(self, u, v): self.graph[u].append(v) def __generate_graph(self): width = settings.Field.horizontal_count() height = settings.Field.vertical_count() for i in range(height): for j in range(width): point = i * width + j point_left = i * width + j - 1 point_left_column = point_left - width * i point_right = i * width + j + 1 point_right_column = point_right % width point_up = (i - 1) * width + j point_up_row = math.floor(point_up / width) point_down = (i + 1) * width + j point_down_row = math.floor(point_down / width) if point_left_column >= 0: self.__add_edge(point, point_left) if point_right_column > 0: self.__add_edge(point, point_right) if point_up_row >= 0: self.__add_edge(point, point_up) if point_down_row < height: self.__add_edge(point, point_down) return self.graph def __shortest_path_bfs(self, start_node, target_node): path_list = [[start_node]] path_index = 0 visited_nodes = {start_node} if start_node == target_node: return path_list[0] while path_index < len(path_list): current_path = path_list[path_index] prev_node = current_path[-1] next_nodes = self.graph[prev_node] if target_node in next_nodes: current_path.append(target_node) return current_path for next_node in next_nodes: if not next_node in visited_nodes: new_path = current_path[:] new_path.append(next_node) path_list.append(new_path) visited_nodes.add(next_node) path_index += 1 return False # static @staticmethod def generate_target_fields(fields): width = settings.Field.horizontal_count() height = settings.Field.vertical_count() fields_to_visit = [] for i in range(height): for j in range(width): point = i * width + j if fields[j][i] == 'dirt': fields_to_visit.append(point) return fields_to_visit