Last active
November 27, 2019 21:17
-
-
Save tammoippen/61b123261bae1acb90526ba708610b4a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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