123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475 |
- """Demo to show how to solve the Tower of Hanoi"""
- # Credits:
- # https://github.com/gjbex/training-material/blob/master/Misc/Notebooks/hanoi.ipynb
- # Creative Commons Zero v1.0 Universal licence
- from vedo import Plotter, Cylinder, Box
- from copy import deepcopy
- class Hanoi:
- def __init__(self, nr_disks):
- self._nr_disks = nr_disks
- self._towers = [list(range(nr_disks, 0, -1)), list(), list()]
- @property
- def nr_disks(self):
- return self._nr_disks
- @property
- def nr_moves(self):
- return 2**self.nr_disks - 1
- @property
- def towers(self):
- return deepcopy(self._towers)
- def tower(self, n):
- return self._towers[n].copy()
- def move_disk(self, from_tower, to_tower):
- disk = self._towers[from_tower].pop()
- self._towers[to_tower].append(disk)
- return disk, from_tower, to_tower
- def move_disks(self, n, from_tower, to_tower):
- if n == 1:
- yield self.move_disk(from_tower, to_tower)
- else:
- helper = 3 - from_tower - to_tower
- yield from self.move_disks(n - 1, from_tower, helper)
- yield self.move_disk(from_tower, to_tower)
- yield from self.move_disks(n - 1, helper, to_tower)
- def moves(self):
- yield from self.move_disks(self.nr_disks, 0, 1)
- nr_disks = 5
- hanoi = Hanoi(nr_disks)
- tower_states = list([hanoi.towers])
- for _ in hanoi.moves():
- tower_states.append(hanoi.towers)
- disks = { hanoi.nr_disks - i : Cylinder(r=0.2*(hanoi.nr_disks-i+1), c=i)
- for i in range(hanoi.nr_disks) }
- plt = Plotter(interactive=False, size=(800, 600), bg='wheat', bg2='lb')
- plt += list(disks.values())
- plt += Box(pos=(3,0,-0.5), size=(12,4,0.1))
- cam = dict(
- pos=(14.60, -20.56, 7.680),
- focal_point=(3.067, 0.5583, 1.910),
- viewup=(-0.1043, 0.2088, 0.9724),
- )
- plt.show(camera=cam)
- for t in range(len(tower_states)):
- state = tower_states[t]
- for tower_nr in range(3):
- for i, disk in enumerate(state[tower_nr]):
- disks[disk].pos([3 * tower_nr, 0, i+0.5])
- plt.render()
- plt.interactive().close()
|