oici, pour les curieux, l'algorithme qui permet de dessiner les tours de Hanoï. On peut afficher n'importe qu'elle configuration avec une simple ligne de code.
# -*- coding: utf-8 -*-
import pdb
import math
import random
def scrumble(x, radius=1):
return (x[0] + radius*(2*random.random() - 1), x[1] + radius*(2*random.random() - 1))
def shake_color(color, target=255, weight=0):
result = []
for c in color:
c = (c + weight*target)/(weight + 1)
c *= 1 + (random.random() - .5)/5
c = math.floor(c)
if c < 0:
c = 0
elif c > 255:
c = 255
result.append(c)
return str(result[0]) + "," + str(result[1]) + "," + str(result[2])
def h(a,b,c):
"""Dessine les tours de Hanoï
en mettant les disque décrits sur les pieux a, b et c.
Par exemple : h("321", "", "4")
La taille des disques est indiquée par un chiffre unique.
Ils sont empilés successivement.
"""
m = "0"
for y in (a,b,c):
for x in y:
if x > m:
m = x
nbDisks = int(m)
H = 12*nbDisks
W = 6 + 12*nbDisks
print("<svg style='display:inline-block' width='{0}' height='{1}' xmlns='http://www.w3.org/2000/svg'>".format(3*W + 12, H + 24))
print("<defs>")
colors = ((255, 0, 0), (255, 127, 0), (255, 255, 0), (0, 255, 0), (0, 255, 255), (0, 127, 255), (0, 0, 255), (127, 0, 255))
i = 0
for color in colors:
print("<linearGradient id='G{0}'>".format(i))
print("<stop offset='{0}' stop-color='rgb({1})'/>".format(0, shake_color(color)))
print("<stop offset='{0}%' stop-color='rgb({1})'/>".format(random.randint(5,25), shake_color(color, 255, 9)))
print("<stop offset='{0}%' stop-color='rgb({1})'/>".format(random.randint(30,45), shake_color(color)))
print("<stop offset='{0}%' stop-color='rgb({1})'/>".format(random.randint(55,70), shake_color(color)))
print("<stop offset='{0}%' stop-color='rgb({1})'/>".format(random.randint(75,95), shake_color(color, 0, 2)))
print("<stop offset='{0}%' stop-color='rgb({1})'/>".format(100, shake_color(color, 0, 8)))
print("</linearGradient>")
i += 1
print("</defs>")
print("<g stroke='black' stroke-width='2' fill='#bbb'>")
xs = []
points = [
scrumble((-4.00, 10 + 4*H/4), 2),
(-3.75, 12 + 3*H/4),
(-3.50, 12 + 2*H/4),
(-3.25, 12 + 1*H/4),
(-3.00, 12 + 0*H/4),
(0, 0),
(3.00, 12 + 0*H/4),
(3.25, 12 + 1*H/4),
(3.50, 12 + 2*H/4),
(3.75, 12 + 3*H/4),
scrumble((4.00, 10 + 4*H/4), 2)]
for i in range(3):
# Dessin des pieux.
x = (i + 0.5)*W + 3
pt = points[0]
print("<path d='M{0:.2f},{1:.2f} ".format(x + pt[0], pt[1]), end='')
j = 1
while j < len(points):
pt1 = scrumble(points[j])
pt2 = scrumble(points[j + 1])
print("Q{0:.2f},{1:.2f},{2:.2f},{3:.2f} ".format(x + pt1[0], pt1[1], x + pt2[0], pt2[1]), end='')
j += 2
print("'/>")
xs.append((i + 0.5)*W)
# Affichage de la base
print("<path d='M6,{0:.2f} ".format(H + 12), end='')
pt1 = scrumble((6 + 1*3*W/4, H + 12))
pt2 = scrumble((6 + 2*3*W/4, H + 12))
print("Q{0:.2f},{1:.2f},{2:.2f},{3:.2f} ".format(pt1[0], pt1[1], pt2[0], pt2[1]), end='')
pt1 = pt2
pt2 = scrumble((6 + 3*3*W/4, H + 12))
print("Q{0:.2f},{1:.2f},{2:.2f},{3:.2f} ".format(pt1[0], pt1[1], pt2[0], pt2[1]), end='')
pt1 = pt2
pt2 = scrumble((6 + 4*3*W/4, H + 12))
print("Q{0:.2f},{1:.2f},{2:.2f},{3:.2f} ".format(pt1[0], pt1[1], pt2[0], pt2[1]), end='')
pt2 = scrumble((6 + 4*3*W/4, H + 22))
print("L{0:.2f},{1:.2f} ".format(pt2[0], pt2[1]))
pt1 = pt2
pt2 = scrumble((6 + 3*3*W/4, H + 22), 2)
print("Q{0:.2f},{1:.2f},{2:.2f},{3:.2f} ".format(pt1[0], pt1[1], pt2[0], pt2[1]), end='')
pt1 = pt2
pt2 = scrumble((6 + 2*3*W/4, H + 22), 2)
print("Q{0:.2f},{1:.2f},{2:.2f},{3:.2f} ".format(pt1[0], pt1[1], pt2[0], pt2[1]), end='')
pt1 = pt2
pt2 = scrumble((6 + 1*3*W/4, H + 22), 2)
print("Q{0:.2f},{1:.2f},{2:.2f},{3:.2f} ".format(pt1[0], pt1[1], pt2[0], pt2[1]), end='')
pt1 = pt2
pt2 = scrumble((6, H + 22), 2)
print("Q{0:.2f},{1:.2f},{2:.2f},{3:.2f} ".format(pt1[0], pt1[1], pt2[0], pt2[1]), end='')
print("Z'/>")
# Affichage des disques
for i in range(3):
disks = (a,b,c)[i]
x = xs[i] + 3
y = H + 12
for d in disks:
if not d.isdigit():
continue
w = 6*int(d)
y -= 12
pt1 = scrumble((x - w, y), 0)
print("<path fill='url(#G{2})' d='M{0:.2f},{1:.2f} ".format(pt1[0], pt1[1], (int(d) - 1)%8), end='')
pt1 = scrumble((x, y), 2)
pt2 = scrumble((x + w, y), 2)
print("Q{0:.2f},{1:.2f},{2:.2f},{3:.2f} ".format(pt1[0], pt1[1], pt2[0], pt2[1]), end='')
pt1 = scrumble((x + w + 6, y + 6), 2)
pt2 = scrumble((x + w, y + 12), 2)
print("Q{0:.2f},{1:.2f},{2:.2f},{3:.2f} ".format(pt1[0], pt1[1], pt2[0], pt2[1]), end='')
pt1 = scrumble((x, y + 12), 2)
pt2 = scrumble((x - w, y + 12), 2)
print("Q{0:.2f},{1:.2f},{2:.2f},{3:.2f} ".format(pt1[0], pt1[1], pt2[0], pt2[1]), end='')
pt1 = scrumble((x - w - 6, y + 6), 2)
pt2 = scrumble((x - w, y), 0)
print("Q{0:.2f},{1:.2f},{2:.2f},{3:.2f} ".format(pt1[0], pt1[1], pt2[0], pt2[1]), end='')
print("'/>")
print("<text stroke-width='.25' x='{0:.2f}' y='{1:.2f}' font-size='9' stroke='black' fill='black'>".format(
x - w + 6, y + 10), end='')
print(d, end='')
print("</text>", end='')
print("</g></svg>")