Created
July 4, 2018 12:03
-
-
Save vadella/775b975bf351f1d8629d660e820eea8b to your computer and use it in GitHub Desktop.
My hanoi implementation
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
from enum import IntEnum | |
from itertools import repeat | |
from PIL import Image | |
BUFFER_PEG = 10 | |
LINE_WIDTH = 1 | |
BUFFER_STEP = 5 | |
class Color(IntEnum): | |
BLACK = 0 | |
WHITE = 1 | |
def hanoi_gen(disks, source, helper, target, state): | |
if disks: | |
yield from hanoi_gen(disks - 1, source, target, helper, state) | |
target.append(source.pop()) | |
yield ( | |
tuple(state['source']), | |
tuple(state['target']), | |
tuple(state['helper']), | |
) | |
yield from hanoi_gen(disks - 1, helper, source, target, state) | |
def solve_tower(disks): | |
source = list(range(disks, 0, -1)) | |
target = list() | |
helper = list() | |
yield tuple(source), tuple(target), tuple(helper) | |
state = dict( | |
source=source, | |
target=target, | |
helper=helper | |
) | |
yield from hanoi_gen(disks, source, helper, target, state) | |
def whitespace(width, image_width): | |
return repeat(Color.WHITE, width * image_width) | |
def line(width, image_width): | |
return repeat(Color.BLACK, width * image_width) | |
def pad_disk(disk_width, num_disks): | |
blank_width = num_disks - disk_width | |
yield from repeat(Color.WHITE, blank_width) | |
yield from repeat(Color.BLACK, disk_width * 2) | |
yield from repeat(Color.WHITE, blank_width) | |
def buffer_peg(): | |
return repeat(Color.WHITE, BUFFER_PEG) | |
def format_row(disks, num_disks): | |
yield from buffer_peg() | |
for disk_width in disks: | |
yield from pad_disk(disk_width, num_disks) | |
yield from buffer_peg() | |
def pad_left_reverse(peg, size, fillvalue=0): | |
yield from repeat(fillvalue, size - len(peg)) | |
yield from reversed(peg) | |
def format_step(step, num_disks): | |
pegs = map( | |
lambda peg: pad_left_reverse(peg, num_disks, fillvalue=0), | |
step | |
) | |
for row in zip(*pegs): | |
yield from format_row(row, num_disks) | |
def format_steps(steps, image_width, num_disks): | |
for step in steps: | |
yield from whitespace(BUFFER_STEP, image_width) | |
yield from format_step(step, num_disks) | |
yield from whitespace(BUFFER_STEP, image_width) | |
yield from line(LINE_WIDTH, image_width) | |
if __name__ == '__main__': | |
num_disks = 5 | |
steps = solve_tower(num_disks) | |
image_width = num_disks * 2 * 3 + 4 * BUFFER_PEG | |
data = list(format_steps(steps, image_width, num_disks)) | |
with Image.new('1', (image_width, len(data) // image_width)) as image: | |
image.putdata(data) | |
name = 'my_hanoi.png' | |
image.save(name) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment