diff --git a/S1/TP 8/lsystem.py b/S1/TP 8/lsystem.py new file mode 100644 index 0000000..753027e --- /dev/null +++ b/S1/TP 8/lsystem.py @@ -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)