101 lines
3.3 KiB
Python
101 lines
3.3 KiB
Python
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
|