@norgsmen: Ein paar Punkte zum Quelltext:
Fangen wir mit der Namensgebung an. Attribute auf Objekten beschreiben woraus das Objekt besteht. Ein `Stack` besteht aus Elementen und nicht aus einem Container. Der Stack selbst ist ja ein/der Container für diese Elemente. Wir haben bereits an einer Stelle einen generischen Namen für ein einzelnes Element: `item`, also wäre `_items` ein passender Attributname.
Abkürzungen in Namen sind nicht gut, weil sie den Quelltext schwerer lesbar/verständlich machen. `temp` ist eine recht generische Abkürzung steht in anderen Programmen auch gerne mal für `temperature`, es ist also keine allgemein bekannte Abkürzung mit der so gut wie jeder das gleiche verbindet.
Das die `__repr__()`-Methode falsch ist, wurde ja von Sirius3 bereits angemerkt. Richtig wäre entweder eine Zeichenkette mit einem Ausdruck, der als Quelltext ausgeführt wieder ein gleichwertiges `Stack`-Objekt liefern würde, oder die Darstellung sollte in ”spitze Klammern” ("<…>") eingefasst werden. So machen das alle anderen Datentypen. Da man einen `Stack` mit Inhalt nicht in einem Ausdruck erstellen kann, müsste man entweder *das* ändern, oder man ist bei den ”spitzen Klammern”.
Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.
Wenn Code auf Modulebene steht, sollte der nicht auch noch Variablendefinitionen und Funktionsdefinitionen mischen. Das macht es noch schwerer einen Überblick zu behalten.
Das man der Funktion beim ersten Aufruf die Anzahl der Scheiben mitgeben muss ist ja eigentlich redundant, denn das ist immer die Anzahl der Elemente von `begin`. Das Argument kann man also Optional machen und vom `Stack` abfragen wenn der eine `__len__()`-Methode bekommt.
Nichts an der `hanoi()`-Funktion erfordert, das die Elemente ganze Zahlen sind. Der Funktion ist das schlicht egal. Wenn man schon Type-Annotationen macht, sollte man die nicht unnötig einschränkend machen.
Zwischenstand:
Code: Alles auswählen
from typing import Generic, List, Optional, TypeVar
T = TypeVar("T")
class Stack(Generic[T]):
def __init__(self) -> None:
self._items: List[T] = []
def __len__(self) -> int:
return len(self._items)
def push(self, item: T) -> None:
self._items.append(item)
def pop(self) -> T:
return self._items.pop()
def __repr__(self) -> str:
return f"<{self.__class__.__name__} {self._items!r}>"
def hanoi(
begin: Stack[T],
end: Stack[T],
temporary: Stack[T],
n: Optional[int] = None,
) -> None:
if n is None:
n = len(begin)
if n == 1:
end.push(begin.pop())
else:
hanoi(begin, temporary, end, n - 1)
hanoi(begin, end, temporary, 1)
hanoi(temporary, end, begin, n - 1)
def main():
tower_a: Stack[int] = Stack()
tower_b: Stack[int] = Stack()
tower_c: Stack[int] = Stack()
for i in [1, 2, 3]:
tower_a.push(i)
hanoi(tower_a, tower_c, tower_b)
print(tower_a)
print(tower_b)
print(tower_c)
if __name__ == "__main__":
main()
Ausgabe:
Hier das ganze ohne die Typannotationen:
Code: Alles auswählen
class Stack:
def __init__(self):
self._items = []
def __len__(self):
return len(self._items)
def push(self, item):
self._items.append(item)
def pop(self):
return self._items.pop()
def __repr__(self):
return f"<{self.__class__.__name__} {self._items!r}>"
def hanoi(begin, end, temporary, n=None):
if n is None:
n = len(begin)
if n == 1:
end.push(begin.pop())
else:
hanoi(begin, temporary, end, n - 1)
hanoi(begin, end, temporary, 1)
hanoi(temporary, end, begin, n - 1)
def main():
tower_a = Stack()
tower_b = Stack()
tower_c = Stack()
for i in [1, 2, 3]:
tower_a.push(i)
hanoi(tower_a, tower_c, tower_b)
print(tower_a)
print(tower_b)
print(tower_c)
if __name__ == "__main__":
main()
Und dann noch mal ohne die Klasse, die eigentlich nur `append()` in `push()` umbenennt:
Code: Alles auswählen
def hanoi(begin, end, temporary, n=None):
if n is None:
n = len(begin)
if n == 1:
end.append(begin.pop())
else:
hanoi(begin, temporary, end, n - 1)
hanoi(begin, end, temporary, 1)
hanoi(temporary, end, begin, n - 1)
def main():
tower_a = [1, 2, 3]
tower_b = []
tower_c = []
hanoi(tower_a, tower_c, tower_b)
print(tower_a)
print(tower_b)
print(tower_c)
if __name__ == "__main__":
main()