3. Annexes

Voici, 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.
3 2 1
h("","321","")
5 1 4 2 3 6
h("5142","36","")
3 9 3 6 5 4 8 3
h("393","654","83")

# -*- 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>")


Pages : 1 2 3 4 5 6 7
Les tours de Hanoï
18 février 2013
Sommaire général