Skip to content

Instantly share code, notes, and snippets.

@tammoippen
Last active November 27, 2019 21:17
Show Gist options
  • Save tammoippen/61b123261bae1acb90526ba708610b4a to your computer and use it in GitHub Desktop.
Save tammoippen/61b123261bae1acb90526ba708610b4a to your computer and use it in GitHub Desktop.
# execute like: python hanoi.py a b 5
from time import sleep
DO_SLEEP = False
class Hanoi:
def __init__(self, pilon: str, height: int):
self.pilons = {
'a': [],
'b': [],
'c': [],
}
self.pilons[pilon] = list(range(height, 0, -1))
def pretty(self):
max_ring = max(max(p, default=0) for p in self.pilons.values())
res = [f'{"A":^{max_ring}} ¦ {"B":^{max_ring}} ¦ {"C":^{max_ring}}',
'=' * (3 * max_ring + 6)]
for h in range(max_ring + 1):
a, b, c = 0, 0, 0
if h < len(self.pilons['a']):
a = self.pilons['a'][h]
if h < len(self.pilons['b']):
b = self.pilons['b'][h]
if h < len(self.pilons['c']):
c = self.pilons['c'][h]
res += [f'{"-" * a:^{max_ring}} ¦ {"-" * b:^{max_ring}} ¦ {"-" * c:^{max_ring}}']
print('\033[2J\033[H' + '\n'.join(reversed(res + [''])))
def invariant(self):
if not all(all(pilon[i] > pilon[i+1] for i in range(len(pilon)-1)) for pilon in self.pilons.values()):
print('ERROR' + str(self))
raise Exception()
def move(self, src, tgt):
self.pilons[tgt].append(self.pilons[src].pop())
self.invariant()
def move(hanoi, src, tgt, other, lvl=0):
# lvl indicates on which level we are operating right now
# we might have to move the rings above me to the other pilon
has_rings_above = len(hanoi.pilons[src]) > lvl + 1
if has_rings_above:
other_height = len(hanoi.pilons[other])
move(hanoi, src, other, tgt, lvl + 1)
# move this ring to the target
hanoi.move(src, tgt)
hanoi.pretty()
if DO_SLEEP:
sleep(.5)
# move the rings, that were above me previously, back ontop of me
if has_rings_above:
move(hanoi, other, tgt, src, other_height)
if __name__ == "__main__":
import sys
# arguments: python hanoi.py a b 5
src = sys.argv[1]
tgt = sys.argv[2]
height = int(sys.argv[3])
DO_SLEEP = height < 10
h = Hanoi(src, height)
others = h.pilons.keys() - {src, tgt}
assert len(others) == 1
other = others.pop()
# do the moving
h.pretty()
move(h, src, tgt, other)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment