I recently started learning more about recursion in Python and quickly got myself into the Tower of Hanoi problem.
I already have a recursive solution in Python, which prints the moves I should play to solve the problem, but I would like to visualize it and see the pieces moving.
What would be a possible approach to it?
If you model your pegs as a list of lists with the larger discs at the lower indices, it should be relatively simple to implement a printing function and a movement function (that also prints). You can then feed your movements to that function.
def printHanoi(pegs):
height = sum(map(len,pegs))
for r in reversed(range(height)):
for peg in pegs:
disc = "-" * (0 if r>=len(peg) else peg[r])
print(f"{disc:>{height}}|{disc:{height}}", end=" ")
print()
invalid = any(p[::-1]!=sorted(p) for p in pegs)
print("="*(height*6+5),"INVALID"*invalid)
print()
def moveHanoi(pegs,fromPeg,toPeg):
pegs[toPeg].append(pegs[fromPeg].pop(-1))
printHanoi(pegs)
Output:
pegs = [[3,2,1],[],[]]
printHanoi(pegs)
moveHanoi(pegs,0,2)
moveHanoi(pegs,0,1)
moveHanoi(pegs,2,1)
moveHanoi(pegs,0,2)
-|- | |
--|-- | |
---|--- | |
=======================
| | |
--|-- | |
---|--- | -|-
=======================
| | |
| | |
---|--- --|-- -|-
=======================
| | |
| -|- |
---|--- --|-- |
=======================
| | |
| -|- |
| --|-- ---|---
=======================
This will work for any tower height and, if your algorithm makes illegal moves, it will illustrate them as well:
pegs = [[5,4,3,2,1],[],[]]
printHanoi(pegs)
moveHanoi(pegs,0,2)
moveHanoi(pegs,0,1)
moveHanoi(pegs,0,2)
-|- | |
--|-- | |
---|--- | |
----|---- | |
-----|----- | |
===================================
| | |
--|-- | |
---|--- | |
----|---- | |
-----|----- | -|-
===================================
| | |
| | |
---|--- | |
----|---- | |
-----|----- --|-- -|-
===================================
| | |
| | |
| | |
----|---- | ---|---
-----|----- --|-- -|-
=================================== INVALID
If you build your Hanoi solver as a generator, you will be able to use it in a for-loop that simply calls the moveHanoi() function:
def solveHanoi(count,fromPeg=0,toPeg=2,tempPeg=1):
if not count: return
yield from solveHanoi(count-1,fromPeg,tempPeg,toPeg)
yield fromPeg,toPeg
yield from solveHanoi(count-1,tempPeg,toPeg,fromPeg)
pegs = [[3,2,1],[],[]]
printHanoi(pegs)
for f,t in solveHanoi(3):
moveHanoi(pegs,f,t)