SzybciorSmartTraktor/graph.py

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