Implemented pr08

This commit is contained in:
Bernhard Schoeffel 2025-05-23 19:15:24 +02:00
parent a6aeff66cd
commit 929963aa3a
2 changed files with 145 additions and 0 deletions

24
data/hoehleLarger.txt Normal file
View 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
View 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)