Ajout TP 8
This commit is contained in:
parent
1730830566
commit
0dc988076e
407
S1/TP 8/lsystem.py
Normal file
407
S1/TP 8/lsystem.py
Normal file
|
@ -0,0 +1,407 @@
|
|||
# PREUD'HOMME BONTOUX Geoffrey - PeiP 12 - 2014/2015
|
||||
# TP n°8 donné le 14/11/2014 - Dessiner avec la tortue ep02
|
||||
# http://www.fil.univ-lille1.fr/~allegraud/info_l1s1/tp_chaines_et_listes.html
|
||||
|
||||
from turtle import *
|
||||
import doctest
|
||||
|
||||
# Réalisez une procédure nommée dessine
|
||||
|
||||
|
||||
def dessine(ordres, l, α):
|
||||
"""
|
||||
Trace sur turtle la séquence d'ordre donnée, avec la longueur l et l'angle α
|
||||
donné.
|
||||
|
||||
CU : ordres str, l numérique, α numérique → ∅
|
||||
"""
|
||||
assert(type(ordres) is str), "ordres doit être du type str"
|
||||
assert(type(l) is float or type(l) is int), "l doit être numérique"
|
||||
assert(type(α) is float or type(α) is int), "α doit être numérique"
|
||||
|
||||
for i in ordres:
|
||||
if i == 'F' or i == 'G':
|
||||
forward(l)
|
||||
elif i == '+':
|
||||
left(α)
|
||||
elif i == '-':
|
||||
right(α)
|
||||
else:
|
||||
assert (False), "ordres doit être composé des caractères 'F', 'G', '+' \
|
||||
ou '-'"
|
||||
|
||||
# Testez votre procédure sur l’exemple précédent.
|
||||
|
||||
# dessine('F--F--F', 100, 60)
|
||||
|
||||
# Tracez chacune des figures ci-dessous :
|
||||
|
||||
# un carré
|
||||
|
||||
# dessine('F-F-F-F', 100, 90)
|
||||
|
||||
# un hexagone régulier
|
||||
|
||||
# dessine('F-F-F-F-F-F', 100, 360/6)
|
||||
|
||||
# (facultatif) une maison
|
||||
|
||||
# Version compressée
|
||||
|
||||
# reset()
|
||||
# dessine('FFF+++FF+++F+++FF+++FFF+++FFFFF+FFFFF++++FFFFF++++FFFFF++++++FFFFF+++FFFFF', 10, 30)
|
||||
|
||||
# Version expliquée
|
||||
|
||||
# L = 10 # On choisi une longueur sufisament petite pour les détails
|
||||
# ANGLE_DEG = 30 # On a besoin d'angles de 90° (pour les murs) et de 60° (pour
|
||||
# # le triangle équilatéral qui sert de toit), on prend donc le PGCD des deux
|
||||
# MUR = 5
|
||||
# ANGLE_DROIT = 90 // ANGLE_DEG
|
||||
# ANGLE_TRIANGLE_DEG = 180 // 3
|
||||
# ROTATION_TRIANGLE_DEG = 180 - ANGLE_TRIANGLE_DEG
|
||||
# ROTATION_TRIANGLE = ROTATION_TRIANGLE_DEG // ANGLE_DEG
|
||||
# DEMITOUR = 180 // ANGLE_DEG
|
||||
# DECALAGE_PORTE_GAUCHE = MUR // 2
|
||||
# HAUTEUR_PORTE = 2
|
||||
# LARGEUR_PORTE = 1
|
||||
# DECALAGE_PORTE_DROITE = MUR - DECALAGE_PORTE_GAUCHE
|
||||
|
||||
# reset()
|
||||
# dessine(# Mur du bas et porte
|
||||
# 'F' * (DECALAGE_PORTE_GAUCHE + LARGEUR_PORTE)
|
||||
# + '+' * ANGLE_DROIT
|
||||
# + 'F' * HAUTEUR_PORTE
|
||||
# + '+' * ANGLE_DROIT
|
||||
# + 'F' * LARGEUR_PORTE
|
||||
# + '+' * ANGLE_DROIT
|
||||
# + 'F' * HAUTEUR_PORTE
|
||||
# + '+' * ANGLE_DROIT
|
||||
# + 'F' * DECALAGE_PORTE_DROITE
|
||||
# # Mur de droite
|
||||
# + '+' * ANGLE_DROIT
|
||||
# + 'F' * MUR
|
||||
# # Toit
|
||||
# + '-' * ANGLE_DROIT
|
||||
# + '+' * ROTATION_TRIANGLE
|
||||
# + 'F' * MUR
|
||||
# + '+' * ROTATION_TRIANGLE
|
||||
# + 'F' * MUR
|
||||
# + '+' * ROTATION_TRIANGLE
|
||||
# + 'F' * MUR
|
||||
# + '+' * DEMITOUR
|
||||
# + 'F' * MUR
|
||||
# + '+' * ANGLE_DROIT
|
||||
# + 'F' * MUR, L, ANGLE_DEG)
|
||||
|
||||
# (facultatif) un mouton
|
||||
|
||||
# Version compressée
|
||||
|
||||
# reset()
|
||||
# dessine('FFFFFFF+++FFF+++FFFFFFF+++FFF+++FFFFFFF+FFF++FFF++++FFF++++++FFF+++++FFFFFFF+FFF', 20, 30)
|
||||
|
||||
# Version expliquée
|
||||
|
||||
# L = 20
|
||||
# ANGLE_DEG = 30
|
||||
# LARGEUR = 7
|
||||
# LONGUEUR = 3
|
||||
# PROFONDEUR = 3
|
||||
# ANGLE_DROIT = 90 // ANGLE_DEG
|
||||
# ANGLE_PERSPECTIVE = 1
|
||||
# DEMITOUR = 180 // ANGLE_DEG
|
||||
#
|
||||
# print(# Face avant
|
||||
# 'F' * LARGEUR
|
||||
# + '+' * ANGLE_DROIT
|
||||
# + 'F' * LONGUEUR
|
||||
# + '+' * ANGLE_DROIT
|
||||
# + 'F' * LARGEUR
|
||||
# + '+' * ANGLE_DROIT
|
||||
# + 'F' * LONGUEUR
|
||||
# + '+' * ANGLE_DROIT
|
||||
# # Arète oblique en bas
|
||||
# + 'F' * LARGEUR
|
||||
# + '+' * ANGLE_PERSPECTIVE
|
||||
# + 'F' * PROFONDEUR
|
||||
# # Arète verticale à droite
|
||||
# + '+' * (ANGLE_DROIT - ANGLE_PERSPECTIVE)
|
||||
# + 'F' * LONGUEUR
|
||||
# # Arète oblique au milieu
|
||||
# + '+' * (ANGLE_DROIT + ANGLE_PERSPECTIVE)
|
||||
# + 'F' * PROFONDEUR
|
||||
# + '+' * DEMITOUR
|
||||
# + 'F' * PROFONDEUR
|
||||
# # Arète horizontale en haut
|
||||
# + '+' * (DEMITOUR - ANGLE_PERSPECTIVE)
|
||||
# + 'F' * LARGEUR
|
||||
# # Arète oblique à gauche
|
||||
# + '+' * ANGLE_PERSPECTIVE
|
||||
# + 'F' * PROFONDEUR
|
||||
# , L, ANGLE_DEG)
|
||||
|
||||
|
||||
# « Ça c'est la caisse. Le mouton que tu veux est dedans. »
|
||||
# - Antoine de Saint Exupery
|
||||
|
||||
# Dériver un ordre par rapport à une variable
|
||||
|
||||
# Soit une chaîne so et une autre chaîne r. On appelle la dérivation de so
|
||||
# par r par rapport à 'F' la chaîne obtenue en remplaçant chacune des
|
||||
# occurrences du caractère 'F' de so par tous les caractères de r.
|
||||
|
||||
# Par exemple, la dérivation de 'F+F' par 'F-F' est 'F-F+F-F'.
|
||||
|
||||
# Réalisez une fonction derive qui revoie la dérivation de la première chaîne passée en paramètre par la seconde par rapport à 'F'.
|
||||
# On définit la dérivée n-ième de so par r par rapport à 'F' comme le
|
||||
# terme un de la suite (un)n∈N définie par récurrence :
|
||||
|
||||
def derive(so, r):
|
||||
"""
|
||||
Revoie la dérivation de la première chaîne passée en paramètre par la
|
||||
seconde par rapport à 'F'.
|
||||
Remplace dans une chaîne donnée toutes les occurences d’un caracère donné
|
||||
par une autre chaîne de caractères.
|
||||
|
||||
CU : so str et r str → str
|
||||
|
||||
>>> derive('', '++')
|
||||
''
|
||||
>>> derive('F+F', 'F-F')
|
||||
'F-F+F-F'
|
||||
"""
|
||||
assert(type(so) is str), "so doit être du type str"
|
||||
assert(type(r) is str), "r doit être du type str"
|
||||
|
||||
retour = ''
|
||||
for i in so:
|
||||
if i == 'F':
|
||||
retour += r
|
||||
else:
|
||||
retour += i
|
||||
return retour
|
||||
|
||||
# Programmez une fonction derive_n
|
||||
|
||||
|
||||
def derive_n(so, r, n):
|
||||
"""
|
||||
Renvoie la dérivation n-ième de la première chaîne par la seconde par
|
||||
rapport à 'F'
|
||||
|
||||
CU : CU : so str et r str et n int → str
|
||||
|
||||
>>> derive_n('F+F', 'F-F', 3)
|
||||
'F-F-F-F-F-F-F-F+F-F-F-F-F-F-F-F'
|
||||
>>> derive_n('FFF', 'F+F+F', 0)
|
||||
'FFF'
|
||||
"""
|
||||
assert(type(n) is int), "n doit être du type int"
|
||||
# derive() s'occupe des autres assertions, inutile de vérifier so deux fois
|
||||
|
||||
retour = so
|
||||
for i in range(0, n):
|
||||
retour = derive(retour, r)
|
||||
return retour
|
||||
|
||||
|
||||
# Fractales
|
||||
|
||||
# N’hésitez pas à accélerer la tortue en utilisant la fonction speed du
|
||||
# module turtle.
|
||||
|
||||
speed(0)
|
||||
|
||||
# Merci.
|
||||
|
||||
# Tracez pour n compris entre 0 et 5, l=35−n et α=60 le résultat de la séquence
|
||||
# d’ordres obtenu en dérivant n fois 'F--F--F' par 'F+F--F+F'
|
||||
|
||||
# n = 3
|
||||
# l = 3 ** (5 - n)
|
||||
# α = 60
|
||||
# ordres = derive_n('F--F--F', 'F+F--F+F', n)
|
||||
# dessine(ordres, l, α)
|
||||
|
||||
|
||||
# Essayez maintenant de dériver plusieurs fois 'F' par 'F+F-F-F+F' avec un angle
|
||||
# de 90°.
|
||||
|
||||
# dessine(derive_n('F', 'F+F-F-F+F', 3), 5, 90)
|
||||
|
||||
|
||||
# Dérivation à plusieurs variables
|
||||
|
||||
# Écrivez une fonction cherche_regle
|
||||
|
||||
def cherche_regle(ordre, liste_vars, liste_regles):
|
||||
"""
|
||||
Renvoie ordre si ordre n’appartient pas à liste_vars ou liste_regles[i] si
|
||||
il existe un indice i vérifiant ordre == liste_vars[i].
|
||||
|
||||
CU : ordre str de taille 1, liste_vars une liste contenant exclusivement des
|
||||
types str, liste_regles une liste contenant exclusivement des types str de
|
||||
même taille que liste_vars → str
|
||||
|
||||
>>> cherche_regle('F', ['F', 'G'], ['F-F', 'G+G'])
|
||||
'F-F'
|
||||
>>> cherche_regle('A', ['F', 'G'], ['F-F', 'G+G'])
|
||||
'A'
|
||||
"""
|
||||
assert(type(ordre) is str and len(ordre) == 1), "ordre doit être du type \
|
||||
str et être de taille 1"
|
||||
assert(type(liste_vars) is list), "liste_vars doit être du type list"
|
||||
for i in liste_vars:
|
||||
assert(type(i) is str), "liste_vars doit contenir exclusivement des \
|
||||
types str"
|
||||
assert(type(liste_regles) is list), "liste_regles doit être du type list"
|
||||
for i in liste_regles:
|
||||
assert(type(i) is str), "liste_regles doit contenir exclusivement des \
|
||||
types str"
|
||||
assert(len(liste_vars) == len(liste_regles)), "liste_regles doit être de \
|
||||
même taille que liste_vars"
|
||||
|
||||
if (ordre in liste_vars):
|
||||
return liste_regles[liste_vars.index(ordre)]
|
||||
else:
|
||||
return ordre
|
||||
|
||||
# Écrivez une fonction derive_mult
|
||||
|
||||
|
||||
def derive_mult(so, liste_regles, liste_vars):
|
||||
"""
|
||||
Renvoie la dérivation de so par liste_regles par rapport à liste_vars.
|
||||
|
||||
CU : so str, liste_vars une liste contenant exclusivement des types str,
|
||||
liste_regles une liste contenant exclusivement des types str de même taille
|
||||
que liste_vars → str
|
||||
|
||||
>>> derive_mult('FGF', ['F', 'G'], ['GG', 'FFF'])
|
||||
'GGFFFGG'
|
||||
"""
|
||||
assert(type(so) is str), "so doit être de type str"
|
||||
# cherche_regle s'occupe des autres assertions
|
||||
|
||||
retour = ''
|
||||
for i in so:
|
||||
retour += cherche_regle(i, liste_regles, liste_vars)
|
||||
return retour
|
||||
|
||||
# Écrivez une fonction derive_mult_n
|
||||
|
||||
|
||||
def derive_mult_n(so, liste_regles, liste_vars, n):
|
||||
"""
|
||||
Renvoie la dérivée de la séquence d’ordres par la liste de règles par
|
||||
rapport à la liste des variables.
|
||||
|
||||
CU : so str, liste_vars une liste contenant exclusivement des types str,
|
||||
liste_regles une liste contenant exclusivement des types str de même taille
|
||||
que liste_vars, n int → str
|
||||
|
||||
>>> derive_mult_n('FGF', ['F', 'G'], ['GG', 'FFF'], 3)
|
||||
'GGGGGGGGGGGGFFFFFFFFFFFFFFFFFFGGGGGGGGGGGG'
|
||||
"""
|
||||
assert(type(n) is int), "n doit être du type int"
|
||||
# deriv_mult() s'occupe des autres assertions
|
||||
|
||||
retour = so
|
||||
for i in range(0, n):
|
||||
retour = derive_mult(retour, liste_regles, liste_vars)
|
||||
return retour
|
||||
|
||||
# Tracez pour n compris entre 0 et 6, l=27−n et α=90 le résultat de la séquence
|
||||
# d’ordres obtenu en dérivant 2n fois 'FX' par ['X+YF+', '-FX-Y'] par rapport
|
||||
# à ['X','Y'].
|
||||
|
||||
# n = 4
|
||||
# l = 2 ** (7 - n)
|
||||
# α = 90
|
||||
# ordres = derive_mult_n('FX', ['X', 'Y'], ['X+YF+', '-FX-Y'], 2 * n)
|
||||
# ordres = derive_mult(ordres, ['X', 'Y'], ['', '']) # Pour éviter les erreurs
|
||||
# # d'assertion
|
||||
# dessine(ordres, l, α)
|
||||
|
||||
|
||||
# Sauvegarde d’une position
|
||||
|
||||
# Écrivez une commande sauvegardant l’état de la tortue
|
||||
# dans une liste de 3 éléments.
|
||||
|
||||
etat = [0, 0, 0]
|
||||
|
||||
|
||||
def sauvegarder_etat():
|
||||
"""
|
||||
Sauvegarde l’état de la tortue dans la variable globale etat
|
||||
|
||||
CU : ∅ → ∅
|
||||
"""
|
||||
|
||||
global etat
|
||||
etat[0] = xcor()
|
||||
etat[1] = ycor()
|
||||
etat[2] = heading()
|
||||
|
||||
# Écrivez une commande permettant de restaurer un état contenu
|
||||
# dans une liste à 3 éléments.
|
||||
|
||||
|
||||
def restaurer_etat():
|
||||
"""
|
||||
Restaure l’état de la tortue depuis la variable globale etat
|
||||
|
||||
CU : ∅ → ∅
|
||||
"""
|
||||
|
||||
global etat
|
||||
penup()
|
||||
goto(etat[0], etat[1])
|
||||
setheading(etat[2])
|
||||
pendown()
|
||||
|
||||
# Modifiez votre procédure dessine pour prendre en compte les deux
|
||||
# nouveaux ordres.
|
||||
|
||||
|
||||
def dessine2(ordres, l, α):
|
||||
"""
|
||||
Trace sur turtle la séquence d'ordre donnée, avec la longueur l et l'angle α
|
||||
donné.
|
||||
|
||||
CU : ordres str, l numérique, α numérique → ∅
|
||||
"""
|
||||
assert(type(ordres) is str), "ordres doit être du type str"
|
||||
assert(type(l) is float or type(l) is int), "l doit être numérique"
|
||||
assert(type(α) is float or type(α) is int), "α doit être numérique"
|
||||
|
||||
for i in ordres:
|
||||
if i == 'F' or i == 'G':
|
||||
forward(l)
|
||||
elif i == '+':
|
||||
left(α)
|
||||
elif i == '-':
|
||||
right(α)
|
||||
elif i == '(':
|
||||
sauvegarder_etat()
|
||||
elif i == ')':
|
||||
restaurer_etat()
|
||||
else:
|
||||
assert (False), "ordres doit être composé des caractères 'F', 'G', '+' \
|
||||
'-', '(' ou ')'"
|
||||
|
||||
# Tracez pour n compris entre 0 et 6, l=4 et α=60 le résultat de la
|
||||
# séquence d’ordres obtenu en dérivant n fois 'G' par ['FF', 'F+(G)--G']
|
||||
# par rapport à ['F','G'].
|
||||
|
||||
# n = 6
|
||||
# l = 4
|
||||
# α = 60
|
||||
# ordres = derive_mult_n('G', ['F', 'G'], ['FF', 'F+(G)--G'], n)
|
||||
# dessine2(ordres, l, α)
|
||||
|
||||
|
||||
def tester():
|
||||
doctest.testmod(verbose=True)
|
Reference in a new issue