forked from hofmannol/AlgoDatSoSe25
Implemented pr08
This commit is contained in:
parent
a6aeff66cd
commit
929963aa3a
24
data/hoehleLarger.txt
Normal file
24
data/hoehleLarger.txt
Normal file
@ -0,0 +1,24 @@
|
||||
"Höhleneingang" <> "Ost/West-Passage"
|
||||
"Höhleneingang" <> "Nord/Süd-Passage"
|
||||
"Nord/Süd-Passage" <> "Nebelraum"
|
||||
"Steiniger Pfad" > "Ost/West-Passage"
|
||||
"Ost/West-Passage" <> "Schwefelgewölbe"
|
||||
"Schwefelgewölbe" > "Steiniger Pfad"
|
||||
"Schatzkammer" > "Nebelraum"
|
||||
"Steiniger Pfad" > "Schatzkammer"
|
||||
"Kristallhöhle" <> "Schwefelgewölbe"
|
||||
"Kristallhöhle" <> "Nebelraum"
|
||||
"Versteckter Gang" > "Kristallhöhle"
|
||||
"Versteckter Gang" > "Schatzkammer"
|
||||
"Unterirdischer See" <> "Kristallhöhle"
|
||||
"Unterirdischer See" <> "Ost/West-Passage"
|
||||
"Geheimgang" > "Unterirdischer See"
|
||||
"Geheimgang" > "Versteckter Gang"
|
||||
"Abgrund" > "Geheimgang"
|
||||
"Abgrund" > "Nebelraum"
|
||||
"Verlorene Kammer" > "Abgrund"
|
||||
"Verlorene Kammer" > "Schwefelgewölbe"
|
||||
"Geheimgang" > "Schatzkammer"
|
||||
"Kristallhöhle" > "Höhleneingang"
|
||||
"Schwefelgewölbe" > "Höhleneingang"
|
||||
"Abgrund" > "Schatzkammer"
|
121
schoeffelbe/pr08.py
Normal file
121
schoeffelbe/pr08.py
Normal file
@ -0,0 +1,121 @@
|
||||
import logging
|
||||
from graphviz import Digraph
|
||||
from collections import deque
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
# logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
import time
|
||||
|
||||
def timeMS(func, *args, **kwargs):
|
||||
startTime = time.perf_counter()
|
||||
result = func(*args, **kwargs)
|
||||
endTime = time.perf_counter()
|
||||
elapsedMS = (endTime - startTime) * 1000 # Convert to milliseconds
|
||||
print(f"{func.__name__} took {elapsedMS:.2f} ms")
|
||||
return result
|
||||
|
||||
from utils.memory_array import MemoryArray
|
||||
from utils.memory_cell import MemoryCell
|
||||
from utils.literal import Literal
|
||||
from utils.memory_range import mrange
|
||||
from utils.memory_manager import MemoryManager
|
||||
|
||||
class Graph:
|
||||
def __init__(self):
|
||||
self.adjacencyList = {}
|
||||
|
||||
def addEdge(self, node1, node2, bidirectional=True):
|
||||
if node1 not in self.adjacencyList:
|
||||
self.adjacencyList[node1] = []
|
||||
if node2 not in self.adjacencyList:
|
||||
self.adjacencyList[node2] = []
|
||||
self.adjacencyList[node1].append(node2)
|
||||
if bidirectional:
|
||||
self.adjacencyList[node2].append(node1)
|
||||
|
||||
def serialize(self):
|
||||
return self.adjacencyList
|
||||
|
||||
def breadthFirstSearch(self, start, goal, edgesGonePassed = None):
|
||||
if start not in self.adjacencyList or goal not in self.adjacencyList:
|
||||
return None, None
|
||||
|
||||
# Dont want to have a class for this, set suffices
|
||||
visited = set()
|
||||
queue = deque([(start, [start], set())]) # (current_node, path, edgesGoneToGetHere)
|
||||
|
||||
while queue:
|
||||
currentNode, path, edgesGone = queue.popleft()
|
||||
|
||||
if currentNode == goal:
|
||||
return path, edgesGone
|
||||
|
||||
if currentNode not in visited:
|
||||
logger.info(f"visiting {currentNode}")
|
||||
visited.add(currentNode)
|
||||
for neighbor in self.adjacencyList[currentNode]:
|
||||
edge = (currentNode, neighbor)
|
||||
if neighbor not in visited and (edgesGonePassed is None or edge not in edgesGonePassed):
|
||||
# Pythonic way of saying neighbour, path no next clear neighbour
|
||||
# and union of edgesGone with current edge
|
||||
queue.append((neighbor, path + [neighbor], edgesGone | {edge}))
|
||||
|
||||
return None, None
|
||||
|
||||
|
||||
def graphvizify(filePath: str, outputFile: str = 'build/hoehleGraph'):
|
||||
graph = Digraph()
|
||||
graph.attr(rankdir='TB')
|
||||
graph.attr('node', shape='circle', style='filled', fillcolor='lightgray')
|
||||
graph.attr('edge', arrowsize='0.7')
|
||||
|
||||
# Reuse the function to also create our Graph... Waste not want not^^
|
||||
caveGraph = Graph();
|
||||
|
||||
with open(filePath, 'r') as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
delimiter = '<>' if '<>' in line else '>' if '>' in line else None
|
||||
if delimiter:
|
||||
node1, node2 = map(str.strip, line.split(delimiter))
|
||||
node1, node2 = map(lambda x: x.strip('"'), map(str.strip, line.split(delimiter)))
|
||||
graph.edge(f"\"{node1}\"", f"\"{node2}\"", dir='none' if delimiter == '<>' else None)
|
||||
caveGraph.addEdge(node1, node2, (delimiter == '<>'));
|
||||
|
||||
try:
|
||||
graph.render(outputFile, view=True)
|
||||
except Exception as e:
|
||||
print(f"Could not display graph: {e}\n Trying to save without viewing!")
|
||||
try:
|
||||
graph.render(outputFile, view=False)
|
||||
print(f"Your built map should be available here: {outputFile}.pdf")
|
||||
except Exception as e:
|
||||
print(f"Could not save graph file: {e}")
|
||||
|
||||
return caveGraph
|
||||
|
||||
if __name__ == "__main__":
|
||||
for filename in [ "data/hoehle.txt", "data/hoehleLarger.txt"]:
|
||||
caveGraph = graphvizify(filename, 'build/hoehleGraph')
|
||||
|
||||
start = "Höhleneingang"
|
||||
goal = "Schatzkammer"
|
||||
shortestPath, edgesGoneInitial = caveGraph.breadthFirstSearch(start, goal)
|
||||
logger.debug(caveGraph.adjacencyList)
|
||||
|
||||
if shortestPath:
|
||||
print(f"Shortest path from {start} to {goal} is:")
|
||||
print(" -> ".join(shortestPath))
|
||||
else:
|
||||
print(f"No path found from {start} to {goal}.")
|
||||
|
||||
returnpath, _ = caveGraph.breadthFirstSearch(goal, start, edgesGoneInitial)
|
||||
|
||||
if returnpath:
|
||||
print(f"Shortest path from {goal} to {start} is:")
|
||||
print(" -> ".join(returnpath))
|
||||
else:
|
||||
print("No path back Home found. Good Luck")
|
||||
|
||||
exit(0)
|
Loading…
x
Reference in New Issue
Block a user